- 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
This commit is contained in:
Brett Zamir
2018-05-16 08:53:27 +08:00
parent 5bcbb948eb
commit 340915be4e
51 changed files with 12031 additions and 12108 deletions

View File

@@ -1,13 +1,14 @@
node_modules node_modules
editor/jquery.js
editor/jspdf/jspdf.min.js editor/jspdf/jspdf.min.js
editor/jspdf/underscore-min.js editor/jspdf/underscore-min.js
jgraduate/jpicker.min.js editor/jgraduate/jpicker.min.js
jgraduate/jquery.jgraduate.js editor/jgraduate/jquery.jgraduate.min.js
jquery-ui editor/jquery-ui
jquerybbq editor/jquerybbq
js-hotkeys editor/js-hotkeys
spinbtn/JQuerySpinBtn.min.js editor/spinbtn/JQuerySpinBtn.min.js
test/qunit test/qunit
test/sinon test/sinon
wave/json2.js wave/json2.js

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true*/ /* globals $, svgedit */
/** /**
* Package: svgedit.browser * Package: svgedit.browser
* *
@@ -12,7 +12,8 @@
// Dependencies: // Dependencies:
// 1) jQuery (for $.alert()) // 1) jQuery (for $.alert())
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.browser) { if (!svgedit.browser) {
svgedit.browser = {}; svgedit.browser = {};
@@ -21,12 +22,12 @@ if (!svgedit.browser) {
// alias // alias
var NS = svgedit.NS; var NS = svgedit.NS;
var supportsSvg_ = (function() { var supportsSvg_ = (function () {
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect; return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
}()); }());
svgedit.browser.supportsSvg = function() { return supportsSvg_; }; svgedit.browser.supportsSvg = function () { return supportsSvg_; };
if(!svgedit.browser.supportsSvg()) { if (!svgedit.browser.supportsSvg()) {
window.location = 'browser-not-supported.html'; window.location = 'browser-not-supported.html';
return; return;
} }
@@ -44,41 +45,41 @@ var isWindows_ = userAgent.indexOf('Windows') >= 0;
var isMac_ = userAgent.indexOf('Macintosh') >= 0; var isMac_ = userAgent.indexOf('Macintosh') >= 0;
var isTouch_ = 'ontouchstart' in window; var isTouch_ = 'ontouchstart' in window;
var supportsSelectors_ = (function() { var supportsSelectors_ = (function () {
return !!svg.querySelector; return !!svg.querySelector;
}()); }());
var supportsXpath_ = (function() { var supportsXpath_ = (function () {
return !!document.evaluate; return !!document.evaluate;
}()); }());
// segList functions (for FF1.5 and 2.0) // segList functions (for FF1.5 and 2.0)
var supportsPathReplaceItem_ = (function() { var supportsPathReplaceItem_ = (function () {
var path = document.createElementNS(NS.SVG, 'path'); var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 10,10'); path.setAttribute('d', 'M0,0 10,10');
var seglist = path.pathSegList; var seglist = path.pathSegList;
var seg = path.createSVGPathSegLinetoAbs(5,5); var seg = path.createSVGPathSegLinetoAbs(5, 5);
try { try {
seglist.replaceItem(seg, 1); seglist.replaceItem(seg, 1);
return true; return true;
} catch(err) {} } catch (err) {}
return false; return false;
}()); }());
var supportsPathInsertItemBefore_ = (function() { var supportsPathInsertItemBefore_ = (function () {
var path = document.createElementNS(NS.SVG, 'path'); var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 10,10'); path.setAttribute('d', 'M0,0 10,10');
var seglist = path.pathSegList; var seglist = path.pathSegList;
var seg = path.createSVGPathSegLinetoAbs(5,5); var seg = path.createSVGPathSegLinetoAbs(5, 5);
try { try {
seglist.insertItemBefore(seg, 1); seglist.insertItemBefore(seg, 1);
return true; return true;
} catch(err) {} } catch (err) {}
return false; return false;
}()); }());
// text character positioning (for IE9) // text character positioning (for IE9)
var supportsGoodTextCharPos_ = (function() { var supportsGoodTextCharPos_ = (function () {
var svgroot = document.createElementNS(NS.SVG, 'svg'); var svgroot = document.createElementNS(NS.SVG, 'svg');
var svgcontent = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgroot); document.documentElement.appendChild(svgroot);
@@ -92,7 +93,7 @@ var supportsGoodTextCharPos_ = (function() {
return (pos === 0); return (pos === 0);
}()); }());
var supportsPathBBox_ = (function() { var supportsPathBBox_ = (function () {
var svgcontent = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgcontent); document.documentElement.appendChild(svgcontent);
var path = document.createElementNS(NS.SVG, 'path'); 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 // Support for correct bbox sizing on groups with horizontal/vertical lines
var supportsHVLineContainerBBox_ = (function() { var supportsHVLineContainerBBox_ = (function () {
var svgcontent = document.createElementNS(NS.SVG, 'svg'); var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgcontent); document.documentElement.appendChild(svgcontent);
var path = document.createElementNS(NS.SVG, 'path'); var path = document.createElementNS(NS.SVG, 'path');
@@ -121,31 +122,31 @@ var supportsHVLineContainerBBox_ = (function() {
return (bbox.width == 15); return (bbox.width == 15);
}()); }());
var supportsEditableText_ = (function() { var supportsEditableText_ = (function () {
// TODO: Find better way to check support for this // TODO: Find better way to check support for this
return isOpera_; return isOpera_;
}()); }());
var supportsGoodDecimals_ = (function() { var supportsGoodDecimals_ = (function () {
// Correct decimals on clone attributes (Opera < 10.5/win/non-en) // Correct decimals on clone attributes (Opera < 10.5/win/non-en)
var rect = document.createElementNS(NS.SVG, 'rect'); var rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('x', 0.1); rect.setAttribute('x', 0.1);
var crect = rect.cloneNode(false); var crect = rect.cloneNode(false);
var retValue = (crect.getAttribute('x').indexOf(',') == -1); var retValue = (crect.getAttribute('x').indexOf(',') === -1);
if(!retValue) { if (!retValue) {
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n'+ $.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' +
'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.'); 'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.');
} }
return retValue; return retValue;
}()); }());
var supportsNonScalingStroke_ = (function() { var supportsNonScalingStroke_ = (function () {
var rect = document.createElementNS(NS.SVG, 'rect'); var rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('style', 'vector-effect:non-scaling-stroke'); rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
return rect.style.vectorEffect === 'non-scaling-stroke'; return rect.style.vectorEffect === 'non-scaling-stroke';
}()); }());
var supportsNativeSVGTransformLists_ = (function() { var supportsNativeSVGTransformLists_ = (function () {
var rect = document.createElementNS(NS.SVG, 'rect'); var rect = document.createElementNS(NS.SVG, 'rect');
var rxform = rect.transform.baseVal; var rxform = rect.transform.baseVal;
var t1 = svg.createSVGTransform(); var t1 = svg.createSVGTransform();
@@ -163,26 +164,25 @@ var supportsNativeSVGTransformLists_ = (function() {
// Public API // Public API
svgedit.browser.isOpera = function() { return isOpera_; }; svgedit.browser.isOpera = function () { return isOpera_; };
svgedit.browser.isWebkit = function() { return isWebkit_; }; svgedit.browser.isWebkit = function () { return isWebkit_; };
svgedit.browser.isGecko = function() { return isGecko_; }; svgedit.browser.isGecko = function () { return isGecko_; };
svgedit.browser.isIE = function() { return isIE_; }; svgedit.browser.isIE = function () { return isIE_; };
svgedit.browser.isChrome = function() { return isChrome_; }; svgedit.browser.isChrome = function () { return isChrome_; };
svgedit.browser.isWindows = function() { return isWindows_; }; svgedit.browser.isWindows = function () { return isWindows_; };
svgedit.browser.isMac = function() { return isMac_; }; svgedit.browser.isMac = function () { return isMac_; };
svgedit.browser.isTouch = function() { return isTouch_; }; svgedit.browser.isTouch = function () { return isTouch_; };
svgedit.browser.supportsSelectors = function() { return supportsSelectors_; }; svgedit.browser.supportsSelectors = function () { return supportsSelectors_; };
svgedit.browser.supportsXpath = function() { return supportsXpath_; }; 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.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_; };
}()); }());

View File

@@ -3,7 +3,7 @@
// CREATE A NEW FILE config.js AND ADD CONTENTS // CREATE A NEW FILE config.js AND ADD CONTENTS
// SUCH AS SHOWN BELOW INTO THAT FILE. // SUCH AS SHOWN BELOW INTO THAT FILE.
/*globals svgEditor*/ /* globals svgEditor */
/* /*
The config.js file is intended for the setting of configuration or 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 preferences which must run early on; if this is not needed, it is
@@ -60,13 +60,13 @@ svgEditor.setConfig({
// canvasName: 'default', // canvasName: 'default',
// canvas_expansion: 3, // canvas_expansion: 3,
// initFill: { // initFill: {
// color: 'FF0000', // solid red // color: 'FF0000', // solid red
// opacity: 1 // opacity: 1
// }, // },
// initStroke: { // initStroke: {
// width: 5, // width: 5,
// color: '000000', // solid black // color: '000000', // solid black
// opacity: 1 // opacity: 1
// }, // },
// initOpacity: 1, // initOpacity: 1,
// colorPickerCSS: null, // colorPickerCSS: null,

View File

@@ -1,5 +1,5 @@
/*globals $, svgEditor*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true*/ /* globals $, svgEditor */
/** /**
* Package: svgedit.contextmenu * Package: svgedit.contextmenu
* *
@@ -9,58 +9,58 @@
*/ */
// Dependencies: // Dependencies:
// 1) jQuery (for dom injection of context menus) // 1) jQuery (for dom injection of context menus)
var svgedit = svgedit || {}; var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define
(function() { (function () {
var self = this; var self = this;
if (!svgedit.contextmenu) { if (!svgedit.contextmenu) {
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 = {}; if (menuItem.id in self.contextMenuExtensions) {
var menuItemIsValid = function(menuItem) { console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function'; return;
}; }
var addContextMenuItem = function(menuItem) { // Register menuItem action, see below for deferred menu dom injection
// menuItem: {id, label, shortcut, action} console.log('Registed contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}');
if (!menuItemIsValid(menuItem)) { self.contextMenuExtensions[menuItem.id] = menuItem;
console.error("Menu items must be defined and have at least properties: id, label, action, where action must be a function"); // TODO: Need to consider how to handle custom enable/disable behavior
return; };
} var hasCustomHandler = function (handlerKey) {
if (menuItem.id in self.contextMenuExtensions) { return self.contextMenuExtensions[handlerKey] && true;
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"'); };
return; var getCustomHandler = function (handlerKey) {
} return self.contextMenuExtensions[handlerKey].action;
// Register menuItem action, see below for deferred menu dom injection };
console.log("Registed contextmenu item: {id:"+ menuItem.id+", label:"+menuItem.label+"}"); var injectExtendedContextMenuItemIntoDom = function (menuItem) {
self.contextMenuExtensions[menuItem.id] = menuItem; if (Object.keys(self.contextMenuExtensions).length === 0) {
//TODO: Need to consider how to handle custom enable/disable behavior // 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.
var hasCustomHandler = function(handlerKey) { $('#cmenu_canvas').append("<li class='separator'>");
return self.contextMenuExtensions[handlerKey] && true; }
}; var shortcut = menuItem.shortcut || '';
var getCustomHandler = function(handlerKey) { $('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" +
return self.contextMenuExtensions[handlerKey].action; menuItem.label + "<span class='shortcut'>" +
}; shortcut + '</span></a></li>');
var injectExtendedContextMenuItemIntoDom = function(menuItem) { };
if (Object.keys(self.contextMenuExtensions).length === 0) { // Defer injection to wait out initial menu processing. This probably goes away once all context
// all menuItems appear at the bottom of the menu in their own container. // menu behavior is brought here.
// if this is the first extension menu we need to add the separator. svgEditor.ready(function () {
$("#cmenu_canvas").append("<li class='separator'>"); var menuItem;
} for (menuItem in self.contextMenuExtensions) {
var shortcut = menuItem.shortcut || ""; injectExtendedContextMenuItemIntoDom(self.contextMenuExtensions[menuItem]);
$("#cmenu_canvas").append("<li class='disabled'><a href='#" + menuItem.id + "'>" }
+ menuItem.label + "<span class='shortcut'>" });
+ shortcut + "</span></a></li>"); svgedit.contextmenu.resetCustomMenus = function () { self.contextMenuExtensions = {}; };
}; svgedit.contextmenu.add = addContextMenuItem;
// Defer injection to wait out initial menu processing. This probably goes away once all context svgedit.contextmenu.hasCustomHandler = hasCustomHandler;
// menu behavior is brought here. svgedit.contextmenu.getCustomHandler = getCustomHandler;
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;
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals $, svgroot */ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true, forin: true*/ /* globals $, svgroot */
/** /**
* Coords. * Coords.
* *
@@ -16,17 +16,18 @@
// 6) units.js // 6) units.js
// 7) svgtransformlist.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) { if (!svgedit.coords) {
svgedit.coords = {}; svgedit.coords = {};
} }
// this is how we map paths to our preferred relative segment types // 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', var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
'H', 'h', 'V', 'v', 'S', 's', 'T', 't']; 'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
/** /**
* @typedef editorContext * @typedef editorContext
@@ -39,8 +40,8 @@ var editorContext_ = null;
/** /**
* @param {editorContext} editorContext * @param {editorContext} editorContext
*/ */
svgedit.coords.init = function(editorContext) { svgedit.coords.init = function (editorContext) {
editorContext_ = editorContext; editorContext_ = editorContext;
}; };
/** /**
@@ -49,269 +50,267 @@ svgedit.coords.init = function(editorContext) {
* @param {object} changes - Object with changes to be remapped * @param {object} changes - Object with changes to be remapped
* @param {SVGMatrix} m - Matrix object to use for remapping coordinates * @param {SVGMatrix} m - Matrix object to use for remapping coordinates
*/ */
svgedit.coords.remapElement = function(selected, changes, m) { svgedit.coords.remapElement = function (selected, changes, m) {
var i, type, var i, type,
remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); }, remap = function (x, y) { return svgedit.math.transformPoint(x, y, m); },
scalew = function(w) { return m.a * w; }, scalew = function (w) { return m.a * w; },
scaleh = function(h) { return m.d * h; }, scaleh = function (h) { return m.d * h; },
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg', doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
finishUp = function() { finishUp = function () {
var o; var o;
if (doSnapping) { if (doSnapping) {
for (o in changes) { for (o in changes) {
changes[o] = svgedit.utilities.snapToGrid(changes[o]); changes[o] = svgedit.utilities.snapToGrid(changes[o]);
} }
} }
svgedit.utilities.assignAttributes(selected, changes, 1000, true); svgedit.utilities.assignAttributes(selected, changes, 1000, true);
}, },
box = svgedit.utilities.getBBox(selected); box = svgedit.utilities.getBBox(selected);
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
type = i === 0 ? 'fill' : 'stroke'; type = i === 0 ? 'fill' : 'stroke';
var attrVal = selected.getAttribute(type); var attrVal = selected.getAttribute(type);
if (attrVal && attrVal.indexOf('url(') === 0) { if (attrVal && attrVal.indexOf('url(') === 0) {
if (m.a < 0 || m.d < 0) { if (m.a < 0 || m.d < 0) {
var grad = svgedit.utilities.getRefElem(attrVal); var grad = svgedit.utilities.getRefElem(attrVal);
var newgrad = grad.cloneNode(true); var newgrad = grad.cloneNode(true);
if (m.a < 0) { if (m.a < 0) {
// flip x // flip x
var x1 = newgrad.getAttribute('x1'); var x1 = newgrad.getAttribute('x1');
var x2 = newgrad.getAttribute('x2'); var x2 = newgrad.getAttribute('x2');
newgrad.setAttribute('x1', -(x1 - 1)); newgrad.setAttribute('x1', -(x1 - 1));
newgrad.setAttribute('x2', -(x2 - 1)); newgrad.setAttribute('x2', -(x2 - 1));
} }
if (m.d < 0) { if (m.d < 0) {
// flip y // flip y
var y1 = newgrad.getAttribute('y1'); var y1 = newgrad.getAttribute('y1');
var y2 = newgrad.getAttribute('y2'); var y2 = newgrad.getAttribute('y2');
newgrad.setAttribute('y1', -(y1 - 1)); newgrad.setAttribute('y1', -(y1 - 1));
newgrad.setAttribute('y2', -(y2 - 1)); newgrad.setAttribute('y2', -(y2 - 1));
} }
newgrad.id = editorContext_.getDrawing().getNextId(); newgrad.id = editorContext_.getDrawing().getNextId();
svgedit.utilities.findDefs().appendChild(newgrad); svgedit.utilities.findDefs().appendChild(newgrad);
selected.setAttribute(type, 'url(#' + newgrad.id + ')'); selected.setAttribute(type, 'url(#' + newgrad.id + ')');
} }
// Not really working :( // Not really working :(
// if (selected.tagName === 'path') { // if (selected.tagName === 'path') {
// reorientGrads(selected, m); // reorientGrads(selected, m);
// } // }
} }
} }
var elName = selected.tagName; var elName = selected.tagName;
var chlist, mt; var chlist, mt;
if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') { if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') {
// if it was a translate, then just update x,y // 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) ) { if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0)) {
// [T][M] = [M][T'] // [T][M] = [M][T']
// therefore [T'] = [M_inv][T][M] // therefore [T'] = [M_inv][T][M]
var existing = svgedit.math.transformListToTransform(selected).matrix, var existing = svgedit.math.transformListToTransform(selected).matrix,
t_new = svgedit.math.matrixMultiply(existing.inverse(), m, existing); tNew = svgedit.math.matrixMultiply(existing.inverse(), m, existing);
changes.x = parseFloat(changes.x) + t_new.e; changes.x = parseFloat(changes.x) + tNew.e;
changes.y = parseFloat(changes.y) + t_new.f; changes.y = parseFloat(changes.y) + tNew.f;
} else { } else {
// we just absorb all matrices into the element and don't do any remapping // we just absorb all matrices into the element and don't do any remapping
chlist = svgedit.transformlist.getTransformList(selected); chlist = svgedit.transformlist.getTransformList(selected);
mt = svgroot.createSVGTransform(); mt = svgroot.createSVGTransform();
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
chlist.clear(); chlist.clear();
chlist.appendItem(mt); chlist.appendItem(mt);
} }
} }
var c, pt, pt1, pt2, len; var c, pt, pt1, pt2, len;
// now we have a set of changes and an applied reduced transform list // now we have a set of changes and an applied reduced transform list
// we apply the changes directly to the DOM // we apply the changes directly to the DOM
switch (elName) { switch (elName) {
case 'foreignObject': case 'foreignObject':
case 'rect': case 'rect':
case 'image': case 'image':
// Allow images to be inverted (give them matrix when flipped) // Allow images to be inverted (give them matrix when flipped)
if (elName === 'image' && (m.a < 0 || m.d < 0)) { if (elName === 'image' && (m.a < 0 || m.d < 0)) {
// Convert to matrix // Convert to matrix
chlist = svgedit.transformlist.getTransformList(selected); chlist = svgedit.transformlist.getTransformList(selected);
mt = svgroot.createSVGTransform(); mt = svgroot.createSVGTransform();
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m)); mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
chlist.clear(); chlist.clear();
chlist.appendItem(mt); chlist.appendItem(mt);
} else { } else {
pt1 = remap(changes.x, changes.y); pt1 = remap(changes.x, changes.y);
changes.width = scalew(changes.width); changes.width = scalew(changes.width);
changes.height = scaleh(changes.height); changes.height = scaleh(changes.height);
changes.x = pt1.x + Math.min(0, changes.width); changes.x = pt1.x + Math.min(0, changes.width);
changes.y = pt1.y + Math.min(0, changes.height); changes.y = pt1.y + Math.min(0, changes.height);
changes.width = Math.abs(changes.width); changes.width = Math.abs(changes.width);
changes.height = Math.abs(changes.height); changes.height = Math.abs(changes.height);
} }
finishUp(); finishUp();
break; break;
case 'ellipse': case 'ellipse':
c = remap(changes.cx, changes.cy); c = remap(changes.cx, changes.cy);
changes.cx = c.x; changes.cx = c.x;
changes.cy = c.y; changes.cy = c.y;
changes.rx = scalew(changes.rx); changes.rx = scalew(changes.rx);
changes.ry = scaleh(changes.ry); changes.ry = scaleh(changes.ry);
changes.rx = Math.abs(changes.rx); changes.rx = Math.abs(changes.rx);
changes.ry = Math.abs(changes.ry); changes.ry = Math.abs(changes.ry);
finishUp(); finishUp();
break; break;
case 'circle': case 'circle':
c = remap(changes.cx,changes.cy); c = remap(changes.cx, changes.cy);
changes.cx = c.x; changes.cx = c.x;
changes.cy = c.y; changes.cy = c.y;
// take the minimum of the new selected box's dimensions for the new circle radius // 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 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; var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
changes.r = Math.min(w/2, h/2); changes.r = Math.min(w / 2, h / 2);
if (changes.r) {changes.r = Math.abs(changes.r);} if (changes.r) { changes.r = Math.abs(changes.r); }
finishUp(); finishUp();
break; break;
case 'line': case 'line':
pt1 = remap(changes.x1, changes.y1); pt1 = remap(changes.x1, changes.y1);
pt2 = remap(changes.x2, changes.y2); pt2 = remap(changes.x2, changes.y2);
changes.x1 = pt1.x; changes.x1 = pt1.x;
changes.y1 = pt1.y; changes.y1 = pt1.y;
changes.x2 = pt2.x; changes.x2 = pt2.x;
changes.y2 = pt2.y; changes.y2 = pt2.y;
// deliberately fall through here // deliberately fall through here
case 'text': case 'text':
case 'tspan': case 'tspan':
case 'use': case 'use':
finishUp(); finishUp();
break; break;
case 'g': case 'g':
var gsvg = $(selected).data('gsvg'); var gsvg = $(selected).data('gsvg');
if (gsvg) { if (gsvg) {
svgedit.utilities.assignAttributes(gsvg, changes, 1000, true); svgedit.utilities.assignAttributes(gsvg, changes, 1000, true);
} }
break; break;
case 'polyline': case 'polyline':
case 'polygon': case 'polygon':
len = changes.points.length; len = changes.points.length;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
pt = changes.points[i]; pt = changes.points[i];
pt = remap(pt.x, pt.y); pt = remap(pt.x, pt.y);
changes.points[i].x = pt.x; changes.points[i].x = pt.x;
changes.points[i].y = pt.y; changes.points[i].y = pt.y;
} }
len = changes.points.length; len = changes.points.length;
var pstr = ''; var pstr = '';
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
pt = changes.points[i]; pt = changes.points[i];
pstr += pt.x + ',' + pt.y + ' '; pstr += pt.x + ',' + pt.y + ' ';
} }
selected.setAttribute('points', pstr); selected.setAttribute('points', pstr);
break; break;
case 'path': case 'path':
var seg; var seg;
var segList = selected.pathSegList; var segList = selected.pathSegList;
len = segList.numberOfItems; len = segList.numberOfItems;
changes.d = []; changes.d = [];
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
seg = segList.getItem(i); seg = segList.getItem(i);
changes.d[i] = { changes.d[i] = {
type: seg.pathSegType, type: seg.pathSegType,
x: seg.x, x: seg.x,
y: seg.y, y: seg.y,
x1: seg.x1, x1: seg.x1,
y1: seg.y1, y1: seg.y1,
x2: seg.x2, x2: seg.x2,
y2: seg.y2, y2: seg.y2,
r1: seg.r1, r1: seg.r1,
r2: seg.r2, r2: seg.r2,
angle: seg.angle, angle: seg.angle,
largeArcFlag: seg.largeArcFlag, largeArcFlag: seg.largeArcFlag,
sweepFlag: seg.sweepFlag sweepFlag: seg.sweepFlag
}; };
} }
len = changes.d.length; len = changes.d.length;
var firstseg = changes.d[0], var firstseg = changes.d[0],
currentpt = remap(firstseg.x, firstseg.y); currentpt = remap(firstseg.x, firstseg.y);
changes.d[0].x = currentpt.x; changes.d[0].x = currentpt.x;
changes.d[0].y = currentpt.y; changes.d[0].y = currentpt.y;
for (i = 1; i < len; ++i) { for (i = 1; i < len; ++i) {
seg = changes.d[i]; seg = changes.d[i];
type = seg.type; type = seg.type;
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2 // if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
// if relative, we want to scalew, scaleh // if relative, we want to scalew, scaleh
if (type % 2 == 0) { // absolute if (type % 2 == 0) { // absolute
var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands
thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands
pt = remap(thisx,thisy); pt = remap(thisx, thisy);
pt1 = remap(seg.x1, seg.y1); pt1 = remap(seg.x1, seg.y1);
pt2 = remap(seg.x2, seg.y2); pt2 = remap(seg.x2, seg.y2);
seg.x = pt.x; seg.x = pt.x;
seg.y = pt.y; seg.y = pt.y;
seg.x1 = pt1.x; seg.x1 = pt1.x;
seg.y1 = pt1.y; seg.y1 = pt1.y;
seg.x2 = pt2.x; seg.x2 = pt2.x;
seg.y2 = pt2.y; seg.y2 = pt2.y;
seg.r1 = scalew(seg.r1); seg.r1 = scalew(seg.r1);
seg.r2 = scaleh(seg.r2); seg.r2 = scaleh(seg.r2);
} } else { // relative
else { // relative seg.x = scalew(seg.x);
seg.x = scalew(seg.x); seg.y = scaleh(seg.y);
seg.y = scaleh(seg.y); seg.x1 = scalew(seg.x1);
seg.x1 = scalew(seg.x1); seg.y1 = scaleh(seg.y1);
seg.y1 = scaleh(seg.y1); seg.x2 = scalew(seg.x2);
seg.x2 = scalew(seg.x2); seg.y2 = scaleh(seg.y2);
seg.y2 = scaleh(seg.y2); seg.r1 = scalew(seg.r1);
seg.r1 = scalew(seg.r1); seg.r2 = scaleh(seg.r2);
seg.r2 = scaleh(seg.r2); }
} } // for each segment
} // for each segment
var dstr = ''; var dstr = '';
len = changes.d.length; len = changes.d.length;
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
seg = changes.d[i]; seg = changes.d[i];
type = seg.type; type = seg.type;
dstr += pathMap[type]; dstr += pathMap[type];
switch (type) { switch (type) {
case 13: // relative horizontal line (h) case 13: // relative horizontal line (h)
case 12: // absolute horizontal line (H) case 12: // absolute horizontal line (H)
dstr += seg.x + ' '; dstr += seg.x + ' ';
break; break;
case 15: // relative vertical line (v) case 15: // relative vertical line (v)
case 14: // absolute vertical line (V) case 14: // absolute vertical line (V)
dstr += seg.y + ' '; dstr += seg.y + ' ';
break; break;
case 3: // relative move (m) case 3: // relative move (m)
case 5: // relative line (l) case 5: // relative line (l)
case 19: // relative smooth quad (t) case 19: // relative smooth quad (t)
case 2: // absolute move (M) case 2: // absolute move (M)
case 4: // absolute line (L) case 4: // absolute line (L)
case 18: // absolute smooth quad (T) case 18: // absolute smooth quad (T)
dstr += seg.x + ',' + seg.y + ' '; dstr += seg.x + ',' + seg.y + ' ';
break; break;
case 7: // relative cubic (c) case 7: // relative cubic (c)
case 6: // absolute cubic (C) case 6: // absolute cubic (C)
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' + dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
seg.x + ',' + seg.y + ' '; seg.x + ',' + seg.y + ' ';
break; break;
case 9: // relative quad (q) case 9: // relative quad (q)
case 8: // absolute quad (Q) case 8: // absolute quad (Q)
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' '; dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
break; break;
case 11: // relative elliptical arc (a) case 11: // relative elliptical arc (a)
case 10: // absolute elliptical arc (A) case 10: // absolute elliptical arc (A)
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) + dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' '; ' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
break; break;
case 17: // relative smooth cubic (s) case 17: // relative smooth cubic (s)
case 16: // absolute smooth cubic (S) case 16: // absolute smooth cubic (S)
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' '; dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
break; break;
} }
} }
selected.setAttribute('d', dstr); selected.setAttribute('d', dstr);
break; break;
} }
}; };
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true, todo: true*/ /* globals $, svgedit */
/** /**
* Package: svgedit.draw * Package: svgedit.draw
* *
@@ -13,7 +13,8 @@
// 2) browser.js // 2) browser.js
// 3) svgutils.js // 3) svgutils.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.draw) { if (!svgedit.draw) {
svgedit.draw = {}; svgedit.draw = {};
@@ -28,25 +29,22 @@ var RandomizeModes = {
ALWAYS_RANDOMIZE: 1, ALWAYS_RANDOMIZE: 1,
NEVER_RANDOMIZE: 2 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. * Called to ensure that drawings will or will not have randomized ids.
* The currentDrawing will have its nonce set if it doesn't already. * The currentDrawing will have its nonce set if it doesn't already.
* @param {boolean} enableRandomization - flag indicating if documents should have randomized ids * @param {boolean} enableRandomization - flag indicating if documents should have randomized ids
* @param {svgedit.draw.Drawing} currentDrawing * @param {svgedit.draw.Drawing} currentDrawing
*/ */
svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) { svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) {
randomize_ids = enableRandomization === false ? randomizeIds = enableRandomization === false
RandomizeModes.NEVER_RANDOMIZE : ? RandomizeModes.NEVER_RANDOMIZE
RandomizeModes.ALWAYS_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)); 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(); currentDrawing.clearNonce();
} }
}; };
@@ -56,12 +54,12 @@ svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) {
* @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object * @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object
* encapsulates. If the svgElem has a se:nonce attribute on it, then * encapsulates. If the svgElem has a se:nonce attribute on it, then
* IDs will use the nonce as they are generated. * 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 || if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||
svgElem.tagName != 'svg' || svgElem.namespaceURI != NS.SVG) { svgElem.tagName != 'svg' || svgElem.namespaceURI != NS.SVG) {
throw "Error: svgedit.draw.Drawing instance initialized without a <svg> element"; throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');
} }
/** /**
@@ -80,7 +78,7 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
* The prefix to prepend to each element id in the drawing. * The prefix to prepend to each element id in the drawing.
* @type {String} * @type {String}
*/ */
this.idPrefix = opt_idPrefix || "svg_"; this.idPrefix = optIdPrefix || 'svg_';
/** /**
* An array of released element ids to immediately reuse. * An array of released element ids to immediately reuse.
@@ -120,9 +118,9 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce'); var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');
// If already set in the DOM, use the nonce throughout the document // If already set in the DOM, use the nonce throughout the document
// else, if randomizeIds(true) has been called, create and set the nonce. // 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; this.nonce_ = n;
} else if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE) { } else if (randomizeIds == RandomizeModes.ALWAYS_RANDOMIZE) {
this.setNonce(Math.floor(Math.random() * 100001)); this.setNonce(Math.floor(Math.random() * 100001));
} }
}; };
@@ -150,14 +148,14 @@ svgedit.draw.Drawing.prototype.getSvgElem = function () {
/** /**
* @returns {!string|number} The previously set nonce * @returns {!string|number} The previously set nonce
*/ */
svgedit.draw.Drawing.prototype.getNonce = function() { svgedit.draw.Drawing.prototype.getNonce = function () {
return this.nonce_; return this.nonce_;
}; };
/** /**
* @param {!string|number} n The nonce to set * @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.XMLNS, 'xmlns:se', NS.SE);
this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n); this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);
this.nonce_ = n; this.nonce_ = n;
@@ -177,9 +175,9 @@ svgedit.draw.Drawing.prototype.clearNonce = function () {
* @return {String} The latest object Id. * @return {String} The latest object Id.
*/ */
svgedit.draw.Drawing.prototype.getId = function () { svgedit.draw.Drawing.prototype.getId = function () {
return this.nonce_ ? return this.nonce_
this.idPrefix + this.nonce_ + '_' + this.obj_num : ? this.idPrefix + this.nonce_ + '_' + this.obj_num
this.idPrefix + this.obj_num; : this.idPrefix + this.obj_num;
}; };
/** /**
@@ -250,7 +248,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) {
* Returns the number of layers in the current drawing. * Returns the number of layers in the current drawing.
* @returns {integer} 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; return this.all_layers.length;
}; };
@@ -262,7 +260,6 @@ svgedit.draw.Drawing.prototype.hasLayer = function (name) {
return this.layer_map[name] !== undefined; 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. * 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. * @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. * @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; return this.current_layer ? this.current_layer.getGroup() : null;
}; };
@@ -283,7 +280,7 @@ svgedit.draw.Drawing.prototype.getCurrentLayer = function() {
* Get a layer by name. * Get a layer by name.
* @returns {SVGGElement} The SVGGElement representing the named layer or null. * @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]; var layer = this.layer_map[name];
return layer ? layer.getGroup() : null; return layer ? layer.getGroup() : null;
}; };
@@ -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. * @returns {Object} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.
*/ */
svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) { svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
var layer_count = this.getNumLayers(); var layerCount = this.getNumLayers();
if (!this.current_layer || newpos < 0 || newpos >= layer_count) { if (!this.current_layer || newpos < 0 || newpos >= layerCount) {
return null; return null;
} }
var oldpos; var oldpos;
for (oldpos = 0; oldpos < layer_count; ++oldpos) { for (oldpos = 0; oldpos < layerCount; ++oldpos) {
if (this.all_layers[oldpos] == this.current_layer) {break;} if (this.all_layers[oldpos] == this.current_layer) { break; }
} }
// some unknown error condition (current_layer not in all_layers) // 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 (oldpos != newpos) {
// if our new position is below us, we need to insert before the node after newpos // if our new position is below us, we need to insert before the node after newpos
var refGroup = null; var refGroup = null;
var current_group = this.current_layer.getGroup(); var currentGroup = this.current_layer.getGroup();
var oldNextSibling = current_group.nextSibling; var oldNextSibling = currentGroup.nextSibling;
if (newpos > oldpos ) { if (newpos > oldpos) {
if (newpos < layer_count-1) { if (newpos < layerCount - 1) {
refGroup = this.all_layers[newpos+1].getGroup(); refGroup = this.all_layers[newpos + 1].getGroup();
} }
}
// if our new position is above us, we need to insert before the node at newpos // if our new position is above us, we need to insert before the node at newpos
else { } else {
refGroup = this.all_layers[newpos].getGroup(); refGroup = this.all_layers[newpos].getGroup();
} }
this.svgElem_.insertBefore(current_group, refGroup); this.svgElem_.insertBefore(currentGroup, refGroup);
this.identifyLayers(); this.identifyLayers();
this.setCurrentLayer(this.getLayerName(newpos)); this.setCurrentLayer(this.getLayerName(newpos));
return { return {
currentGroup: current_group, currentGroup: currentGroup,
oldNextSibling: oldNextSibling oldNextSibling: oldNextSibling
}; };
} }
@@ -362,25 +358,25 @@ svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
}; };
svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) { svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
var current_group = this.current_layer.getGroup(); var currentGroup = this.current_layer.getGroup();
var prevGroup = $(current_group).prev()[0]; var prevGroup = $(currentGroup).prev()[0];
if (!prevGroup) {return;} if (!prevGroup) { return; }
hrService.startBatchCommand('Merge Layer'); hrService.startBatchCommand('Merge Layer');
var layerNextSibling = current_group.nextSibling; var layerNextSibling = currentGroup.nextSibling;
hrService.removeElement(current_group, layerNextSibling, this.svgElem_); hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);
while (current_group.firstChild) { while (currentGroup.firstChild) {
var child = current_group.firstChild; var child = currentGroup.firstChild;
if (child.localName == 'title') { if (child.localName == 'title') {
hrService.removeElement(child, child.nextSibling, current_group); hrService.removeElement(child, child.nextSibling, currentGroup);
current_group.removeChild(child); currentGroup.removeChild(child);
continue; continue;
} }
var oldNextSibling = child.nextSibling; var oldNextSibling = child.nextSibling;
prevGroup.appendChild(child); prevGroup.appendChild(child);
hrService.moveElement(child, oldNextSibling, current_group); hrService.moveElement(child, oldNextSibling, currentGroup);
} }
// Remove current layer's group // 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); var index = this.all_layers.indexOf(this.current_layer);
if (index > 0) { if (index > 0) {
var name = this.current_layer.getName(); 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); this.all_layers.splice(index, 1);
delete this.layer_map[name]; delete this.layer_map[name];
} }
@@ -399,7 +395,7 @@ svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) { svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
// Set the current layer to the last layer. // 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'); hrService.startBatchCommand('Merge all Layers');
while (this.all_layers.length > 1) { 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. * @param {string} name - The name of the layer you want to switch to.
* @returns {boolean} true if the current layer was switched, otherwise false * @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]; var layer = this.layer_map[name];
if (layer) { if (layer) {
if (this.current_layer) { if (this.current_layer) {
@@ -428,13 +424,12 @@ svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) {
return false; return false;
}; };
/** /**
* Deletes the current layer from the drawing and then clears the selection. * Deletes the current layer from the drawing and then clears the selection.
* This function then calls the 'changed' handler. This is an undoable action. * This function then calls the 'changed' handler. This is an undoable action.
* @returns {SVGGElement} The SVGGElement of the layer removed or null. * @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) { if (this.current_layer && this.getNumLayers() > 1) {
var oldLayerGroup = this.current_layer.removeGroup(); var oldLayerGroup = this.current_layer.removeGroup();
this.identifyLayers(); this.identifyLayers();
@@ -448,8 +443,8 @@ svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() {
* @param group The group element to search in. * @param group The group element to search in.
* @returns {string} The layer name or empty string. * @returns {string} The layer name or empty string.
*/ */
function findLayerNameInGroup(group) { function findLayerNameInGroup (group) {
var name = $("title", group).text(); var name = $('title', group).text();
// Hack for Opera 10.60 // Hack for Opera 10.60
if (!name && svgedit.browser.isOpera() && group.querySelectorAll) { if (!name && svgedit.browser.isOpera() && group.querySelectorAll) {
@@ -463,18 +458,18 @@ function findLayerNameInGroup(group) {
* @param {Array.<string>} existingLayerNames - Existing layer names. * @param {Array.<string>} existingLayerNames - Existing layer names.
* @returns {string} - The new name. * @returns {string} - The new name.
*/ */
function getNewLayerName(existingLayerNames) { function getNewLayerName (existingLayerNames) {
var i = 1; var i = 1;
// TODO(codedread): What about internationalization of "Layer"? // TODO(codedread): What about internationalization of "Layer"?
while (existingLayerNames.indexOf(("Layer " + i)) >= 0) { i++; } while (existingLayerNames.indexOf(('Layer ' + i)) >= 0) { i++; }
return "Layer " + i; return 'Layer ' + i;
} }
/** /**
* Updates layer system and sets the current layer to the * Updates layer system and sets the current layer to the
* top-most layer (last <g> child of this drawing). * top-most layer (last <g> child of this drawing).
*/ */
svgedit.draw.Drawing.prototype.identifyLayers = function() { svgedit.draw.Drawing.prototype.identifyLayers = function () {
this.all_layers = []; this.all_layers = [];
this.layer_map = {}; this.layer_map = {};
var numchildren = this.svgElem_.childNodes.length; var numchildren = this.svgElem_.childNodes.length;
@@ -486,7 +481,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
var child = this.svgElem_.childNodes.item(i); var child = this.svgElem_.childNodes.item(i);
// for each g, find its layer name // for each g, find its layer name
if (child && child.nodeType == 1) { if (child && child.nodeType == 1) {
if (child.tagName == "g") { if (child.tagName === 'g') {
childgroups = true; childgroups = true;
var name = findLayerNameInGroup(child); var name = findLayerNameInGroup(child);
if (name) { if (name) {
@@ -525,7 +520,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
* @returns {SVGGElement} The SVGGElement of the new layer, which is * @returns {SVGGElement} The SVGGElement of the new layer, which is
* also the current layer of this drawing. * 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) { if (this.current_layer) {
this.current_layer.deactivate(); 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 * @returns {SVGGElement} The SVGGElement of the new layer, which is
* also the current layer of this drawing. * also the current layer of this drawing.
*/ */
svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) { svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) {
if (!this.current_layer) {return null;} if (!this.current_layer) { return null; }
this.current_layer.deactivate(); this.current_layer.deactivate();
// Check for duplicate name. // Check for duplicate name.
if (name === undefined || name === null || name === '' || this.layer_map[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 // Create new group and add to DOM just after current_layer
var currentGroup = this.current_layer.getGroup(); var currentGroup = this.current_layer.getGroup();
var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_); var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_);
var group = layer.getGroup(); var group = layer.getGroup();
// Clone children // Clone children
var children = currentGroup.childNodes; var children = currentGroup.childNodes;
var index; var index;
for (index = 0; index < children.length; index++) { for (index = 0; index < children.length; index++) {
var ch = children[index]; var ch = children[index];
if (ch.localName == 'title') {continue;} if (ch.localName == 'title') { continue; }
group.appendChild(this.copyElem(ch)); 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. * @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. * @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]; var layer = this.layer_map[layername];
return layer ? layer.isVisible() : false; 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 * @returns {?SVGGElement} The SVGGElement representing the layer if the
* layername was valid, otherwise null. * 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') { if (typeof bVisible !== 'boolean') {
return null; return null;
} }
var layer = this.layer_map[layername]; var layer = this.layer_map[layername];
if (!layer) {return null;} if (!layer) { return null; }
layer.setVisible(bVisible); layer.setVisible(bVisible);
return layer.getGroup(); return layer.getGroup();
}; };
/** /**
* Returns the opacity of the given layer. If the input name is not a layer, null is returned. * 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 * @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 * @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 * 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]; var layer = this.layer_map[layername];
if (!layer) {return null;} if (!layer) { return null; }
return layer.getOpacity(); 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 {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 * @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) { if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {
return; return;
} }
@@ -661,11 +655,9 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) {
* @param {Element} el - DOM element to clone * @param {Element} el - DOM element to clone
* @returns {Element} * @returns {Element}
*/ */
svgedit.draw.Drawing.prototype.copyElem = function(el) { svgedit.draw.Drawing.prototype.copyElem = function (el) {
var self = this; var self = this;
var getNextIdClosure = function() { return self.getNextId();} var getNextIdClosure = function () { return self.getNextId(); };
return svgedit.utilities.copyElem(el, getNextIdClosure) return svgedit.utilities.copyElem(el, getNextIdClosure);
} };
}()); }());

View File

@@ -1,79 +1,80 @@
/*globals $, EmbeddedSVGEdit*/ /* eslint-disable no-var */
/*jslint vars: true */ /* globals $, EmbeddedSVGEdit */
var initEmbed; 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 // Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
$(function () {'use strict'; $(function () {
'use strict';
var svgCanvas = null; var svgCanvas = null;
var frame; var frame;
initEmbed = function () { initEmbed = function () {
var doc, mainButton; var doc, mainButton;
svgCanvas = new EmbeddedSVGEdit(frame); svgCanvas = new EmbeddedSVGEdit(frame);
// Hide main button, as we will be controlling new, load, save, etc. from the host document // Hide main button, as we will be controlling new, load, save, etc. from the host document
doc = frame.contentDocument || frame.contentWindow.document; doc = frame.contentDocument || frame.contentWindow.document;
mainButton = doc.getElementById('main_button'); mainButton = doc.getElementById('main_button');
mainButton.style.display = 'none'; mainButton.style.display = 'none';
}; };
function handleSvgData(data, error) { function handleSvgData (data, error) {
if (error) { if (error) {
alert('error ' + error); alert('error ' + error);
} else { } else {
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data); alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
} }
} }
function loadSvg() { function loadSvg () {
var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>'; var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>';
svgCanvas.setSvgString(svgexample); svgCanvas.setSvgString(svgexample);
} }
function saveSvg() { function saveSvg () {
svgCanvas.getSvgString()(handleSvgData); svgCanvas.getSvgString()(handleSvgData);
} }
function exportPNG() { function exportPNG () {
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
var exportWindow = window.open( var exportWindow = window.open(
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'), 'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
'svg-edit-exportWindow' 'svg-edit-exportWindow'
); );
svgCanvas.rasterExport('PNG', null, exportWindow.name); svgCanvas.rasterExport('PNG', null, exportWindow.name);
} }
function exportPDF() { function exportPDF () {
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage; 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) { svgCanvas.bind('exportedPDF', function (win, data) {
alert(data.dataurlstring); alert(data.dataurlstring);
}); });
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring) svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
return; return;
*/ */
var exportWindow = window.open( var exportWindow = window.open(
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'), 'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
'svg-edit-exportWindow' 'svg-edit-exportWindow'
); );
svgCanvas.exportPDF(exportWindow.name); svgCanvas.exportPDF(exportWindow.name);
} }
// Add event handlers // Add event handlers
$('#load').click(loadSvg); $('#load').click(loadSvg);
$('#save').click(saveSvg); $('#save').click(saveSvg);
$('#exportPNG').click(exportPNG); $('#exportPNG').click(exportPNG);
$('#exportPDF').click(exportPDF); $('#exportPDF').click(exportPDF);
$('body').append( $('body').append(
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' + $('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>' '" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
) )
); );
frame = document.getElementById('svgedit'); frame = document.getElementById('svgedit');
}); });

View File

@@ -1,4 +1,5 @@
/* /* eslint-disable no-var */
/*
Embedded SVG-edit API Embedded SVG-edit API
General usage: General usage:
@@ -9,11 +10,11 @@ var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit);
svgCanvas.setSvgString('string') svgCanvas.setSvgString('string')
- Or if a callback is needed: - Or if a callback is needed:
svgCanvas.setSvgString('string')(function(data, error){ svgCanvas.setSvgString('string')(function(data, error){
if (error){ if (error){
// There was an error // There was an error
} else{ } else{
// Handle data // Handle data
} }
}) })
Everything is done with the same API as the real svg-edit, 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)}) 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; var cbid = 0;
function getCallbackSetter (d) { function getCallbackSetter (d) {
return function () { return function () {
var t = this, // New callback var t = this, // New callback
args = [].slice.call(arguments), args = [].slice.call(arguments),
cbid = t.send(d, args, function(){}); // The callback (currently it's nothing, but will be set later) cbid = t.send(d, args, function () {}); // The callback (currently it's nothing, but will be set later)
return function(newcallback){ return function (newcallback) {
t.callbacks[cbid] = newcallback; // Set callback t.callbacks[cbid] = newcallback; // Set callback
};
}; };
};
} }
/* /*
@@ -57,32 +59,32 @@ function getCallbackSetter (d) {
* of same domain control * of same domain control
*/ */
function addCallback (t, data) { function addCallback (t, data) {
var result = data.result || data.error, var result = data.result || data.error,
cbid = data.id; cbid = data.id;
if (t.callbacks[cbid]) { if (t.callbacks[cbid]) {
if (data.result) { if (data.result) {
t.callbacks[cbid](result); t.callbacks[cbid](result);
} else { } else {
t.callbacks[cbid](result, 'error'); t.callbacks[cbid](result, 'error');
}
} }
}
} }
function messageListener (e) { function messageListener (e) {
// We accept and post strings as opposed to objects for the sake of IE9 support; this // We accept and post strings as opposed to objects for the sake of IE9 support; this
// will most likely be changed in the future // will most likely be changed in the future
if (typeof e.data !== 'string') { if (typeof e.data !== 'string') {
return; return;
} }
var allowedOrigins = this.allowedOrigins, var allowedOrigins = this.allowedOrigins,
data = e.data && JSON.parse(e.data); data = e.data && JSON.parse(e.data);
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' || if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
e.source !== this.frame.contentWindow || e.source !== this.frame.contentWindow ||
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1) (allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
) { ) {
return; return;
} }
addCallback(this, data); addCallback(this, data);
} }
function getMessageListener (t) { function getMessageListener (t) {
@@ -98,82 +100,79 @@ function getMessageListener (t) {
* If supplied, it should probably be the same as svgEditor's allowedOrigins * If supplied, it should probably be the same as svgEditor's allowedOrigins
*/ */
function EmbeddedSVGEdit (frame, allowedOrigins) { function EmbeddedSVGEdit (frame, allowedOrigins) {
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
return new EmbeddedSVGEdit(frame); return new EmbeddedSVGEdit(frame);
} }
this.allowedOrigins = allowedOrigins || []; this.allowedOrigins = allowedOrigins || [];
// Initialize communication // Initialize communication
this.frame = frame; this.frame = frame;
this.callbacks = {}; this.callbacks = {};
// List of functions extracted with this: // List of functions extracted with this:
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html // 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 // 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', // var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', // 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
// 'moveSelectedToLayer', 'clear']; // '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 // 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 svgCanvas = frame.contentWindow.svgCanvas;
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} }; // var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
// alert("['" + l.join("', '") + "']"); // alert("['" + l.join("', '") + "']");
// Run in svgedit itself // Run in svgedit itself
var i, var i,
functions = [ 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' '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. // TODO: rewrite the following, it's pretty scary.
for (i = 0; i < functions.length; i++) { for (i = 0; i < functions.length; i++) {
this[functions[i]] = getCallbackSetter(functions[i]); this[functions[i]] = getCallbackSetter(functions[i]);
} }
// Older IE may need a polyfill for addEventListener, but so it would for SVG // Older IE may need a polyfill for addEventListener, but so it would for SVG
window.addEventListener('message', getMessageListener(this), false); window.addEventListener('message', getMessageListener(this), false);
} }
EmbeddedSVGEdit.prototype.send = function (name, args, callback){ EmbeddedSVGEdit.prototype.send = function (name, args, callback) {
var t = this; var t = this;
cbid++; cbid++;
this.callbacks[cbid] = callback; this.callbacks[cbid] = callback;
setTimeout((function (cbid) { setTimeout((function (cbid) {
return function () { // Delay for the callback to be set in case its synchronous return function () { // Delay for the callback to be set in case its synchronous
/* /*
* Todo: Handle non-JSON arguments and return values (undefined, * Todo: Handle non-JSON arguments and return values (undefined,
* nonfinite numbers, functions, and built-in objects like Date, * nonfinite numbers, functions, and built-in objects like Date,
* RegExp), etc.? Allow promises instead of callbacks? Review * RegExp), etc.? Allow promises instead of callbacks? Review
* SVG-Edit functions for whether JSON-able parameters can be * SVG-Edit functions for whether JSON-able parameters can be
* made compatile with all API functionality * made compatile with all API functionality
*/ */
// We accept and post strings for the sake of IE9 support // We accept and post strings for the sake of IE9 support
if (window.location.origin === t.frame.contentWindow.location.origin) { if (window.location.origin === t.frame.contentWindow.location.origin) {
// Although we do not really need this API if we are working same // 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 // domain, it could allow us to write in a way that would work
// cross-domain as well, assuming we stick to the argument limitations // cross-domain as well, assuming we stick to the argument limitations
// of the current JSON-based communication API (e.g., not passing // of the current JSON-based communication API (e.g., not passing
// callbacks). We might be able to address these shortcomings; see // callbacks). We might be able to address these shortcomings; see
// the todo elsewhere in this file. // the todo elsewhere in this file.
var message = {id: cbid}, var message = {id: cbid},
svgCanvas = t.frame.contentWindow.svgCanvas; svgCanvas = t.frame.contentWindow.svgCanvas;
try { try {
message.result = svgCanvas[name].apply(svgCanvas, args); message.result = svgCanvas[name].apply(svgCanvas, args);
} } catch (err) {
catch (err) { message.error = err.message;
message.error = err.message; }
} addCallback(t, 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}), '*');
else { // Requires the ext-xdomain-messaging.js extension }
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*'); };
} }(cbid)), 0);
};
}(cbid)), 0);
return cbid; return cbid;
}; };
window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API 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 window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-arrows.js * ext-arrows.js
* *
@@ -9,65 +9,64 @@
* *
*/ */
svgEditor.addExtension('Arrows', function(S) { svgEditor.addExtension('Arrows', function (S) {
var svgcontent = S.svgcontent, var // svgcontent = S.svgcontent,
addElem = S.addSvgElementFromJson, addElem = S.addSvgElementFromJson,
nonce = S.nonce, nonce = S.nonce,
randomize_ids = S.randomize_ids, randomizeIds = S.randomize_ids,
selElems, pathdata, selElems, pathdata,
lang_list = { langList = {
'en':[ 'en': [
{'id': 'arrow_none', 'textContent': 'No arrow' } {'id': 'arrow_none', 'textContent': 'No arrow'}
], ],
'fr':[ 'fr': [
{'id': 'arrow_none', 'textContent': 'Sans flèche' } {'id': 'arrow_none', 'textContent': 'Sans flèche'}
] ]
}, },
arrowprefix, arrowprefix,
prefix = 'se_arrow_'; prefix = 'se_arrow_';
function setArrowNonce(window, n) { function setArrowNonce (window, n) {
randomize_ids = true; randomizeIds = true;
arrowprefix = prefix + n + '_'; arrowprefix = prefix + n + '_';
pathdata.fw.id = arrowprefix + 'fw'; pathdata.fw.id = arrowprefix + 'fw';
pathdata.bk.id = arrowprefix + 'bk'; pathdata.bk.id = arrowprefix + 'bk';
} }
function unsetArrowNonce(window) { function unsetArrowNonce (window) {
randomize_ids = false; randomizeIds = false;
arrowprefix = prefix; arrowprefix = prefix;
pathdata.fw.id = arrowprefix + 'fw'; pathdata.fw.id = arrowprefix + 'fw';
pathdata.bk.id = arrowprefix + 'bk'; pathdata.bk.id = arrowprefix + 'bk';
} }
svgCanvas.bind('setnonce', setArrowNonce); svgCanvas.bind('setnonce', setArrowNonce);
svgCanvas.bind('unsetnonce', unsetArrowNonce); svgCanvas.bind('unsetnonce', unsetArrowNonce);
if (randomize_ids) { if (randomizeIds) {
arrowprefix = prefix + nonce + '_'; arrowprefix = prefix + nonce + '_';
} else { } else {
arrowprefix = prefix; arrowprefix = prefix;
} }
pathdata = { 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'} 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); var str = elem.getAttribute(attr);
if(!str) {return null;} if (!str) { return null; }
var m = str.match(/\(\#(.*)\)/); var m = str.match(/\(#(.*)\)/);
if(!m || m.length !== 2) { if (!m || m.length !== 2) {
return null; return null;
} }
return S.getElem(m[1]); return S.getElem(m[1]);
} }
function showPanel(on) { function showPanel (on) {
$('#arrow_panel').toggle(on); $('#arrow_panel').toggle(on);
if(on) { if (on) {
var el = selElems[0]; var el = selElems[0];
var end = el.getAttribute('marker-end'); var end = el.getAttribute('marker-end');
var start = el.getAttribute('marker-start'); var start = el.getAttribute('marker-start');
@@ -95,21 +94,21 @@ svgEditor.addExtension('Arrows', function(S) {
} }
} }
function resetMarker() { function resetMarker () {
var el = selElems[0]; var el = selElems[0];
el.removeAttribute('marker-start'); el.removeAttribute('marker-start');
el.removeAttribute('marker-mid'); el.removeAttribute('marker-mid');
el.removeAttribute('marker-end'); 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 // TODO: Make marker (or use?) per arrow type, since refX can be different
id = id || arrowprefix + dir; id = id || arrowprefix + dir;
var marker = S.getElem(id); var marker = S.getElem(id);
var data = pathdata[dir]; var data = pathdata[dir];
if (type == 'mid') { if (type === 'mid') {
data.refx = 5; data.refx = 5;
} }
@@ -143,25 +142,25 @@ svgEditor.addExtension('Arrows', function(S) {
return marker; return marker;
} }
function setArrow() { function setArrow () {
var type = this.value; var type = this.value;
resetMarker(); resetMarker();
if (type == 'none') { if (type === 'none') {
return; return;
} }
// Set marker on element // Set marker on element
var dir = 'fw'; var dir = 'fw';
if (type == 'mid_bk') { if (type === 'mid_bk') {
type = 'mid'; type = 'mid';
dir = 'bk'; dir = 'bk';
} else if (type == 'both') { } else if (type === 'both') {
addMarker('bk', type); addMarker('bk', type);
svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')'); svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')');
type = 'end'; type = 'end';
dir = 'fw'; dir = 'fw';
} else if (type == 'start') { } else if (type === 'start') {
dir = 'bk'; dir = 'bk';
} }
@@ -170,57 +169,57 @@ svgEditor.addExtension('Arrows', function(S) {
S.call('changed', selElems); S.call('changed', selElems);
} }
function colorChanged(elem) { function colorChanged (elem) {
var color = elem.getAttribute('stroke'); var color = elem.getAttribute('stroke');
var mtypes = ['start', 'mid', 'end']; var mtypes = ['start', 'mid', 'end'];
var defs = S.findDefs(); var defs = S.findDefs();
$.each(mtypes, function(i, type) { $.each(mtypes, function (i, type) {
var marker = getLinked(elem, 'marker-'+type); var marker = getLinked(elem, 'marker-' + type);
if(!marker) {return;} if (!marker) { return; }
var cur_color = $(marker).children().attr('fill'); var curColor = $(marker).children().attr('fill');
var cur_d = $(marker).children().attr('d'); var curD = $(marker).children().attr('d');
var new_marker = null; var newMarker = null;
if(cur_color === color) {return;} if (curColor === color) { return; }
var all_markers = $(defs).find('marker'); var allMarkers = $(defs).find('marker');
// Different color, check if already made // Different color, check if already made
all_markers.each(function() { allMarkers.each(function () {
var attrs = $(this).children().attr(['fill', 'd']); 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 // 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 // Create a new marker with this color
var last_id = marker.id; var lastId = marker.id;
var dir = last_id.indexOf('_fw') !== -1?'fw':'bk'; 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 // Check if last marker can be removed
var remove = true; var remove = true;
$(S.svgcontent).find('line, polyline, path, polygon').each(function() { $(S.svgcontent).find('line, polyline, path, polygon').each(function () {
var elem = this; var elem = this;
$.each(mtypes, function(j, mtype) { $.each(mtypes, function (j, mtype) {
if($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') { if ($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') {
remove = false; remove = false;
return remove; return remove;
} }
}); });
if(!remove) {return false;} if (!remove) { return false; }
}); });
// Not found, so can safely remove // Not found, so can safely remove
if(remove) { if (remove) {
$(marker).remove(); $(marker).remove();
} }
}); });
@@ -246,26 +245,26 @@ svgEditor.addExtension('Arrows', function(S) {
change: setArrow change: setArrow
} }
}], }],
callback: function() { callback: function () {
$('#arrow_panel').hide(); $('#arrow_panel').hide();
// Set ID so it can be translated in locale file // Set ID so it can be translated in locale file
$('#arrow_list option')[0].id = 'connector_no_arrow'; $('#arrow_list option')[0].id = 'connector_no_arrow';
}, },
addLangData: function(lang) { addLangData: function (lang) {
return { return {
data: lang_list[lang] data: langList[lang]
}; };
}, },
selectedChanged: function(opts) { selectedChanged: function (opts) {
// Use this to update the current selected elements // Use this to update the current selected elements
selElems = opts.elems; selElems = opts.elems;
var i = selElems.length; var i = selElems.length;
var marker_elems = ['line', 'path', 'polyline', 'polygon']; var markerElems = ['line', 'path', 'polyline', 'polygon'];
while(i--) { while (i--) {
var elem = selElems[i]; var elem = selElems[i];
if(elem && $.inArray(elem.tagName, marker_elems) !== -1) { if (elem && $.inArray(elem.tagName, markerElems) !== -1) {
if(opts.selectedElement && !opts.multiselected) { if (opts.selectedElement && !opts.multiselected) {
showPanel(true); showPanel(true);
} else { } else {
showPanel(false); showPanel(false);
@@ -275,16 +274,16 @@ svgEditor.addExtension('Arrows', function(S) {
} }
} }
}, },
elementChanged: function(opts) { elementChanged: function (opts) {
var elem = opts.elems[0]; var elem = opts.elems[0];
if(elem && ( if (elem && (
elem.getAttribute('marker-start') || elem.getAttribute('marker-start') ||
elem.getAttribute('marker-mid') || elem.getAttribute('marker-mid') ||
elem.getAttribute('marker-end') elem.getAttribute('marker-end')
)) { )) {
// var start = elem.getAttribute('marker-start'); // var start = elem.getAttribute('marker-start');
// var mid = elem.getAttribute('marker-mid'); // var mid = elem.getAttribute('marker-mid');
// var end = elem.getAttribute('marker-end'); // var end = elem.getAttribute('marker-end');
// Has marker, so see if it should match color // Has marker, so see if it should match color
colorChanged(elem); colorChanged(elem);
} }

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals svgEditor, $ */
/* /*
* ext-closepath.js * ext-closepath.js
* *
@@ -11,30 +11,31 @@
// This extension adds a simple button to the contextual panel for paths // This extension adds a simple button to the contextual panel for paths
// The button toggles whether the path is open or closed // The button toggles whether the path is open or closed
svgEditor.addExtension('ClosePath', function() {'use strict'; svgEditor.addExtension('ClosePath', function () {
'use strict';
var selElems, var selElems,
updateButton = function(path) { updateButton = function (path) {
var seglist = path.pathSegList, 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', showbutton = closed ? '#tool_openpath' : '#tool_closepath',
hidebutton = closed ? '#tool_closepath' : '#tool_openpath'; hidebutton = closed ? '#tool_closepath' : '#tool_openpath';
$(hidebutton).hide(); $(hidebutton).hide();
$(showbutton).show(); $(showbutton).show();
}, },
showPanel = function(on) { showPanel = function (on) {
$('#closepath_panel').toggle(on); $('#closepath_panel').toggle(on);
if (on) { if (on) {
var path = selElems[0]; var path = selElems[0];
if (path) {updateButton(path);} if (path) { updateButton(path); }
} }
}, },
toggleClosed = function() { toggleClosed = function () {
var path = selElems[0]; var path = selElems[0];
if (path) { if (path) {
var seglist = path.pathSegList, var seglist = path.pathSegList,
last = seglist.numberOfItems - 1; last = seglist.numberOfItems - 1;
// is closed // is closed
if (seglist.getItem(last).pathSegType == 1) { if (seglist.getItem(last).pathSegType === 1) {
seglist.removeItem(last); seglist.removeItem(last);
} else { } else {
seglist.appendItem(path.createSVGPathSegClosePath()); seglist.appendItem(path.createSVGPathSegClosePath());
@@ -52,7 +53,7 @@ svgEditor.addExtension('ClosePath', function() {'use strict';
panel: 'closepath_panel', panel: 'closepath_panel',
title: 'Open path', title: 'Open path',
events: { events: {
click: function() { click: function () {
toggleClosed(); toggleClosed();
} }
} }
@@ -63,20 +64,20 @@ svgEditor.addExtension('ClosePath', function() {'use strict';
panel: 'closepath_panel', panel: 'closepath_panel',
title: 'Close path', title: 'Close path',
events: { events: {
click: function() { click: function () {
toggleClosed(); toggleClosed();
} }
} }
}], }],
callback: function() { callback: function () {
$('#closepath_panel').hide(); $('#closepath_panel').hide();
}, },
selectedChanged: function(opts) { selectedChanged: function (opts) {
selElems = opts.elems; selElems = opts.elems;
var i = selElems.length; var i = selElems.length;
while (i--) { while (i--) {
var elem = selElems[i]; var elem = selElems[i];
if (elem && elem.tagName == 'path') { if (elem && elem.tagName === 'path') {
if (opts.selectedElement && !opts.multiselected) { if (opts.selectedElement && !opts.multiselected) {
showPanel(true); showPanel(true);
} else { } else {

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, continue: true, eqeq: true, todo: true*/ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-connector.js * ext-connector.js
* *
@@ -9,7 +9,7 @@
* *
*/ */
svgEditor.addExtension("Connector", function(S) { svgEditor.addExtension('Connector', function (S) {
var svgcontent = S.svgcontent, var svgcontent = S.svgcontent,
svgroot = S.svgroot, svgroot = S.svgroot,
getNextId = S.getNextId, getNextId = S.getNextId,
@@ -18,153 +18,151 @@ svgEditor.addExtension("Connector", function(S) {
selManager = S.selectorManager, selManager = S.selectorManager,
curConfig = svgEditor.curConfig, curConfig = svgEditor.curConfig,
started = false, started = false,
start_x, startX,
start_y, startY,
cur_line, curLine,
start_elem, startElem,
end_elem, endElem,
connections = [], connections = [],
conn_sel = ".se_connector", connSel = '.se_connector',
se_ns, seNs,
// connect_str = "-SE_CONNECT-", // connect_str = '-SE_CONNECT-',
selElems = [], selElems = [],
elData = $.data; elData = $.data;
var lang_list = { var langList = {
"en":[ 'en': [
{"id": "mode_connect", "title": "Connect two objects" } {'id': 'mode_connect', 'title': 'Connect two objects'}
], ],
"fr":[ 'fr': [
{"id": "mode_connect", "title": "Connecter deux objets"} {'id': 'mode_connect', 'title': 'Connecter deux objets'}
] ]
}; };
function getBBintersect(x, y, bb, offset) { function getBBintersect (x, y, bb, offset) {
if(offset) { if (offset) {
offset -= 0; offset -= 0;
bb = $.extend({}, bb); bb = $.extend({}, bb);
bb.width += offset; bb.width += offset;
bb.height += offset; bb.height += offset;
bb.x -= offset/2; bb.x -= offset / 2;
bb.y -= offset/2; bb.y -= offset / 2;
} }
var mid_x = bb.x + bb.width/2; var midX = bb.x + bb.width / 2;
var mid_y = bb.y + bb.height/2; var midY = bb.y + bb.height / 2;
var len_x = x - mid_x; var lenX = x - midX;
var len_y = y - mid_y; var lenY = y - midY;
var slope = Math.abs(len_y/len_x); var slope = Math.abs(lenY / lenX);
var ratio; var ratio;
if(slope < bb.height/bb.width) { if (slope < bb.height / bb.width) {
ratio = (bb.width/2) / Math.abs(len_x); ratio = (bb.width / 2) / Math.abs(lenX);
} else { } else {
ratio = (bb.height/2) / Math.abs(len_y); ratio = (bb.height / 2) / Math.abs(lenY);
} }
return { return {
x: mid_x + len_x * ratio, x: midX + lenX * ratio,
y: mid_y + len_y * ratio y: midY + lenY * ratio
}; };
} }
function getOffset(side, line) { function getOffset (side, line) {
var give_offset = !!line.getAttribute('marker-' + side); var giveOffset = !!line.getAttribute('marker-' + side);
// var give_offset = $(line).data(side+'_off'); // var giveOffset = $(line).data(side+'_off');
// TODO: Make this number (5) be based on marker width/height // TODO: Make this number (5) be based on marker width/height
var size = line.getAttribute('stroke-width') * 5; var size = line.getAttribute('stroke-width') * 5;
return give_offset ? size : 0; return giveOffset ? size : 0;
} }
function showPanel(on) { function showPanel (on) {
var conn_rules = $('#connector_rules'); var connRules = $('#connector_rules');
if(!conn_rules.length) { if (!connRules.length) {
conn_rules = $('<style id="connector_rules"></style>').appendTo('head'); connRules = $('<style id="connector_rules"></style>').appendTo('head');
} }
conn_rules.text(!on?"":"#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }"); connRules.text(!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }');
$('#connector_panel').toggle(on); $('#connector_panel').toggle(on);
} }
function setPoint(elem, pos, x, y, setMid) { function setPoint (elem, pos, x, y, setMid) {
var i, pts = elem.points; var i, pts = elem.points;
var pt = svgroot.createSVGPoint(); var pt = svgroot.createSVGPoint();
pt.x = x; pt.x = x;
pt.y = y; 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 // TODO: Test for this on init, then use alt only if needed
try { try {
pts.replaceItem(pt, pos); 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 // Should only occur in FF which formats points attr as "n,n n,n", so just split
var pt_arr = elem.getAttribute("points").split(" "); var ptArr = elem.getAttribute('points').split(' ');
for (i = 0; i < pt_arr.length; i++) { for (i = 0; i < ptArr.length; i++) {
if (i === pos) { 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 // Add center point
var pt_start = pts.getItem(0); var ptStart = pts.getItem(0);
var pt_end = pts.getItem(pts.numberOfItems-1); var ptEnd = pts.getItem(pts.numberOfItems - 1);
setPoint(elem, 1, (pt_end.x + pt_start.x)/2, (pt_end.y + pt_start.y)/2); 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 // Update line with element
var i = connections.length; var i = connections.length;
while(i--) { while (i--) {
var conn = connections[i]; var conn = connections[i];
var line = conn.connector; var line = conn.connector;
var elem = conn.elem; // var elem = conn.elem;
var pre = conn.is_start?'start':'end'; var pre = conn.is_start ? 'start' : 'end';
// var sw = line.getAttribute('stroke-width') * 5; // var sw = line.getAttribute('stroke-width') * 5;
// Update bbox for this element // Update bbox for this element
var bb = elData(line, pre+'_bb'); var bb = elData(line, pre + '_bb');
bb.x = conn.start_x + diff_x; bb.x = conn.start_x + diffX;
bb.y = conn.start_y + diff_y; bb.y = conn.start_y + diffY;
elData(line, pre+'_bb', bb); elData(line, pre + '_bb', bb);
var alt_pre = conn.is_start?'end':'start'; var altPre = conn.is_start ? 'end' : 'start';
// Get center pt of connected element // Get center pt of connected element
var bb2 = elData(line, alt_pre+'_bb'); var bb2 = elData(line, altPre + '_bb');
var src_x = bb2.x + bb2.width/2; var srcX = bb2.x + bb2.width / 2;
var src_y = bb2.y + bb2.height/2; var srcY = bb2.y + bb2.height / 2;
// Set point of element being moved // Set point of element being moved
var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0 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); setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
// Set point of connected element // 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); setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
} }
} }
function findConnectors(elems) { function findConnectors (elems) {
var i; var i;
if (!elems) {elems = selElems;} if (!elems) { elems = selElems; }
var connectors = $(svgcontent).find(conn_sel); var connectors = $(svgcontent).find(connSel);
connections = []; connections = [];
// Loop through connectors to see if one is connected to the element // Loop through connectors to see if one is connected to the element
connectors.each(function() { connectors.each(function () {
var add_this; var addThis;
function add () { function add () {
if ($.inArray(this, elems) !== -1) { if ($.inArray(this, elems) !== -1) {
// Pretend this element is selected // Pretend this element is selected
add_this = true; addThis = true;
} }
} }
@@ -173,31 +171,31 @@ svgEditor.addExtension("Connector", function(S) {
['start', 'end'].forEach(function (pos, i) { ['start', 'end'].forEach(function (pos, i) {
var key = 'c_' + pos; var key = 'c_' + pos;
var part = elData(this, key); var part = elData(this, key);
if(part == null) { if (part == null) {
part = document.getElementById( part = document.getElementById(
this.attributes['se:connector'].value.split(' ')[i] this.attributes['se:connector'].value.split(' ')[i]
); );
elData(this, 'c_'+pos, part.id); elData(this, 'c_' + pos, part.id);
elData(this, pos+'_bb', svgCanvas.getStrokedBBox([part])); elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part]));
} else part = document.getElementById(part); } else part = document.getElementById(part);
parts.push(part); parts.push(part);
}.bind(this)); }.bind(this));
for (i = 0; i < 2; i++) { 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 // The connected element might be part of a selected group
$(c_elem).parents().each(add); $(cElem).parents().each(add);
if(!c_elem || !c_elem.parentNode) { if (!cElem || !cElem.parentNode) {
$(this).remove(); $(this).remove();
continue; continue;
} }
if($.inArray(c_elem, elems) !== -1 || add_this) { if ($.inArray(cElem, elems) !== -1 || addThis) {
var bb = svgCanvas.getStrokedBBox([c_elem]); var bb = svgCanvas.getStrokedBBox([cElem]);
connections.push({ connections.push({
elem: c_elem, elem: cElem,
connector: this, connector: this,
is_start: (i === 0), is_start: (i === 0),
start_x: bb.x, start_x: bb.x,
@@ -208,7 +206,7 @@ svgEditor.addExtension("Connector", function(S) {
}); });
} }
function updateConnectors(elems) { function updateConnectors (elems) {
// Updates connector lines based on selected elements // Updates connector lines based on selected elements
// Is not used on mousemove, as it runs getStrokedBBox every time, // Is not used on mousemove, as it runs getStrokedBBox every time,
// which isn't necessary there. // which isn't necessary there.
@@ -222,227 +220,222 @@ svgEditor.addExtension("Connector", function(S) {
var line = conn.connector; var line = conn.connector;
var elem = conn.elem; var elem = conn.elem;
var sw = line.getAttribute('stroke-width') * 5; // var sw = line.getAttribute('stroke-width') * 5;
var pre = conn.is_start?'start':'end'; var pre = conn.is_start ? 'start' : 'end';
// Update bbox for this element // Update bbox for this element
var bb = svgCanvas.getStrokedBBox([elem]); var bb = svgCanvas.getStrokedBBox([elem]);
bb.x = conn.start_x; bb.x = conn.start_x;
bb.y = conn.start_y; bb.y = conn.start_y;
elData(line, pre+'_bb', bb); elData(line, pre + '_bb', bb);
var add_offset = elData(line, pre+'_off'); /* var addOffset = */ elData(line, pre + '_off');
var alt_pre = conn.is_start?'end':'start'; var altPre = conn.is_start ? 'end' : 'start';
// Get center pt of connected element // Get center pt of connected element
var bb2 = elData(line, alt_pre+'_bb'); var bb2 = elData(line, altPre + '_bb');
var src_x = bb2.x + bb2.width/2; var srcX = bb2.x + bb2.width / 2;
var src_y = bb2.y + bb2.height/2; var srcY = bb2.y + bb2.height / 2;
// Set point of element being moved // 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); setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
// Set point of connected element // 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); setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
// Update points attribute manually for webkit // Update points attribute manually for webkit
if (navigator.userAgent.indexOf('AppleWebKit') !== -1) { if (navigator.userAgent.indexOf('AppleWebKit') !== -1) {
var pts = line.points; var pts = line.points;
var len = pts.numberOfItems; var len = pts.numberOfItems;
var pt_arr = []; var ptArr = [];
for (j = 0; j < len; j++) { for (j = 0; j < len; j++) {
pt = pts.getItem(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 // Do once
(function() { (function () {
var gse = svgCanvas.groupSelectedElements; var gse = svgCanvas.groupSelectedElements;
svgCanvas.groupSelectedElements = function() { svgCanvas.groupSelectedElements = function () {
svgCanvas.removeFromSelection($(conn_sel).toArray()); svgCanvas.removeFromSelection($(connSel).toArray());
return gse.apply(this, arguments); return gse.apply(this, arguments);
}; };
var mse = svgCanvas.moveSelectedElements; var mse = svgCanvas.moveSelectedElements;
svgCanvas.moveSelectedElements = function() { svgCanvas.moveSelectedElements = function () {
var cmd = mse.apply(this, arguments); var cmd = mse.apply(this, arguments);
updateConnectors(); updateConnectors();
return cmd; return cmd;
}; };
se_ns = svgCanvas.getEditorNS(); seNs = svgCanvas.getEditorNS();
}()); }());
// Do on reset // Do on reset
function init() { function init () {
// Make sure all connectors have data set // Make sure all connectors have data set
$(svgcontent).find('*').each(function() { $(svgcontent).find('*').each(function () {
var conn = this.getAttributeNS(se_ns, "connector"); var conn = this.getAttributeNS(seNs, 'connector');
if(conn) { if (conn) {
this.setAttribute('class', conn_sel.substr(1)); this.setAttribute('class', connSel.substr(1));
var conn_data = conn.split(' '); var connData = conn.split(' ');
var sbb = svgCanvas.getStrokedBBox([getElem(conn_data[0])]); var sbb = svgCanvas.getStrokedBBox([getElem(connData[0])]);
var ebb = svgCanvas.getStrokedBBox([getElem(conn_data[1])]); var ebb = svgCanvas.getStrokedBBox([getElem(connData[1])]);
$(this).data('c_start',conn_data[0]) $(this).data('c_start', connData[0])
.data('c_end',conn_data[1]) .data('c_end', connData[1])
.data('start_bb', sbb) .data('start_bb', sbb)
.data('end_bb', ebb); .data('end_bb', ebb);
svgCanvas.getEditorNS(true); svgCanvas.getEditorNS(true);
} }
}); });
// updateConnectors(); // updateConnectors();
} }
// $(svgroot).parent().mousemove(function(e) { // $(svgroot).parent().mousemove(function (e) {
// // if(started // // if (started
// // || svgCanvas.getMode() != "connector" // // || svgCanvas.getMode() !== 'connector'
// // || e.target.parentNode.parentNode != svgcontent) return; // // || e.target.parentNode.parentNode !== svgcontent) return;
// //
// console.log('y') // console.log('y')
// // if(e.target.parentNode.parentNode === svgcontent) { // // if (e.target.parentNode.parentNode === svgcontent) {
// // // //
// // } // // }
// }); // });
return { return {
name: "Connector", name: 'Connector',
svgicons: svgEditor.curConfig.imgPath + "conn.svg", svgicons: svgEditor.curConfig.imgPath + 'conn.svg',
buttons: [{ buttons: [{
id: "mode_connect", id: 'mode_connect',
type: "mode", type: 'mode',
icon: svgEditor.curConfig.imgPath + "cut.png", icon: svgEditor.curConfig.imgPath + 'cut.png',
title: "Connect two objects", title: 'Connect two objects',
includeWith: { includeWith: {
button: '#tool_line', button: '#tool_line',
isDefault: false, isDefault: false,
position: 1 position: 1
}, },
events: { events: {
'click': function() { 'click': function () {
svgCanvas.setMode("connector"); svgCanvas.setMode('connector');
} }
} }
}], }],
addLangData: function(lang) { addLangData: function (lang) {
return { return {
data: lang_list[lang] data: langList[lang]
}; };
}, },
mouseDown: function(opts) { mouseDown: function (opts) {
var e = opts.event; var e = opts.event;
start_x = opts.start_x; startX = opts.start_x;
start_y = opts.start_y; startY = opts.start_y;
var mode = svgCanvas.getMode(); var mode = svgCanvas.getMode();
if (mode == "connector") { if (mode === 'connector') {
if (started) { return; }
if (started) {return;} var mouseTarget = e.target;
var mouse_target = e.target; var parents = $(mouseTarget).parents();
var parents = $(mouse_target).parents(); if ($.inArray(svgcontent, parents) !== -1) {
if($.inArray(svgcontent, parents) !== -1) {
// Connectable element // Connectable element
// If child of foreignObject, use parent // If child of foreignObject, use parent
var fo = $(mouse_target).closest("foreignObject"); var fo = $(mouseTarget).closest('foreignObject');
start_elem = fo.length ? fo[0] : mouse_target; startElem = fo.length ? fo[0] : mouseTarget;
// Get center of source element // Get center of source element
var bb = svgCanvas.getStrokedBBox([start_elem]); var bb = svgCanvas.getStrokedBBox([startElem]);
var x = bb.x + bb.width/2; var x = bb.x + bb.width / 2;
var y = bb.y + bb.height/2; var y = bb.y + bb.height / 2;
started = true; started = true;
cur_line = addElem({ curLine = addElem({
"element": "polyline", 'element': 'polyline',
"attr": { 'attr': {
"id": getNextId(), 'id': getNextId(),
"points": (x+','+y+' '+x+','+y+' '+start_x+','+start_y), 'points': (x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY),
"stroke": '#' + curConfig.initStroke.color, 'stroke': '#' + curConfig.initStroke.color,
"stroke-width": (!start_elem.stroke_width || start_elem.stroke_width == 0) ? curConfig.initStroke.width : start_elem.stroke_width, 'stroke-width': (!startElem.stroke_width || startElem.stroke_width === 0) ? curConfig.initStroke.width : startElem.stroke_width,
"fill": "none", 'fill': 'none',
"opacity": curConfig.initStroke.opacity, 'opacity': curConfig.initStroke.opacity,
"style": "pointer-events:none" 'style': 'pointer-events:none'
} }
}); });
elData(cur_line, 'start_bb', bb); elData(curLine, 'start_bb', bb);
} }
return { return {
started: true started: true
}; };
} }
if (mode == "select") { if (mode === 'select') {
findConnectors(); findConnectors();
} }
}, },
mouseMove: function(opts) { mouseMove: function (opts) {
var zoom = svgCanvas.getZoom(); var zoom = svgCanvas.getZoom();
var e = opts.event; // var e = opts.event;
var x = opts.mouse_x/zoom; var x = opts.mouse_x / zoom;
var y = opts.mouse_y/zoom; var y = opts.mouse_y / zoom;
var diff_x = x - start_x, var diffX = x - startX,
diff_y = y - start_y; diffY = y - startY;
var mode = svgCanvas.getMode(); var mode = svgCanvas.getMode();
if (mode == "connector" && started) { if (mode === 'connector' && started) {
// var sw = curLine.getAttribute('stroke-width') * 3;
var sw = cur_line.getAttribute('stroke-width') * 3;
// Set start point (adjusts based on bb) // Set start point (adjusts based on bb)
var pt = getBBintersect(x, y, elData(cur_line, 'start_bb'), getOffset('start', cur_line)); var pt = getBBintersect(x, y, elData(curLine, 'start_bb'), getOffset('start', curLine));
start_x = pt.x; startX = pt.x;
start_y = pt.y; startY = pt.y;
setPoint(cur_line, 0, pt.x, pt.y, true); setPoint(curLine, 0, pt.x, pt.y, true);
// Set end point // Set end point
setPoint(cur_line, 'end', x, y, true); setPoint(curLine, 'end', x, y, true);
} else if (mode == "select") { } else if (mode === 'select') {
var slen = selElems.length; var slen = selElems.length;
while(slen--) { while (slen--) {
var elem = selElems[slen]; var elem = selElems[slen];
// Look for selected connector elements // Look for selected connector elements
if(elem && elData(elem, 'c_start')) { if (elem && elData(elem, 'c_start')) {
// Remove the "translate" transform given to move // Remove the "translate" transform given to move
svgCanvas.removeFromSelection([elem]); svgCanvas.removeFromSelection([elem]);
svgCanvas.getTransformList(elem).clear(); svgCanvas.getTransformList(elem).clear();
} }
} }
if(connections.length) { if (connections.length) {
updateLine(diff_x, diff_y); updateLine(diffX, diffY);
} }
} }
}, },
mouseUp: function(opts) { mouseUp: function (opts) {
var zoom = svgCanvas.getZoom(); // var zoom = svgCanvas.getZoom();
var e = opts.event, var e = opts.event,
x = opts.mouse_x/zoom, // x = opts.mouse_x / zoom,
y = opts.mouse_y/zoom, // y = opts.mouse_y / zoom,
mouse_target = e.target; mouseTarget = e.target;
if(svgCanvas.getMode() == "connector") { if (svgCanvas.getMode() === 'connector') {
var fo = $(mouse_target).closest("foreignObject"); var fo = $(mouseTarget).closest('foreignObject');
if (fo.length) {mouse_target = fo[0];} if (fo.length) { mouseTarget = fo[0]; }
var parents = $(mouse_target).parents(); var parents = $(mouseTarget).parents();
if (mouse_target == start_elem) { if (mouseTarget === startElem) {
// Start line through click // Start line through click
started = true; started = true;
return { return {
@@ -453,7 +446,7 @@ svgEditor.addExtension("Connector", function(S) {
} }
if ($.inArray(svgcontent, parents) === -1) { if ($.inArray(svgcontent, parents) === -1) {
// Not a valid target element, so remove line // Not a valid target element, so remove line
$(cur_line).remove(); $(curLine).remove();
started = false; started = false;
return { return {
keep: false, keep: false,
@@ -462,18 +455,18 @@ svgEditor.addExtension("Connector", function(S) {
}; };
} }
// Valid end element // Valid end element
end_elem = mouse_target; endElem = mouseTarget;
var start_id = start_elem.id, end_id = end_elem.id; var startId = startElem.id, endId = endElem.id;
var conn_str = start_id + " " + end_id; var connStr = startId + ' ' + endId;
var alt_str = end_id + " " + start_id; var altStr = endId + ' ' + startId;
// Don't create connector if one already exists // Don't create connector if one already exists
var dupe = $(svgcontent).find(conn_sel).filter(function() { var dupe = $(svgcontent).find(connSel).filter(function () {
var conn = this.getAttributeNS(se_ns, "connector"); var conn = this.getAttributeNS(seNs, 'connector');
if (conn == conn_str || conn == alt_str) {return true;} if (conn === connStr || conn === altStr) { return true; }
}); });
if(dupe.length) { if (dupe.length) {
$(cur_line).remove(); $(curLine).remove();
return { return {
keep: false, keep: false,
element: null, element: null,
@@ -481,34 +474,34 @@ svgEditor.addExtension("Connector", function(S) {
}; };
} }
var bb = svgCanvas.getStrokedBBox([end_elem]); var bb = svgCanvas.getStrokedBBox([endElem]);
var pt = getBBintersect(start_x, start_y, bb, getOffset('start', cur_line)); var pt = getBBintersect(startX, startY, bb, getOffset('start', curLine));
setPoint(cur_line, 'end', pt.x, pt.y, true); setPoint(curLine, 'end', pt.x, pt.y, true);
$(cur_line) $(curLine)
.data("c_start", start_id) .data('c_start', startId)
.data("c_end", end_id) .data('c_end', endId)
.data("end_bb", bb); .data('end_bb', bb);
se_ns = svgCanvas.getEditorNS(true); seNs = svgCanvas.getEditorNS(true);
cur_line.setAttributeNS(se_ns, "se:connector", conn_str); curLine.setAttributeNS(seNs, 'se:connector', connStr);
cur_line.setAttribute('class', conn_sel.substr(1)); curLine.setAttribute('class', connSel.substr(1));
cur_line.setAttribute('opacity', 1); curLine.setAttribute('opacity', 1);
svgCanvas.addToSelection([cur_line]); svgCanvas.addToSelection([curLine]);
svgCanvas.moveToBottomSelectedElement(); svgCanvas.moveToBottomSelectedElement();
selManager.requestSelector(cur_line).showGrips(false); selManager.requestSelector(curLine).showGrips(false);
started = false; started = false;
return { return {
keep: true, keep: true,
element: cur_line, element: curLine,
started: started started: started
}; };
} }
}, },
selectedChanged: function(opts) { selectedChanged: function (opts) {
// TODO: Find better way to skip operations if no connectors are in use // TODO: Find better way to skip operations if no connectors are in use
if(!$(svgcontent).find(conn_sel).length) {return;} if (!$(svgcontent).find(connSel).length) { return; }
if(svgCanvas.getMode() == 'connector') { if (svgCanvas.getMode() === 'connector') {
svgCanvas.setMode('select'); svgCanvas.setMode('select');
} }
@@ -517,11 +510,11 @@ svgEditor.addExtension("Connector", function(S) {
var i = selElems.length; var i = selElems.length;
while(i--) { while (i--) {
var elem = selElems[i]; var elem = selElems[i];
if(elem && elData(elem, 'c_start')) { if (elem && elData(elem, 'c_start')) {
selManager.requestSelector(elem).showGrips(false); 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 // TODO: Set up context tools and hide most regular line tools
showPanel(true); showPanel(true);
} else { } else {
@@ -533,7 +526,7 @@ svgEditor.addExtension("Connector", function(S) {
} }
updateConnectors(); updateConnectors();
}, },
elementChanged: function(opts) { elementChanged: function (opts) {
var elem = opts.elems[0]; var elem = opts.elems[0];
if (elem && elem.tagName === 'svg' && elem.id === 'svgcontent') { if (elem && elem.tagName === 'svg' && elem.id === 'svgcontent') {
// Update svgcontent (can change on import) // Update svgcontent (can change on import)
@@ -544,17 +537,17 @@ svgEditor.addExtension("Connector", function(S) {
// Has marker, so change offset // Has marker, so change offset
var start; var start;
if (elem && ( if (elem && (
elem.getAttribute("marker-start") || elem.getAttribute('marker-start') ||
elem.getAttribute("marker-mid") || elem.getAttribute('marker-mid') ||
elem.getAttribute("marker-end") elem.getAttribute('marker-end')
)) { )) {
start = elem.getAttribute("marker-start"); start = elem.getAttribute('marker-start');
var mid = elem.getAttribute("marker-mid"); var mid = elem.getAttribute('marker-mid');
var end = elem.getAttribute("marker-end"); var end = elem.getAttribute('marker-end');
cur_line = elem; curLine = elem;
$(elem) $(elem)
.data("start_off", !!start) .data('start_off', !!start)
.data("end_off", !!end); .data('end_off', !!end);
if (elem.tagName === 'line' && mid) { if (elem.tagName === 'line' && mid) {
// Convert to polyline to accept mid-arrow // Convert to polyline to accept mid-arrow
@@ -565,16 +558,16 @@ svgEditor.addExtension("Connector", function(S) {
var y2 = Number(elem.getAttribute('y2')); var y2 = Number(elem.getAttribute('y2'));
var id = elem.id; var id = elem.id;
var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' '); var midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
var pline = addElem({ var pline = addElem({
"element": "polyline", 'element': 'polyline',
"attr": { 'attr': {
"points": (x1+','+y1+ mid_pt +x2+','+y2), 'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2),
"stroke": elem.getAttribute('stroke'), 'stroke': elem.getAttribute('stroke'),
"stroke-width": elem.getAttribute('stroke-width'), 'stroke-width': elem.getAttribute('stroke-width'),
"marker-mid": mid, 'marker-mid': mid,
"fill": "none", 'fill': 'none',
"opacity": elem.getAttribute('opacity') || 1 'opacity': elem.getAttribute('opacity') || 1
} }
}); });
$(elem).after(pline).remove(); $(elem).after(pline).remove();
@@ -585,36 +578,37 @@ svgEditor.addExtension("Connector", function(S) {
} }
} }
// Update line if it's a connector // 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')); start = getElem(elData(elem, 'c_start'));
updateConnectors([start]); updateConnectors([start]);
} else { } else {
updateConnectors(); updateConnectors();
} }
}, },
IDsUpdated: function(input) { IDsUpdated: function (input) {
var remove = []; var remove = [];
input.elems.forEach(function(elem){ input.elems.forEach(function (elem) {
if('se:connector' in elem.attr) { if ('se:connector' in elem.attr) {
elem.attr['se:connector'] = elem.attr['se:connector'].split(' ') 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 // 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 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); remove.push(elem.attr.id);
}
} }
}); });
return {remove: remove}; return {remove: remove};
}, },
toolButtonStateUpdate: function(opts) { toolButtonStateUpdate: function (opts) {
if (opts.nostroke) { if (opts.nostroke) {
if ($('#mode_connect').hasClass('tool_button_current')) { if ($('#mode_connect').hasClass('tool_button_current')) {
svgEditor.clickSelect(); svgEditor.clickSelect();
} }
} }
$('#mode_connect') $('#mode_connect')
.toggleClass('disabled',opts.nostroke); .toggleClass('disabled', opts.nostroke);
} }
}; };
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals svgEditor, svgedit, $ */
/* /*
* ext-eyedropper.js * ext-eyedropper.js
* *
@@ -15,26 +15,27 @@
// 3) svg_editor.js // 3) svg_editor.js
// 4) svgcanvas.js // 4) svgcanvas.js
svgEditor.addExtension("eyedropper", function(S) {'use strict'; svgEditor.addExtension('eyedropper', function (S) {
'use strict';
var // NS = svgedit.NS, var // NS = svgedit.NS,
// svgcontent = S.svgcontent, // svgcontent = S.svgcontent,
// svgdoc = S.svgroot.parentNode.ownerDocument, // svgdoc = S.svgroot.parentNode.ownerDocument,
svgCanvas = svgEditor.canvas, svgCanvas = svgEditor.canvas,
ChangeElementCommand = svgedit.history.ChangeElementCommand, ChangeElementCommand = svgedit.history.ChangeElementCommand,
addToHistory = function(cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); }, addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); },
currentStyle = { currentStyle = {
fillPaint: "red", fillOpacity: 1.0, fillPaint: 'red', fillOpacity: 1.0,
strokePaint: "black", strokeOpacity: 1.0, strokePaint: 'black', strokeOpacity: 1.0,
strokeWidth: 5, strokeDashArray: null, strokeWidth: 5, strokeDashArray: null,
opacity: 1.0, opacity: 1.0,
strokeLinecap: 'butt', strokeLinecap: 'butt',
strokeLinejoin: 'miter' strokeLinejoin: 'miter'
}; };
function getStyle(opts) { function getStyle (opts) {
// if we are in eyedropper mode, we don't want to disable the eye-dropper tool // if we are in eyedropper mode, we don't want to disable the eye-dropper tool
var mode = svgCanvas.getMode(); var mode = svgCanvas.getMode();
if (mode == "eyedropper") {return;} if (mode === 'eyedropper') { return; }
var elem = null; var elem = null;
var tool = $('#tool_eyedropper'); var tool = $('#tool_eyedropper');
@@ -45,34 +46,32 @@ svgEditor.addExtension("eyedropper", function(S) {'use strict';
elem = opts.elems[0]; elem = opts.elems[0];
tool.removeClass('disabled'); tool.removeClass('disabled');
// grab the current style // grab the current style
currentStyle.fillPaint = elem.getAttribute("fill") || "black"; currentStyle.fillPaint = elem.getAttribute('fill') || 'black';
currentStyle.fillOpacity = elem.getAttribute("fill-opacity") || 1.0; currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0;
currentStyle.strokePaint = elem.getAttribute("stroke"); currentStyle.strokePaint = elem.getAttribute('stroke');
currentStyle.strokeOpacity = elem.getAttribute("stroke-opacity") || 1.0; currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0;
currentStyle.strokeWidth = elem.getAttribute("stroke-width"); currentStyle.strokeWidth = elem.getAttribute('stroke-width');
currentStyle.strokeDashArray = elem.getAttribute("stroke-dasharray"); currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray');
currentStyle.strokeLinecap = elem.getAttribute("stroke-linecap"); currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap');
currentStyle.strokeLinejoin = elem.getAttribute("stroke-linejoin"); currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin');
currentStyle.opacity = elem.getAttribute("opacity") || 1.0; currentStyle.opacity = elem.getAttribute('opacity') || 1.0;
}
// disable eye-dropper tool // disable eye-dropper tool
else { } else {
tool.addClass('disabled'); tool.addClass('disabled');
} }
} }
return { return {
name: "eyedropper", name: 'eyedropper',
svgicons: svgEditor.curConfig.extPath + "eyedropper-icon.xml", svgicons: svgEditor.curConfig.extPath + 'eyedropper-icon.xml',
buttons: [{ buttons: [{
id: "tool_eyedropper", id: 'tool_eyedropper',
type: "mode", type: 'mode',
title: "Eye Dropper Tool", title: 'Eye Dropper Tool',
key: "I", key: 'I',
events: { events: {
"click": function() { click: function () {
svgCanvas.setMode("eyedropper"); svgCanvas.setMode('eyedropper');
} }
} }
}], }],
@@ -81,28 +80,28 @@ svgEditor.addExtension("eyedropper", function(S) {'use strict';
selectedChanged: getStyle, selectedChanged: getStyle,
elementChanged: getStyle, elementChanged: getStyle,
mouseDown: function(opts) { mouseDown: function (opts) {
var mode = svgCanvas.getMode(); var mode = svgCanvas.getMode();
if (mode == "eyedropper") { if (mode === 'eyedropper') {
var e = opts.event; var e = opts.event;
var target = e.target; var target = e.target;
if ($.inArray(target.nodeName, ['svg', 'g', 'use']) === -1) { if ($.inArray(target.nodeName, ['svg', 'g', 'use']) === -1) {
var changes = {}; var changes = {};
var change = function(elem, attrname, newvalue) { var change = function (elem, attrname, newvalue) {
changes[attrname] = elem.getAttribute(attrname); changes[attrname] = elem.getAttribute(attrname);
elem.setAttribute(attrname, newvalue); elem.setAttribute(attrname, newvalue);
}; };
if (currentStyle.fillPaint) {change(target, "fill", currentStyle.fillPaint);} if (currentStyle.fillPaint) { change(target, 'fill', currentStyle.fillPaint); }
if (currentStyle.fillOpacity) {change(target, "fill-opacity", currentStyle.fillOpacity);} if (currentStyle.fillOpacity) { change(target, 'fill-opacity', currentStyle.fillOpacity); }
if (currentStyle.strokePaint) {change(target, "stroke", currentStyle.strokePaint);} if (currentStyle.strokePaint) { change(target, 'stroke', currentStyle.strokePaint); }
if (currentStyle.strokeOpacity) {change(target, "stroke-opacity", currentStyle.strokeOpacity);} if (currentStyle.strokeOpacity) { change(target, 'stroke-opacity', currentStyle.strokeOpacity); }
if (currentStyle.strokeWidth) {change(target, "stroke-width", currentStyle.strokeWidth);} if (currentStyle.strokeWidth) { change(target, 'stroke-width', currentStyle.strokeWidth); }
if (currentStyle.strokeDashArray) {change(target, "stroke-dasharray", currentStyle.strokeDashArray);} if (currentStyle.strokeDashArray) { change(target, 'stroke-dasharray', currentStyle.strokeDashArray); }
if (currentStyle.opacity) {change(target, "opacity", currentStyle.opacity);} if (currentStyle.opacity) { change(target, 'opacity', currentStyle.opacity); }
if (currentStyle.strokeLinecap) {change(target, "stroke-linecap", currentStyle.strokeLinecap);} if (currentStyle.strokeLinecap) { change(target, 'stroke-linecap', currentStyle.strokeLinecap); }
if (currentStyle.strokeLinejoin) {change(target, "stroke-linejoin", currentStyle.strokeLinejoin);} if (currentStyle.strokeLinejoin) { change(target, 'stroke-linejoin', currentStyle.strokeLinejoin); }
addToHistory(new ChangeElementCommand(target, changes)); addToHistory(new ChangeElementCommand(target, changes));
} }

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, todo: true*/ /* globals svgEditor, svgedit, svgCanvas, $ */
/* /*
* ext-foreignobject.js * ext-foreignobject.js
* *
@@ -10,11 +10,11 @@
* *
*/ */
svgEditor.addExtension("foreignObject", function(S) { svgEditor.addExtension('foreignObject', function (S) {
var NS = svgedit.NS, var NS = svgedit.NS,
Utils = svgedit.utilities, Utils = svgedit.utilities,
svgcontent = S.svgcontent, // svgcontent = S.svgcontent,
addElem = S.addSvgElementFromJson, // addElem = S.addSvgElementFromJson,
selElems, selElems,
editingforeign = false, editingforeign = false,
svgdoc = S.svgroot.parentNode.ownerDocument, svgdoc = S.svgroot.parentNode.ownerDocument,
@@ -27,16 +27,16 @@ svgEditor.addExtension("foreignObject", function(S) {
$('#svg_source_textarea').css('height', height); $('#svg_source_textarea').css('height', height);
}; };
function showPanel(on) { function showPanel (on) {
var fc_rules = $('#fc_rules'); var fcRules = $('#fc_rules');
if(!fc_rules.length) { if (!fcRules.length) {
fc_rules = $('<style id="fc_rules"></style>').appendTo('head'); fcRules = $('<style id="fc_rules"></style>').appendTo('head');
} }
fc_rules.text(!on?"":" #tool_topath { display: none !important; }"); fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#foreignObject_panel').toggle(on); $('#foreignObject_panel').toggle(on);
} }
function toggleSourceButtons(on) { function toggleSourceButtons (on) {
$('#tool_source_save, #tool_source_cancel').toggle(!on); $('#tool_source_save, #tool_source_cancel').toggle(!on);
$('#foreign_save, #foreign_cancel').toggle(on); $('#foreign_save, #foreign_cancel').toggle(on);
} }
@@ -50,7 +50,7 @@ svgEditor.addExtension("foreignObject", function(S) {
// //
// Returns: // Returns:
// This function returns false if the set was unsuccessful, true otherwise. // This function returns false if the set was unsuccessful, true otherwise.
function setForeignString(xmlString) { function setForeignString (xmlString) {
var elt = selElems[0]; var elt = selElems[0];
try { try {
// convert string into XML document // 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 // run it through our sanitizer to remove anything we do not support
S.sanitizeSvg(newDoc.documentElement); S.sanitizeSvg(newDoc.documentElement);
elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt); elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
S.call("changed", [elt]); S.call('changed', [elt]);
svgCanvas.clearSelection(); svgCanvas.clearSelection();
} catch(e) { } catch (e) {
console.log(e); console.log(e);
return false; return false;
} }
@@ -68,9 +68,9 @@ svgEditor.addExtension("foreignObject", function(S) {
return true; return true;
} }
function showForeignEditor() { function showForeignEditor () {
var elt = selElems[0]; var elt = selElems[0];
if (!elt || editingforeign) {return;} if (!elt || editingforeign) { return; }
editingforeign = true; editingforeign = true;
toggleSourceButtons(true); toggleSourceButtons(true);
elt.removeAttribute('fill'); elt.removeAttribute('fill');
@@ -82,78 +82,78 @@ svgEditor.addExtension("foreignObject", function(S) {
$('#svg_source_textarea').focus(); $('#svg_source_textarea').focus();
} }
function setAttr(attr, val) { function setAttr (attr, val) {
svgCanvas.changeSelectedAttribute(attr, val); svgCanvas.changeSelectedAttribute(attr, val);
S.call("changed", selElems); S.call('changed', selElems);
} }
return { return {
name: "foreignObject", name: 'foreignObject',
svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml", svgicons: svgEditor.curConfig.extPath + 'foreignobject-icons.xml',
buttons: [{ buttons: [{
id: "tool_foreign", id: 'tool_foreign',
type: "mode", type: 'mode',
title: "Foreign Object Tool", title: 'Foreign Object Tool',
events: { events: {
'click': function() { 'click': function () {
svgCanvas.setMode('foreign'); svgCanvas.setMode('foreign');
} }
} }
},{ }, {
id: "edit_foreign", id: 'edit_foreign',
type: "context", type: 'context',
panel: "foreignObject_panel", panel: 'foreignObject_panel',
title: "Edit ForeignObject Content", title: 'Edit ForeignObject Content',
events: { events: {
'click': function() { 'click': function () {
showForeignEditor(); showForeignEditor();
} }
} }
}], }],
context_tools: [{ context_tools: [{
type: "input", type: 'input',
panel: "foreignObject_panel", panel: 'foreignObject_panel',
title: "Change foreignObject's width", title: "Change foreignObject's width",
id: "foreign_width", id: 'foreign_width',
label: "w", label: 'w',
size: 3, size: 3,
events: { events: {
change: function() { change: function () {
setAttr('width', this.value); setAttr('width', this.value);
} }
} }
},{ }, {
type: "input", type: 'input',
panel: "foreignObject_panel", panel: 'foreignObject_panel',
title: "Change foreignObject's height", title: "Change foreignObject's height",
id: "foreign_height", id: 'foreign_height',
label: "h", label: 'h',
events: { events: {
change: function() { change: function () {
setAttr('height', this.value); setAttr('height', this.value);
} }
} }
}, { }, {
type: "input", type: 'input',
panel: "foreignObject_panel", panel: 'foreignObject_panel',
title: "Change foreignObject's font size", title: "Change foreignObject's font size",
id: "foreign_font_size", id: 'foreign_font_size',
label: "font-size", label: 'font-size',
size: 2, size: 2,
defval: 16, defval: 16,
events: { events: {
change: function() { change: function () {
setAttr('font-size', this.value); setAttr('font-size', this.value);
} }
} }
} }
], ],
callback: function() { callback: function () {
$('#foreignObject_panel').hide(); $('#foreignObject_panel').hide();
var endChanges = function() { var endChanges = function () {
$('#svg_source_editor').hide(); $('#svg_source_editor').hide();
editingforeign = false; editingforeign = false;
$('#svg_source_textarea').blur(); $('#svg_source_textarea').blur();
@@ -161,17 +161,16 @@ svgEditor.addExtension("foreignObject", function(S) {
}; };
// TODO: Needs to be done after orig icon loads // TODO: Needs to be done after orig icon loads
setTimeout(function() { setTimeout(function () {
// Create source save/cancel buttons // Create source save/cancel buttons
var save = $('#tool_source_save').clone() /* var save = */ $('#tool_source_save').clone()
.hide().attr('id', 'foreign_save').unbind() .hide().attr('id', 'foreign_save').unbind()
.appendTo("#tool_source_back").click(function() { .appendTo('#tool_source_back').click(function () {
if (!editingforeign) { return; }
if (!editingforeign) {return;}
if (!setForeignString($('#svg_source_textarea').val())) { if (!setForeignString($('#svg_source_textarea').val())) {
$.confirm("Errors found. Revert to original?", function(ok) { $.confirm('Errors found. Revert to original?', function (ok) {
if(!ok) {return false;} if (!ok) { return false; }
endChanges(); endChanges();
}); });
} else { } else {
@@ -180,29 +179,28 @@ svgEditor.addExtension("foreignObject", function(S) {
// setSelectMode(); // setSelectMode();
}); });
var cancel = $('#tool_source_cancel').clone() /* var cancel = */ $('#tool_source_cancel').clone()
.hide().attr('id', 'foreign_cancel').unbind() .hide().attr('id', 'foreign_cancel').unbind()
.appendTo("#tool_source_back").click(function() { .appendTo('#tool_source_back').click(function () {
endChanges(); endChanges();
}); });
}, 3000); }, 3000);
}, },
mouseDown: function(opts) { mouseDown: function (opts) {
var e = opts.event; // var e = opts.event;
if(svgCanvas.getMode() == "foreign") {
if (svgCanvas.getMode() === 'foreign') {
started = true; started = true;
newFO = S.addSvgElementFromJson({ newFO = S.addSvgElementFromJson({
"element": "foreignObject", 'element': 'foreignObject',
"attr": { 'attr': {
"x": opts.start_x, 'x': opts.start_x,
"y": opts.start_y, 'y': opts.start_y,
"id": S.getNextId(), 'id': S.getNextId(),
"font-size": 16, //cur_text.font_size, 'font-size': 16, // cur_text.font_size,
"width": "48", 'width': '48',
"height": "20", 'height': '20',
"style": "pointer-events:inherit" 'style': 'pointer-events:inherit'
} }
}); });
var m = svgdoc.createElementNS(NS.MATH, 'math'); var m = svgdoc.createElementNS(NS.MATH, 'math');
@@ -210,11 +208,11 @@ svgEditor.addExtension("foreignObject", function(S) {
m.setAttribute('display', 'inline'); m.setAttribute('display', 'inline');
var mi = svgdoc.createElementNS(NS.MATH, 'mi'); var mi = svgdoc.createElementNS(NS.MATH, 'mi');
mi.setAttribute('mathvariant', 'normal'); mi.setAttribute('mathvariant', 'normal');
mi.textContent = "\u03A6"; mi.textContent = '\u03A6';
var mo = svgdoc.createElementNS(NS.MATH, 'mo'); var mo = svgdoc.createElementNS(NS.MATH, 'mo');
mo.textContent = "\u222A"; mo.textContent = '\u222A';
var mi2 = svgdoc.createElementNS(NS.MATH, 'mi'); var mi2 = svgdoc.createElementNS(NS.MATH, 'mi');
mi2.textContent = "\u2133"; mi2.textContent = '\u2133';
m.appendChild(mi); m.appendChild(mi);
m.appendChild(mo); m.appendChild(mo);
m.appendChild(mi2); m.appendChild(mi2);
@@ -224,34 +222,32 @@ svgEditor.addExtension("foreignObject", function(S) {
}; };
} }
}, },
mouseUp: function(opts) { mouseUp: function (opts) {
var e = opts.event; // var e = opts.event;
if(svgCanvas.getMode() == "foreign" && started) { if (svgCanvas.getMode() === 'foreign' && started) {
var attrs = $(newFO).attr(["width", "height"]); var attrs = $(newFO).attr(['width', 'height']);
var keep = (attrs.width != 0 || attrs.height != 0); var keep = (attrs.width !== '0' || attrs.height !== '0');
svgCanvas.addToSelection([newFO], true); svgCanvas.addToSelection([newFO], true);
return { return {
keep: keep, keep: keep,
element: newFO element: newFO
}; };
} }
}, },
selectedChanged: function(opts) { selectedChanged: function (opts) {
// Use this to update the current selected elements // Use this to update the current selected elements
selElems = opts.elems; selElems = opts.elems;
var i = selElems.length; var i = selElems.length;
while(i--) { while (i--) {
var elem = selElems[i]; var elem = selElems[i];
if(elem && elem.tagName === 'foreignObject') { if (elem && elem.tagName === 'foreignObject') {
if(opts.selectedElement && !opts.multiselected) { if (opts.selectedElement && !opts.multiselected) {
$('#foreign_font_size').val(elem.getAttribute("font-size")); $('#foreign_font_size').val(elem.getAttribute('font-size'));
$('#foreign_width').val(elem.getAttribute("width")); $('#foreign_width').val(elem.getAttribute('width'));
$('#foreign_height').val(elem.getAttribute("height")); $('#foreign_height').val(elem.getAttribute('height'));
showPanel(true); showPanel(true);
} else { } else {
showPanel(false); showPanel(false);
@@ -261,8 +257,8 @@ svgEditor.addExtension("foreignObject", function(S) {
} }
} }
}, },
elementChanged: function(opts) { elementChanged: function (opts) {
var elem = opts.elems[0]; // var elem = opts.elems[0];
} }
}; };
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true*/ /* globals svgEditor, svgedit, svgCanvas, $ */
/* /*
* ext-grid.js * ext-grid.js
* *
@@ -14,7 +14,8 @@
// 1) units.js // 1) units.js
// 2) everything else // 2) everything else
svgEditor.addExtension('view_grid', function() { 'use strict'; svgEditor.addExtension('view_grid', function () {
'use strict';
var NS = svgedit.NS, var NS = svgedit.NS,
svgdoc = document.getElementById('svgcanvas').ownerDocument, svgdoc = document.getElementById('svgcanvas').ownerDocument,
@@ -44,8 +45,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
assignAttributes(gridPattern, { assignAttributes(gridPattern, {
'id': 'gridpattern', 'id': 'gridpattern',
'patternUnits': 'userSpaceOnUse', 'patternUnits': 'userSpaceOnUse',
'x': 0, //-(value.strokeWidth / 2), // position for strokewidth 'x': 0, // -(value.strokeWidth / 2), // position for strokewidth
'y': 0, //-(value.strokeWidth / 2), // position for strokewidth 'y': 0, // -(value.strokeWidth / 2), // position for strokewidth
'width': 100, 'width': 100,
'height': 100 'height': 100
}); });
@@ -74,56 +75,56 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
}); });
$('#canvasGrid').append(gridBox); $('#canvasGrid').append(gridBox);
function updateGrid(zoom) { function updateGrid (zoom) {
var i; var i;
// TODO: Try this with <line> elements, then compare performance difference // TODO: Try this with <line> elements, then compare performance difference
var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px
var u_multi = unit * zoom; var uMulti = unit * zoom;
// Calculate the main number interval // Calculate the main number interval
var raw_m = 100 / u_multi; var rawM = 100 / uMulti;
var multi = 1; var multi = 1;
for (i = 0; i < intervals.length; i++) { for (i = 0; i < intervals.length; i++) {
var num = intervals[i]; var num = intervals[i];
multi = num; multi = num;
if (raw_m <= num) { if (rawM <= num) {
break; break;
} }
} }
var big_int = multi * u_multi; var bigInt = multi * uMulti;
// Set the canvas size to the width of the container // Set the canvas size to the width of the container
hcanvas.width = big_int; hcanvas.width = bigInt;
hcanvas.height = big_int; hcanvas.height = bigInt;
var ctx = hcanvas.getContext('2d'); var ctx = hcanvas.getContext('2d');
var cur_d = 0.5; var curD = 0.5;
var part = big_int / 10; var part = bigInt / 10;
ctx.globalAlpha = 0.2; ctx.globalAlpha = 0.2;
ctx.strokeStyle = svgEditor.curConfig.gridColor; ctx.strokeStyle = svgEditor.curConfig.gridColor;
for (i = 1; i < 10; i++) { for (i = 1; i < 10; i++) {
var sub_d = Math.round(part * i) + 0.5; var subD = Math.round(part * i) + 0.5;
// var line_num = (i % 2)?12:10; // var lineNum = (i % 2)?12:10;
var line_num = 0; var lineNum = 0;
ctx.moveTo(sub_d, big_int); ctx.moveTo(subD, bigInt);
ctx.lineTo(sub_d, line_num); ctx.lineTo(subD, lineNum);
ctx.moveTo(big_int, sub_d); ctx.moveTo(bigInt, subD);
ctx.lineTo(line_num ,sub_d); ctx.lineTo(lineNum, subD);
} }
ctx.stroke(); ctx.stroke();
ctx.beginPath(); ctx.beginPath();
ctx.globalAlpha = 0.5; ctx.globalAlpha = 0.5;
ctx.moveTo(cur_d, big_int); ctx.moveTo(curD, bigInt);
ctx.lineTo(cur_d, 0); ctx.lineTo(curD, 0);
ctx.moveTo(big_int, cur_d); ctx.moveTo(bigInt, curD);
ctx.lineTo(0, cur_d); ctx.lineTo(0, curD);
ctx.stroke(); ctx.stroke();
var datauri = hcanvas.toDataURL('image/png'); var datauri = hcanvas.toDataURL('image/png');
gridimg.setAttribute('width', big_int); gridimg.setAttribute('width', bigInt);
gridimg.setAttribute('height', big_int); gridimg.setAttribute('height', bigInt);
gridimg.parentNode.setAttribute('width', big_int); gridimg.parentNode.setAttribute('width', bigInt);
gridimg.parentNode.setAttribute('height', big_int); gridimg.parentNode.setAttribute('height', bigInt);
svgCanvas.setHref(gridimg, datauri); svgCanvas.setHref(gridimg, datauri);
} }
@@ -138,8 +139,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
name: 'view_grid', name: 'view_grid',
svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml', svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml',
zoomChanged: function(zoom) { zoomChanged: function (zoom) {
if (showGrid) {updateGrid(zoom);} if (showGrid) { updateGrid(zoom); }
}, },
callback: function () { callback: function () {
if (showGrid) { if (showGrid) {
@@ -152,7 +153,7 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
panel: 'editor_panel', panel: 'editor_panel',
title: 'Show/Hide Grid', title: 'Show/Hide Grid',
events: { events: {
click: function() { click: function () {
svgEditor.curConfig.showGrid = showGrid = !showGrid; svgEditor.curConfig.showGrid = showGrid = !showGrid;
gridUpdate(); gridUpdate();
} }

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-helloworld.js * ext-helloworld.js
* *
@@ -15,66 +15,65 @@
user the point on the canvas that was clicked on. user the point on the canvas that was clicked on.
*/ */
svgEditor.addExtension("Hello World", function() {'use strict'; svgEditor.addExtension('Hello World', function () {
'use strict';
return { return {
name: "Hello World", name: 'Hello World',
// For more notes on how to make an icon file, see the source of // For more notes on how to make an icon file, see the source of
// the helloworld-icon.xml // the helloworld-icon.xml
svgicons: svgEditor.curConfig.extPath + "helloworld-icon.xml", svgicons: svgEditor.curConfig.extPath + 'helloworld-icon.xml',
// Multiple buttons can be added in this array // Multiple buttons can be added in this array
buttons: [{ buttons: [{
// Must match the icon ID in helloworld-icon.xml // Must match the icon ID in helloworld-icon.xml
id: "hello_world", id: 'hello_world',
// This indicates that the button will be added to the "mode" // This indicates that the button will be added to the "mode"
// button panel on the left side // button panel on the left side
type: "mode", type: 'mode',
// Tooltip text // Tooltip text
title: "Say 'Hello World'", title: "Say 'Hello World'",
// Events // Events
events: { events: {
'click': function() { 'click': function () {
// The action taken when the button is clicked on. // The action taken when the button is clicked on.
// For "mode" buttons, any other button will // For "mode" buttons, any other button will
// automatically be de-pressed. // automatically be de-pressed.
svgCanvas.setMode("hello_world"); 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);
} }
} }
}; }],
}); // 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);
}
}
};
});

View File

@@ -1,5 +1,5 @@
/*globals $, svgEditor, svgedit, svgCanvas, DOMParser*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, es5: true, todo: true */ /* globals $, svgEditor, svgedit, svgCanvas, DOMParser */
/* /*
* ext-imagelib.js * ext-imagelib.js
* *
@@ -9,7 +9,8 @@
* *
*/ */
svgEditor.addExtension("imagelib", function() {'use strict'; svgEditor.addExtension('imagelib', function () {
'use strict';
var uiStrings = svgEditor.uiStrings; var uiStrings = svgEditor.uiStrings;
@@ -23,7 +24,8 @@ svgEditor.addExtension("imagelib", function() {'use strict';
} }
}); });
var img_libs = [{ var imgLibs = [
{
name: 'Demo library (local)', name: 'Demo library (local)',
url: svgEditor.curConfig.extPath + 'imagelib/index.html', url: svgEditor.curConfig.extPath + 'imagelib/index.html',
description: 'Demonstration library for SVG-edit on this server' 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(); $('#imgbrowse_holder').hide();
} }
function importImage(url) { function importImage (url) {
var newImage = svgCanvas.addSvgElementFromJson({ var newImage = svgCanvas.addSvgElementFromJson({
"element": "image", 'element': 'image',
"attr": { 'attr': {
"x": 0, 'x': 0,
"y": 0, 'y': 0,
"width": 0, 'width': 0,
"height": 0, 'height': 0,
"id": svgCanvas.getNextId(), 'id': svgCanvas.getNextId(),
"style": "pointer-events:inherit" 'style': 'pointer-events:inherit'
} }
}); });
svgCanvas.clearSelection(); svgCanvas.clearSelection();
@@ -62,16 +64,16 @@ svgEditor.addExtension("imagelib", function() {'use strict';
} }
var mode = 's'; var mode = 's';
var multi_arr = []; var multiArr = [];
var tranfer_stopped = false; var transferStopped = false;
var pending = {}; var pending = {};
var preview, submit; var preview, submit;
window.addEventListener("message", function(evt) { window.addEventListener('message', function (evt) {
// Receive postMessage data // Receive postMessage data
var response = evt.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 // Do nothing
return; return;
} }
@@ -80,172 +82,168 @@ svgEditor.addExtension("imagelib", function() {'use strict';
if (res.namespace) { // Part of embedAPI communications if (res.namespace) { // Part of embedAPI communications
return; return;
} }
} } catch (e) {}
catch (e) {}
var char1 = response.charAt(0); var char1 = response.charAt(0);
var id; var id;
var svg_str; var svgStr;
var img_str; var imgStr;
if (char1 != "{" && tranfer_stopped) { if (char1 !== '{' && transferStopped) {
tranfer_stopped = false; transferStopped = false;
return; return;
} }
if (char1 == '|') { if (char1 === '|') {
var secondpos = response.indexOf('|', 1); var secondpos = response.indexOf('|', 1);
id = response.substr(1, secondpos-1); id = response.substr(1, secondpos - 1);
response = response.substr(secondpos+1); response = response.substr(secondpos + 1);
char1 = response.charAt(0); char1 = response.charAt(0);
} }
// Hide possible transfer dialog box // Hide possible transfer dialog box
$('#dialog_box').hide(); $('#dialog_box').hide();
var entry, cur_meta; var entry, curMeta;
switch (char1) { switch (char1) {
case '{': case '{':
// Metadata // Metadata
tranfer_stopped = false; transferStopped = false;
cur_meta = JSON.parse(response); curMeta = JSON.parse(response);
pending[cur_meta.id] = cur_meta; pending[curMeta.id] = curMeta;
var name = (cur_meta.name || 'file'); var name = (curMeta.name || 'file');
var message = uiStrings.notification.retrieving.replace('%s', name); var message = uiStrings.notification.retrieving.replace('%s', name);
if (mode != 'm') { if (mode !== 'm') {
$.process_cancel(message, function() { $.process_cancel(message, function () {
tranfer_stopped = true; transferStopped = true;
// Should a message be sent back to the frame? // Should a message be sent back to the frame?
$('#dialog_box').hide(); $('#dialog_box').hide();
}); });
} else { } else {
entry = $('<div>' + message + '</div>').data('id', cur_meta.id); entry = $('<div>' + message + '</div>').data('id', curMeta.id);
preview.append(entry); preview.append(entry);
cur_meta.entry = entry; curMeta.entry = entry;
} }
return; return;
case '<': case '<':
svg_str = true; 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; break;
case 'd': } else if (response.indexOf('data:image/') === 0) {
if (response.indexOf('data:image/svg+xml') === 0) { imgStr = true;
var pre = 'data:image/svg+xml;base64,'; break;
var src = response.substring(pre.length); }
response = svgedit.utilities.decode64(src); // Else fall through
svg_str = true; default:
break; // TODO: See if there's a way to base64 encode the binary data stream
} else if (response.indexOf('data:image/') === 0) { // var str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
img_str = 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 // Assume it's raw image data
// importImage(str); // importImage(str);
// Don't give warning as postMessage may have been used by something else // Don't give warning as postMessage may have been used by something else
if (mode !== 'm') { if (mode !== 'm') {
closeBrowser(); closeBrowser();
} else { } else {
pending[id].entry.remove(); pending[id].entry.remove();
} }
// $.alert('Unexpected data was returned: ' + response, function() { // $.alert('Unexpected data was returned: ' + response, function() {
// if (mode !== 'm') { // if (mode !== 'm') {
// closeBrowser(); // closeBrowser();
// } else { // } else {
// pending[id].entry.remove(); // pending[id].entry.remove();
// } // }
// }); // });
return; return;
} }
switch (mode) { switch (mode) {
case 's': case 's':
// Import one // Import one
if (svg_str) { if (svgStr) {
svgCanvas.importSvgString(response); svgCanvas.importSvgString(response);
} else if (img_str) { } else if (imgStr) {
importImage(response); importImage(response);
} }
closeBrowser(); closeBrowser();
break; break;
case 'm': case 'm':
// Import multiple // Import multiple
multi_arr.push([(svg_str ? 'svg' : 'img'), response]); multiArr.push([(svgStr ? 'svg' : 'img'), response]);
var title; var title;
cur_meta = pending[id]; curMeta = pending[id];
if (svg_str) { if (svgStr) {
if (cur_meta && cur_meta.name) { if (curMeta && curMeta.name) {
title = cur_meta.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 (cur_meta) {
preview.children().each(function() {
if ($(this).data('id') == id) {
if (cur_meta.preview_url) {
$(this).html('<img src="' + cur_meta.preview_url + '">' + title);
} else {
$(this).text(title);
}
submit.removeAttr('disabled');
}
});
} else {
preview.append('<div>'+title+'</div>');
submit.removeAttr('disabled');
}
} else { } else {
if (cur_meta && cur_meta.preview_url) { // Try to find a title
title = cur_meta.name || ''; var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
} title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
if (cur_meta && cur_meta.preview_url) {
entry = '<img src="' + cur_meta.preview_url + '">' + title;
} else {
entry = '<img src="' + response + '">';
}
if (cur_meta) {
preview.children().each(function() {
if ($(this).data('id') == id) {
$(this).html(entry);
submit.removeAttr('disabled');
}
});
} else {
preview.append($('<div>').append(entry));
submit.removeAttr('disabled');
}
} }
break; if (curMeta) {
case 'o': preview.children().each(function () {
// Open if ($(this).data('id') === id) {
if (!svg_str) {break;} if (curMeta.preview_url) {
svgEditor.openPrep(function(ok) { $(this).html('<img src="' + curMeta.preview_url + '">' + title);
if (!ok) {return;} } else {
svgCanvas.clear(); $(this).text(title);
svgCanvas.setSvgString(response); }
// updateCanvas(); submit.removeAttr('disabled');
}); }
closeBrowser(); });
break; } else {
preview.append('<div>' + title + '</div>');
submit.removeAttr('disabled');
}
} else {
if (curMeta && curMeta.preview_url) {
title = curMeta.name || '';
}
if (curMeta && curMeta.preview_url) {
entry = '<img src="' + curMeta.preview_url + '">' + title;
} else {
entry = '<img src="' + response + '">';
}
if (curMeta) {
preview.children().each(function () {
if ($(this).data('id') === id) {
$(this).html(entry);
submit.removeAttr('disabled');
}
});
} else {
preview.append($('<div>').append(entry));
submit.removeAttr('disabled');
}
}
break;
case 'o':
// Open
if (!svgStr) { break; }
svgEditor.openPrep(function (ok) {
if (!ok) { return; }
svgCanvas.clear();
svgCanvas.setSvgString(response);
// updateCanvas();
});
closeBrowser();
break;
} }
}, true); }, true);
function toggleMulti(show) { function toggleMulti (show) {
$('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)}); $('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)});
if (!preview) { if (!preview) {
preview = $('<div id=imglib_preview>').css({ preview = $('<div id=imglib_preview>').css({
@@ -260,46 +258,44 @@ svgEditor.addExtension("imagelib", function() {'use strict';
submit = $('<button disabled>Import selected</button>') submit = $('<button disabled>Import selected</button>')
.appendTo('#imgbrowse') .appendTo('#imgbrowse')
.on("click touchend", function() { .on('click touchend', function () {
$.each(multi_arr, function(i) { $.each(multiArr, function (i) {
var type = this[0]; var type = this[0];
var data = this[1]; var data = this[1];
if (type == 'svg') { if (type === 'svg') {
svgCanvas.importSvgString(data); svgCanvas.importSvgString(data);
} else { } else {
importImage(data); importImage(data);
} }
svgCanvas.moveSelectedElements(i*20, i*20, false); 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); preview.toggle(show);
submit.toggle(show); submit.toggle(show);
} }
function showBrowser() { function showBrowser () {
var browser = $('#imgbrowse'); var browser = $('#imgbrowse');
if (!browser.length) { if (!browser.length) {
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\ $('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>' +
</div></div>').insertAfter('#svg_docprops'); '</div></div>').insertAfter('#svg_docprops');
browser = $('#imgbrowse'); browser = $('#imgbrowse');
var all_libs = uiStrings.imagelib.select_lib; var allLibs = uiStrings.imagelib.select_lib;
var lib_opts = $('<ul id=imglib_opts>').appendTo(browser); var libOpts = $('<ul id=imglib_opts>').appendTo(browser);
var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>'); var frame = $('<iframe/>').prependTo(browser).hide().wrap('<div id=lib_framewrap>');
var header = $('<h1>').prependTo(browser).text(all_libs).css({ var header = $('<h1>').prependTo(browser).text(allLibs).css({
position: 'absolute', position: 'absolute',
top: 0, top: 0,
left: 0, left: 0,
@@ -308,42 +304,42 @@ svgEditor.addExtension("imagelib", function() {'use strict';
var cancel = $('<button>' + uiStrings.common.cancel + '</button>') var cancel = $('<button>' + uiStrings.common.cancel + '</button>')
.appendTo(browser) .appendTo(browser)
.on("click touchend", function() { .on('click touchend', function () {
$('#imgbrowse_holder').hide(); $('#imgbrowse_holder').hide();
}).css({ }).css({
position: 'absolute', position: 'absolute',
top: 5, top: 5,
right: -10 right: -10
}); });
var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser); var leftBlock = $('<span>').css({position: 'absolute', top: 5, left: 10}).appendTo(browser);
var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>') var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>')
.appendTo(leftBlock) .appendTo(leftBlock)
.on("click touchend", function() { .on('click touchend', function () {
frame.attr('src', 'about:blank').hide(); frame.attr('src', 'about:blank').hide();
lib_opts.show(); libOpts.show();
header.text(all_libs); header.text(allLibs);
back.hide(); back.hide();
}).css({ }).css({
'margin-right': 5 'margin-right': 5
}).hide(); }).hide();
var type = $('<select><option value=s>' + /* var type = */ $('<select><option value=s>' +
uiStrings.imagelib.import_single + '</option><option value=m>' + uiStrings.imagelib.import_single + '</option><option value=m>' +
uiStrings.imagelib.import_multi + '</option><option value=o>' + uiStrings.imagelib.import_multi + '</option><option value=o>' +
uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function() { uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function () {
mode = $(this).val(); mode = $(this).val();
switch (mode) { switch (mode) {
case 's': case 's':
case 'o': case 'o':
toggleMulti(false); toggleMulti(false);
break; break;
case 'm': case 'm':
// Import multiple // Import multiple
toggleMulti(true); toggleMulti(true);
break; break;
} }
}).css({ }).css({
'margin-top': 10 'margin-top': 10
@@ -352,113 +348,109 @@ svgEditor.addExtension("imagelib", function() {'use strict';
cancel.prepend($.getSvgIcon('cancel', true)); cancel.prepend($.getSvgIcon('cancel', true));
back.prepend($.getSvgIcon('tool_imagelib', true)); back.prepend($.getSvgIcon('tool_imagelib', true));
$.each(img_libs, function(i, opts) { $.each(imgLibs, function (i, opts) {
$('<li>') $('<li>')
.appendTo(lib_opts) .appendTo(libOpts)
.text(opts.name) .text(opts.name)
.on("click touchend", function() { .on('click touchend', function () {
frame.attr('src', opts.url).show(); frame.attr('src', opts.url).show();
header.text(opts.name); header.text(opts.name);
lib_opts.hide(); libOpts.hide();
back.show(); back.show();
}).append('<span>' + opts.description + '</span>'); }).append('<span>' + opts.description + '</span>');
}); });
} else { } else {
$('#imgbrowse_holder').show(); $('#imgbrowse_holder').show();
} }
} }
return { return {
svgicons: svgEditor.curConfig.extPath + "ext-imagelib.xml", svgicons: svgEditor.curConfig.extPath + 'ext-imagelib.xml',
buttons: [{ buttons: [{
id: "tool_imagelib", id: 'tool_imagelib',
type: "app_menu", // _flyout type: 'app_menu', // _flyout
position: 4, position: 4,
title: "Image library", title: 'Image library',
events: { events: {
"mouseup": showBrowser 'mouseup': showBrowser
} }
}], }],
callback: function() { callback: function () {
$('<style>').text(
$('<style>').text('\ '#imgbrowse_holder {' +
#imgbrowse_holder {\ 'position: absolute;' +
position: absolute;\ 'top: 0;' +
top: 0;\ 'left: 0;' +
left: 0;\ 'width: 100%;' +
width: 100%;\ 'height: 100%;' +
height: 100%;\ 'background-color: rgba(0, 0, 0, .5);' +
background-color: rgba(0, 0, 0, .5);\ 'z-index: 5;' +
z-index: 5;\ '}' +
}\ '#imgbrowse {' +
\ 'position: absolute;' +
#imgbrowse {\ 'top: 25px;' +
position: absolute;\ 'left: 25px;' +
top: 25px;\ 'right: 25px;' +
left: 25px;\ 'bottom: 25px;' +
right: 25px;\ 'min-width: 300px;' +
bottom: 25px;\ 'min-height: 200px;' +
min-width: 300px;\ 'background: #B0B0B0;' +
min-height: 200px;\ 'border: 1px outset #777;' +
background: #B0B0B0;\ '}' +
border: 1px outset #777;\ '#imgbrowse h1 {' +
}\ 'font-size: 20px;' +
#imgbrowse h1 {\ 'margin: .4em;' +
font-size: 20px;\ 'text-align: center;' +
margin: .4em;\ '}' +
text-align: center;\ '#lib_framewrap,' +
}\ '#imgbrowse > ul {' +
#lib_framewrap,\ 'position: absolute;' +
#imgbrowse > ul {\ 'top: 45px;' +
position: absolute;\ 'left: 10px;' +
top: 45px;\ 'right: 10px;' +
left: 10px;\ 'bottom: 10px;' +
right: 10px;\ 'background: white;' +
bottom: 10px;\ 'margin: 0;' +
background: white;\ 'padding: 0;' +
margin: 0;\ '}' +
padding: 0;\ '#imgbrowse > ul {' +
}\ 'overflow: auto;' +
#imgbrowse > ul {\ '}' +
overflow: auto;\ '#imgbrowse > div {' +
}\ 'border: 1px solid #666;' +
#imgbrowse > div {\ '}' +
border: 1px solid #666;\ '#imglib_preview > div {' +
}\ 'padding: 5px;' +
#imglib_preview > div {\ 'font-size: 12px;' +
padding: 5px;\ '}' +
font-size: 12px;\ '#imglib_preview img {' +
}\ 'display: block;' +
#imglib_preview img {\ 'margin: 0 auto;' +
display: block;\ 'max-height: 100px;' +
margin: 0 auto;\ '}' +
max-height: 100px;\ '#imgbrowse li {' +
}\ 'list-style: none;' +
#imgbrowse li {\ 'padding: .5em;' +
list-style: none;\ 'background: #E8E8E8;' +
padding: .5em;\ 'border-bottom: 1px solid #B0B0B0;' +
background: #E8E8E8;\ 'line-height: 1.2em;' +
border-bottom: 1px solid #B0B0B0;\ 'font-style: sans-serif;' +
line-height: 1.2em;\ '}' +
font-style: sans-serif;\ '#imgbrowse li > span {' +
}\ 'color: #666;' +
#imgbrowse li > span {\ 'font-size: 15px;' +
color: #666;\ 'display: block;' +
font-size: 15px;\ '}' +
display: block;\ '#imgbrowse li:hover {' +
}\ 'background: #FFC;' +
#imgbrowse li:hover {\ 'cursor: pointer;' +
background: #FFC;\ '}' +
cursor: pointer;\ '#imgbrowse iframe {' +
}\ 'width: 100%;' +
#imgbrowse iframe {\ 'height: 100%;' +
width: 100%;\ 'border: 0;' +
height: 100%;\ '}'
border: 0;\ ).appendTo('head');
}\
').appendTo('head');
} }
}; };
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, todo: true */ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-markers.js * ext-markers.js
* *
@@ -32,236 +32,235 @@
* *
*/ */
svgEditor.addExtension("Markers", function(S) { svgEditor.addExtension('Markers', function (S) {
var // svgcontent = S.svgcontent, var // svgcontent = S.svgcontent,
addElem = S.addSvgElementFromJson, addElem = S.addSvgElementFromJson,
selElems; selElems;
var mtypes = ['start','mid','end']; var mtypes = ['start', 'mid', 'end'];
var marker_prefix = 'se_marker_'; var markerPrefix = 'se_marker_';
var id_prefix = 'mkr_'; var idPrefix = 'mkr_';
// note - to add additional marker types add them below with a unique id // note - to add additional marker types add them below with a unique id
// and add the associated icon(s) to marker-icons.svg // and add the associated icon(s) to marker-icons.svg
// the geometry is normallized to a 100x100 box with the origin at lower left // the geometry is normallized to a 100x100 box with the origin at lower left
// Safari did not like negative values for low left of viewBox // Safari did not like negative values for low left of viewBox
// remember that the coordinate system has +y downward // remember that the coordinate system has +y downward
var marker_types = { var markerTypes = {
nomarker: {}, nomarker: {},
leftarrow: leftarrow:
{element:'path', attr:{d:'M0,50 L100,90 L70,50 L100,10 Z'}}, {element: 'path', attr: {d: 'M0,50 L100,90 L70,50 L100,10 Z'}},
rightarrow: rightarrow:
{element:'path', attr:{d:'M100,50 L0,90 L30,50 L0,10 Z'}}, {element: 'path', attr: {d: 'M100,50 L0,90 L30,50 L0,10 Z'}},
textmarker: textmarker:
{element:'text', attr: {x:0, y:0,'stroke-width':0,'stroke':'none','font-size':75,'font-family':'serif','text-anchor':'left', {element: 'text', attr: {x: 0, y: 0, 'stroke-width': 0, 'stroke': 'none', 'font-size': 75, 'font-family': 'serif', 'text-anchor': 'left',
'xml:space': 'preserve'}}, 'xml:space': 'preserve'}},
forwardslash: forwardslash:
{element:'path', attr:{d:'M30,100 L70,0'}}, {element: 'path', attr: {d: 'M30,100 L70,0'}},
reverseslash: reverseslash:
{element:'path', attr:{d:'M30,0 L70,100'}}, {element: 'path', attr: {d: 'M30,0 L70,100'}},
verticalslash: verticalslash:
{element:'path', attr:{d:'M50,0 L50,100'}}, {element: 'path', attr: {d: 'M50,0 L50,100'}},
box: box:
{element:'path', attr:{d:'M20,20 L20,80 L80,80 L80,20 Z'}}, {element: 'path', attr: {d: 'M20,20 L20,80 L80,80 L80,20 Z'}},
star: star:
{element:'path', attr:{d:'M10,30 L90,30 L20,90 L50,10 L80,90 Z'}}, {element: 'path', attr: {d: 'M10,30 L90,30 L20,90 L50,10 L80,90 Z'}},
xmark: xmark:
{element:'path', attr:{d:'M20,80 L80,20 M80,80 L20,20'}}, {element: 'path', attr: {d: 'M20,80 L80,20 M80,80 L20,20'}},
triangle: triangle:
{element:'path', attr:{d:'M10,80 L50,20 L80,80 Z'}}, {element: 'path', attr: {d: 'M10,80 L50,20 L80,80 Z'}},
mcircle: mcircle:
{element:'circle', attr:{r:30, cx:50, cy:50}} {element: 'circle', attr: {r: 30, cx: 50, cy: 50}}
}; };
var langList = {
var lang_list = { 'en': [
"en":[ {id: 'start_marker_list', title: 'Select start marker type'},
{id: "start_marker_list", title: "Select start marker type" }, {id: 'mid_marker_list', title: 'Select mid marker type'},
{id: "mid_marker_list", title: "Select mid marker type" }, {id: 'end_marker_list', title: 'Select end marker type'},
{id: "end_marker_list", title: "Select end marker type" }, {id: 'nomarker', title: 'No Marker'},
{id: "nomarker", title: "No Marker" }, {id: 'leftarrow', title: 'Left Arrow'},
{id: "leftarrow", title: "Left Arrow" }, {id: 'rightarrow', title: 'Right Arrow'},
{id: "rightarrow", title: "Right Arrow" }, {id: 'textmarker', title: 'Text Marker'},
{id: "textmarker", title: "Text Marker" }, {id: 'forwardslash', title: 'Forward Slash'},
{id: "forwardslash", title: "Forward Slash" }, {id: 'reverseslash', title: 'Reverse Slash'},
{id: "reverseslash", title: "Reverse Slash" }, {id: 'verticalslash', title: 'Vertical Slash'},
{id: "verticalslash", title: "Vertical Slash" }, {id: 'box', title: 'Box'},
{id: "box", title: "Box" }, {id: 'star', title: 'Star'},
{id: "star", title: "Star" }, {id: 'xmark', title: 'X'},
{id: "xmark", title: "X" }, {id: 'triangle', title: 'Triangle'},
{id: "triangle", title: "Triangle" }, {id: 'mcircle', title: 'Circle'},
{id: "mcircle", title: "Circle" }, {id: 'leftarrow_o', title: 'Open Left Arrow'},
{id: "leftarrow_o", title: "Open Left Arrow" }, {id: 'rightarrow_o', title: 'Open Right Arrow'},
{id: "rightarrow_o", title: "Open Right Arrow" }, {id: 'box_o', title: 'Open Box'},
{id: "box_o", title: "Open Box" }, {id: 'star_o', title: 'Open Star'},
{id: "star_o", title: "Open Star" }, {id: 'triangle_o', title: 'Open Triangle'},
{id: "triangle_o", title: "Open Triangle" }, {id: 'mcircle_o', title: 'Open Circle'}
{id: "mcircle_o", title: "Open Circle" }
] ]
}; };
// duplicate shapes to support unfilled (open) marker types with an _o suffix // duplicate shapes to support unfilled (open) marker types with an _o suffix
$.each(['leftarrow','rightarrow','box','star','mcircle','triangle'],function(i,v) { $.each(['leftarrow', 'rightarrow', 'box', 'star', 'mcircle', 'triangle'], function (i, v) {
marker_types[v+'_o'] = marker_types[v]; markerTypes[v + '_o'] = markerTypes[v];
}); });
// elem = a graphic element will have an attribute like marker-start // elem = a graphic element will have an attribute like marker-start
// attr - marker-start, marker-mid, or marker-end // attr - marker-start, marker-mid, or marker-end
// returns the marker element that is linked to the graphic element // returns the marker element that is linked to the graphic element
function getLinked(elem, attr) { function getLinked (elem, attr) {
var str = elem.getAttribute(attr); var str = elem.getAttribute(attr);
if(!str) {return null;} if (!str) { return null; }
var m = str.match(/\(\#(.*)\)/); var m = str.match(/\(#(.*)\)/);
if(!m || m.length !== 2) { if (!m || m.length !== 2) {
return null; return null;
} }
return S.getElem(m[1]); return S.getElem(m[1]);
} }
function setIcon(pos,id) { function setIcon (pos, id) {
if (id.substr(0,1) !== '\\') {id = '\\textmarker';} if (id.substr(0, 1) !== '\\') { id = '\\textmarker'; }
var ci = '#'+id_prefix+pos+'_'+id.substr(1); var ci = '#' + idPrefix + pos + '_' + id.substr(1);
svgEditor.setIcon('#cur_' + pos +'_marker_list', $(ci).children()); svgEditor.setIcon('#cur_' + pos + '_marker_list', $(ci).children());
$(ci).addClass('current').siblings().removeClass('current'); $(ci).addClass('current').siblings().removeClass('current');
} }
// toggles context tool panel off/on // toggles context tool panel off/on
//sets the controls with the selected element's settings // sets the controls with the selected element's settings
function showPanel(on) { function showPanel (on) {
$('#marker_panel').toggle(on); $('#marker_panel').toggle(on);
if(on) { if (on) {
var el = selElems[0]; var el = selElems[0];
var val; var val;
var ci; var ci;
$.each(mtypes, function(i, pos) { $.each(mtypes, function (i, pos) {
var m = getLinked(el, "marker-" + pos); var m = getLinked(el, 'marker-' + pos);
var txtbox = $('#' + pos + '_marker'); var txtbox = $('#' + pos + '_marker');
if (!m) { if (!m) {
val = '\\nomarker'; val = '\\nomarker';
ci = val; ci = val;
txtbox.hide(); // hide text box txtbox.hide(); // hide text box
} else { } else {
if (!m.attributes.se_type) {return;} // not created by this extension if (!m.attributes.se_type) { return; } // not created by this extension
val = '\\' + m.attributes.se_type.textContent; val = '\\' + m.attributes.se_type.textContent;
ci = val; ci = val;
if (val === '\\textmarker') { if (val === '\\textmarker') {
val = m.lastChild.textContent; val = m.lastChild.textContent;
//txtbox.show(); // show text box // txtbox.show(); // show text box
} else { } else {
txtbox.hide(); // hide text box txtbox.hide(); // hide text box
} }
} }
txtbox.val(val); txtbox.val(val);
setIcon(pos,ci); setIcon(pos, ci);
}); });
} }
} }
function addMarker(id, val) { function addMarker (id, val) {
var txt_box_bg = '#ffffff'; var txtBoxBg = '#ffffff';
var txt_box_border = 'none'; var txtBoxBorder = 'none';
var txt_box_stroke_width = 0; var txtBoxStrokeWidth = 0;
var marker = S.getElem(id); var marker = S.getElem(id);
if (marker) {return;} if (marker) { return; }
if (val == '' || val == '\\nomarker') {return;} if (val === '' || val === '\\nomarker') { return; }
var el = selElems[0]; var el = selElems[0];
var color = el.getAttribute('stroke'); var color = el.getAttribute('stroke');
//NOTE: Safari didn't like a negative value in viewBox // NOTE: Safari didn't like a negative value in viewBox
//so we use a standardized 0 0 100 100 // so we use a standardized 0 0 100 100
//with 50 50 being mapped to the marker position // with 50 50 being mapped to the marker position
var refX = 50; var refX = 50;
var refY = 50; var refY = 50;
var viewBox = "0 0 100 100"; var viewBox = '0 0 100 100';
var markerWidth = 5; var markerWidth = 5;
var markerHeight = 5; var markerHeight = 5;
var strokeWidth = 10; var strokeWidth = 10;
var se_type; var seType;
if (val.substr(0,1) === '\\') {se_type = val.substr(1);} if (val.substr(0, 1) === '\\') {
else {se_type = 'textmarker';} seType = val.substr(1);
} else { seType = 'textmarker'; }
if (!marker_types[se_type]) {return;} // an unknown type! if (!markerTypes[seType]) { return; } // an unknown type!
// create a generic marker // create a generic marker
marker = addElem({ marker = addElem({
"element": "marker", 'element': 'marker',
"attr": { 'attr': {
"id": id, 'id': id,
"markerUnits": "strokeWidth", 'markerUnits': 'strokeWidth',
"orient": "auto", 'orient': 'auto',
"style": "pointer-events:none", 'style': 'pointer-events:none',
"se_type": se_type 'se_type': seType
} }
}); });
if (se_type != 'textmarker') { if (seType !== 'textmarker') {
var mel = addElem(marker_types[se_type]); var mel = addElem(markerTypes[seType]);
var fillcolor = color; var fillcolor = color;
if (se_type.substr(-2) === '_o') {fillcolor = 'none';} if (seType.substr(-2) === '_o') { fillcolor = 'none'; }
mel.setAttribute('fill', fillcolor); mel.setAttribute('fill', fillcolor);
mel.setAttribute('stroke', color); mel.setAttribute('stroke', color);
mel.setAttribute('stroke-width', strokeWidth); mel.setAttribute('stroke-width', strokeWidth);
marker.appendChild(mel); marker.appendChild(mel);
} else { } else {
var text = addElem(marker_types[se_type]); var text = addElem(markerTypes[seType]);
// have to add text to get bounding box // have to add text to get bounding box
text.textContent = val; text.textContent = val;
var tb = text.getBBox(); var tb = text.getBBox();
//alert( tb.x + " " + tb.y + " " + tb.width + " " + tb.height); // alert(tb.x + ' ' + tb.y + ' ' + tb.width + ' ' + tb.height);
var pad = 1; var pad = 1;
var bb = tb; var bb = tb;
bb.x = 0; bb.x = 0;
bb.y = 0; bb.y = 0;
bb.width += pad*2; bb.width += pad * 2;
bb.height += pad*2; bb.height += pad * 2;
// shift text according to its size // shift text according to its size
text.setAttribute('x', pad); text.setAttribute('x', pad);
text.setAttribute('y', bb.height - pad - tb.height/4); // kludge? text.setAttribute('y', bb.height - pad - tb.height / 4); // kludge?
text.setAttribute('fill',color); text.setAttribute('fill', color);
refX = bb.width/2 + pad; refX = bb.width / 2 + pad;
refY = bb.height/2 + pad; refY = bb.height / 2 + pad;
viewBox = bb.x + " " + bb.y + " " + bb.width + " " + bb.height; viewBox = bb.x + ' ' + bb.y + ' ' + bb.width + ' ' + bb.height;
markerWidth = bb.width/10; markerWidth = bb.width / 10;
markerHeight = bb.height/10; markerHeight = bb.height / 10;
var box = addElem({ var box = addElem({
"element": "rect", 'element': 'rect',
"attr": { 'attr': {
"x": bb.x, 'x': bb.x,
"y": bb.y, 'y': bb.y,
"width": bb.width, 'width': bb.width,
"height": bb.height, 'height': bb.height,
"fill": txt_box_bg, 'fill': txtBoxBg,
"stroke": txt_box_border, 'stroke': txtBoxBorder,
"stroke-width": txt_box_stroke_width 'stroke-width': txtBoxStrokeWidth
} }
}); });
marker.setAttribute("orient",0); marker.setAttribute('orient', 0);
marker.appendChild(box); marker.appendChild(box);
marker.appendChild(text); marker.appendChild(text);
} }
marker.setAttribute("viewBox",viewBox); marker.setAttribute('viewBox', viewBox);
marker.setAttribute("markerWidth", markerWidth); marker.setAttribute('markerWidth', markerWidth);
marker.setAttribute("markerHeight", markerHeight); marker.setAttribute('markerHeight', markerHeight);
marker.setAttribute("refX", refX); marker.setAttribute('refX', refX);
marker.setAttribute("refY", refY); marker.setAttribute('refY', refY);
S.findDefs().appendChild(marker); S.findDefs().appendChild(marker);
return marker; return marker;
} }
function convertline(elem) { function convertline (elem) {
// this routine came from the connectors extension // this routine came from the connectors extension
// it is needed because midpoint markers don't work with line elements // it is needed because midpoint markers don't work with line elements
if (!(elem.tagName === 'line')) {return elem;} if (!(elem.tagName === 'line')) { return elem; }
// Convert to polyline to accept mid-arrow // Convert to polyline to accept mid-arrow
@@ -271,21 +270,21 @@ svgEditor.addExtension("Markers", function(S) {
var y2 = Number(elem.getAttribute('y2')); var y2 = Number(elem.getAttribute('y2'));
var id = elem.id; var id = elem.id;
var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' '); var midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
var pline = addElem({ var pline = addElem({
"element": "polyline", 'element': 'polyline',
"attr": { 'attr': {
"points": (x1+','+y1+ mid_pt +x2+','+y2), 'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2),
"stroke": elem.getAttribute('stroke'), 'stroke': elem.getAttribute('stroke'),
"stroke-width": elem.getAttribute('stroke-width'), 'stroke-width': elem.getAttribute('stroke-width'),
"fill": "none", 'fill': 'none',
"opacity": elem.getAttribute('opacity') || 1 'opacity': elem.getAttribute('opacity') || 1
} }
}); });
$.each(mtypes, function(i, pos) { // get any existing marker definitions $.each(mtypes, function (i, pos) { // get any existing marker definitions
var nam = 'marker-'+pos; var nam = 'marker-' + pos;
var m = elem.getAttribute(nam); var m = elem.getAttribute(nam);
if (m) {pline.setAttribute(nam,elem.getAttribute(nam));} if (m) { pline.setAttribute(nam, elem.getAttribute(nam)); }
}); });
var batchCmd = new S.BatchCommand(); var batchCmd = new S.BatchCommand();
@@ -300,85 +299,85 @@ svgEditor.addExtension("Markers", function(S) {
return pline; return pline;
} }
function setMarker() { function setMarker () {
var poslist={'start_marker':'start','mid_marker':'mid','end_marker':'end'}; var poslist = {'start_marker': 'start', 'mid_marker': 'mid', 'end_marker': 'end'};
var pos = poslist[this.id]; var pos = poslist[this.id];
var marker_name = 'marker-'+pos; var markerName = 'marker-' + pos;
var val = this.value; var val = this.value;
var el = selElems[0]; var el = selElems[0];
var marker = getLinked(el, marker_name); var marker = getLinked(el, markerName);
if (marker) {$(marker).remove();} if (marker) { $(marker).remove(); }
el.removeAttribute(marker_name); el.removeAttribute(markerName);
if (val == '') {val = '\\nomarker';} if (val === '') { val = '\\nomarker'; }
if (val == '\\nomarker') { if (val === '\\nomarker') {
setIcon(pos,val); setIcon(pos, val);
S.call("changed", selElems); S.call('changed', selElems);
return; return;
} }
// Set marker on element // Set marker on element
var id = marker_prefix + pos + '_' + el.id; var id = markerPrefix + pos + '_' + el.id;
addMarker(id, val); addMarker(id, val);
svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")"); svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
if (el.tagName === 'line' && pos == 'mid') {el = convertline(el);} if (el.tagName === 'line' && pos === 'mid') { el = convertline(el); }
S.call("changed", selElems); S.call('changed', selElems);
setIcon(pos,val); setIcon(pos, val);
} }
// called when the main system modifies an object // called when the main system modifies an object
// this routine changes the associated markers to be the same color // this routine changes the associated markers to be the same color
function colorChanged(elem) { function colorChanged (elem) {
var color = elem.getAttribute('stroke'); var color = elem.getAttribute('stroke');
$.each(mtypes, function(i, pos) { $.each(mtypes, function (i, pos) {
var marker = getLinked(elem, 'marker-'+pos); var marker = getLinked(elem, 'marker-' + pos);
if (!marker) {return;} if (!marker) { return; }
if (!marker.attributes.se_type) {return;} // not created by this extension if (!marker.attributes.se_type) { return; } // not created by this extension
var ch = marker.lastElementChild; var ch = marker.lastElementChild;
if (!ch) {return;} if (!ch) { return; }
var curfill = ch.getAttribute('fill'); var curfill = ch.getAttribute('fill');
var curstroke = ch.getAttribute('stroke'); var curstroke = ch.getAttribute('stroke');
if (curfill && curfill != 'none') {ch.setAttribute('fill', color);} if (curfill && curfill !== 'none') { ch.setAttribute('fill', color); }
if (curstroke && curstroke != 'none') {ch.setAttribute('stroke', color);} if (curstroke && curstroke !== 'none') { ch.setAttribute('stroke', color); }
}); });
} }
// called when the main system creates or modifies an object // called when the main system creates or modifies an object
// primary purpose is create new markers for cloned objects // primary purpose is create new markers for cloned objects
function updateReferences(el) { function updateReferences (el) {
$.each(mtypes, function (i, pos) { $.each(mtypes, function (i, pos) {
var id = marker_prefix + pos + '_' + el.id; var id = markerPrefix + pos + '_' + el.id;
var marker_name = 'marker-'+pos; var markerName = 'marker-' + pos;
var marker = getLinked(el, marker_name); var marker = getLinked(el, markerName);
if (!marker || !marker.attributes.se_type) {return;} // not created by this extension if (!marker || !marker.attributes.se_type) { return; } // not created by this extension
var url = el.getAttribute(marker_name); var url = el.getAttribute(markerName);
if (url) { if (url) {
var len = el.id.length; var len = el.id.length;
var linkid = url.substr(-len-1, len); var linkid = url.substr(-len - 1, len);
if (el.id != linkid) { if (el.id !== linkid) {
var val = $('#'+pos + '_marker').attr('value'); var val = $('#' + pos + '_marker').attr('value');
addMarker(id, val); addMarker(id, val);
svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")"); svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
if (el.tagName === 'line' && pos == 'mid') {el = convertline(el);} if (el.tagName === 'line' && pos === 'mid') { el = convertline(el); }
S.call("changed", selElems); S.call('changed', selElems);
} }
} }
}); });
} }
// simulate a change event a text box that stores the current element's marker type // simulate a change event a text box that stores the current element's marker type
function triggerTextEntry(pos, val) { function triggerTextEntry (pos, val) {
$('#'+pos+'_marker').val(val); $('#' + pos + '_marker').val(val);
$('#'+pos+'_marker').change(); $('#' + pos + '_marker').change();
// var txtbox = $('#'+pos+'_marker'); // var txtbox = $('#'+pos+'_marker');
// if (val.substr(0,1)=='\\') {txtbox.hide();} // if (val.substr(0,1)=='\\') {txtbox.hide();}
// else {txtbox.show();} // else {txtbox.show();}
} }
function showTextPrompt(pos) { function showTextPrompt (pos) {
var def = $('#'+pos+'_marker').val(); var def = $('#' + pos + '_marker').val();
if (def.substr(0,1) === '\\') {def = '';} if (def.substr(0, 1) === '\\') { def = ''; }
$.prompt('Enter text for ' + pos + ' marker', def , function(txt) { $.prompt('Enter text for ' + pos + ' marker', def, function (txt) {
if (txt) {triggerTextEntry(pos, txt);} if (txt) { triggerTextEntry(pos, txt); }
}); });
} }
@@ -406,66 +405,64 @@ svgEditor.addExtension("Markers", function(S) {
} }
*/ */
// callback function for a toolbar button click // callback function for a toolbar button click
function setArrowFromButton(obj) { function setArrowFromButton (obj) {
var parts = this.id.split('_'); var parts = this.id.split('_');
var pos = parts[1]; var pos = parts[1];
var val = parts[2]; var val = parts[2];
if (parts[3]) { val += '_' + parts[3];} if (parts[3]) { val += '_' + parts[3]; }
if (val != 'textmarker') { if (val !== 'textmarker') {
triggerTextEntry(pos, '\\'+val); triggerTextEntry(pos, '\\' + val);
} else { } else {
showTextPrompt(pos); showTextPrompt(pos);
} }
} }
function getTitle(lang, id) { function getTitle (lang, id) {
var i, list = lang_list[lang]; var i, list = langList[lang];
for (i in list) { for (i in list) {
if (list.hasOwnProperty(i) && list[i].id == id) { if (list.hasOwnProperty(i) && list[i].id === id) {
return list[i].title; return list[i].title;
} }
} }
return id; return id;
} }
// build the toolbar button array from the marker definitions // build the toolbar button array from the marker definitions
// TODO: need to incorporate language specific titles // TODO: need to incorporate language specific titles
function buildButtonList() { function buildButtonList () {
var buttons=[]; var buttons = [];
// var i = 0; // var i = 0;
/* /*
buttons.push({ buttons.push({
id:id_prefix + 'markers_off', id: idPrefix + 'markers_off',
title:'Turn off all markers', title: 'Turn off all markers',
type:'context', type: 'context',
events: { 'click': setMarkerSet }, events: { 'click': setMarkerSet },
panel: 'marker_panel' panel: 'marker_panel'
}); });
buttons.push({ buttons.push({
id:id_prefix + 'markers_dimension', id: idPrefix + 'markers_dimension',
title:'Dimension', title: 'Dimension',
type:'context', type: 'context',
events: { 'click': setMarkerSet }, events: { 'click': setMarkerSet },
panel: 'marker_panel' panel: 'marker_panel'
}); });
buttons.push({ buttons.push({
id:id_prefix + 'markers_label', id: idPrefix + 'markers_label',
title:'Label', title: 'Label',
type:'context', type: 'context',
events: { 'click': setMarkerSet }, events: { 'click': setMarkerSet },
panel: 'marker_panel' panel: 'marker_panel'
}); });
*/ */
$.each(mtypes, function (k, pos) { $.each(mtypes, function (k, pos) {
var listname = pos + "_marker_list"; var listname = pos + '_marker_list';
var def = true; var def = true;
$.each(marker_types, function (id, v) { $.each(markerTypes, function (id, v) {
var title = getTitle('en', id); var title = getTitle('en', String(id));
buttons.push({ buttons.push({
id: id_prefix + pos + '_' + id, id: idPrefix + pos + '_' + id,
svgicon: id, svgicon: id,
title: title, title: title,
type: 'context', type: 'context',
@@ -481,99 +478,98 @@ svgEditor.addExtension("Markers", function(S) {
} }
return { return {
name: "Markers", name: 'Markers',
svgicons: svgEditor.curConfig.extPath + "markers-icons.xml", svgicons: svgEditor.curConfig.extPath + 'markers-icons.xml',
buttons: buildButtonList(), buttons: buildButtonList(),
context_tools: [ context_tools: [
{ {
type: "input", type: 'input',
panel: "marker_panel", panel: 'marker_panel',
title: "Start marker", title: 'Start marker',
id: "start_marker", id: 'start_marker',
label: "s", label: 's',
size: 3, size: 3,
events: { change: setMarker } events: { change: setMarker }
},{ }, {
type: "button-select", type: 'button-select',
panel: "marker_panel", panel: 'marker_panel',
title: getTitle('en', 'start_marker_list'), title: getTitle('en', 'start_marker_list'),
id: "start_marker_list", id: 'start_marker_list',
colnum: 3, colnum: 3,
events: { change: setArrowFromButton } events: { change: setArrowFromButton }
},{ }, {
type: "input", type: 'input',
panel: "marker_panel", panel: 'marker_panel',
title: "Middle marker", title: 'Middle marker',
id: "mid_marker", id: 'mid_marker',
label: "m", label: 'm',
defval: "", defval: '',
size: 3, size: 3,
events: { change: setMarker } events: { change: setMarker }
},{ }, {
type: "button-select", type: 'button-select',
panel: "marker_panel", panel: 'marker_panel',
title: getTitle('en', 'mid_marker_list'), title: getTitle('en', 'mid_marker_list'),
id: "mid_marker_list", id: 'mid_marker_list',
colnum: 3, colnum: 3,
events: { change: setArrowFromButton } events: { change: setArrowFromButton }
},{ }, {
type: "input", type: 'input',
panel: "marker_panel", panel: 'marker_panel',
title: "End marker", title: 'End marker',
id: "end_marker", id: 'end_marker',
label: "e", label: 'e',
size: 3, size: 3,
events: { change: setMarker } events: { change: setMarker }
},{ }, {
type: "button-select", type: 'button-select',
panel: "marker_panel", panel: 'marker_panel',
title: getTitle('en', 'end_marker_list'), title: getTitle('en', 'end_marker_list'),
id: "end_marker_list", id: 'end_marker_list',
colnum: 3, colnum: 3,
events: { change: setArrowFromButton } events: { change: setArrowFromButton }
} ], }
callback: function() { ],
callback: function () {
$('#marker_panel').addClass('toolset').hide(); $('#marker_panel').addClass('toolset').hide();
}, },
addLangData: function(lang) { addLangData: function (lang) {
return { data: lang_list[lang] }; return { data: langList[lang] };
}, },
selectedChanged: function (opts) {
// Use this to update the current selected elements
// console.log('selectChanged',opts);
selElems = opts.elems;
selectedChanged: function(opts) { var i = selElems.length;
// Use this to update the current selected elements var markerElems = ['line', 'path', 'polyline', 'polygon'];
//console.log('selectChanged',opts);
selElems = opts.elems;
var i = selElems.length; while (i--) {
var marker_elems = ['line','path','polyline','polygon']; var elem = selElems[i];
if (elem && $.inArray(elem.tagName, markerElems) !== -1) {
while(i--) { if (opts.selectedElement && !opts.multiselected) {
var elem = selElems[i]; showPanel(true);
if(elem && $.inArray(elem.tagName, marker_elems) !== -1) { } else {
if (opts.selectedElement && !opts.multiselected) { showPanel(false);
showPanel(true); }
} else { } else {
showPanel(false); showPanel(false);
} }
} else {
showPanel(false);
} }
} },
},
elementChanged: function(opts) { elementChanged: function (opts) {
//console.log('elementChanged',opts); // console.log('elementChanged',opts);
var elem = opts.elems[0]; var elem = opts.elems[0];
if (elem && ( if (elem && (
elem.getAttribute("marker-start") || elem.getAttribute('marker-start') ||
elem.getAttribute("marker-mid") || elem.getAttribute('marker-mid') ||
elem.getAttribute("marker-end") elem.getAttribute('marker-end')
)) { )) {
colorChanged(elem); colorChanged(elem);
updateReferences(elem); updateReferences(elem);
}
// changing_flag = false; // Not apparently in use
} }
// changing_flag = false; // Not apparently in use
}
}; };
}); });

View File

@@ -1,5 +1,5 @@
/*globals MathJax, svgEditor, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint es5: true, todo: true, vars: true*/ /* globals MathJax, svgEditor, svgCanvas, $ */
/* /*
* ext-mathjax.js * ext-mathjax.js
* *
@@ -9,265 +9,256 @@
* *
*/ */
svgEditor.addExtension("mathjax", function() {'use strict'; svgEditor.addExtension('mathjax', function () {
// Configuration of the MathJax extention. 'use strict';
// Configuration of the MathJax extention.
// This will be added to the head tag before MathJax is loaded. // This will be added to the head tag before MathJax is loaded.
var /*mathjaxConfiguration = '<script type="text/x-mathjax-config">\ var /* mathjaxConfiguration = '<script type="text/x-mathjax-config">\
MathJax.Hub.Config({\ MathJax.Hub.Config({\
extensions: ["tex2jax.js"],\ extensions: ["tex2jax.js"],\
jax: ["input/TeX","output/SVG"],\ jax: ["input/TeX","output/SVG"],\
showProcessingMessages: true,\ showProcessingMessages: true,\
showMathMenu: false,\ showMathMenu: false,\
showMathMenuMSIE: false,\ showMathMenuMSIE: false,\
errorSettings: {\ errorSettings: {\
message: ["[Math Processing Error]"],\ message: ["[Math Processing Error]"],\
style: {color: "#CC0000", "font-style":"italic"}\ style: {color: "#CC0000", "font-style":"italic"}\
},\ },\
elements: [],\ elements: [],\
tex2jax: {\ tex2jax: {\
ignoreClass: "tex2jax_ignore2", processClass: "tex2jax_process2",\ ignoreClass: "tex2jax_ignore2", processClass: "tex2jax_process2",\
},\ },\
TeX: {\ TeX: {\
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]\ extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]\
},\ },\
"SVG": {\ "SVG": {\
}\ }\
});\ });\
</script>',*/ </script>', */
// mathjaxSrc = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js', // mathjaxSrc = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js',
mathjaxSrcSecure = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG.js', mathjaxSrcSecure = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG.js',
math, math,
locationX, locationX,
locationY, locationY,
mathjaxLoaded = false, mathjaxLoaded = false,
uiStrings = svgEditor.uiStrings; uiStrings = svgEditor.uiStrings;
// TODO: Implement language support. Move these uiStrings to the locale files and the code to the langReady callback. // TODO: Implement language support. Move these uiStrings to the locale files and the code to the langReady callback.
$.extend(uiStrings, { $.extend(uiStrings, {
mathjax: { mathjax: {
embed_svg: 'Save as mathematics', embed_svg: 'Save as mathematics',
embed_mathml: 'Save as figure', embed_mathml: 'Save as figure',
svg_save_warning: 'The math will be transformed into a figure is manipulatable like everything else. You will not be able to manipulate the TeX-code anymore. ', svg_save_warning: 'The math will be transformed into a figure is manipulatable like everything else. You will not be able to manipulate the TeX-code anymore. ',
mathml_save_warning: 'Advised. The math will be saved as a figure.', mathml_save_warning: 'Advised. The math will be saved as a figure.',
title: 'Mathematics code editor' title: 'Mathematics code editor'
} }
}); });
function saveMath () {
var code = $('#mathjax_code_textarea').val();
// displaystyle to force MathJax NOT to use the inline style. Because it is
// less fancy!
MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']);
function saveMath() { /*
var code = $('#mathjax_code_textarea').val(); * The MathJax library doesn't want to bloat your webpage so it creates
// displaystyle to force MathJax NOT to use the inline style. Because it is * every symbol (glymph) you need only once. These are saved in a <svg> on
// less fancy! * the top of your html document, just under the body tag. Each glymph has
MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']); * its unique id and is saved as a <path> in the <defs> tag of the <svg>
*
* Then when the symbols are needed in the rest of your html document they
* are refferd to by a <use> tag.
* Because of bug 1076 we can't just grab the defs tag on the top and add it
* to your formula's <svg> and copy the lot. So we have to replace each
* <use> tag by it's <path>.
*/
MathJax.Hub.queue.Push(
function () {
var mathjaxMath = $('.MathJax_SVG');
var svg = $(mathjaxMath.html());
svg.find('use').each(function () {
var x, y, id, transform;
/* // TODO: find a less pragmatic and more elegant solution to this.
* The MathJax library doesn't want to bloat your webpage so it creates if ($(this).attr('href')) {
* every symbol (glymph) you need only once. These are saved in a <svg> on id = $(this).attr('href').slice(1); // Works in Chrome.
* the top of your html document, just under the body tag. Each glymph has } else {
* its unique id and is saved as a <path> in the <defs> tag of the <svg> id = $(this).attr('xlink:href').slice(1); // Works in Firefox.
* }
* Then when the symbols are needed in the rest of your html document they
* are refferd to by a <use> tag.
* Because of bug 1076 we can't just grab the defs tag on the top and add it
* to your formula's <svg> and copy the lot. So we have to replace each
* <use> tag by it's <path>.
*/
MathJax.Hub.queue.Push(
function() {
var mathjaxMath = $('.MathJax_SVG');
var svg = $(mathjaxMath.html());
svg.find('use').each(function() {
var x, y, id, transform;
// TODO: find a less pragmatic and more elegant solution to this. var glymph = $('#' + id).clone().removeAttr('id');
if ($(this).attr('href')) { x = $(this).attr('x');
id = $(this).attr('href').slice(1); // Works in Chrome. y = $(this).attr('y');
} else { transform = $(this).attr('transform');
id = $(this).attr('xlink:href').slice(1); // Works in Firefox. if (transform && (x || y)) {
} glymph.attr('transform', transform + ' translate(' + x + ',' + y + ')');
} else if (transform) {
glymph.attr('transform', transform);
} else if (x || y) {
glymph.attr('transform', 'translate(' + x + ',' + y + ')');
}
$(this).replaceWith(glymph);
});
// Remove the style tag because it interferes with SVG-Edit.
svg.removeAttr('style');
svg.attr('xmlns', 'http://www.w3.org/2000/svg');
svgCanvas.importSvgString($('<div>').append(svg.clone()).html(), true);
svgCanvas.ungroupSelectedElement();
// TODO: To undo the adding of the Formula you now have to undo twice.
// This should only be once!
svgCanvas.moveSelectedElements(locationX, locationY, true);
}
);
}
var glymph = $('#' + id).clone().removeAttr('id'); return {
x = $(this).attr('x'); name: 'MathJax',
y = $(this).attr('y'); svgicons: svgEditor.curConfig.extPath + 'mathjax-icons.xml',
transform = $(this).attr('transform'); buttons: [{
if (transform && ( x || y )) { id: 'tool_mathjax',
glymph.attr('transform', transform + ' translate(' + x + ',' + y + ')'); type: 'mode',
} title: 'Add Mathematics',
else if (transform) { events: {
glymph.attr('transform', transform); click: function () {
} // Only load Mathjax when needed, we don't want to strain Svg-Edit any more.
else if (x || y) { // From this point on it is very probable that it will be needed, so load it.
glymph.attr('transform', 'translate(' + x + ',' + y + ')'); if (mathjaxLoaded === false) {
} $('<div id="mathjax">' +
$(this).replaceWith(glymph); '<!-- Here is where MathJax creates the math -->' +
}); '<div id="mathjax_creator" class="tex2jax_process" style="display:none">' +
// Remove the style tag because it interferes with SVG-Edit. '$${}$$' +
svg.removeAttr('style'); '</div>' +
svg.attr('xmlns', 'http://www.w3.org/2000/svg'); '<div id="mathjax_overlay"></div>' +
svgCanvas.importSvgString($('<div>').append(svg.clone()).html(), true); '<div id="mathjax_container">' +
svgCanvas.ungroupSelectedElement(); '<div id="tool_mathjax_back" class="toolbar_button">' +
// TODO: To undo the adding of the Formula you now have to undo twice. '<button id="tool_mathjax_save">OK</button>' +
// This should only be once! '<button id="tool_mathjax_cancel">Cancel</button>' +
svgCanvas.moveSelectedElements(locationX, locationY, true); '</div>' +
} '<fieldset>' +
); '<legend id="mathjax_legend">Mathematics Editor</legend>' +
} '<label>' +
'<span id="mathjax_explication">Please type your mathematics in ' +
'<a href="http://en.wikipedia.org/wiki/Help:Displaying_a_formula" target="_blank">TeX</a> code.</span></label>' +
'<textarea id="mathjax_code_textarea" spellcheck="false"></textarea>' +
'</fieldset>' +
'</div>' +
'</div>'
).insertAfter('#svg_prefs').hide();
return { // Make the MathEditor draggable.
name: "MathJax", $('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'});
svgicons: svgEditor.curConfig.extPath + "mathjax-icons.xml",
buttons: [{
id: "tool_mathjax",
type: "mode",
title: "Add Mathematics",
events: {
click: function() {
// Only load Mathjax when needed, we don't want to strain Svg-Edit any more.
// From this point on it is very probable that it will be needed, so load it.
if (mathjaxLoaded === false) {
$('<div id="mathjax">\ // Add functionality and picture to cancel button.
<!-- Here is where MathJax creates the math -->\ $('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true))
<div id="mathjax_creator" class="tex2jax_process" style="display:none">\ .on('click touched', function () {
$${}$$\ $('#mathjax').hide();
</div>\ });
<div id="mathjax_overlay"></div>\
<div id="mathjax_container">\
<div id="tool_mathjax_back" class="toolbar_button">\
<button id="tool_mathjax_save">OK</button>\
<button id="tool_mathjax_cancel">Cancel</button>\
</div>\
<fieldset>\
<legend id="mathjax_legend">Mathematics Editor</legend>\
<label>\
<span id="mathjax_explication">Please type your mathematics in \
<a href="http://en.wikipedia.org/wiki/Help:Displaying_a_formula" target="_blank">TeX</a> code.</span></label>\
<textarea id="mathjax_code_textarea" spellcheck="false"></textarea>\
</fieldset>\
</div>\
</div>'
).insertAfter('#svg_prefs').hide();
// Make the MathEditor draggable. // Add functionality and picture to the save button.
$('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'}); $('#tool_mathjax_save').prepend($.getSvgIcon('ok', true))
.on('click touched', function () {
saveMath();
$('#mathjax').hide();
});
// Add functionality and picture to cancel button. // MathJax preprocessing has to ignore most of the page.
$('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true)) $('body').addClass('tex2jax_ignore');
.on("click touched", function() {
$('#mathjax').hide();
});
// Add functionality and picture to the save button. // Now get (and run) the MathJax Library.
$('#tool_mathjax_save').prepend($.getSvgIcon('ok', true)) $.getScript(mathjaxSrcSecure)
.on("click touched", function() { .done(function (script, textStatus) {
saveMath(); // When MathJax is loaded get the div where the math will be rendered.
$('#mathjax').hide(); MathJax.Hub.queue.Push(function () {
}); math = MathJax.Hub.getAllJax('#mathjax_creator')[0];
console.log(math);
mathjaxLoaded = true;
console.log('MathJax Loaded');
});
})
// If it fails.
.fail(function () {
console.log('Failed loadeing MathJax.');
$.alert('Failed loading MathJax. You will not be able to change the mathematics.');
});
}
// Set the mode.
svgCanvas.setMode('mathjax');
}
}
}],
// MathJax preprocessing has to ignore most of the page. mouseDown: function () {
$('body').addClass('tex2jax_ignore'); if (svgCanvas.getMode() === 'mathjax') {
return {started: true};
}
},
mouseUp: function (opts) {
if (svgCanvas.getMode() === 'mathjax') {
// Get the coordinates from your mouse.
var zoom = svgCanvas.getZoom();
// Get the actual coordinate by dividing by the zoom value
locationX = opts.mouse_x / zoom;
locationY = opts.mouse_y / zoom;
// Now get (and run) the MathJax Library. $('#mathjax').show();
$.getScript(mathjaxSrcSecure) return {started: false}; // Otherwise the last selected object dissapears.
.done(function(script, textStatus) { }
},
callback: function () {
$('<style>').text(
'#mathjax fieldset{' +
'padding: 5px;' +
'margin: 5px;' +
'border: 1px solid #DDD;' +
'}' +
'#mathjax label{' +
'display: block;' +
'margin: .5em;' +
'}' +
'#mathjax legend {' +
'max-width:195px;' +
'}' +
'#mathjax_overlay {' +
'position: absolute;' +
'top: 0;' +
'left: 0;' +
'right: 0;' +
'bottom: 0;' +
'background-color: black;' +
'opacity: 0.6;' +
'z-index: 20000;' +
'}' +
'#mathjax_container {' +
'position: absolute;' +
'top: 50px;' +
'padding: 10px;' +
'background-color: #B0B0B0;' +
'border: 1px outset #777;' +
'opacity: 1.0;' +
'font-family: Verdana, Helvetica, sans-serif;' +
'font-size: .8em;' +
'z-index: 20001;' +
'}' +
'#tool_mathjax_back {' +
'margin-left: 1em;' +
'overflow: auto;' +
'}' +
'#mathjax_legend{' +
'font-weight: bold;' +
'font-size:1.1em;' +
'}' +
'#mathjax_code_textarea {\\n' +
'margin: 5px .7em;' +
'overflow: hidden;' +
'width: 416px;' +
'display: block;' +
'height: 100px;' +
'}'
).appendTo('head');
// When MathJax is loaded get the div where the math will be rendered. // Add the MathJax configuration.
MathJax.Hub.queue.Push(function() { // $(mathjaxConfiguration).appendTo('head');
math = MathJax.Hub.getAllJax('#mathjax_creator')[0]; }
console.log(math); };
mathjaxLoaded = true;
console.log('MathJax Loaded');
});
})
// If it fails.
.fail(function() {
console.log("Failed loadeing MathJax.");
$.alert("Failed loading MathJax. You will not be able to change the mathematics.");
});
}
// Set the mode.
svgCanvas.setMode("mathjax");
}
}
}],
mouseDown: function() {
if (svgCanvas.getMode() === "mathjax") {
return {started: true};
}
},
mouseUp: function(opts) {
if (svgCanvas.getMode() === "mathjax") {
// Get the coordinates from your mouse.
var zoom = svgCanvas.getZoom();
// Get the actual coordinate by dividing by the zoom value
locationX = opts.mouse_x / zoom;
locationY = opts.mouse_y / zoom;
$('#mathjax').show();
return {started: false}; // Otherwise the last selected object dissapears.
}
},
callback: function() {
$('<style>').text('\
#mathjax fieldset{\
padding: 5px;\
margin: 5px;\
border: 1px solid #DDD;\
}\
#mathjax label{\
display: block;\
margin: .5em;\
}\
#mathjax legend {\
max-width:195px;\
}\
#mathjax_overlay {\
position: absolute;\
top: 0;\
left: 0;\
right: 0;\
bottom: 0;\
background-color: black;\
opacity: 0.6;\
z-index: 20000;\
}\
\
#mathjax_container {\
position: absolute;\
top: 50px;\
padding: 10px;\
background-color: #B0B0B0;\
border: 1px outset #777;\
opacity: 1.0;\
font-family: Verdana, Helvetica, sans-serif;\
font-size: .8em;\
z-index: 20001;\
}\
\
#tool_mathjax_back {\
margin-left: 1em;\
overflow: auto;\
}\
\
#mathjax_legend{\
font-weight: bold;\
font-size:1.1em;\
}\
\
#mathjax_code_textarea {\\n\
margin: 5px .7em;\
overflow: hidden;\
width: 416px;\
display: block;\
height: 100px;\
}\
').appendTo('head');
// Add the MathJax configuration.
//$(mathjaxConfiguration).appendTo('head');
}
};
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, $ */ /* eslint-disable no-var */
/*jslint es5: true, vars: true*/ /* globals svgEditor, svgedit, $ */
/* /*
* ext-overview_window.js * ext-overview_window.js
* *
@@ -10,11 +10,12 @@
*/ */
var overviewWindowGlobals = {}; var overviewWindowGlobals = {};
svgEditor.addExtension("overview_window", function() { 'use strict'; svgEditor.addExtension('overview_window', function () {
'use strict';
// Disabled in Chrome 48-, see https://github.com/SVG-Edit/svgedit/issues/26 and // Disabled in Chrome 48-, see https://github.com/SVG-Edit/svgedit/issues/26 and
// https://code.google.com/p/chromium/issues/detail?id=565120. // https://code.google.com/p/chromium/issues/detail?id=565120.
if (svgedit.browser.isChrome()) { if (svgedit.browser.isChrome()) {
var verIndex = navigator.userAgent.indexOf("Chrome/") + 7; var verIndex = navigator.userAgent.indexOf('Chrome/') + 7;
var chromeVersion = parseInt(navigator.userAgent.substring(verIndex), 10); var chromeVersion = parseInt(navigator.userAgent.substring(verIndex), 10);
if (chromeVersion < 49) { if (chromeVersion < 49) {
return; return;
@@ -22,130 +23,129 @@ svgEditor.addExtension("overview_window", function() { 'use strict';
} }
// Define and insert the base html element. // Define and insert the base html element.
var propsWindowHtml= "\ var propsWindowHtml =
<div id=\"overview_window_content_pane\" style=\" width:100%; word-wrap:break-word; display:inline-block; margin-top:20px;\">\ '<div id="overview_window_content_pane" style="width:100%; word-wrap:break-word; display:inline-block; margin-top:20px;">' +
<div id=\"overview_window_content\" style=\"position:relative; left:12px; top:0px;\">\ '<div id="overview_window_content" style="position:relative; left:12px; top:0px;">' +
<div style=\"background-color:#A0A0A0; display:inline-block; overflow:visible;\">\ '<div style="background-color:#A0A0A0; display:inline-block; overflow:visible;">' +
<svg id=\"overviewMiniView\" width=\"150\" height=\"100\" x=\"0\" y=\"0\" viewBox=\"0 0 4800 3600\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\ '<svg id="overviewMiniView" width="150" height="100" x="0" y="0" viewBox="0 0 4800 3600" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">' +
<use x=\"0\" y=\"0\" xlink:href=\"#svgroot\"> </use>\ '<use x="0" y="0" xlink:href="#svgroot"> </use>' +
</svg>\ '</svg>' +
<div id=\"overview_window_view_box\" style=\"min-width:50px; min-height:50px; position:absolute; top:30px; left:30px; z-index:5; background-color:rgba(255,0,102,0.3);\">\ '<div id="overview_window_view_box" style="min-width:50px; min-height:50px; position:absolute; top:30px; left:30px; z-index:5; background-color:rgba(255,0,102,0.3);">' +
</div>\ '</div>' +
</div>\ '</div>' +
</div>\ '</div>' +
</div>"; '</div>';
$("#sidepanels").append(propsWindowHtml); $('#sidepanels').append(propsWindowHtml);
// Define dynamic animation of the view box. // Define dynamic animation of the view box.
var updateViewBox = function(){ var updateViewBox = function () {
var portHeight=parseFloat($("#workarea").css("height")); var portHeight = parseFloat($('#workarea').css('height'));
var portWidth=parseFloat($("#workarea").css("width")); var portWidth = parseFloat($('#workarea').css('width'));
var portX=$("#workarea").scrollLeft(); var portX = $('#workarea').scrollLeft();
var portY=$("#workarea").scrollTop(); var portY = $('#workarea').scrollTop();
var windowWidth=parseFloat($("#svgcanvas").css("width")); var windowWidth = parseFloat($('#svgcanvas').css('width'));
var windowHeight=parseFloat($("#svgcanvas").css("height")); var windowHeight = parseFloat($('#svgcanvas').css('height'));
var overviewWidth=$("#overviewMiniView").attr("width"); var overviewWidth = $('#overviewMiniView').attr('width');
var overviewHeight=$("#overviewMiniView").attr("height"); var overviewHeight = $('#overviewMiniView').attr('height');
var viewBoxX=portX/windowWidth*overviewWidth; var viewBoxX = portX / windowWidth * overviewWidth;
var viewBoxY=portY/windowHeight*overviewHeight; var viewBoxY = portY / windowHeight * overviewHeight;
var viewBoxWidth=portWidth/windowWidth*overviewWidth; var viewBoxWidth = portWidth / windowWidth * overviewWidth;
var viewBoxHeight=portHeight/windowHeight*overviewHeight; var viewBoxHeight = portHeight / windowHeight * overviewHeight;
$("#overview_window_view_box").css("min-width",viewBoxWidth+"px"); $('#overview_window_view_box').css('min-width', viewBoxWidth + 'px');
$("#overview_window_view_box").css("min-height",viewBoxHeight+"px"); $('#overview_window_view_box').css('min-height', viewBoxHeight + 'px');
$("#overview_window_view_box").css("top",viewBoxY+"px"); $('#overview_window_view_box').css('top', viewBoxY + 'px');
$("#overview_window_view_box").css("left",viewBoxX+"px"); $('#overview_window_view_box').css('left', viewBoxX + 'px');
}; };
$("#workarea").scroll(function(){ $('#workarea').scroll(function () {
if(!(overviewWindowGlobals.viewBoxDragging)){ if (!(overviewWindowGlobals.viewBoxDragging)) {
updateViewBox(); updateViewBox();
} }
}); });
$("#workarea").resize(updateViewBox); $('#workarea').resize(updateViewBox);
updateViewBox(); updateViewBox();
// Compensate for changes in zoom and canvas size. // Compensate for changes in zoom and canvas size.
var updateViewDimensions= function(){ var updateViewDimensions = function () {
var viewWidth=$("#svgroot").attr("width"); var viewWidth = $('#svgroot').attr('width');
var viewHeight=$("#svgroot").attr("height"); var viewHeight = $('#svgroot').attr('height');
var viewX=640; var viewX = 640;
var viewY=480; var viewY = 480;
if(svgedit.browser.isIE()) if (svgedit.browser.isIE()) {
{
// This has only been tested with Firefox 10 and IE 9 (without chrome frame). // This has only been tested with Firefox 10 and IE 9 (without chrome frame).
// I am not sure if if is Firefox or IE that is being non compliant here. // I am not sure if if is Firefox or IE that is being non compliant here.
// Either way the one that is noncompliant may become more compliant later. // Either way the one that is noncompliant may become more compliant later.
//TAG:HACK // TAG:HACK
//TAG:VERSION_DEPENDENT // TAG:VERSION_DEPENDENT
//TAG:BROWSER_SNIFFING // TAG:BROWSER_SNIFFING
viewX=0; viewX = 0;
viewY=0; viewY = 0;
} }
var svgWidth_old=$("#overviewMiniView").attr("width"); var svgWidthOld = $('#overviewMiniView').attr('width');
var svgHeight_new=viewHeight/viewWidth*svgWidth_old; var svgHeightNew = viewHeight / viewWidth * svgWidthOld;
$("#overviewMiniView").attr("viewBox",viewX+" "+viewY+" "+viewWidth+" "+viewHeight); $('#overviewMiniView').attr('viewBox', viewX + ' ' + viewY + ' ' + viewWidth + ' ' + viewHeight);
$("#overviewMiniView").attr("height",svgHeight_new); $('#overviewMiniView').attr('height', svgHeightNew);
updateViewBox(); updateViewBox();
}; };
updateViewDimensions(); updateViewDimensions();
// Set up the overview window as a controller for the view port. // Set up the overview window as a controller for the view port.
overviewWindowGlobals.viewBoxDragging=false; overviewWindowGlobals.viewBoxDragging = false;
var updateViewPortFromViewBox = function(){ var updateViewPortFromViewBox = function () {
var windowWidth = parseFloat($('#svgcanvas').css('width'));
var windowHeight = parseFloat($('#svgcanvas').css('height'));
var overviewWidth = $('#overviewMiniView').attr('width');
var overviewHeight = $('#overviewMiniView').attr('height');
var viewBoxX = parseFloat($('#overview_window_view_box').css('left'));
var viewBoxY = parseFloat($('#overview_window_view_box').css('top'));
var windowWidth =parseFloat($("#svgcanvas").css("width" )); var portX = viewBoxX / overviewWidth * windowWidth;
var windowHeight=parseFloat($("#svgcanvas").css("height")); var portY = viewBoxY / overviewHeight * windowHeight;
var overviewWidth =$("#overviewMiniView").attr("width" );
var overviewHeight=$("#overviewMiniView").attr("height");
var viewBoxX=parseFloat($("#overview_window_view_box").css("left"));
var viewBoxY=parseFloat($("#overview_window_view_box").css("top" ));
var portX=viewBoxX/overviewWidth *windowWidth; $('#workarea').scrollLeft(portX);
var portY=viewBoxY/overviewHeight*windowHeight; $('#workarea').scrollTop(portY);
$("#workarea").scrollLeft(portX);
$("#workarea").scrollTop(portY);
}; };
$( "#overview_window_view_box" ).draggable({ containment: "parent" $('#overview_window_view_box').draggable({
,drag: updateViewPortFromViewBox containment: 'parent',
,start:function(){overviewWindowGlobals.viewBoxDragging=true; } drag: updateViewPortFromViewBox,
,stop :function(){overviewWindowGlobals.viewBoxDragging=false;} start: function () { overviewWindowGlobals.viewBoxDragging = true; },
stop: function () { overviewWindowGlobals.viewBoxDragging = false; }
}); });
$("#overviewMiniView").click(function(evt){ $('#overviewMiniView').click(function (evt) {
// Firefox doesn't support evt.offsetX and evt.offsetY. // Firefox doesn't support evt.offsetX and evt.offsetY.
var mouseX=(evt.offsetX || evt.originalEvent.layerX); var mouseX = (evt.offsetX || evt.originalEvent.layerX);
var mouseY=(evt.offsetY || evt.originalEvent.layerY); var mouseY = (evt.offsetY || evt.originalEvent.layerY);
var overviewWidth =$("#overviewMiniView").attr("width" ); var overviewWidth = $('#overviewMiniView').attr('width');
var overviewHeight=$("#overviewMiniView").attr("height"); var overviewHeight = $('#overviewMiniView').attr('height');
var viewBoxWidth =parseFloat($("#overview_window_view_box").css("min-width" )); var viewBoxWidth = parseFloat($('#overview_window_view_box').css('min-width'));
var viewBoxHeight=parseFloat($("#overview_window_view_box").css("min-height")); var viewBoxHeight = parseFloat($('#overview_window_view_box').css('min-height'));
var viewBoxX=mouseX - 0.5 * viewBoxWidth; var viewBoxX = mouseX - 0.5 * viewBoxWidth;
var viewBoxY=mouseY- 0.5 * viewBoxHeight; var viewBoxY = mouseY - 0.5 * viewBoxHeight;
//deal with constraints // deal with constraints
if(viewBoxX<0){ if (viewBoxX < 0) {
viewBoxX=0; viewBoxX = 0;
} }
if(viewBoxY<0){ if (viewBoxY < 0) {
viewBoxY=0; viewBoxY = 0;
} }
if(viewBoxX+viewBoxWidth>overviewWidth){ if (viewBoxX + viewBoxWidth > overviewWidth) {
viewBoxX=overviewWidth-viewBoxWidth; viewBoxX = overviewWidth - viewBoxWidth;
} }
if(viewBoxY+viewBoxHeight>overviewHeight){ if (viewBoxY + viewBoxHeight > overviewHeight) {
viewBoxY=overviewHeight-viewBoxHeight; viewBoxY = overviewHeight - viewBoxHeight;
} }
$("#overview_window_view_box").css("top",viewBoxY+"px"); $('#overview_window_view_box').css('top', viewBoxY + 'px');
$("#overview_window_view_box").css("left",viewBoxX+"px"); $('#overview_window_view_box').css('left', viewBoxX + 'px');
updateViewPortFromViewBox(); updateViewPortFromViewBox();
}); });
return { return {
name: "overview window", name: 'overview window',
canvasUpdated: updateViewDimensions, canvasUpdated: updateViewDimensions,
workareaResized: updateViewBox workareaResized: updateViewBox
}; };

View File

@@ -1,5 +1,4 @@
/*globals svgEditor, svgCanvas*/ /* globals svgEditor, svgCanvas */
/*jslint eqeq: true*/
/* /*
* ext-panning.js * ext-panning.js
* *
@@ -13,7 +12,8 @@
This is a very basic SVG-Edit extension to let tablet/mobile devices panning without problem This is a very basic SVG-Edit extension to let tablet/mobile devices panning without problem
*/ */
svgEditor.addExtension('ext-panning', function() {'use strict'; svgEditor.addExtension('ext-panning', function () {
'use strict';
return { return {
name: 'Extension Panning', name: 'Extension Panning',
svgicons: svgEditor.curConfig.extPath + 'ext-panning.xml', svgicons: svgEditor.curConfig.extPath + 'ext-panning.xml',
@@ -22,19 +22,19 @@ svgEditor.addExtension('ext-panning', function() {'use strict';
type: 'mode', type: 'mode',
title: 'Panning', title: 'Panning',
events: { events: {
click: function() { click: function () {
svgCanvas.setMode('ext-panning'); svgCanvas.setMode('ext-panning');
} }
} }
}], }],
mouseDown: function() { mouseDown: function () {
if (svgCanvas.getMode() == 'ext-panning') { if (svgCanvas.getMode() === 'ext-panning') {
svgEditor.setPanning(true); svgEditor.setPanning(true);
return {started: true}; return {started: true};
} }
}, },
mouseUp: function() { mouseUp: function () {
if (svgCanvas.getMode() == 'ext-panning') { if (svgCanvas.getMode() === 'ext-panning') {
svgEditor.setPanning(false); svgEditor.setPanning(false);
return { return {
keep: false, keep: false,

View File

@@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg"> <svg xmlns="http://www.w3.org/2000/svg">
<g id="ext-panning"> <g id="ext-panning">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"> <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<path fill="#7f0000" stroke="#000000" stroke-width="10" d="m1.00037,150.34581l55.30305,-55.30267l0,27.65093l22.17356,0l0,-44.21833l44.21825,0l0,-22.17357l-27.65095,0l55.30267,-55.30292l55.3035,55.30292l-27.65175,0l0,22.17357l44.21835,0l0,44.21833l22.17357,0l0,-27.65093l55.30345,55.30267l-55.30345,55.3035l0,-27.65175l-22.17357,0l0,44.21834l-44.21835,0l0,22.17355l27.65175,0l-55.3035,55.30348l-55.30267,-55.30348l27.65095,0l0,-22.17355l-44.21825,0l0,-44.21834l-22.17356,0l0,27.65175l-55.30305,-55.3035z"></path> <path fill="#7f0000" stroke="#000000" stroke-width="10" d="m1.00037,150.34581l55.30305,-55.30267l0,27.65093l22.17356,0l0,-44.21833l44.21825,0l0,-22.17357l-27.65095,0l55.30267,-55.30292l55.3035,55.30292l-27.65175,0l0,22.17357l44.21835,0l0,44.21833l22.17357,0l0,-27.65093l55.30345,55.30267l-55.30345,55.3035l0,-27.65175l-22.17357,0l0,44.21834l-44.21835,0l0,22.17355l27.65175,0l-55.3035,55.30348l-55.30267,-55.30348l27.65095,0l0,-22.17355l-44.21825,0l0,-44.21834l-22.17356,0l0,27.65175l-55.30305,-55.3035z"></path>
</svg> </svg>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 732 B

After

Width:  |  Height:  |  Size: 724 B

View File

@@ -1,22 +1,22 @@
/*globals $, svgCanvas, svgEditor*/ /* eslint-disable no-var */
/*jslint regexp:true*/ /* globals $, svgCanvas, svgEditor */
// TODO: Might add support for "exportImage" custom // TODO: Might add support for "exportImage" custom
// handler as in "ext-server_opensave.js" (and in savefile.php) // handler as in "ext-server_opensave.js" (and in savefile.php)
svgEditor.addExtension("php_savefile", { svgEditor.addExtension('php_savefile', {
callback: function() { callback: function () {
'use strict'; 'use strict';
function getFileNameFromTitle () { function getFileNameFromTitle () {
var title = svgCanvas.getDocumentTitle(); var title = svgCanvas.getDocumentTitle();
return $.trim(title); return $.trim(title);
} }
var save_svg_action = svgEditor.curConfig.extPath + 'savefile.php'; var saveSvgAction = svgEditor.curConfig.extPath + 'savefile.php';
svgEditor.setCustomHandlers({ svgEditor.setCustomHandlers({
save: function(win, data) { save: function (win, data) {
var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data,
filename = getFileNameFromTitle(); filename = getFileNameFromTitle();
$.post(save_svg_action, {output_svg: svg, filename: filename}); $.post(saveSvgAction, {output_svg: svg, filename: filename});
} }
}); });
} }

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, svgedit, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, todo: true */ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-polygon.js * ext-polygon.js
* *
@@ -8,9 +8,10 @@
* All rights reserved * All rights reserved
* *
*/ */
svgEditor.addExtension("polygon", function(S) {'use strict'; svgEditor.addExtension('polygon', function (S) {
'use strict';
var // NS = svgedit.NS, var // NS = svgedit.NS,
// svgcontent = S.svgcontent, // svgcontent = S.svgcontent,
// addElem = S.addSvgElementFromJson, // addElem = S.addSvgElementFromJson,
selElems, selElems,
@@ -18,53 +19,51 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
// svgdoc = S.svgroot.parentNode.ownerDocument, // svgdoc = S.svgroot.parentNode.ownerDocument,
// newFOG, newFOGParent, newDef, newImageName, newMaskID, modeChangeG, // newFOG, newFOGParent, newDef, newImageName, newMaskID, modeChangeG,
// edg = 0, // edg = 0,
// undoCommand = "Not image"; // undoCommand = 'Not image';
started, newFO; started, newFO;
// var ccZoom; // var ccZoom;
// var wEl, hEl; // var wEl, hEl;
// var wOffset, hOffset; // var wOffset, hOffset;
// var ccRBG; // var ccRBG;
var ccRgbEl; // var ccOpacity;
// var ccOpacity; // var brushW, brushH;
// var brushW, brushH;
var shape;
// var ccDebug = document.getElementById('debugpanel'); // var ccDebug = document.getElementById('debugpanel');
/* var properlySourceSizeTextArea = function(){ /* var properlySourceSizeTextArea = function(){
// TODO: remove magic numbers here and get values from CSS // TODO: remove magic numbers here and get values from CSS
var height = $('#svg_source_container').height() - 80; var height = $('#svg_source_container').height() - 80;
$('#svg_source_textarea').css('height', height); $('#svg_source_textarea').css('height', height);
}; */ }; */
function showPanel(on){ function showPanel (on) {
var fc_rules = $('#fc_rules'); var fcRules = $('#fc_rules');
if (!fc_rules.length) { if (!fcRules.length) {
fc_rules = $('<style id="fc_rules"></style>').appendTo('head'); fcRules = $('<style id="fc_rules"></style>').appendTo('head');
} }
fc_rules.text(!on ? "" : " #tool_topath { display: none !important; }"); fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#polygon_panel').toggle(on); $('#polygon_panel').toggle(on);
} }
/* /*
function toggleSourceButtons(on){ function toggleSourceButtons(on){
$('#tool_source_save, #tool_source_cancel').toggle(!on); $('#tool_source_save, #tool_source_cancel').toggle(!on);
$('#polygon_save, #polygon_cancel').toggle(on); $('#polygon_save, #polygon_cancel').toggle(on);
} }
*/ */
function setAttr(attr, val){ function setAttr (attr, val) {
svgCanvas.changeSelectedAttribute(attr, val); svgCanvas.changeSelectedAttribute(attr, val);
S.call("changed", selElems); S.call('changed', selElems);
} }
function cot(n){ function cot (n) {
return 1 / Math.tan(n); return 1 / Math.tan(n);
} }
function sec(n){ function sec (n) {
return 1 / Math.cos(n); return 1 / Math.cos(n);
} }
/** /**
* Obtained from http://code.google.com/p/passenger-top/source/browse/instiki/public/svg-edit/editor/extensions/ext-itex.js?r=3 * Obtained from http://code.google.com/p/passenger-top/source/browse/instiki/public/svg-edit/editor/extensions/ext-itex.js?r=3
@@ -95,13 +94,13 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
$.post(ajaxEndpoint, {'tex': tex, 'display': 'inline'}, function(data){ $.post(ajaxEndpoint, {'tex': tex, 'display': 'inline'}, function(data){
var children = data.documentElement.childNodes; var children = data.documentElement.childNodes;
while (children.length > 0) { while (children.length > 0) {
mrow.appendChild(svgdoc.adoptNode(children[0], true)); mrow.appendChild(svgdoc.adoptNode(children[0], true));
} }
S.sanitizeSvg(math); S.sanitizeSvg(math);
S.call("changed", [elt]); S.call('changed', [elt]);
}); });
elt.replaceChild(math, elt.firstChild); elt.replaceChild(math, elt.firstChild);
S.call("changed", [elt]); S.call('changed', [elt]);
svgCanvas.clearSelection(); svgCanvas.clearSelection();
} catch(e) { } catch(e) {
console.log(e); console.log(e);
@@ -111,184 +110,177 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
return true; return true;
} }
*/ */
return { return {
name: "polygon", name: 'polygon',
svgicons: svgEditor.curConfig.extPath + "polygon-icons.svg", svgicons: svgEditor.curConfig.extPath + 'polygon-icons.svg',
buttons: [{ buttons: [{
id: "tool_polygon", id: 'tool_polygon',
type: "mode", type: 'mode',
title: "Polygon Tool", title: 'Polygon Tool',
position: 11, position: 11,
events: { events: {
'click': function(){ 'click': function () {
svgCanvas.setMode('polygon'); svgCanvas.setMode('polygon');
showPanel(true); showPanel(true);
} }
} }
}], }],
context_tools: [{ context_tools: [{
type: "input", type: 'input',
panel: "polygon_panel", panel: 'polygon_panel',
title: "Number of Sides", title: 'Number of Sides',
id: "polySides", id: 'polySides',
label: "sides", label: 'sides',
size: 3, size: 3,
defval: 5, defval: 5,
events: { events: {
change: function(){ change: function () {
setAttr('sides', this.value); setAttr('sides', this.value);
} }
} }
}], }],
callback: function(){ callback: function () {
$('#polygon_panel').hide();
$('#polygon_panel').hide(); var endChanges = function () {
};
var endChanges = function(){ // TODO: Needs to be done after orig icon loads
}; setTimeout(function () {
// Create source save/cancel buttons
// TODO: Needs to be done after orig icon loads /* var save = */ $('#tool_source_save').clone().hide().attr('id', 'polygon_save').unbind().appendTo('#tool_source_back').click(function () {
setTimeout(function(){ if (!editingitex) {
// Create source save/cancel buttons
var save = $('#tool_source_save').clone().hide().attr('id', 'polygon_save').unbind().appendTo("#tool_source_back").click(function(){
if (!editingitex) {
return; return;
} }
// Todo: Uncomment the setItexString() function above and handle ajaxEndpoint? // Todo: Uncomment the setItexString() function above and handle ajaxEndpoint?
if (!setItexString($('#svg_source_textarea').val())) { /*
$.confirm("Errors found. Revert to original?", function(ok){ if (!setItexString($('#svg_source_textarea').val())) {
if (!ok) { $.confirm('Errors found. Revert to original?', function (ok) {
if (!ok) {
return false; return false;
} }
endChanges(); endChanges();
}); });
} } else { */
else { endChanges();
endChanges(); // }
} // setSelectMode();
// setSelectMode(); });
});
var cancel = $('#tool_source_cancel').clone().hide().attr('id', 'polygon_cancel').unbind().appendTo("#tool_source_back").click(function(){ /* var cancel = */ $('#tool_source_cancel').clone().hide().attr('id', 'polygon_cancel').unbind().appendTo('#tool_source_back').click(function () {
endChanges(); endChanges();
}); });
}, 3000);
},
mouseDown: function (opts) {
// var e = opts.event;
var rgb = svgCanvas.getColor('fill');
// var ccRgbEl = rgb.substring(1, rgb.length);
var sRgb = svgCanvas.getColor('stroke');
// ccSRgbEl = sRgb.substring(1, rgb.length);
var sWidth = svgCanvas.getStrokeWidth();
}, 3000); if (svgCanvas.getMode() === 'polygon') {
}, started = true;
mouseDown: function(opts){
// var e = opts.event;
var rgb = svgCanvas.getColor("fill");
ccRgbEl = rgb.substring(1, rgb.length);
var sRgb = svgCanvas.getColor("stroke");
// ccSRgbEl = sRgb.substring(1, rgb.length);
var sWidth = svgCanvas.getStrokeWidth();
if (svgCanvas.getMode() == "polygon") { newFO = S.addSvgElementFromJson({
started = true; 'element': 'polygon',
'attr': {
'cx': opts.start_x,
'cy': opts.start_y,
'id': S.getNextId(),
'shape': 'regularPoly',
'sides': document.getElementById('polySides').value,
'orient': 'x',
'edge': 0,
'fill': rgb,
'strokecolor': sRgb,
'strokeWidth': sWidth
}
});
newFO = S.addSvgElementFromJson({ return {
"element": "polygon", started: true
"attr": { };
"cx": opts.start_x,
"cy": opts.start_y,
"id": S.getNextId(),
"shape": "regularPoly",
"sides": document.getElementById("polySides").value,
"orient": "x",
"edge": 0,
"fill": rgb,
"strokecolor": sRgb,
"strokeWidth": sWidth
}
});
return {
started: true
};
}
},
mouseMove: function(opts){
if (!started) {
return;
} }
if (svgCanvas.getMode() == "polygon") { },
// var e = opts.event; mouseMove: function (opts) {
var x = opts.mouse_x; if (!started) {
var y = opts.mouse_y; return;
var c = $(newFO).attr(["cx", "cy", "sides", "orient", "fill", "strokecolor", "strokeWidth"]); }
var cx = c.cx, cy = c.cy, fill = c.fill, strokecolor = c.strokecolor, strokewidth = c.strokeWidth, sides = c.sides, if (svgCanvas.getMode() === 'polygon') {
// var e = opts.event;
var x = opts.mouse_x;
var y = opts.mouse_y;
var c = $(newFO).attr(['cx', 'cy', 'sides', 'orient', 'fill', 'strokecolor', 'strokeWidth']);
var cx = c.cx, cy = c.cy, fill = c.fill, strokecolor = c.strokecolor, strokewidth = c.strokeWidth, sides = c.sides,
// orient = c.orient, // orient = c.orient,
edg = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5; edg = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5;
newFO.setAttributeNS(null, "edge", edg); newFO.setAttributeNS(null, 'edge', edg);
var inradius = (edg / 2) * cot(Math.PI / sides); var inradius = (edg / 2) * cot(Math.PI / sides);
var circumradius = inradius * sec(Math.PI / sides); var circumradius = inradius * sec(Math.PI / sides);
var points = ''; var points = '';
var s; var s;
for (s = 0; sides >= s; s++) { for (s = 0; sides >= s; s++) {
var angle = 2.0 * Math.PI * s / sides; var angle = 2.0 * Math.PI * s / sides;
x = (circumradius * Math.cos(angle)) + cx; x = (circumradius * Math.cos(angle)) + cx;
y = (circumradius * Math.sin(angle)) + cy; y = (circumradius * Math.sin(angle)) + cy;
points += x + ',' + y + ' '; points += x + ',' + y + ' ';
} }
//var poly = newFO.createElementNS(NS.SVG, 'polygon'); // var poly = newFO.createElementNS(NS.SVG, 'polygon');
newFO.setAttributeNS(null, 'points', points); newFO.setAttributeNS(null, 'points', points);
newFO.setAttributeNS(null, 'fill', fill); newFO.setAttributeNS(null, 'fill', fill);
newFO.setAttributeNS(null, 'stroke', strokecolor); newFO.setAttributeNS(null, 'stroke', strokecolor);
newFO.setAttributeNS(null, 'stroke-width', strokewidth); newFO.setAttributeNS(null, 'stroke-width', strokewidth);
// newFO.setAttributeNS(null, 'transform', "rotate(-90)"); // newFO.setAttributeNS(null, 'transform', 'rotate(-90)');
shape = newFO.getAttributeNS(null, 'shape'); // var shape = newFO.getAttributeNS(null, 'shape');
//newFO.appendChild(poly); // newFO.appendChild(poly);
//DrawPoly(cx, cy, sides, edg, orient); // DrawPoly(cx, cy, sides, edg, orient);
return { return {
started: true started: true
}; };
} }
},
}, mouseUp: function (opts) {
if (svgCanvas.getMode() === 'polygon') {
var attrs = $(newFO).attr('edge');
var keep = (attrs.edge !== '0');
// svgCanvas.addToSelection([newFO], true);
return {
keep: keep,
element: newFO
};
}
},
selectedChanged: function (opts) {
// Use this to update the current selected elements
selElems = opts.elems;
mouseUp: function(opts){ var i = selElems.length;
if (svgCanvas.getMode() == "polygon") {
var attrs = $(newFO).attr("edge");
var keep = (attrs.edge != 0);
// svgCanvas.addToSelection([newFO], true);
return {
keep: keep,
element: newFO
};
}
}, while (i--) {
selectedChanged: function(opts){ var elem = selElems[i];
// Use this to update the current selected elements if (elem && elem.getAttributeNS(null, 'shape') === 'regularPoly') {
selElems = opts.elems; if (opts.selectedElement && !opts.multiselected) {
$('#polySides').val(elem.getAttribute('sides'));
var i = selElems.length; showPanel(true);
} else {
while (i--) { showPanel(false);
var elem = selElems[i]; }
if (elem && elem.getAttributeNS(null, 'shape') === 'regularPoly') { } else {
if (opts.selectedElement && !opts.multiselected) { showPanel(false);
$('#polySides').val(elem.getAttribute("sides")); }
}
showPanel(true); },
} elementChanged: function (opts) {
else { // var elem = opts.elems[0];
showPanel(false); }
} };
}
else {
showPanel(false);
}
}
},
elementChanged: function(opts){
// var elem = opts.elems[0];
}
};
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, svgCanvas, canvg, $, top*/ /* eslint-disable no-var */
/*jslint vars: true*/ /* globals svgEditor, svgedit, svgCanvas, canvg, $, top */
/* /*
* ext-server_moinsave.js * ext-server_moinsave.js
* *
@@ -12,48 +12,47 @@
* *
*/ */
svgEditor.addExtension("server_opensave", { svgEditor.addExtension('server_opensave', {
callback: function() {'use strict'; callback: function () {
'use strict';
var Utils = svgedit.utilities; var Utils = svgedit.utilities;
var save_svg_action = '/+modify'; var saveSvgAction = '/+modify';
// Create upload target (hidden iframe) // Create upload target (hidden iframe)
var target = $('<iframe name="output_frame" src="#"/>').hide().appendTo('body'); /* var target = */ $('<iframe name="output_frame" src="#"/>').hide().appendTo('body');
svgEditor.setCustomHandlers({ svgEditor.setCustomHandlers({
save: function(win, data) { save: function (win, data) {
var svg = "<?xml version=\"1.0\"?>\n" + data; var svg = '<?xml version="1.0"?>\n' + data;
var qstr = $.param.querystring(); var qstr = $.param.querystring();
var name = qstr.substr(9).split('/+get/')[1]; var name = qstr.substr(9).split('/+get/')[1];
var svg_data = Utils.encode64(svg); var svgData = Utils.encode64(svg);
if(!$('#export_canvas').length) { if (!$('#export_canvas').length) {
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
} }
var c = $('#export_canvas')[0]; var c = $('#export_canvas')[0];
c.width = svgCanvas.contentW; c.width = svgCanvas.contentW;
c.height = svgCanvas.contentH; c.height = svgCanvas.contentH;
Utils.buildCanvgCallback(function () { Utils.buildCanvgCallback(function () {
canvg(c, svg, {renderCallback: function() { canvg(c, svg, {renderCallback: function () {
var datauri = c.toDataURL('image/png'); var datauri = c.toDataURL('image/png');
// var uiStrings = svgEditor.uiStrings; // var uiStrings = svgEditor.uiStrings;
var png_data = Utils.encode64(datauri); // Brett: This encoding seems unnecessary var pngData = Utils.encode64(datauri); // Brett: This encoding seems unnecessary
var form = $('<form>').attr({ /* var form = */ $('<form>').attr({
method: 'post', method: 'post',
action: save_svg_action + '/' + name, action: saveSvgAction + '/' + name,
target: 'output_frame' target: 'output_frame'
}).append('<input type="hidden" name="png_data" value="' + png_data + '">') }).append('<input type="hidden" name="png_data" value="' + pngData + '">')
.append('<input type="hidden" name="filepath" value="' + svg_data + '">') .append('<input type="hidden" name="filepath" value="' + svgData + '">')
.append('<input type="hidden" name="filename" value="' + 'drawing.svg">') .append('<input type="hidden" name="filename" value="' + 'drawing.svg">')
.append('<input type="hidden" name="contenttype" value="application/x-svgdraw">') .append('<input type="hidden" name="contenttype" value="application/x-svgdraw">')
.appendTo('body') .appendTo('body')
.submit().remove(); .submit().remove();
}}); }});
})(); })();
alert("Saved! Return to Item View!"); alert('Saved! Return to Item View!');
top.window.location = '/'+name; top.window.location = '/' + name;
} }
}); });
} }
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, svgCanvas, canvg, $*/ /* eslint-disable no-var */
/*jslint eqeq: true, browser:true*/ /* globals svgEditor, svgedit, svgCanvas, canvg, $ */
/* /*
* ext-server_opensave.js * ext-server_opensave.js
* *
@@ -9,15 +9,15 @@
* *
*/ */
svgEditor.addExtension("server_opensave", { svgEditor.addExtension('server_opensave', {
callback: function() { callback: function () {
'use strict'; 'use strict';
function getFileNameFromTitle () { function getFileNameFromTitle () {
var title = svgCanvas.getDocumentTitle(); var title = svgCanvas.getDocumentTitle();
// We convert (to underscore) only those disallowed Win7 file name characters // We convert (to underscore) only those disallowed Win7 file name characters
return $.trim(title).replace(/[\/\\:*?"<>|]/g, '_'); return $.trim(title).replace(/[/\\:*?"<>|]/g, '_');
} }
function xhtmlEscape(str) { function xhtmlEscape (str) {
return str.replace(/&(?!amp;)/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;'); // < is actually disallowed above anyways return str.replace(/&(?!amp;)/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;'); // < is actually disallowed above anyways
} }
function clientDownloadSupport (filename, suffix, uri) { function clientDownloadSupport (filename, suffix, uri) {
@@ -29,17 +29,17 @@ svgEditor.addExtension("server_opensave", {
return true; return true;
} }
} }
var open_svg_action, import_svg_action, import_img_action, var openSvgAction, importSvgAction, importImgAction,
open_svg_form, import_svg_form, import_img_form, openSvgForm, importSvgForm, importImgForm,
save_svg_action = svgEditor.curConfig.extPath + 'filesave.php', saveSvgAction = svgEditor.curConfig.extPath + 'filesave.php',
save_img_action = svgEditor.curConfig.extPath + 'filesave.php', saveImgAction = svgEditor.curConfig.extPath + 'filesave.php',
// Create upload target (hidden iframe) // Create upload target (hidden iframe)
cancelled = false, cancelled = false,
Utils = svgedit.utilities; Utils = svgedit.utilities;
$('<iframe name="output_frame" src="#"/>').hide().appendTo('body'); $('<iframe name="output_frame" src="#"/>').hide().appendTo('body');
svgEditor.setCustomHandlers({ svgEditor.setCustomHandlers({
save: function(win, data) { save: function (win, data) {
var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, // Firefox doesn't seem to know it is UTF-8 (no matter whether we use or skip the clientDownload code) despite the Content-Disposition header containing UTF-8, but adding the encoding works var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data, // Firefox doesn't seem to know it is UTF-8 (no matter whether we use or skip the clientDownload code) despite the Content-Disposition header containing UTF-8, but adding the encoding works
filename = getFileNameFromTitle(); filename = getFileNameFromTitle();
@@ -49,7 +49,7 @@ svgEditor.addExtension("server_opensave", {
$('<form>').attr({ $('<form>').attr({
method: 'post', method: 'post',
action: save_svg_action, action: saveSvgAction,
target: 'output_frame' target: 'output_frame'
}).append('<input type="hidden" name="output_svg" value="' + xhtmlEscape(svg) + '">') }).append('<input type="hidden" name="output_svg" value="' + xhtmlEscape(svg) + '">')
.append('<input type="hidden" name="filename" value="' + xhtmlEscape(filename) + '">') .append('<input type="hidden" name="filename" value="' + xhtmlEscape(filename) + '">')
@@ -64,7 +64,7 @@ svgEditor.addExtension("server_opensave", {
} }
$('<form>').attr({ $('<form>').attr({
method: 'post', method: 'post',
action: save_img_action, action: saveImgAction,
target: 'output_frame' target: 'output_frame'
}).append('<input type="hidden" name="output_img" value="' + datauri + '">') }).append('<input type="hidden" name="output_img" value="' + datauri + '">')
.append('<input type="hidden" name="mime" value="application/pdf">') .append('<input type="hidden" name="mime" value="application/pdf">')
@@ -73,13 +73,13 @@ svgEditor.addExtension("server_opensave", {
.submit().remove(); .submit().remove();
}, },
// Todo: Integrate this extension with a new built-in exportWindowType, "download" // Todo: Integrate this extension with a new built-in exportWindowType, "download"
exportImage: function(win, data) { exportImage: function (win, data) {
var c, var c,
issues = data.issues, issues = data.issues,
mimeType = data.mimeType, mimeType = data.mimeType,
quality = data.quality; quality = data.quality;
if(!$('#export_canvas').length) { if (!$('#export_canvas').length) {
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
} }
c = $('#export_canvas')[0]; c = $('#export_canvas')[0];
@@ -87,7 +87,7 @@ svgEditor.addExtension("server_opensave", {
c.width = svgCanvas.contentW; c.width = svgCanvas.contentW;
c.height = svgCanvas.contentH; c.height = svgCanvas.contentH;
Utils.buildCanvgCallback(function () { Utils.buildCanvgCallback(function () {
canvg(c, data.svg, {renderCallback: function() { canvg(c, data.svg, {renderCallback: function () {
var pre, filename, suffix, var pre, filename, suffix,
datauri = quality ? c.toDataURL(mimeType, quality) : c.toDataURL(mimeType), datauri = quality ? c.toDataURL(mimeType, quality) : c.toDataURL(mimeType),
// uiStrings = svgEditor.uiStrings, // uiStrings = svgEditor.uiStrings,
@@ -95,11 +95,11 @@ svgEditor.addExtension("server_opensave", {
// Check if there are issues // Check if there are issues
if (issues.length) { if (issues.length) {
pre = "\n \u2022 "; pre = '\n \u2022 ';
note += ("\n\n" + pre + issues.join(pre)); note += ('\n\n' + pre + issues.join(pre));
} }
if(note.length) { if (note.length) {
alert(note); alert(note);
} }
@@ -112,7 +112,7 @@ svgEditor.addExtension("server_opensave", {
$('<form>').attr({ $('<form>').attr({
method: 'post', method: 'post',
action: save_img_action, action: saveImgAction,
target: 'output_frame' target: 'output_frame'
}).append('<input type="hidden" name="output_img" value="' + datauri + '">') }).append('<input type="hidden" name="output_img" value="' + datauri + '">')
.append('<input type="hidden" name="mime" value="' + mimeType + '">') .append('<input type="hidden" name="mime" value="' + mimeType + '">')
@@ -125,15 +125,15 @@ svgEditor.addExtension("server_opensave", {
}); });
// Do nothing if client support is found // Do nothing if client support is found
if (window.FileReader) {return;} if (window.FileReader) { return; }
// Change these to appropriate script file // Change these to appropriate script file
open_svg_action = svgEditor.curConfig.extPath + 'fileopen.php?type=load_svg'; openSvgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=load_svg';
import_svg_action = svgEditor.curConfig.extPath + 'fileopen.php?type=import_svg'; importSvgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=import_svg';
import_img_action = svgEditor.curConfig.extPath + 'fileopen.php?type=import_img'; importImgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=import_img';
// Set up function for PHP uploader to use // Set up function for PHP uploader to use
svgEditor.processFile = function(str64, type) { svgEditor.processFile = function (str64, type) {
var xmlstr; var xmlstr;
if (cancelled) { if (cancelled) {
cancelled = false; cancelled = false;
@@ -147,59 +147,58 @@ svgEditor.addExtension("server_opensave", {
} }
switch (type) { switch (type) {
case 'load_svg': case 'load_svg':
svgCanvas.clear(); svgCanvas.clear();
svgCanvas.setSvgString(xmlstr); svgCanvas.setSvgString(xmlstr);
svgEditor.updateCanvas(); svgEditor.updateCanvas();
break; break;
case 'import_svg': case 'import_svg':
svgCanvas.importSvgString(xmlstr); svgCanvas.importSvgString(xmlstr);
svgEditor.updateCanvas(); svgEditor.updateCanvas();
break; break;
case 'import_img': case 'import_img':
svgCanvas.setGoodImage(str64); svgCanvas.setGoodImage(str64);
break; break;
} }
}; };
// Create upload form // Create upload form
open_svg_form = $('<form>'); openSvgForm = $('<form>');
open_svg_form.attr({ openSvgForm.attr({
enctype: 'multipart/form-data', enctype: 'multipart/form-data',
method: 'post', method: 'post',
action: open_svg_action, action: openSvgAction,
target: 'output_frame' target: 'output_frame'
}); });
// Create import form // Create import form
import_svg_form = open_svg_form.clone().attr('action', import_svg_action); importSvgForm = openSvgForm.clone().attr('action', importSvgAction);
// Create image form // Create image form
import_img_form = open_svg_form.clone().attr('action', import_img_action); importImgForm = openSvgForm.clone().attr('action', importImgAction);
// It appears necessary to rebuild this input every time a file is // It appears necessary to rebuild this input every time a file is
// selected so the same file can be picked and the change event can fire. // selected so the same file can be picked and the change event can fire.
function rebuildInput(form) { function rebuildInput (form) {
form.empty(); form.empty();
var inp = $('<input type="file" name="svg_file">').appendTo(form); var inp = $('<input type="file" name="svg_file">').appendTo(form);
function submit () {
function submit() {
// This submits the form, which returns the file data using svgEditor.processFile() // This submits the form, which returns the file data using svgEditor.processFile()
form.submit(); form.submit();
rebuildInput(form); rebuildInput(form);
$.process_cancel("Uploading...", function() { $.process_cancel('Uploading...', function () {
cancelled = true; cancelled = true;
$('#dialog_box').hide(); $('#dialog_box').hide();
}); });
} }
if(form[0] == open_svg_form[0]) { if (form[0] === openSvgForm[0]) {
inp.change(function() { inp.change(function () {
// This takes care of the "are you sure" dialog box // This takes care of the "are you sure" dialog box
svgEditor.openPrep(function(ok) { svgEditor.openPrep(function (ok) {
if(!ok) { if (!ok) {
rebuildInput(form); rebuildInput(form);
return; return;
} }
@@ -207,7 +206,7 @@ svgEditor.addExtension("server_opensave", {
}); });
}); });
} else { } else {
inp.change(function() { inp.change(function () {
// This submits the form, which returns the file data using svgEditor.processFile() // This submits the form, which returns the file data using svgEditor.processFile()
submit(); submit();
}); });
@@ -215,14 +214,13 @@ svgEditor.addExtension("server_opensave", {
} }
// Create the input elements // Create the input elements
rebuildInput(open_svg_form); rebuildInput(openSvgForm);
rebuildInput(import_svg_form); rebuildInput(importSvgForm);
rebuildInput(import_img_form); rebuildInput(importImgForm);
// Add forms to buttons // Add forms to buttons
$("#tool_open").show().prepend(open_svg_form); $('#tool_open').show().prepend(openSvgForm);
$("#tool_import").show().prepend(import_svg_form); $('#tool_import').show().prepend(importSvgForm);
$("#tool_image").prepend(import_img_form); $('#tool_image').prepend(importImgForm);
} }
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, $, DOMParser*/ /* eslint-disable no-var */
/*jslint es5: true, vars: true, eqeq: true*/ /* globals svgEditor, $, DOMParser */
/* /*
* ext-shapes.js * ext-shapes.js
* *
@@ -10,11 +10,12 @@
* *
*/ */
svgEditor.addExtension('shapes', function() {'use strict'; svgEditor.addExtension('shapes', function () {
var current_d, cur_shape_id; 'use strict';
var currentD, curShapeId;
var canv = svgEditor.canvas; var canv = svgEditor.canvas;
var cur_shape; var curShape;
var start_x, start_y; var startX, startY;
var svgroot = canv.getRootElem(); var svgroot = canv.getRootElem();
var lastBBox = {}; var lastBBox = {};
@@ -73,67 +74,66 @@ svgEditor.addExtension('shapes', function() {'use strict';
} }
}; };
var cur_lib = library.basic; var curLib = library.basic;
var mode_id = 'shapelib'; var modeId = 'shapelib';
var startClientPos = {}; var startClientPos = {};
function loadIcons() { function loadIcons () {
$('#shape_buttons').empty().append(cur_lib.buttons); $('#shape_buttons').empty().append(curLib.buttons);
} }
function makeButtons(cat, shapes) { function makeButtons (cat, shapes) {
var size = cur_lib.size || 300; var size = curLib.size || 300;
var fill = cur_lib.fill || false; var fill = curLib.fill || false;
var off = size * 0.05; var off = size * 0.05;
var vb = [-off, -off, size + off*2, size + off*2].join(' '); var vb = [-off, -off, size + off * 2, size + off * 2].join(' ');
var stroke = fill ? 0: (size/30); var stroke = fill ? 0 : (size / 30);
var shape_icon = new DOMParser().parseFromString( var shapeIcon = new DOMParser().parseFromString(
'<svg xmlns="http://www.w3.org/2000/svg"><svg viewBox="' + vb + '"><path fill="'+(fill?'#333':'none')+'" stroke="#000" stroke-width="' + stroke + '" /></svg></svg>', '<svg xmlns="http://www.w3.org/2000/svg"><svg viewBox="' + vb + '"><path fill="' + (fill ? '#333' : 'none') + '" stroke="#000" stroke-width="' + stroke + '" /></svg></svg>',
'text/xml'); 'text/xml');
var width = 24; var width = 24;
var height = 24; var height = 24;
shape_icon.documentElement.setAttribute('width', width); shapeIcon.documentElement.setAttribute('width', width);
shape_icon.documentElement.setAttribute('height', height); shapeIcon.documentElement.setAttribute('height', height);
var svg_elem = $(document.importNode(shape_icon.documentElement,true)); var svgElem = $(document.importNode(shapeIcon.documentElement, true));
var data = shapes.data; var data = shapes.data;
cur_lib.buttons = []; curLib.buttons = [];
var id; var id;
for (id in data) { for (id in data) {
var path_d = data[id]; var pathD = data[id];
var icon = svg_elem.clone(); var icon = svgElem.clone();
icon.find('path').attr('d', path_d); icon.find('path').attr('d', pathD);
var icon_btn = icon.wrap('<div class="tool_button">').parent().attr({ var iconBtn = icon.wrap('<div class="tool_button">').parent().attr({
id: mode_id + '_' + id, id: modeId + '_' + id,
title: id title: id
}); });
// Store for later use // Store for later use
cur_lib.buttons.push(icon_btn[0]); curLib.buttons.push(iconBtn[0]);
} }
} }
function loadLibrary(cat_id) { function loadLibrary (catId) {
var lib = library[catId];
var lib = library[cat_id];
if (!lib) { if (!lib) {
$('#shape_buttons').html('Loading...'); $('#shape_buttons').html('Loading...');
$.getJSON(svgEditor.curConfig.extPath + 'shapelib/' + cat_id + '.json', function(result) { $.getJSON(svgEditor.curConfig.extPath + 'shapelib/' + catId + '.json', function (result) {
cur_lib = library[cat_id] = { curLib = library[catId] = {
data: result.data, data: result.data,
size: result.size, size: result.size,
fill: result.fill fill: result.fill
}; };
makeButtons(cat_id, result); makeButtons(catId, result);
loadIcons(); loadIcons();
}); });
return; return;
} }
cur_lib = lib; curLib = lib;
if (!lib.buttons.length) {makeButtons(cat_id, lib);} if (!lib.buttons.length) { makeButtons(catId, lib); }
loadIcons(); loadIcons();
} }
@@ -145,53 +145,52 @@ svgEditor.addExtension('shapes', function() {'use strict';
position: 6, position: 6,
title: 'Shape library', title: 'Shape library',
events: { events: {
click: function() { click: function () {
canv.setMode(mode_id); canv.setMode(modeId);
} }
} }
}], }],
callback: function() { callback: function () {
$('<style>').text('\ $('<style>').text(
#shape_buttons {\ '#shape_buttons {' +
overflow: auto;\ 'overflow: auto;' +
width: 180px;\ 'width: 180px;' +
max-height: 300px;\ 'max-height: 300px;' +
display: table-cell;\ 'display: table-cell;' +
vertical-align: middle;\ 'vertical-align: middle;' +
}\ '}' +
\ '#shape_cats {' +
#shape_cats {\ 'min-width: 110px;' +
min-width: 110px;\ 'display: table-cell;' +
display: table-cell;\ 'vertical-align: middle;' +
vertical-align: middle;\ 'height: 300px;' +
height: 300px;\ '}' +
}\ '#shape_cats > div {' +
#shape_cats > div {\ 'line-height: 1em;' +
line-height: 1em;\ 'padding: .5em;' +
padding: .5em;\ 'border:1px solid #B0B0B0;' +
border:1px solid #B0B0B0;\ 'background: #E8E8E8;' +
background: #E8E8E8;\ 'margin-bottom: -1px;' +
margin-bottom: -1px;\ '}' +
}\ '#shape_cats div:hover {' +
#shape_cats div:hover {\ 'background: #FFFFCC;' +
background: #FFFFCC;\ '}' +
}\ '#shape_cats div.current {' +
#shape_cats div.current {\ 'font-weight: bold;' +
font-weight: bold;\ '}').appendTo('head');
}').appendTo('head');
var btn_div = $('<div id="shape_buttons">'); var btnDiv = $('<div id="shape_buttons">');
$('#tools_shapelib > *').wrapAll(btn_div); $('#tools_shapelib > *').wrapAll(btnDiv);
var shower = $('#tools_shapelib_show'); var shower = $('#tools_shapelib_show');
loadLibrary('basic'); loadLibrary('basic');
// Do mouseup on parent element rather than each button // Do mouseup on parent element rather than each button
$('#shape_buttons').mouseup(function(evt) { $('#shape_buttons').mouseup(function (evt) {
var btn = $(evt.target).closest('div.tool_button'); var btn = $(evt.target).closest('div.tool_button');
if (!btn.length) {return;} if (!btn.length) { return; }
var copy = btn.children().clone(); var copy = btn.children().clone();
shower.children(':not(.flyout_arrow_horiz)').remove(); shower.children(':not(.flyout_arrow_horiz)').remove();
@@ -199,22 +198,22 @@ svgEditor.addExtension('shapes', function() {'use strict';
.append(copy) .append(copy)
.attr('data-curopt', '#' + btn[0].id) // This sets the current mode .attr('data-curopt', '#' + btn[0].id) // This sets the current mode
.mouseup(); .mouseup();
canv.setMode(mode_id); canv.setMode(modeId);
cur_shape_id = btn[0].id.substr((mode_id+'_').length); curShapeId = btn[0].id.substr((modeId + '_').length);
current_d = cur_lib.data[cur_shape_id]; currentD = curLib.data[curShapeId];
$('.tools_flyout').fadeOut(); $('.tools_flyout').fadeOut();
}); });
var shape_cats = $('<div id="shape_cats">'); var shapeCats = $('<div id="shape_cats">');
var cat_str = ''; var catStr = '';
$.each(categories, function(id, label) { $.each(categories, function (id, label) {
cat_str += '<div data-cat=' + id + '>' + label + '</div>'; catStr += '<div data-cat=' + id + '>' + label + '</div>';
}); });
shape_cats.html(cat_str).children().bind('mouseup', function() { shapeCats.html(catStr).children().bind('mouseup', function () {
var catlink = $(this); var catlink = $(this);
catlink.siblings().removeClass('current'); catlink.siblings().removeClass('current');
catlink.addClass('current'); catlink.addClass('current');
@@ -224,134 +223,133 @@ svgEditor.addExtension('shapes', function() {'use strict';
return false; return false;
}); });
shape_cats.children().eq(0).addClass('current'); shapeCats.children().eq(0).addClass('current');
$('#tools_shapelib').append(shape_cats); $('#tools_shapelib').append(shapeCats);
shower.mouseup(function() { shower.mouseup(function () {
canv.setMode(current_d ? mode_id : 'select'); canv.setMode(currentD ? modeId : 'select');
}); });
$('#tool_shapelib').remove(); $('#tool_shapelib').remove();
var h = $('#tools_shapelib').height(); var h = $('#tools_shapelib').height();
$('#tools_shapelib').css({ $('#tools_shapelib').css({
'margin-top': -(h/2 - 15), 'margin-top': -(h / 2 - 15),
'margin-left': 3 'margin-left': 3
}); });
}, },
mouseDown: function(opts) { mouseDown: function (opts) {
var mode = canv.getMode(); var mode = canv.getMode();
if (mode !== mode_id) {return;} if (mode !== modeId) { return; }
start_x = opts.start_x; startX = opts.start_x;
var x = start_x; var x = startX;
start_y = opts.start_y; startY = opts.start_y;
var y = start_y; var y = startY;
var cur_style = canv.getStyle(); var curStyle = canv.getStyle();
startClientPos.x = opts.event.clientX; startClientPos.x = opts.event.clientX;
startClientPos.y = opts.event.clientY; startClientPos.y = opts.event.clientY;
cur_shape = canv.addSvgElementFromJson({ curShape = canv.addSvgElementFromJson({
'element': 'path', 'element': 'path',
'curStyles': true, 'curStyles': true,
'attr': { 'attr': {
'd': current_d, 'd': currentD,
'id': canv.getNextId(), 'id': canv.getNextId(),
'opacity': cur_style.opacity / 2, 'opacity': curStyle.opacity / 2,
'style': 'pointer-events:none' 'style': 'pointer-events:none'
} }
}); });
// Make sure shape uses absolute values // Make sure shape uses absolute values
if (/[a-z]/.test(current_d)) { if (/[a-z]/.test(currentD)) {
current_d = cur_lib.data[cur_shape_id] = canv.pathActions.convertPath(cur_shape); currentD = curLib.data[curShapeId] = canv.pathActions.convertPath(curShape);
cur_shape.setAttribute('d', current_d); curShape.setAttribute('d', currentD);
canv.pathActions.fixEnd(cur_shape); canv.pathActions.fixEnd(curShape);
} }
cur_shape.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(0.005) translate(' + -x + ',' + -y + ')'); curShape.setAttribute('transform', 'translate(' + x + ',' + y + ') scale(0.005) translate(' + -x + ',' + -y + ')');
canv.recalculateDimensions(cur_shape); canv.recalculateDimensions(curShape);
var tlist = canv.getTransformList(cur_shape); /* var tlist = */ canv.getTransformList(curShape);
lastBBox = cur_shape.getBBox(); lastBBox = curShape.getBBox();
return { return {
started: true started: true
}; };
}, },
mouseMove: function(opts) { mouseMove: function (opts) {
var mode = canv.getMode(); var mode = canv.getMode();
if (mode !== mode_id) {return;} if (mode !== modeId) { return; }
var zoom = canv.getZoom(); var zoom = canv.getZoom();
var evt = opts.event; var evt = opts.event;
var x = opts.mouse_x/zoom; var x = opts.mouse_x / zoom;
var y = opts.mouse_y/zoom; var y = opts.mouse_y / zoom;
var tlist = canv.getTransformList(cur_shape), var tlist = canv.getTransformList(curShape),
box = cur_shape.getBBox(), box = curShape.getBBox(),
left = box.x, top = box.y, width = box.width, left = box.x, top = box.y, width = box.width,
height = box.height; height = box.height;
var dx = (x-start_x), dy = (y-start_y); var dx = (x - startX), dy = (y - startY);
var newbox = { var newbox = {
'x': Math.min(start_x,x), 'x': Math.min(startX, x),
'y': Math.min(start_y,y), 'y': Math.min(startY, y),
'width': Math.abs(x-start_x), 'width': Math.abs(x - startX),
'height': Math.abs(y-start_y) 'height': Math.abs(y - startY)
}; };
var tx = 0, ty = 0, var tx = 0, ty = 0,
sy = height ? (height+dy)/height : 1, sy = height ? (height + dy) / height : 1,
sx = width ? (width+dx)/width : 1; sx = width ? (width + dx) / width : 1;
sx = (newbox.width / lastBBox.width) || 1; sx = (newbox.width / lastBBox.width) || 1;
sy = (newbox.height / lastBBox.height) || 1; sy = (newbox.height / lastBBox.height) || 1;
// Not perfect, but mostly works... // Not perfect, but mostly works...
if (x < start_x) { if (x < startX) {
tx = lastBBox.width; tx = lastBBox.width;
} }
if (y < start_y) {ty = lastBBox.height;} if (y < startY) { ty = lastBBox.height; }
// update the transform list with translate,scale,translate // update the transform list with translate,scale,translate
var translateOrigin = svgroot.createSVGTransform(), var translateOrigin = svgroot.createSVGTransform(),
scale = svgroot.createSVGTransform(), scale = svgroot.createSVGTransform(),
translateBack = svgroot.createSVGTransform(); translateBack = svgroot.createSVGTransform();
translateOrigin.setTranslate(-(left+tx), -(top+ty)); translateOrigin.setTranslate(-(left + tx), -(top + ty));
if (!evt.shiftKey) { if (!evt.shiftKey) {
var max = Math.min(Math.abs(sx), Math.abs(sy)); var max = Math.min(Math.abs(sx), Math.abs(sy));
sx = max * (sx < 0 ? -1 : 1); sx = max * (sx < 0 ? -1 : 1);
sy = max * (sy < 0 ? -1 : 1); sy = max * (sy < 0 ? -1 : 1);
} }
scale.setScale(sx,sy); scale.setScale(sx, sy);
translateBack.setTranslate(left+tx, top+ty); translateBack.setTranslate(left + tx, top + ty);
tlist.appendItem(translateBack); tlist.appendItem(translateBack);
tlist.appendItem(scale); tlist.appendItem(scale);
tlist.appendItem(translateOrigin); tlist.appendItem(translateOrigin);
canv.recalculateDimensions(cur_shape); canv.recalculateDimensions(curShape);
lastBBox = cur_shape.getBBox(); lastBBox = curShape.getBBox();
}, },
mouseUp: function(opts) { mouseUp: function (opts) {
var mode = canv.getMode(); var mode = canv.getMode();
if (mode !== mode_id) {return;} if (mode !== modeId) { return; }
var keepObject = (opts.event.clientX != startClientPos.x && opts.event.clientY != startClientPos.y); var keepObject = (opts.event.clientX !== startClientPos.x && opts.event.clientY !== startClientPos.y);
return { return {
keep: keepObject, keep: keepObject,
element: cur_shape, element: curShape,
started: false started: false
}; };
} }
}; };
}); });

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgedit, svgCanvas, $*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals svgEditor, svgCanvas, $ */
/* /*
* ext-star.js * ext-star.js
* *
@@ -9,7 +9,8 @@
* *
*/ */
svgEditor.addExtension('star', function(S){'use strict'; svgEditor.addExtension('star', function (S) {
'use strict';
var // NS = svgedit.NS, var // NS = svgedit.NS,
// svgcontent = S.svgcontent, // svgcontent = S.svgcontent,
@@ -17,19 +18,18 @@ svgEditor.addExtension('star', function(S){'use strict';
// editingitex = false, // editingitex = false,
// svgdoc = S.svgroot.parentNode.ownerDocument, // svgdoc = S.svgroot.parentNode.ownerDocument,
started, started,
newFO, newFO;
// edg = 0, // edg = 0,
// newFOG, newFOGParent, newDef, newImageName, newMaskID, // newFOG, newFOGParent, newDef, newImageName, newMaskID,
// undoCommand = 'Not image', // undoCommand = 'Not image',
// modeChangeG, ccZoom, wEl, hEl, wOffset, hOffset, ccRgbEl, brushW, brushH, // modeChangeG, ccZoom, wEl, hEl, wOffset, hOffset, ccRgbEl, brushW, brushH;
shape;
function showPanel(on){ function showPanel (on) {
var fc_rules = $('#fc_rules'); var fcRules = $('#fc_rules');
if (!fc_rules.length) { if (!fcRules.length) {
fc_rules = $('<style id="fc_rules"></style>').appendTo('head'); fcRules = $('<style id="fc_rules"></style>').appendTo('head');
} }
fc_rules.text(!on ? '' : ' #tool_topath { display: none !important; }'); fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
$('#star_panel').toggle(on); $('#star_panel').toggle(on);
} }
@@ -39,7 +39,7 @@ svgEditor.addExtension('star', function(S){'use strict';
} }
*/ */
function setAttr(attr, val){ function setAttr (attr, val) {
svgCanvas.changeSelectedAttribute(attr, val); svgCanvas.changeSelectedAttribute(attr, val);
S.call('changed', selElems); S.call('changed', selElems);
} }
@@ -63,7 +63,7 @@ svgEditor.addExtension('star', function(S){'use strict';
title: 'Star Tool', title: 'Star Tool',
position: 12, position: 12,
events: { events: {
click: function(){ click: function () {
showPanel(true); showPanel(true);
svgCanvas.setMode('star'); svgCanvas.setMode('star');
} }
@@ -79,7 +79,7 @@ svgEditor.addExtension('star', function(S){'use strict';
size: 3, size: 3,
defval: 5, defval: 5,
events: { events: {
change: function(){ change: function () {
setAttr('point', this.value); setAttr('point', this.value);
} }
} }
@@ -100,23 +100,23 @@ svgEditor.addExtension('star', function(S){'use strict';
size: 3, size: 3,
defval: 0, defval: 0,
events: { events: {
change: function(){ change: function () {
setAttr('radialshift', this.value); setAttr('radialshift', this.value);
} }
} }
}], }],
callback: function(){ callback: function () {
$('#star_panel').hide(); $('#star_panel').hide();
// var endChanges = function(){}; // var endChanges = function(){};
}, },
mouseDown: function(opts){ mouseDown: function (opts) {
var rgb = svgCanvas.getColor('fill'); var rgb = svgCanvas.getColor('fill');
// var ccRgbEl = rgb.substring(1, rgb.length); // var ccRgbEl = rgb.substring(1, rgb.length);
var sRgb = svgCanvas.getColor('stroke'); var sRgb = svgCanvas.getColor('stroke');
// var ccSRgbEl = sRgb.substring(1, rgb.length); // var ccSRgbEl = sRgb.substring(1, rgb.length);
var sWidth = svgCanvas.getStrokeWidth(); var sWidth = svgCanvas.getStrokeWidth();
if (svgCanvas.getMode() == 'star') { if (svgCanvas.getMode() === 'star') {
started = true; started = true;
newFO = S.addSvgElementFromJson({ newFO = S.addSvgElementFromJson({
@@ -141,11 +141,11 @@ svgEditor.addExtension('star', function(S){'use strict';
}; };
} }
}, },
mouseMove: function(opts){ mouseMove: function (opts) {
if (!started) { if (!started) {
return; return;
} }
if (svgCanvas.getMode() == 'star') { if (svgCanvas.getMode() === 'star') {
var x = opts.mouse_x; var x = opts.mouse_x;
var y = opts.mouse_y; var y = opts.mouse_y;
var c = $(newFO).attr(['cx', 'cy', 'point', 'orient', 'fill', 'strokecolor', 'strokeWidth', 'radialshift']); var c = $(newFO).attr(['cx', 'cy', 'point', 'orient', 'fill', 'strokecolor', 'strokeWidth', 'radialshift']);
@@ -158,9 +158,9 @@ svgEditor.addExtension('star', function(S){'use strict';
var s; var s;
for (s = 0; point >= s; s++) { for (s = 0; point >= s; s++) {
var angle = 2.0 * Math.PI * (s / point); var angle = 2.0 * Math.PI * (s / point);
if ('point' == orient) { if (orient === 'point') {
angle -= (Math.PI / 2); angle -= (Math.PI / 2);
} else if ('edge' == orient) { } else if (orient === 'edge') {
angle = (angle + (Math.PI / point)) - (Math.PI / 2); angle = (angle + (Math.PI / point)) - (Math.PI / 2);
} }
@@ -169,11 +169,11 @@ svgEditor.addExtension('star', function(S){'use strict';
polyPoints += x + ',' + y + ' '; polyPoints += x + ',' + y + ' ';
if (null != inradius) { if (inradius != null) {
angle = (2.0 * Math.PI * (s / point)) + (Math.PI / point); angle = (2.0 * Math.PI * (s / point)) + (Math.PI / point);
if ('point' == orient) { if (orient === 'point') {
angle -= (Math.PI / 2); angle -= (Math.PI / 2);
} else if ('edge' == orient) { } else if (orient === 'edge') {
angle = (angle + (Math.PI / point)) - (Math.PI / 2); angle = (angle + (Math.PI / point)) - (Math.PI / 2);
} }
angle += radialShift; angle += radialShift;
@@ -188,25 +188,24 @@ svgEditor.addExtension('star', function(S){'use strict';
newFO.setAttributeNS(null, 'fill', fill); newFO.setAttributeNS(null, 'fill', fill);
newFO.setAttributeNS(null, 'stroke', strokecolor); newFO.setAttributeNS(null, 'stroke', strokecolor);
newFO.setAttributeNS(null, 'stroke-width', strokewidth); newFO.setAttributeNS(null, 'stroke-width', strokewidth);
shape = newFO.getAttributeNS(null, 'shape'); /* var shape = */ newFO.getAttributeNS(null, 'shape');
return { return {
started: true started: true
}; };
} }
}, },
mouseUp: function(){ mouseUp: function () {
if (svgCanvas.getMode() == 'star') { if (svgCanvas.getMode() === 'star') {
var attrs = $(newFO).attr(['r']); var attrs = $(newFO).attr(['r']);
// svgCanvas.addToSelection([newFO], true); // svgCanvas.addToSelection([newFO], true);
return { return {
keep: (attrs.r != 0), keep: (attrs.r !== '0'),
element: newFO element: newFO
}; };
} }
}, },
selectedChanged: function(opts){ selectedChanged: function (opts) {
// Use this to update the current selected elements // Use this to update the current selected elements
selElems = opts.elems; selElems = opts.elems;
@@ -220,8 +219,7 @@ svgEditor.addExtension('star', function(S){'use strict';
$('#starNumPoints').val(elem.getAttribute('point')); $('#starNumPoints').val(elem.getAttribute('point'));
$('#radialShift').val(elem.getAttribute('radialshift')); $('#radialShift').val(elem.getAttribute('radialshift'));
showPanel(true); showPanel(true);
} } else {
else {
showPanel(false); showPanel(false);
} }
} else { } else {
@@ -229,7 +227,7 @@ svgEditor.addExtension('star', function(S){'use strict';
} }
} }
}, },
elementChanged: function(opts){ elementChanged: function (opts) {
// var elem = opts.elems[0]; // var elem = opts.elems[0];
} }
}; };

View File

@@ -1,5 +1,5 @@
/*globals svgEditor, svgCanvas, $, widget*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, regexp: true, continue: true*/ /* globals svgEditor, svgCanvas, $, widget */
/* /*
* ext-storage.js * ext-storage.js
* *
@@ -26,7 +26,7 @@ TODOS
2. We might provide control of storage settings through the UI besides the 2. We might provide control of storage settings through the UI besides the
initial (or URL-forced) dialog. initial (or URL-forced) dialog.
*/ */
svgEditor.addExtension('storage', function() { svgEditor.addExtension('storage', function () {
// We could empty any already-set data for users when they decline storage, // We could empty any already-set data for users when they decline storage,
// but it would be a risk for users who wanted to store but accidentally // but it would be a risk for users who wanted to store but accidentally
// said "no"; instead, we'll let those who already set it, delete it themselves; // said "no"; instead, we'll let those who already set it, delete it themselves;
@@ -53,8 +53,7 @@ svgEditor.addExtension('storage', function() {
loc.href = loc.href.replace(/([&?])storagePrompt=[^&]*(&?)/, function (n0, n1, amp) { loc.href = loc.href.replace(/([&?])storagePrompt=[^&]*(&?)/, function (n0, n1, amp) {
return (val ? n1 : '') + val + (!val && amp ? n1 : (amp || '')); return (val ? n1 : '') + val + (!val && amp ? n1 : (amp || ''));
}); });
} } else {
else {
loc.href += (loc.href.indexOf('?') > -1 ? '&' : '?') + val; loc.href += (loc.href.indexOf('?') > -1 ? '&' : '?') + val;
} }
} }
@@ -63,8 +62,7 @@ svgEditor.addExtension('storage', function() {
var name = 'svgedit-' + svgEditor.curConfig.canvasName; var name = 'svgedit-' + svgEditor.curConfig.canvasName;
if (!val) { if (!val) {
storage.removeItem(name); storage.removeItem(name);
} } else {
else {
storage.setItem(name, val); storage.setItem(name, val);
} }
} }
@@ -78,7 +76,7 @@ svgEditor.addExtension('storage', function() {
expireCookie('store'); expireCookie('store');
} }
function emptyStorage() { function emptyStorage () {
setSVGContentStorage(''); setSVGContentStorage('');
var name; var name;
for (name in svgEditor.curPrefs) { for (name in svgEditor.curPrefs) {
@@ -92,7 +90,7 @@ svgEditor.addExtension('storage', function() {
} }
} }
// emptyStorage(); // emptyStorage();
/** /**
* Listen for unloading: If and only if opted in by the user, set the content * Listen for unloading: If and only if opted in by the user, set the content
@@ -103,7 +101,7 @@ svgEditor.addExtension('storage', function() {
* 3. Use localStorage (where available) or cookies to set preferences. * 3. Use localStorage (where available) or cookies to set preferences.
*/ */
function setupBeforeUnloadListener () { function setupBeforeUnloadListener () {
window.addEventListener('beforeunload', function(e) { window.addEventListener('beforeunload', function (e) {
// Don't save anything unless the user opted in to storage // Don't save anything unless the user opted in to storage
if (!document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/)) { if (!document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/)) {
return; return;
@@ -121,18 +119,16 @@ svgEditor.addExtension('storage', function() {
for (key in curPrefs) { for (key in curPrefs) {
if (curPrefs.hasOwnProperty(key)) { // It's our own config, so we don't need to iterate up the prototype chain if (curPrefs.hasOwnProperty(key)) { // It's our own config, so we don't need to iterate up the prototype chain
var val = curPrefs[key], var val = curPrefs[key],
store = (val != undefined); store = (val !== undefined);
key = 'svg-edit-' + key; key = 'svg-edit-' + key;
if (!store) { if (!store) {
continue; continue;
} }
if (storage) { if (storage) {
storage.setItem(key, val); storage.setItem(key, val);
} } else if (window.widget) {
else if (window.widget) {
widget.setPreferenceForKey(val, key); widget.setPreferenceForKey(val, key);
} } else {
else {
val = encodeURIComponent(val); val = encodeURIComponent(val);
document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT'; document.cookie = encodeURIComponent(key) + '=' + val + '; expires=Fri, 31 Dec 9999 23:59:59 GMT';
} }
@@ -195,7 +191,6 @@ svgEditor.addExtension('storage', function() {
) )
// ...then show the storage prompt. // ...then show the storage prompt.
)) { )) {
var options = []; var options = [];
if (storage) { if (storage) {
options.unshift( options.unshift(
@@ -203,8 +198,7 @@ svgEditor.addExtension('storage', function() {
{value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefsOnly}, {value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefsOnly},
{value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefsOrContent} {value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefsOrContent}
); );
} } else {
else {
options.unshift( options.unshift(
{value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefs}, {value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefs},
{value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefs} {value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefs}
@@ -242,8 +236,7 @@ svgEditor.addExtension('storage', function() {
replaceStoragePrompt(); replaceStoragePrompt();
return; return;
} }
} } else { // The user does not wish storage (or cancelled, which we treat equivalently)
else { // The user does not wish storage (or cancelled, which we treat equivalently)
removeStoragePrefCookie(); removeStoragePrefCookie();
if (pref && // If the user explicitly expresses wish for no storage if (pref && // If the user explicitly expresses wish for no storage
emptyStorageOnDecline emptyStorageOnDecline
@@ -284,8 +277,7 @@ svgEditor.addExtension('storage', function() {
tooltip: uiStrings.confirmSetStorage.rememberTooltip tooltip: uiStrings.confirmSetStorage.rememberTooltip
} }
); );
} } else if (!noStorageOnLoad || forceStorage) {
else if (!noStorageOnLoad || forceStorage) {
setupBeforeUnloadListener(); setupBeforeUnloadListener();
} }
} }

View File

@@ -1,67 +1,67 @@
/*globals svgEditor*/ /* eslint-disable no-var */
/* globals svgEditor */
/* /*
Depends on Firefox add-on and executables from https://github.com/brettz9/webappfind Depends on Firefox add-on and executables from https://github.com/brettz9/webappfind
Todos: Todos:
1. See WebAppFind Readme for SVG-related todos 1. See WebAppFind Readme for SVG-related todos
*/ */
(function () {'use strict'; (function () {
'use strict';
var pathID, var pathID,
saveMessage = 'webapp-save', saveMessage = 'webapp-save',
readMessage = 'webapp-read', readMessage = 'webapp-read',
excludedMessages = [readMessage, saveMessage]; excludedMessages = [readMessage, saveMessage];
window.addEventListener('message', function(e) { window.addEventListener('message', function (e) {
if (e.origin !== window.location.origin || // PRIVACY AND SECURITY! (for viewing and saving, respectively) if (e.origin !== window.location.origin || // PRIVACY AND SECURITY! (for viewing and saving, respectively)
(!Array.isArray(e.data) || excludedMessages.indexOf(e.data[0]) > -1) // Validate format and avoid our post below (!Array.isArray(e.data) || excludedMessages.indexOf(e.data[0]) > -1) // Validate format and avoid our post below
) { ) {
return; return;
} }
var svgString, var svgString,
messageType = e.data[0]; messageType = e.data[0];
switch (messageType) { switch (messageType) {
case 'webapp-view': case 'webapp-view':
// Populate the contents // Populate the contents
pathID = e.data[1]; pathID = e.data[1];
svgString = e.data[2]; svgString = e.data[2];
svgEditor.loadFromString(svgString); svgEditor.loadFromString(svgString);
/*if ($('#tool_save_file')) { /* if ($('#tool_save_file')) {
$('#tool_save_file').disabled = false; $('#tool_save_file').disabled = false;
}*/ } */
break; break;
case 'webapp-save-end': case 'webapp-save-end':
alert('save complete for pathID ' + e.data[1] + '!'); alert('save complete for pathID ' + e.data[1] + '!');
break; break;
default: default:
throw 'Unexpected mode'; throw new Error('Unexpected mode');
} }
}, false); }, false);
window.postMessage([readMessage], window.location.origin !== 'null' ? window.location.origin : '*'); // Avoid "null" string error for file: protocol (even though file protocol not currently supported by add-on) window.postMessage([readMessage], window.location.origin !== 'null' ? window.location.origin : '*'); // Avoid "null" string error for file: protocol (even though file protocol not currently supported by add-on)
svgEditor.addExtension('WebAppFind', function() { svgEditor.addExtension('WebAppFind', function () {
return {
return { name: 'WebAppFind',
name: 'WebAppFind', svgicons: svgEditor.curConfig.extPath + 'webappfind-icon.svg',
svgicons: svgEditor.curConfig.extPath + 'webappfind-icon.svg', buttons: [{
buttons: [{ id: 'webappfind_save', //
id: 'webappfind_save', // type: 'app_menu',
type: 'app_menu', title: 'Save Image back to Disk',
title: 'Save Image back to Disk', position: 4, // Before 0-based index position 4 (after the regular "Save Image (S)")
position: 4, // Before 0-based index position 4 (after the regular "Save Image (S)") events: {
events: { click: function () {
click: function () { if (!pathID) { // Not ready yet as haven't received first payload
if (!pathID) { // Not ready yet as haven't received first payload return;
return; }
} window.postMessage([saveMessage, pathID, svgEditor.canvas.getSvgString()], window.location.origin);
window.postMessage([saveMessage, pathID, svgEditor.canvas.getSvgString()], window.location.origin); }
} }
} }]
}] };
};
}); });
}()); }());

View File

@@ -1,12 +1,14 @@
/* eslint-disable no-var */
/* globals svgEditor, svgCanvas */
/** /**
* Should not be needed for same domain control (just call via child frame), * Should not be needed for same domain control (just call via child frame),
* but an API common for cross-domain and same domain use can be found * but an API common for cross-domain and same domain use can be found
* in embedapi.js with a demo at embedapi.html * in embedapi.js with a demo at embedapi.html
*/ */
/*globals svgEditor, svgCanvas*/ svgEditor.addExtension('xdomain-messaging', function () {
svgEditor.addExtension('xdomain-messaging', function() {'use strict'; 'use strict';
try { try {
window.addEventListener('message', function(e) { window.addEventListener('message', function (e) {
// We accept and post strings for the sake of IE9 support // We accept and post strings for the sake of IE9 support
if (typeof e.data !== 'string' || e.data.charAt() === '|') { if (typeof e.data !== 'string' || e.data.charAt() === '|') {
return; return;
@@ -35,8 +37,7 @@ svgEditor.addExtension('xdomain-messaging', function() {'use strict';
} }
e.source.postMessage(JSON.stringify(message), '*'); e.source.postMessage(JSON.stringify(message), '*');
}, false); }, false);
} } catch (err) {
catch (err) {
console.log('Error with xdomain message listener: ' + err); console.log('Error with xdomain message listener: ' + err);
} }
}); });

View File

@@ -13,12 +13,12 @@
// return it to the editor // return it to the editor
if (!isset($_REQUEST['type'])) { if (!isset($_REQUEST['type'])) {
echo "No type given"; echo 'No type given';
exit; exit;
} }
$type = $_REQUEST['type']; $type = $_REQUEST['type'];
if (!in_array($type, array('load_svg', 'import_svg', 'import_img'))) { if (!in_array($type, array('load_svg', 'import_svg', 'import_img'))) {
echo "Not a recognized type"; echo 'Not a recognized type';
exit; exit;
} }
@@ -34,7 +34,7 @@
if ($type == 'import_img') { if ($type == 'import_img') {
$info = getimagesize($file); $info = getimagesize($file);
if (!in_array($info['mime'], $allowedMimeTypesBySuffix)) { if (!in_array($info['mime'], $allowedMimeTypesBySuffix)) {
echo "Disallowed MIME for supplied file"; echo 'Disallowed MIME for supplied file';
exit; exit;
} }
$prefix = 'data:' . $info['mime'] . ';base64,'; $prefix = 'data:' . $info['mime'] . ';base64,';

View File

@@ -44,16 +44,16 @@ if ($suffix == '.svg') {
$contents = base64_decode(substr($contents, $pos)); $contents = base64_decode(substr($contents, $pos));
} }
header("Cache-Control: public"); header('Cache-Control: public');
header("Content-Description: File Transfer"); header('Content-Description: File Transfer');
// See http://tools.ietf.org/html/rfc6266#section-4.1 // See http://tools.ietf.org/html/rfc6266#section-4.1
header("Content-Disposition: attachment; filename*=UTF-8''" . encodeRFC5987ValueChars( header("Content-Disposition: attachment; filename*=UTF-8''" . encodeRFC5987ValueChars(
// preg_replace('@[\\\\/:*?"<>|]@', '', $file) // If we wanted to strip Windows-disallowed characters server-side (but not a security issue, so we can strip client-side instead) // preg_replace('@[\\\\/:*?"<>|]@', '', $file) // If we wanted to strip Windows-disallowed characters server-side (but not a security issue, so we can strip client-side instead)
$file $file
)); ));
header("Content-Type: " . $mime); header('Content-Type: ' . $mime);
header("Content-Transfer-Encoding: binary"); header('Content-Transfer-Encoding: binary');
echo $contents; echo $contents;

View File

@@ -2,6 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>-</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
</head> </head>
<body> <body>
@@ -11,59 +12,6 @@
<br> <br>
<a href="../../images/logo.png">logo.png</a> <a href="../../images/logo.png">logo.png</a>
<script> <script src="index.js"></script>
/* eslint-disable no-var */
/* globals $ */
$('a').click(function() {'use strict';
var metaStr;
var href = this.href;
var target = window.parent;
// Convert Non-SVG images to data URL first
// (this could also have been done server-side by the library)
if (this.href.indexOf('.svg') === -1) {
metaStr = JSON.stringify({
name: $(this).text(),
id: href
});
target.postMessage(metaStr, '*');
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
// load the raster image into the canvas
canvas.getContext('2d').drawImage(this, 0, 0);
// retrieve the data: URL
var dataurl;
try {
dataurl = canvas.toDataURL();
} catch(err) {
// This fails in Firefox with file:// URLs :(
alert('Data URL conversion failed: ' + err);
dataurl = '';
}
target.postMessage('|' + href + '|' + dataurl, '*');
};
img.src = href;
} else {
// Send metadata (also indicates file is about to be sent)
metaStr = JSON.stringify({
name: $(this).text(),
id: href
});
target.postMessage(metaStr, '*');
// Do ajax request for image's href value
$.get(href, function (data) {
data = '|' + href + '|' + data;
// This is where the magic happens!
target.postMessage(data, '*');
}, 'html'); // 'html' is necessary to keep returned data as a string
}
return false;
});
</script>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,51 @@
/* eslint-disable no-var */
/* globals $ */
$('a').click(function () {
'use strict';
var metaStr;
var href = this.href;
var target = window.parent;
// Convert Non-SVG images to data URL first
// (this could also have been done server-side by the library)
if (this.href.indexOf('.svg') === -1) {
metaStr = JSON.stringify({
name: $(this).text(),
id: href
});
target.postMessage(metaStr, '*');
var img = new Image();
img.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
// load the raster image into the canvas
canvas.getContext('2d').drawImage(this, 0, 0);
// retrieve the data: URL
var dataurl;
try {
dataurl = canvas.toDataURL();
} catch (err) {
// This fails in Firefox with file:// URLs :(
alert('Data URL conversion failed: ' + err);
dataurl = '';
}
target.postMessage('|' + href + '|' + dataurl, '*');
};
img.src = href;
} else {
// Send metadata (also indicates file is about to be sent)
metaStr = JSON.stringify({
name: $(this).text(),
id: href
});
target.postMessage(metaStr, '*');
// Do ajax request for image's href value
$.get(href, function (data) {
data = '|' + href + '|' + data;
// This is where the magic happens!
target.postMessage(data, '*');
}, 'html'); // 'html' is necessary to keep returned data as a string
}
return false;
});

View File

@@ -1,5 +1,5 @@
/*globals svgedit*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true, continue: true, forin: true*/ /* globals svgedit */
/** /**
* Package: svedit.history * Package: svedit.history
* *
@@ -13,7 +13,8 @@
// 2) svgtransformlist.js // 2) svgtransformlist.js
// 3) svgutils.js // 3) svgutils.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.history) { if (!svgedit.history) {
svgedit.history = {}; svgedit.history = {};
@@ -27,7 +28,7 @@ svgedit.history.HistoryEventTypes = {
AFTER_UNAPPLY: 'after_unapply' AFTER_UNAPPLY: 'after_unapply'
}; };
var removedElements = {}; // var removedElements = {};
/** /**
* An interface that all command objects must implement. * An interface that all command objects must implement.
@@ -61,18 +62,18 @@ var removedElements = {};
* @param {Element} oldParent - The element's parent before it was moved * @param {Element} oldParent - The element's parent before it was moved
* @param {string} [text] - An optional string visible to user related to this change * @param {string} [text] - An optional string visible to user related to this change
*/ */
svgedit.history.MoveElementCommand = function(elem, oldNextSibling, oldParent, text) { svgedit.history.MoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
this.elem = elem; this.elem = elem;
this.text = text ? ("Move " + elem.tagName + " to " + text) : ("Move " + elem.tagName); this.text = text ? ('Move ' + elem.tagName + ' to ' + text) : ('Move ' + elem.tagName);
this.oldNextSibling = oldNextSibling; this.oldNextSibling = oldNextSibling;
this.oldParent = oldParent; this.oldParent = oldParent;
this.newNextSibling = elem.nextSibling; this.newNextSibling = elem.nextSibling;
this.newParent = elem.parentNode; this.newParent = elem.parentNode;
}; };
svgedit.history.MoveElementCommand.type = function() { return 'svgedit.history.MoveElementCommand'; }; svgedit.history.MoveElementCommand.type = function () { return 'svgedit.history.MoveElementCommand'; };
svgedit.history.MoveElementCommand.prototype.type = svgedit.history.MoveElementCommand.type; svgedit.history.MoveElementCommand.prototype.type = svgedit.history.MoveElementCommand.type;
svgedit.history.MoveElementCommand.prototype.getText = function() { svgedit.history.MoveElementCommand.prototype.getText = function () {
return this.text; return this.text;
}; };
@@ -80,7 +81,7 @@ svgedit.history.MoveElementCommand.prototype.getText = function() {
* Re-positions the element * Re-positions the element
* @param {handleHistoryEvent: function} * @param {handleHistoryEvent: function}
*/ */
svgedit.history.MoveElementCommand.prototype.apply = function(handler) { svgedit.history.MoveElementCommand.prototype.apply = function (handler) {
// TODO(codedread): Refactor this common event code into a base HistoryCommand class. // TODO(codedread): Refactor this common event code into a base HistoryCommand class.
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
@@ -97,7 +98,7 @@ svgedit.history.MoveElementCommand.prototype.apply = function(handler) {
* Positions the element back to its original location * Positions the element back to its original location
* @param {handleHistoryEvent: function} * @param {handleHistoryEvent: function}
*/ */
svgedit.history.MoveElementCommand.prototype.unapply = function(handler) { svgedit.history.MoveElementCommand.prototype.unapply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
@@ -111,11 +112,10 @@ svgedit.history.MoveElementCommand.prototype.unapply = function(handler) {
// Function: svgedit.history.MoveElementCommand.elements // Function: svgedit.history.MoveElementCommand.elements
// Returns array with element associated with this command // Returns array with element associated with this command
svgedit.history.MoveElementCommand.prototype.elements = function() { svgedit.history.MoveElementCommand.prototype.elements = function () {
return [this.elem]; return [this.elem];
}; };
// Class: svgedit.history.InsertElementCommand // Class: svgedit.history.InsertElementCommand
// implements svgedit.history.HistoryCommand // implements svgedit.history.HistoryCommand
// History command for an element that was added to the DOM // History command for an element that was added to the DOM
@@ -123,23 +123,23 @@ svgedit.history.MoveElementCommand.prototype.elements = function() {
// Parameters: // Parameters:
// elem - The newly added DOM element // elem - The newly added DOM element
// text - An optional string visible to user related to this change // text - An optional string visible to user related to this change
svgedit.history.InsertElementCommand = function(elem, text) { svgedit.history.InsertElementCommand = function (elem, text) {
this.elem = elem; this.elem = elem;
this.text = text || ("Create " + elem.tagName); this.text = text || ('Create ' + elem.tagName);
this.parent = elem.parentNode; this.parent = elem.parentNode;
this.nextSibling = this.elem.nextSibling; this.nextSibling = this.elem.nextSibling;
}; };
svgedit.history.InsertElementCommand.type = function() { return 'svgedit.history.InsertElementCommand'; }; svgedit.history.InsertElementCommand.type = function () { return 'svgedit.history.InsertElementCommand'; };
svgedit.history.InsertElementCommand.prototype.type = svgedit.history.InsertElementCommand.type; svgedit.history.InsertElementCommand.prototype.type = svgedit.history.InsertElementCommand.type;
// Function: svgedit.history.InsertElementCommand.getText // Function: svgedit.history.InsertElementCommand.getText
svgedit.history.InsertElementCommand.prototype.getText = function() { svgedit.history.InsertElementCommand.prototype.getText = function () {
return this.text; return this.text;
}; };
// Function: svgedit.history.InsertElementCommand.apply // Function: svgedit.history.InsertElementCommand.apply
// Re-Inserts the new element // Re-Inserts the new element
svgedit.history.InsertElementCommand.prototype.apply = function(handler) { svgedit.history.InsertElementCommand.prototype.apply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
} }
@@ -153,7 +153,7 @@ svgedit.history.InsertElementCommand.prototype.apply = function(handler) {
// Function: svgedit.history.InsertElementCommand.unapply // Function: svgedit.history.InsertElementCommand.unapply
// Removes the element // Removes the element
svgedit.history.InsertElementCommand.prototype.unapply = function(handler) { svgedit.history.InsertElementCommand.prototype.unapply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
@@ -168,11 +168,10 @@ svgedit.history.InsertElementCommand.prototype.unapply = function(handler) {
// Function: svgedit.history.InsertElementCommand.elements // Function: svgedit.history.InsertElementCommand.elements
// Returns array with element associated with this command // Returns array with element associated with this command
svgedit.history.InsertElementCommand.prototype.elements = function() { svgedit.history.InsertElementCommand.prototype.elements = function () {
return [this.elem]; return [this.elem];
}; };
// Class: svgedit.history.RemoveElementCommand // Class: svgedit.history.RemoveElementCommand
// implements svgedit.history.HistoryCommand // implements svgedit.history.HistoryCommand
// History command for an element removed from the DOM // History command for an element removed from the DOM
@@ -182,26 +181,26 @@ svgedit.history.InsertElementCommand.prototype.elements = function() {
// oldNextSibling - the DOM element's nextSibling when it was in the DOM // oldNextSibling - the DOM element's nextSibling when it was in the DOM
// oldParent - The DOM element's parent // oldParent - The DOM element's parent
// text - An optional string visible to user related to this change // text - An optional string visible to user related to this change
svgedit.history.RemoveElementCommand = function(elem, oldNextSibling, oldParent, text) { svgedit.history.RemoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
this.elem = elem; this.elem = elem;
this.text = text || ("Delete " + elem.tagName); this.text = text || ('Delete ' + elem.tagName);
this.nextSibling = oldNextSibling; this.nextSibling = oldNextSibling;
this.parent = oldParent; this.parent = oldParent;
// special hack for webkit: remove this element's entry in the svgTransformLists map // special hack for webkit: remove this element's entry in the svgTransformLists map
svgedit.transformlist.removeElementFromListMap(elem); svgedit.transformlist.removeElementFromListMap(elem);
}; };
svgedit.history.RemoveElementCommand.type = function() { return 'svgedit.history.RemoveElementCommand'; }; svgedit.history.RemoveElementCommand.type = function () { return 'svgedit.history.RemoveElementCommand'; };
svgedit.history.RemoveElementCommand.prototype.type = svgedit.history.RemoveElementCommand.type; svgedit.history.RemoveElementCommand.prototype.type = svgedit.history.RemoveElementCommand.type;
// Function: svgedit.history.RemoveElementCommand.getText // Function: svgedit.history.RemoveElementCommand.getText
svgedit.history.RemoveElementCommand.prototype.getText = function() { svgedit.history.RemoveElementCommand.prototype.getText = function () {
return this.text; return this.text;
}; };
// Function: RemoveElementCommand.apply // Function: RemoveElementCommand.apply
// Re-removes the new element // Re-removes the new element
svgedit.history.RemoveElementCommand.prototype.apply = function(handler) { svgedit.history.RemoveElementCommand.prototype.apply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
} }
@@ -217,7 +216,7 @@ svgedit.history.RemoveElementCommand.prototype.apply = function(handler) {
// Function: RemoveElementCommand.unapply // Function: RemoveElementCommand.unapply
// Re-adds the new element // Re-adds the new element
svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) { svgedit.history.RemoveElementCommand.prototype.unapply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
@@ -225,12 +224,11 @@ svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) {
svgedit.transformlist.removeElementFromListMap(this.elem); svgedit.transformlist.removeElementFromListMap(this.elem);
if (this.nextSibling == null) { if (this.nextSibling == null) {
if (window.console) { if (window.console) {
console.log('Error: reference element was lost'); console.log('Error: reference element was lost');
} }
} }
this.parent.insertBefore(this.elem, this.nextSibling); this.parent.insertBefore(this.elem, this.nextSibling);
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
} }
@@ -238,11 +236,10 @@ svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) {
// Function: RemoveElementCommand.elements // Function: RemoveElementCommand.elements
// Returns array with element associated with this command // Returns array with element associated with this command
svgedit.history.RemoveElementCommand.prototype.elements = function() { svgedit.history.RemoveElementCommand.prototype.elements = function () {
return [this.elem]; return [this.elem];
}; };
// Class: svgedit.history.ChangeElementCommand // Class: svgedit.history.ChangeElementCommand
// implements svgedit.history.HistoryCommand // implements svgedit.history.HistoryCommand
// History command to make a change to an element. // History command to make a change to an element.
@@ -252,66 +249,70 @@ svgedit.history.RemoveElementCommand.prototype.elements = function() {
// elem - The DOM element that was changed // elem - The DOM element that was changed
// attrs - An object with the attributes to be changed and the values they had *before* the change // attrs - An object with the attributes to be changed and the values they had *before* the change
// text - An optional string visible to user related to this change // text - An optional string visible to user related to this change
svgedit.history.ChangeElementCommand = function(elem, attrs, text) { svgedit.history.ChangeElementCommand = function (elem, attrs, text) {
this.elem = elem; this.elem = elem;
this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName); this.text = text ? ('Change ' + elem.tagName + ' ' + text) : ('Change ' + elem.tagName);
this.newValues = {}; this.newValues = {};
this.oldValues = attrs; this.oldValues = attrs;
var attr; var attr;
for (attr in attrs) { for (attr in attrs) {
if (attr == "#text") {this.newValues[attr] = elem.textContent;} if (attr === '#text') {
else if (attr == "#href") {this.newValues[attr] = svgedit.utilities.getHref(elem);} this.newValues[attr] = elem.textContent;
else {this.newValues[attr] = elem.getAttribute(attr);} } else if (attr === '#href') {
this.newValues[attr] = svgedit.utilities.getHref(elem);
} else {
this.newValues[attr] = elem.getAttribute(attr);
}
} }
}; };
svgedit.history.ChangeElementCommand.type = function() { return 'svgedit.history.ChangeElementCommand'; }; svgedit.history.ChangeElementCommand.type = function () { return 'svgedit.history.ChangeElementCommand'; };
svgedit.history.ChangeElementCommand.prototype.type = svgedit.history.ChangeElementCommand.type; svgedit.history.ChangeElementCommand.prototype.type = svgedit.history.ChangeElementCommand.type;
// Function: svgedit.history.ChangeElementCommand.getText // Function: svgedit.history.ChangeElementCommand.getText
svgedit.history.ChangeElementCommand.prototype.getText = function() { svgedit.history.ChangeElementCommand.prototype.getText = function () {
return this.text; return this.text;
}; };
// Function: svgedit.history.ChangeElementCommand.apply // Function: svgedit.history.ChangeElementCommand.apply
// Performs the stored change action // Performs the stored change action
svgedit.history.ChangeElementCommand.prototype.apply = function(handler) { svgedit.history.ChangeElementCommand.prototype.apply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
} }
var bChangedTransform = false; var bChangedTransform = false;
var attr; var attr;
for (attr in this.newValues ) { for (attr in this.newValues) {
if (this.newValues[attr]) { if (this.newValues[attr]) {
if (attr == "#text") {this.elem.textContent = this.newValues[attr];} if (attr === '#text') {
else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.newValues[attr]);} this.elem.textContent = this.newValues[attr];
else {this.elem.setAttribute(attr, this.newValues[attr]);} } else if (attr === '#href') {
} svgedit.utilities.setHref(this.elem, this.newValues[attr]);
else { } else {
if (attr == "#text") { this.elem.setAttribute(attr, this.newValues[attr]);
this.elem.textContent = "";
} }
else { } else {
this.elem.setAttribute(attr, ""); if (attr === '#text') {
this.elem.textContent = '';
} else {
this.elem.setAttribute(attr, '');
this.elem.removeAttribute(attr); this.elem.removeAttribute(attr);
} }
} }
if (attr == "transform") { bChangedTransform = true; } if (attr === 'transform') { bChangedTransform = true; }
} }
// relocate rotational transform, if necessary // relocate rotational transform, if necessary
if (!bChangedTransform) { if (!bChangedTransform) {
var angle = svgedit.utilities.getRotationAngle(this.elem); var angle = svgedit.utilities.getRotationAngle(this.elem);
if (angle) { if (angle) {
// TODO: These instances of elem either need to be declared as global var bbox = this.elem.getBBox();
// (which would not be good for conflicts) or declare/use this.elem var cx = bbox.x + bbox.width / 2,
var bbox = elem.getBBox(); cy = bbox.y + bbox.height / 2;
var cx = bbox.x + bbox.width/2, var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
cy = bbox.y + bbox.height/2; if (rotate !== this.elem.getAttribute('transform')) {
var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); this.elem.setAttribute('transform', rotate);
if (rotate != elem.getAttribute("transform")) {
elem.setAttribute("transform", rotate);
} }
} }
} }
@@ -325,39 +326,41 @@ svgedit.history.ChangeElementCommand.prototype.apply = function(handler) {
// Function: svgedit.history.ChangeElementCommand.unapply // Function: svgedit.history.ChangeElementCommand.unapply
// Reverses the stored change action // Reverses the stored change action
svgedit.history.ChangeElementCommand.prototype.unapply = function(handler) { svgedit.history.ChangeElementCommand.prototype.unapply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
var bChangedTransform = false; var bChangedTransform = false;
var attr; var attr;
for (attr in this.oldValues ) { for (attr in this.oldValues) {
if (this.oldValues[attr]) { if (this.oldValues[attr]) {
if (attr == "#text") {this.elem.textContent = this.oldValues[attr];} if (attr === '#text') {
else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.oldValues[attr]);} this.elem.textContent = this.oldValues[attr];
else { } else if (attr === '#href') {
svgedit.utilities.setHref(this.elem, this.oldValues[attr]);
} else {
this.elem.setAttribute(attr, this.oldValues[attr]); this.elem.setAttribute(attr, this.oldValues[attr]);
} }
} } else {
else { if (attr === '#text') {
if (attr == "#text") { this.elem.textContent = '';
this.elem.textContent = ""; } else {
this.elem.removeAttribute(attr);
} }
else {this.elem.removeAttribute(attr);}
} }
if (attr == "transform") { bChangedTransform = true; } if (attr === 'transform') { bChangedTransform = true; }
} }
// relocate rotational transform, if necessary // relocate rotational transform, if necessary
if (!bChangedTransform) { if (!bChangedTransform) {
var angle = svgedit.utilities.getRotationAngle(this.elem); var angle = svgedit.utilities.getRotationAngle(this.elem);
if (angle) { if (angle) {
var bbox = elem.getBBox(); var bbox = this.elem.getBBox();
var cx = bbox.x + bbox.width/2, var cx = bbox.x + bbox.width / 2,
cy = bbox.y + bbox.height/2; cy = bbox.y + bbox.height / 2;
var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join(''); var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
if (rotate != elem.getAttribute("transform")) { if (rotate !== this.elem.getAttribute('transform')) {
elem.setAttribute("transform", rotate); this.elem.setAttribute('transform', rotate);
} }
} }
} }
@@ -374,37 +377,35 @@ svgedit.history.ChangeElementCommand.prototype.unapply = function(handler) {
// Function: ChangeElementCommand.elements // Function: ChangeElementCommand.elements
// Returns array with element associated with this command // Returns array with element associated with this command
svgedit.history.ChangeElementCommand.prototype.elements = function() { svgedit.history.ChangeElementCommand.prototype.elements = function () {
return [this.elem]; return [this.elem];
}; };
// TODO: create a 'typing' command object that tracks changes in text // TODO: create a 'typing' command object that tracks changes in text
// if a new Typing command is created and the top command on the stack is also a Typing // if a new Typing command is created and the top command on the stack is also a Typing
// and they both affect the same element, then collapse the two commands into one // and they both affect the same element, then collapse the two commands into one
// Class: svgedit.history.BatchCommand // Class: svgedit.history.BatchCommand
// implements svgedit.history.HistoryCommand // implements svgedit.history.HistoryCommand
// History command that can contain/execute multiple other commands // History command that can contain/execute multiple other commands
// //
// Parameters: // Parameters:
// text - An optional string visible to user related to this change // text - An optional string visible to user related to this change
svgedit.history.BatchCommand = function(text) { svgedit.history.BatchCommand = function (text) {
this.text = text || "Batch Command"; this.text = text || 'Batch Command';
this.stack = []; this.stack = [];
}; };
svgedit.history.BatchCommand.type = function() { return 'svgedit.history.BatchCommand'; }; svgedit.history.BatchCommand.type = function () { return 'svgedit.history.BatchCommand'; };
svgedit.history.BatchCommand.prototype.type = svgedit.history.BatchCommand.type; svgedit.history.BatchCommand.prototype.type = svgedit.history.BatchCommand.type;
// Function: svgedit.history.BatchCommand.getText // Function: svgedit.history.BatchCommand.getText
svgedit.history.BatchCommand.prototype.getText = function() { svgedit.history.BatchCommand.prototype.getText = function () {
return this.text; return this.text;
}; };
// Function: svgedit.history.BatchCommand.apply // Function: svgedit.history.BatchCommand.apply
// Runs "apply" on all subcommands // Runs "apply" on all subcommands
svgedit.history.BatchCommand.prototype.apply = function(handler) { svgedit.history.BatchCommand.prototype.apply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
} }
@@ -422,13 +423,13 @@ svgedit.history.BatchCommand.prototype.apply = function(handler) {
// Function: svgedit.history.BatchCommand.unapply // Function: svgedit.history.BatchCommand.unapply
// Runs "unapply" on all subcommands // Runs "unapply" on all subcommands
svgedit.history.BatchCommand.prototype.unapply = function(handler) { svgedit.history.BatchCommand.prototype.unapply = function (handler) {
if (handler) { if (handler) {
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this); handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
} }
var i; var i;
for (i = this.stack.length-1; i >= 0; i--) { for (i = this.stack.length - 1; i >= 0; i--) {
this.stack[i].unapply(handler); this.stack[i].unapply(handler);
} }
@@ -439,14 +440,14 @@ svgedit.history.BatchCommand.prototype.unapply = function(handler) {
// Function: svgedit.history.BatchCommand.elements // Function: svgedit.history.BatchCommand.elements
// Iterate through all our subcommands and returns all the elements we are changing // Iterate through all our subcommands and returns all the elements we are changing
svgedit.history.BatchCommand.prototype.elements = function() { svgedit.history.BatchCommand.prototype.elements = function () {
var elems = []; var elems = [];
var cmd = this.stack.length; var cmd = this.stack.length;
while (cmd--) { while (cmd--) {
var thisElems = this.stack[cmd].elements(); var thisElems = this.stack[cmd].elements();
var elem = thisElems.length; var elem = thisElems.length;
while (elem--) { while (elem--) {
if (elems.indexOf(thisElems[elem]) == -1) {elems.push(thisElems[elem]);} if (elems.indexOf(thisElems[elem]) === -1) { elems.push(thisElems[elem]); }
} }
} }
return elems; return elems;
@@ -457,22 +458,21 @@ svgedit.history.BatchCommand.prototype.elements = function() {
// //
// Parameters: // Parameters:
// cmd - The undo command object to add // cmd - The undo command object to add
svgedit.history.BatchCommand.prototype.addSubCommand = function(cmd) { svgedit.history.BatchCommand.prototype.addSubCommand = function (cmd) {
this.stack.push(cmd); this.stack.push(cmd);
}; };
// Function: svgedit.history.BatchCommand.isEmpty // Function: svgedit.history.BatchCommand.isEmpty
// Returns a boolean indicating whether or not the batch command is empty // Returns a boolean indicating whether or not the batch command is empty
svgedit.history.BatchCommand.prototype.isEmpty = function() { svgedit.history.BatchCommand.prototype.isEmpty = function () {
return this.stack.length === 0; return this.stack.length === 0;
}; };
// Class: svgedit.history.UndoManager // Class: svgedit.history.UndoManager
// Parameters: // Parameters:
// historyEventHandler - an object that conforms to the HistoryEventHandler interface // historyEventHandler - an object that conforms to the HistoryEventHandler interface
// (see above) // (see above)
svgedit.history.UndoManager = function(historyEventHandler) { svgedit.history.UndoManager = function (historyEventHandler) {
this.handler_ = historyEventHandler || null; this.handler_ = historyEventHandler || null;
this.undoStackPointer = 0; this.undoStackPointer = 0;
this.undoStack = []; this.undoStack = [];
@@ -485,7 +485,7 @@ svgedit.history.UndoManager = function(historyEventHandler) {
// Function: svgedit.history.UndoManager.resetUndoStack // Function: svgedit.history.UndoManager.resetUndoStack
// Resets the undo stack, effectively clearing the undo/redo history // Resets the undo stack, effectively clearing the undo/redo history
svgedit.history.UndoManager.prototype.resetUndoStack = function() { svgedit.history.UndoManager.prototype.resetUndoStack = function () {
this.undoStack = []; this.undoStack = [];
this.undoStackPointer = 0; this.undoStackPointer = 0;
}; };
@@ -493,34 +493,34 @@ svgedit.history.UndoManager.prototype.resetUndoStack = function() {
// Function: svgedit.history.UndoManager.getUndoStackSize // Function: svgedit.history.UndoManager.getUndoStackSize
// Returns: // Returns:
// Integer with the current size of the undo history stack // Integer with the current size of the undo history stack
svgedit.history.UndoManager.prototype.getUndoStackSize = function() { svgedit.history.UndoManager.prototype.getUndoStackSize = function () {
return this.undoStackPointer; return this.undoStackPointer;
}; };
// Function: svgedit.history.UndoManager.getRedoStackSize // Function: svgedit.history.UndoManager.getRedoStackSize
// Returns: // Returns:
// Integer with the current size of the redo history stack // Integer with the current size of the redo history stack
svgedit.history.UndoManager.prototype.getRedoStackSize = function() { svgedit.history.UndoManager.prototype.getRedoStackSize = function () {
return this.undoStack.length - this.undoStackPointer; return this.undoStack.length - this.undoStackPointer;
}; };
// Function: svgedit.history.UndoManager.getNextUndoCommandText // Function: svgedit.history.UndoManager.getNextUndoCommandText
// Returns: // Returns:
// String associated with the next undo command // String associated with the next undo command
svgedit.history.UndoManager.prototype.getNextUndoCommandText = function() { svgedit.history.UndoManager.prototype.getNextUndoCommandText = function () {
return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer-1].getText() : ""; return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';
}; };
// Function: svgedit.history.UndoManager.getNextRedoCommandText // Function: svgedit.history.UndoManager.getNextRedoCommandText
// Returns: // Returns:
// String associated with the next redo command // String associated with the next redo command
svgedit.history.UndoManager.prototype.getNextRedoCommandText = function() { svgedit.history.UndoManager.prototype.getNextRedoCommandText = function () {
return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : ""; return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';
}; };
// Function: svgedit.history.UndoManager.undo // Function: svgedit.history.UndoManager.undo
// Performs an undo step // Performs an undo step
svgedit.history.UndoManager.prototype.undo = function() { svgedit.history.UndoManager.prototype.undo = function () {
if (this.undoStackPointer > 0) { if (this.undoStackPointer > 0) {
var cmd = this.undoStack[--this.undoStackPointer]; var cmd = this.undoStack[--this.undoStackPointer];
cmd.unapply(this.handler_); cmd.unapply(this.handler_);
@@ -529,7 +529,7 @@ svgedit.history.UndoManager.prototype.undo = function() {
// Function: svgedit.history.UndoManager.redo // Function: svgedit.history.UndoManager.redo
// Performs a redo step // Performs a redo step
svgedit.history.UndoManager.prototype.redo = function() { svgedit.history.UndoManager.prototype.redo = function () {
if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) { if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {
var cmd = this.undoStack[this.undoStackPointer++]; var cmd = this.undoStack[this.undoStackPointer++];
cmd.apply(this.handler_); cmd.apply(this.handler_);
@@ -541,7 +541,7 @@ svgedit.history.UndoManager.prototype.redo = function() {
// //
// Parameters: // Parameters:
// cmd - The command object to add // cmd - The command object to add
svgedit.history.UndoManager.prototype.addCommandToHistory = function(cmd) { svgedit.history.UndoManager.prototype.addCommandToHistory = function (cmd) {
// FIXME: we MUST compress consecutive text changes to the same element // FIXME: we MUST compress consecutive text changes to the same element
// (right now each keystroke is saved as a separate command that includes the // (right now each keystroke is saved as a separate command that includes the
// entire text contents of the text element) // entire text contents of the text element)
@@ -556,7 +556,6 @@ svgedit.history.UndoManager.prototype.addCommandToHistory = function(cmd) {
this.undoStackPointer = this.undoStack.length; this.undoStackPointer = this.undoStack.length;
}; };
// Function: svgedit.history.UndoManager.beginUndoableChange // Function: svgedit.history.UndoManager.beginUndoableChange
// This function tells the canvas to remember the old values of the // This function tells the canvas to remember the old values of the
// attrName attribute for each element sent in. The elements and values // attrName attribute for each element sent in. The elements and values
@@ -567,13 +566,13 @@ svgedit.history.UndoManager.prototype.addCommandToHistory = function(cmd) {
// Parameters: // Parameters:
// attrName - The name of the attribute being changed // attrName - The name of the attribute being changed
// elems - Array of DOM elements being changed // elems - Array of DOM elements being changed
svgedit.history.UndoManager.prototype.beginUndoableChange = function(attrName, elems) { svgedit.history.UndoManager.prototype.beginUndoableChange = function (attrName, elems) {
var p = ++this.undoChangeStackPointer; var p = ++this.undoChangeStackPointer;
var i = elems.length; var i = elems.length;
var oldValues = new Array(i), elements = new Array(i); var oldValues = new Array(i), elements = new Array(i);
while (i--) { while (i--) {
var elem = elems[i]; var elem = elems[i];
if (elem == null) {continue;} if (elem == null) { continue; }
elements[i] = elem; elements[i] = elem;
oldValues[i] = elem.getAttribute(attrName); oldValues[i] = elem.getAttribute(attrName);
} }
@@ -591,23 +590,22 @@ svgedit.history.UndoManager.prototype.beginUndoableChange = function(attrName, e
// //
// Returns: // Returns:
// Batch command object with resulting changes // Batch command object with resulting changes
svgedit.history.UndoManager.prototype.finishUndoableChange = function() { svgedit.history.UndoManager.prototype.finishUndoableChange = function () {
var p = this.undoChangeStackPointer--; var p = this.undoChangeStackPointer--;
var changeset = this.undoableChangeStack[p]; var changeset = this.undoableChangeStack[p];
var i = changeset.elements.length; var i = changeset.elements.length;
var attrName = changeset.attrName; var attrName = changeset.attrName;
var batchCmd = new svgedit.history.BatchCommand("Change " + attrName); var batchCmd = new svgedit.history.BatchCommand('Change ' + attrName);
while (i--) { while (i--) {
var elem = changeset.elements[i]; var elem = changeset.elements[i];
if (elem == null) {continue;} if (elem == null) { continue; }
var changes = {}; var changes = {};
changes[attrName] = changeset.oldValues[i]; changes[attrName] = changeset.oldValues[i];
if (changes[attrName] != elem.getAttribute(attrName)) { if (changes[attrName] !== elem.getAttribute(attrName)) {
batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(elem, changes, attrName)); batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(elem, changes, attrName));
} }
} }
this.undoableChangeStack[p] = null; this.undoableChangeStack[p] = null;
return batchCmd; return batchCmd;
}; };
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals svgedit*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true */ /* globals svgedit */
/** /**
* Package: svgedit.history * Package: svgedit.history
* *
@@ -11,8 +11,8 @@
// Dependencies: // Dependencies:
// 1) history.js // 1) history.js
(function() { (function () {
'use strict'; 'use strict';
if (!svgedit.history) { if (!svgedit.history) {
svgedit.history = {}; svgedit.history = {};
@@ -57,7 +57,7 @@ var history = svgedit.history;
* A value of null is valid for cases where no history recording is required. * A value of null is valid for cases where no history recording is required.
* See singleton: HistoryRecordingService.NO_HISTORY * See singleton: HistoryRecordingService.NO_HISTORY
*/ */
var HistoryRecordingService = history.HistoryRecordingService = function(undoManager) { var HistoryRecordingService = history.HistoryRecordingService = function (undoManager) {
this.undoManager_ = undoManager; this.undoManager_ = undoManager;
this.currentBatchCommand_ = null; this.currentBatchCommand_ = null;
this.batchCommandStack_ = []; this.batchCommandStack_ = [];
@@ -76,8 +76,8 @@ HistoryRecordingService.NO_HISTORY = new HistoryRecordingService();
* @param {string} text - Optional string describing the batch command. * @param {string} text - Optional string describing the batch command.
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.startBatchCommand = function(text) { HistoryRecordingService.prototype.startBatchCommand = function (text) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
this.currentBatchCommand_ = new history.BatchCommand(text); this.currentBatchCommand_ = new history.BatchCommand(text);
this.batchCommandStack_.push(this.currentBatchCommand_); this.batchCommandStack_.push(this.currentBatchCommand_);
return this; return this;
@@ -87,13 +87,13 @@ HistoryRecordingService.prototype.startBatchCommand = function(text) {
* End a batch command and add it to the history or a parent batch command. * End a batch command and add it to the history or a parent batch command.
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.endBatchCommand = function() { HistoryRecordingService.prototype.endBatchCommand = function () {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
if (this.currentBatchCommand_) { if (this.currentBatchCommand_) {
var batchCommand = this.currentBatchCommand_; var batchCommand = this.currentBatchCommand_;
this.batchCommandStack_.pop(); this.batchCommandStack_.pop();
var length = this.batchCommandStack_.length; var length = this.batchCommandStack_.length;
this.currentBatchCommand_ = length ? this.batchCommandStack_[length-1] : null; this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null;
this.addCommand_(batchCommand); this.addCommand_(batchCommand);
} }
return this; return this;
@@ -107,8 +107,8 @@ HistoryRecordingService.prototype.endBatchCommand = function() {
* @param {string} [text] - An optional string visible to user related to this change * @param {string} [text] - An optional string visible to user related to this change
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.moveElement = function(elem, oldNextSibling, oldParent, text) { HistoryRecordingService.prototype.moveElement = function (elem, oldNextSibling, oldParent, text) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
this.addCommand_(new history.MoveElementCommand(elem, oldNextSibling, oldParent, text)); this.addCommand_(new history.MoveElementCommand(elem, oldNextSibling, oldParent, text));
return this; return this;
}; };
@@ -119,13 +119,12 @@ HistoryRecordingService.prototype.moveElement = function(elem, oldNextSibling, o
* @param {string} [text] - An optional string visible to user related to this change * @param {string} [text] - An optional string visible to user related to this change
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.insertElement = function(elem, text) { HistoryRecordingService.prototype.insertElement = function (elem, text) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
this.addCommand_(new history.InsertElementCommand(elem, text)); this.addCommand_(new history.InsertElementCommand(elem, text));
return this; return this;
}; };
/** /**
* Add a RemoveElementCommand to the history or current batch command * Add a RemoveElementCommand to the history or current batch command
* @param {Element} elem - The DOM element that was removed * @param {Element} elem - The DOM element that was removed
@@ -134,13 +133,12 @@ HistoryRecordingService.prototype.insertElement = function(elem, text) {
* @param {string} [text] - An optional string visible to user related to this change * @param {string} [text] - An optional string visible to user related to this change
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.removeElement = function(elem, oldNextSibling, oldParent, text) { HistoryRecordingService.prototype.removeElement = function (elem, oldNextSibling, oldParent, text) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
this.addCommand_(new history.RemoveElementCommand(elem, oldNextSibling, oldParent, text)); this.addCommand_(new history.RemoveElementCommand(elem, oldNextSibling, oldParent, text));
return this; return this;
}; };
/** /**
* Add a ChangeElementCommand to the history or current batch command * Add a ChangeElementCommand to the history or current batch command
* @param {Element} elem - The DOM element that was changed * @param {Element} elem - The DOM element that was changed
@@ -148,8 +146,8 @@ HistoryRecordingService.prototype.removeElement = function(elem, oldNextSibling,
* @param {string} [text] - An optional string visible to user related to this change * @param {string} [text] - An optional string visible to user related to this change
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
*/ */
HistoryRecordingService.prototype.changeElement = function(elem, attrs, text) { HistoryRecordingService.prototype.changeElement = function (elem, attrs, text) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
this.addCommand_(new history.ChangeElementCommand(elem, attrs, text)); this.addCommand_(new history.ChangeElementCommand(elem, attrs, text));
return this; return this;
}; };
@@ -160,14 +158,12 @@ HistoryRecordingService.prototype.changeElement = function(elem, attrs, text) {
* @returns {svgedit.history.HistoryRecordingService} * @returns {svgedit.history.HistoryRecordingService}
* @private * @private
*/ */
HistoryRecordingService.prototype.addCommand_ = function(cmd) { HistoryRecordingService.prototype.addCommand_ = function (cmd) {
if (!this.undoManager_) {return this;} if (!this.undoManager_) { return this; }
if (this.currentBatchCommand_) { if (this.currentBatchCommand_) {
this.currentBatchCommand_.addSubCommand(cmd); this.currentBatchCommand_.addSubCommand(cmd);
} else { } else {
this.undoManager_.addCommandToHistory(cmd); this.undoManager_.addCommandToHistory(cmd);
} }
}; };
}()); }());

115
editor/jquery-svg.js vendored
View File

@@ -1,5 +1,5 @@
/*globals $, jQuery */ /* eslint-disable no-var */
/*jslint vars: true */ /* globals $, jQuery */
/** /**
* jQuery module to work with SVG. * jQuery module to work with SVG.
* *
@@ -10,65 +10,66 @@
// Dependencies: // Dependencies:
// 1) jquery // 1) jquery
(function() {'use strict'; (function () {
'use strict';
// This fixes $(...).attr() to work as expected with SVG elements. // This fixes $(...).attr() to work as expected with SVG elements.
// Does not currently use *AttributeNS() since we rarely need that. // Does not currently use *AttributeNS() since we rarely need that.
// See http://api.jquery.com/attr/ for basic documentation of .attr() // See http://api.jquery.com/attr/ for basic documentation of .attr()
// Additional functionality: // Additional functionality:
// - When getting attributes, a string that's a number is return as type number. // - When getting attributes, a string that's a number is return as type number.
// - If an array is supplied as first parameter, multiple values are returned // - If an array is supplied as first parameter, multiple values are returned
// as an object with values for each given attributes // as an object with values for each given attributes
var proxied = jQuery.fn.attr, var proxied = jQuery.fn.attr,
// TODO use NS.SVG instead // TODO use NS.SVG instead
svgns = "http://www.w3.org/2000/svg"; svgns = 'http://www.w3.org/2000/svg';
jQuery.fn.attr = function(key, value) { jQuery.fn.attr = function (key, value) {
var i, attr; var i, attr;
var len = this.length; var len = this.length;
if (!len) {return proxied.apply(this, arguments);} if (!len) { return proxied.apply(this, arguments); }
for (i = 0; i < len; ++i) { for (i = 0; i < len; ++i) {
var elem = this[i]; var elem = this[i];
// set/get SVG attribute // set/get SVG attribute
if (elem.namespaceURI === svgns) { if (elem.namespaceURI === svgns) {
// Setting attribute // Setting attribute
if (value !== undefined) { if (value !== undefined) {
elem.setAttribute(key, value); elem.setAttribute(key, value);
} else if ($.isArray(key)) { } else if ($.isArray(key)) {
// Getting attributes from array // Getting attributes from array
var j = key.length, obj = {}; var j = key.length, obj = {};
while (j--) { while (j--) {
var aname = key[j]; var aname = key[j];
attr = elem.getAttribute(aname); attr = elem.getAttribute(aname);
// This returns a number when appropriate // This returns a number when appropriate
if (attr || attr === "0") { if (attr || attr === '0') {
attr = isNaN(attr) ? attr : (attr - 0); attr = isNaN(attr) ? attr : (attr - 0);
} }
obj[aname] = attr; obj[aname] = attr;
} }
return obj; return obj;
} }
if (typeof key === "object") { if (typeof key === 'object') {
// Setting attributes form object // Setting attributes form object
var v; var v;
for (v in key) { for (v in key) {
elem.setAttribute(v, key[v]); elem.setAttribute(v, key[v]);
} }
// Getting attribute // Getting attribute
} else { } else {
attr = elem.getAttribute(key); attr = elem.getAttribute(key);
if (attr || attr === "0") { if (attr || attr === '0') {
attr = isNaN(attr) ? attr : (attr - 0); attr = isNaN(attr) ? attr : (attr - 0);
} }
return attr; return attr;
} }
} else { } else {
return proxied.apply(this, arguments); return proxied.apply(this, arguments);
} }
} }
return this; return this;
}; };
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals $ svgedit*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true */ /* globals $ svgedit */
/** /**
* Package: svgedit.history * Package: svgedit.history
* *
@@ -13,15 +13,14 @@
// 1) svgedit.js // 1) svgedit.js
// 2) draw.js // 2) draw.js
(function() { (function () {
'use strict'; 'use strict';
if (!svgedit.draw) { if (!svgedit.draw) {
svgedit.draw = {}; svgedit.draw = {};
} }
var NS = svgedit.NS; var NS = svgedit.NS;
/** /**
* This class encapsulates the concept of a layer in the drawing. It can be constructed with * This class encapsulates the concept of a layer in the drawing. It can be constructed with
* an existing group element or, with three parameters, will create a new layer group element. * an existing group element or, with three parameters, will create a new layer group element.
@@ -39,17 +38,17 @@ var NS = svgedit.NS;
* @param {SVGGElement=} svgElem - The SVG DOM element. If defined, use this to add * @param {SVGGElement=} svgElem - The SVG DOM element. If defined, use this to add
* a new layer to the document. * a new layer to the document.
*/ */
var Layer = svgedit.draw.Layer = function(name, group, svgElem) { var Layer = svgedit.draw.Layer = function (name, group, svgElem) {
this.name_ = name; this.name_ = name;
this.group_ = svgElem ? null : group; this.group_ = svgElem ? null : group;
if (svgElem) { if (svgElem) {
// Create a group element with title and add it to the DOM. // Create a group element with title and add it to the DOM.
var svgdoc = svgElem.ownerDocument; var svgdoc = svgElem.ownerDocument;
this.group_ = svgdoc.createElementNS(NS.SVG, "g"); this.group_ = svgdoc.createElementNS(NS.SVG, 'g');
var layer_title = svgdoc.createElementNS(NS.SVG, "title"); var layerTitle = svgdoc.createElementNS(NS.SVG, 'title');
layer_title.textContent = name; layerTitle.textContent = name;
this.group_.appendChild(layer_title); this.group_.appendChild(layerTitle);
if (group) { if (group) {
$(group).after(this.group_); $(group).after(this.group_);
} else { } else {
@@ -58,9 +57,11 @@ var Layer = svgedit.draw.Layer = function(name, group, svgElem) {
} }
addLayerClass(this.group_); addLayerClass(this.group_);
svgedit.utilities.walkTree(this.group_, function(e){e.setAttribute("style", "pointer-events:inherit");}); svgedit.utilities.walkTree(this.group_, function (e) {
e.setAttribute('style', 'pointer-events:inherit');
});
this.group_.setAttribute("style", svgElem ? "pointer-events:all" : "pointer-events:none"); this.group_.setAttribute('style', svgElem ? 'pointer-events:all' : 'pointer-events:none');
}; };
/** /**
@@ -73,12 +74,11 @@ Layer.CLASS_NAME = 'layer';
*/ */
Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)'); Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)');
/** /**
* Get the layer's name. * Get the layer's name.
* @returns {string} The layer name * @returns {string} The layer name
*/ */
Layer.prototype.getName = function() { Layer.prototype.getName = function () {
return this.name_; return this.name_;
}; };
@@ -86,33 +86,33 @@ Layer.prototype.getName = function() {
* Get the group element for this layer. * Get the group element for this layer.
* @returns {SVGGElement} The layer SVG group * @returns {SVGGElement} The layer SVG group
*/ */
Layer.prototype.getGroup = function() { Layer.prototype.getGroup = function () {
return this.group_; return this.group_;
}; };
/** /**
* Active this layer so it takes pointer events. * Active this layer so it takes pointer events.
*/ */
Layer.prototype.activate = function() { Layer.prototype.activate = function () {
this.group_.setAttribute("style", "pointer-events:all"); this.group_.setAttribute('style', 'pointer-events:all');
}; };
/** /**
* Deactive this layer so it does NOT take pointer events. * Deactive this layer so it does NOT take pointer events.
*/ */
Layer.prototype.deactivate = function() { Layer.prototype.deactivate = function () {
this.group_.setAttribute("style", "pointer-events:none"); this.group_.setAttribute('style', 'pointer-events:none');
}; };
/** /**
* Set this layer visible or hidden based on 'visible' parameter. * Set this layer visible or hidden based on 'visible' parameter.
* @param {boolean} visible - If true, make visible; otherwise, hide it. * @param {boolean} visible - If true, make visible; otherwise, hide it.
*/ */
Layer.prototype.setVisible = function(visible) { Layer.prototype.setVisible = function (visible) {
var expected = visible === undefined || visible ? "inline" : "none"; var expected = visible === undefined || visible ? 'inline' : 'none';
var oldDisplay = this.group_.getAttribute("display"); var oldDisplay = this.group_.getAttribute('display');
if (oldDisplay !== expected) { if (oldDisplay !== expected) {
this.group_.setAttribute("display", expected); this.group_.setAttribute('display', expected);
} }
}; };
@@ -120,7 +120,7 @@ Layer.prototype.setVisible = function(visible) {
* Is this layer visible? * Is this layer visible?
* @returns {boolean} True if visible. * @returns {boolean} True if visible.
*/ */
Layer.prototype.isVisible = function() { Layer.prototype.isVisible = function () {
return this.group_.getAttribute('display') !== 'none'; return this.group_.getAttribute('display') !== 'none';
}; };
@@ -128,7 +128,7 @@ Layer.prototype.isVisible = function() {
* Get layer opacity. * Get layer opacity.
* @returns {number} Opacity value. * @returns {number} Opacity value.
*/ */
Layer.prototype.getOpacity = function() { Layer.prototype.getOpacity = function () {
var opacity = this.group_.getAttribute('opacity'); var opacity = this.group_.getAttribute('opacity');
if (opacity === null || opacity === undefined) { if (opacity === null || opacity === undefined) {
return 1; return 1;
@@ -141,7 +141,7 @@ Layer.prototype.getOpacity = function() {
* nothing happens. * nothing happens.
* @param {number} opacity - A float value in the range 0.0-1.0 * @param {number} opacity - A float value in the range 0.0-1.0
*/ */
Layer.prototype.setOpacity = function(opacity) { Layer.prototype.setOpacity = function (opacity) {
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) { if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {
this.group_.setAttribute('opacity', opacity); this.group_.setAttribute('opacity', opacity);
} }
@@ -151,13 +151,13 @@ Layer.prototype.setOpacity = function(opacity) {
* Append children to this layer. * Append children to this layer.
* @param {SVGGElement} children - The children to append to this layer. * @param {SVGGElement} children - The children to append to this layer.
*/ */
Layer.prototype.appendChildren = function(children) { Layer.prototype.appendChildren = function (children) {
for (var i = 0; i < children.length; ++i) { for (var i = 0; i < children.length; ++i) {
this.group_.appendChild(children[i]); this.group_.appendChild(children[i]);
} }
}; };
Layer.prototype.getTitleElement = function() { Layer.prototype.getTitleElement = function () {
var len = this.group_.childNodes.length; var len = this.group_.childNodes.length;
for (var i = 0; i < len; ++i) { for (var i = 0; i < len; ++i) {
var child = this.group_.childNodes.item(i); var child = this.group_.childNodes.item(i);
@@ -174,7 +174,7 @@ Layer.prototype.getTitleElement = function() {
* @param {svgedit.history.HistoryRecordingService} hrService - History recording service * @param {svgedit.history.HistoryRecordingService} hrService - History recording service
* @returns {string|null} The new name if changed; otherwise, null. * @returns {string|null} The new name if changed; otherwise, null.
*/ */
Layer.prototype.setName = function(name, hrService) { Layer.prototype.setName = function (name, hrService) {
var previousName = this.name_; var previousName = this.name_;
name = svgedit.utilities.toXml(name); name = svgedit.utilities.toXml(name);
// now change the underlying title element contents // now change the underlying title element contents
@@ -184,7 +184,7 @@ Layer.prototype.setName = function(name, hrService) {
title.textContent = name; title.textContent = name;
this.name_ = name; this.name_ = name;
if (hrService) { if (hrService) {
hrService.changeElement(title, {'#text':previousName}); hrService.changeElement(title, {'#text': previousName});
} }
return this.name_; return this.name_;
} }
@@ -196,27 +196,25 @@ Layer.prototype.setName = function(name, hrService) {
* @param {SVGGElement} children - The children to append to this layer. * @param {SVGGElement} children - The children to append to this layer.
* @returns {SVGGElement} The layer SVG group that was just removed. * @returns {SVGGElement} The layer SVG group that was just removed.
*/ */
Layer.prototype.removeGroup = function() { Layer.prototype.removeGroup = function () {
var parent = this.group_.parentNode; var parent = this.group_.parentNode;
var group = parent.removeChild(this.group_); var group = parent.removeChild(this.group_);
this.group_ = undefined; this.group_ = undefined;
return group; return group;
}; };
/** /**
* Add class Layer.CLASS_NAME to the element (usually class='layer'). * Add class Layer.CLASS_NAME to the element (usually class='layer').
* *
* Parameters: * Parameters:
* @param {SVGGElement} elem - The SVG element to update * @param {SVGGElement} elem - The SVG element to update
*/ */
function addLayerClass(elem) { function addLayerClass (elem) {
var classes = elem.getAttribute('class'); var classes = elem.getAttribute('class');
if (classes === null || classes === undefined || classes.length === 0) { if (classes === null || classes === undefined || classes.length === 0) {
elem.setAttribute('class', Layer.CLASS_NAME); elem.setAttribute('class', Layer.CLASS_NAME);
} else if (! Layer.CLASS_REGEX.test(classes)) { } else if (!Layer.CLASS_REGEX.test(classes)) {
elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME); elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);
} }
} }
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true */ /* globals svgedit */
/** /**
* Package: svedit.math * Package: svedit.math
* *
@@ -20,7 +20,8 @@
* @property {number} a - The angle at which to snap * @property {number} a - The angle at which to snap
*/ */
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.math) { if (!svgedit.math) {
svgedit.math = {}; svgedit.math = {};
@@ -41,10 +42,9 @@ var svg = document.createElementNS(svgedit.NS.SVG, 'svg');
* @returns {object} An x, y object representing the transformed point * @returns {object} An x, y object representing the transformed point
*/ */
svgedit.math.transformPoint = function (x, y, m) { svgedit.math.transformPoint = function (x, y, m) {
return { x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f}; return {x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};
}; };
/** /**
* Helper function to check if the matrix performs no actual transform * Helper function to check if the matrix performs no actual transform
* (i.e. exists for identity purposes) * (i.e. exists for identity purposes)
@@ -55,7 +55,6 @@ svgedit.math.isIdentity = function (m) {
return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0); return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
}; };
/** /**
* This function tries to return a SVGMatrix that is the multiplication m1*m2. * This function tries to return a SVGMatrix that is the multiplication m1*m2.
* We also round to zero when it's near zero * We also round to zero when it's near zero
@@ -63,18 +62,18 @@ svgedit.math.isIdentity = function (m) {
* @returns {SVGMatrix} The matrix object resulting from the calculation * @returns {SVGMatrix} The matrix object resulting from the calculation
*/ */
svgedit.math.matrixMultiply = function (matr) { svgedit.math.matrixMultiply = function (matr) {
var args = arguments, i = args.length, m = args[i-1]; var args = arguments, i = args.length, m = args[i - 1];
while (i-- > 1) { while (i-- > 1) {
var m1 = args[i-1]; var m1 = args[i - 1];
m = m1.multiply(m); m = m1.multiply(m);
} }
if (Math.abs(m.a) < NEAR_ZERO) {m.a = 0;} if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; }
if (Math.abs(m.b) < NEAR_ZERO) {m.b = 0;} if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; }
if (Math.abs(m.c) < NEAR_ZERO) {m.c = 0;} if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; }
if (Math.abs(m.d) < NEAR_ZERO) {m.d = 0;} if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; }
if (Math.abs(m.e) < NEAR_ZERO) {m.e = 0;} if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }
if (Math.abs(m.f) < NEAR_ZERO) {m.f = 0;} if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }
return m; return m;
}; };
@@ -85,11 +84,11 @@ svgedit.math.matrixMultiply = function (matr) {
* @returns {boolean} Whether or not a matrix transform was found * @returns {boolean} Whether or not a matrix transform was found
*/ */
svgedit.math.hasMatrixTransform = function (tlist) { svgedit.math.hasMatrixTransform = function (tlist) {
if (!tlist) {return false;} if (!tlist) { return false; }
var num = tlist.numberOfItems; var num = tlist.numberOfItems;
while (num--) { while (num--) {
var xform = tlist.getItem(num); var xform = tlist.getItem(num);
if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) {return true;} if (xform.type == 1 && !svgedit.math.isIdentity(xform.matrix)) { return true; }
} }
return false; return false;
}; };
@@ -164,15 +163,14 @@ svgedit.math.transformListToTransform = function (tlist, min, max) {
var i; var i;
for (i = min; i <= max; ++i) { for (i = min; i <= max; ++i) {
// if our indices are out of range, just use a harmless identity matrix // if our indices are out of range, just use a harmless identity matrix
var mtom = (i >= 0 && i < tlist.numberOfItems ? var mtom = (i >= 0 && i < tlist.numberOfItems
tlist.getItem(i).matrix : ? tlist.getItem(i).matrix
svg.createSVGMatrix()); : svg.createSVGMatrix());
m = svgedit.math.matrixMultiply(m, mtom); m = svgedit.math.matrixMultiply(m, mtom);
} }
return svg.createSVGTransformFromMatrix(m); return svg.createSVGTransformFromMatrix(m);
}; };
/** /**
* Get the matrix object for a given element * Get the matrix object for a given element
* @param {Element} elem - The DOM element to check * @param {Element} elem - The DOM element to check
@@ -183,7 +181,6 @@ svgedit.math.getMatrix = function (elem) {
return svgedit.math.transformListToTransform(tlist).matrix; return svgedit.math.transformListToTransform(tlist).matrix;
}; };
/** /**
* Returns a 45 degree angle coordinate associated with the two given * Returns a 45 degree angle coordinate associated with the two given
* coordinates * coordinates
@@ -208,7 +205,6 @@ svgedit.math.snapToAngle = function (x1, y1, x2, y2) {
}; };
}; };
/** /**
* Check if two rectangles (BBoxes objects) intersect each other * Check if two rectangles (BBoxes objects) intersect each other
* @param {SVGRect} r1 - The first BBox-like object * @param {SVGRect} r1 - The first BBox-like object
@@ -221,5 +217,4 @@ svgedit.math.rectsIntersect = function (r1, r2) {
r2.y < (r1.y + r1.height) && r2.y < (r1.y + r1.height) &&
(r2.y + r2.height) > r1.y; (r2.y + r2.height) > r1.y;
}; };
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit, svgroot*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true, continue: true*/ /* globals $, svgedit, svgroot */
/** /**
* Package: svgedit.path * Package: svgedit.path
* *
@@ -15,7 +15,8 @@
// 3) math.js // 3) math.js
// 4) svgutils.js // 4) svgutils.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.path) { if (!svgedit.path) {
svgedit.path = {}; svgedit.path = {};
@@ -41,33 +42,33 @@ var segData = {
var pathFuncs = []; var pathFuncs = [];
var link_control_pts = true; var linkControlPts = true;
// Stores references to paths via IDs. // Stores references to paths via IDs.
// TODO: Make this cross-document happy. // TODO: Make this cross-document happy.
var pathData = {}; var pathData = {};
svgedit.path.setLinkControlPoints = function(lcp) { svgedit.path.setLinkControlPoints = function (lcp) {
link_control_pts = lcp; linkControlPts = lcp;
}; };
svgedit.path.path = null; svgedit.path.path = null;
var editorContext_ = null; var editorContext_ = null;
svgedit.path.init = function(editorContext) { svgedit.path.init = function (editorContext) {
editorContext_ = editorContext; editorContext_ = editorContext;
pathFuncs = [0, 'ClosePath']; pathFuncs = [0, 'ClosePath'];
var pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc', var pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',
'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth']; 'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'];
$.each(pathFuncsStrs, function(i, s) { $.each(pathFuncsStrs, function (i, s) {
pathFuncs.push(s+'Abs'); pathFuncs.push(s + 'Abs');
pathFuncs.push(s+'Rel'); pathFuncs.push(s + 'Rel');
}); });
}; };
svgedit.path.insertItemBefore = function(elem, newseg, index) { svgedit.path.insertItemBefore = function (elem, newseg, index) {
// Support insertItemBefore on paths for FF2 // Support insertItemBefore on paths for FF2
var list = elem.pathSegList; var list = elem.pathSegList;
@@ -78,13 +79,13 @@ svgedit.path.insertItemBefore = function(elem, newseg, index) {
var len = list.numberOfItems; var len = list.numberOfItems;
var arr = []; var arr = [];
var i; var i;
for (i=0; i < len; i++) { for (i = 0; i < len; i++) {
var cur_seg = list.getItem(i); var curSeg = list.getItem(i);
arr.push(cur_seg); arr.push(curSeg);
} }
list.clear(); list.clear();
for (i=0; i < len; i++) { for (i = 0; i < len; i++) {
if (i == index) { //index+1 if (i == index) { // index + 1
list.appendItem(newseg); list.appendItem(newseg);
} }
list.appendItem(arr[i]); list.appendItem(arr[i]);
@@ -92,20 +93,20 @@ svgedit.path.insertItemBefore = function(elem, newseg, index) {
}; };
// TODO: See if this should just live in replacePathSeg // TODO: See if this should just live in replacePathSeg
svgedit.path.ptObjToArr = function(type, seg_item) { svgedit.path.ptObjToArr = function (type, segItem) {
var arr = segData[type], len = arr.length; var arr = segData[type], len = arr.length;
var i, out = []; var i, out = [];
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
out[i] = seg_item[arr[i]]; out[i] = segItem[arr[i]];
} }
return out; return out;
}; };
svgedit.path.getGripPt = function(seg, alt_pt) { svgedit.path.getGripPt = function (seg, altPt) {
var out = { var out = {
x: alt_pt? alt_pt.x : seg.item.x, x: altPt ? altPt.x : seg.item.x,
y: alt_pt? alt_pt.y : seg.item.y y: altPt ? altPt.y : seg.item.y
}, path = seg.path; }, path = seg.path;
if (path.matrix) { if (path.matrix) {
var pt = svgedit.math.transformPoint(out.x, out.y, path.matrix); var pt = svgedit.math.transformPoint(out.x, out.y, path.matrix);
@@ -118,7 +119,7 @@ svgedit.path.getGripPt = function(seg, alt_pt) {
return out; return out;
}; };
svgedit.path.getPointFromGrip = function(pt, path) { svgedit.path.getPointFromGrip = function (pt, path) {
var out = { var out = {
x: pt.x, x: pt.x,
y: pt.y y: pt.y
@@ -136,11 +137,11 @@ svgedit.path.getPointFromGrip = function(pt, path) {
return out; return out;
}; };
svgedit.path.addPointGrip = function(index, x, y) { svgedit.path.addPointGrip = function (index, x, y) {
// create the container of all the point grips // create the container of all the point grips
var pointGripContainer = svgedit.path.getGripContainer(); var pointGripContainer = svgedit.path.getGripContainer();
var pointGrip = svgedit.utilities.getElem('pathpointgrip_'+index); var pointGrip = svgedit.utilities.getElem('pathpointgrip_' + index);
// create it // create it
if (!pointGrip) { if (!pointGrip) {
pointGrip = document.createElementNS(NS.SVG, 'circle'); pointGrip = document.createElementNS(NS.SVG, 'circle');
@@ -157,8 +158,8 @@ svgedit.path.addPointGrip = function(index, x, y) {
}); });
pointGrip = pointGripContainer.appendChild(pointGrip); pointGrip = pointGripContainer.appendChild(pointGrip);
var grip = $('#pathpointgrip_'+index); var grip = $('#pathpointgrip_' + index);
grip.dblclick(function() { grip.dblclick(function () {
if (svgedit.path.path) { if (svgedit.path.path) {
svgedit.path.path.setSegType(); svgedit.path.path.setSegType();
} }
@@ -175,7 +176,7 @@ svgedit.path.addPointGrip = function(index, x, y) {
return pointGrip; return pointGrip;
}; };
svgedit.path.getGripContainer = function() { svgedit.path.getGripContainer = function () {
var c = svgedit.utilities.getElem('pathpointgrip_container'); var c = svgedit.utilities.getElem('pathpointgrip_container');
if (!c) { if (!c) {
var parent = svgedit.utilities.getElem('selectorParentGroup'); var parent = svgedit.utilities.getElem('selectorParentGroup');
@@ -185,9 +186,9 @@ svgedit.path.getGripContainer = function() {
return c; return c;
}; };
svgedit.path.addCtrlGrip = function(id) { svgedit.path.addCtrlGrip = function (id) {
var pointGrip = svgedit.utilities.getElem('ctrlpointgrip_'+id); var pointGrip = svgedit.utilities.getElem('ctrlpointgrip_' + id);
if (pointGrip) {return pointGrip;} if (pointGrip) { return pointGrip; }
pointGrip = document.createElementNS(NS.SVG, 'circle'); pointGrip = document.createElementNS(NS.SVG, 'circle');
svgedit.utilities.assignAttributes(pointGrip, { svgedit.utilities.assignAttributes(pointGrip, {
@@ -205,13 +206,13 @@ svgedit.path.addCtrlGrip = function(id) {
return pointGrip; return pointGrip;
}; };
svgedit.path.getCtrlLine = function(id) { svgedit.path.getCtrlLine = function (id) {
var ctrlLine = svgedit.utilities.getElem('ctrlLine_'+id); var ctrlLine = svgedit.utilities.getElem('ctrlLine_' + id);
if (ctrlLine) {return ctrlLine;} if (ctrlLine) { return ctrlLine; }
ctrlLine = document.createElementNS(NS.SVG, 'line'); ctrlLine = document.createElementNS(NS.SVG, 'line');
svgedit.utilities.assignAttributes(ctrlLine, { svgedit.utilities.assignAttributes(ctrlLine, {
'id': 'ctrlLine_'+id, 'id': 'ctrlLine_' + id,
'stroke': '#555', 'stroke': '#555',
'stroke-width': 1, 'stroke-width': 1,
'style': 'pointer-events:none' 'style': 'pointer-events:none'
@@ -220,7 +221,7 @@ svgedit.path.getCtrlLine = function(id) {
return ctrlLine; return ctrlLine;
}; };
svgedit.path.getPointGrip = function(seg, update) { svgedit.path.getPointGrip = function (seg, update) {
var index = seg.index; var index = seg.index;
var pointGrip = svgedit.path.addPointGrip(index); var pointGrip = svgedit.path.addPointGrip(index);
@@ -236,17 +237,17 @@ svgedit.path.getPointGrip = function(seg, update) {
return pointGrip; return pointGrip;
}; };
svgedit.path.getControlPoints = function(seg) { svgedit.path.getControlPoints = function (seg) {
var item = seg.item; var item = seg.item;
var index = seg.index; var index = seg.index;
if (!('x1' in item) || !('x2' in item)) {return null;} if (!('x1' in item) || !('x2' in item)) { return null; }
var cpt = {}; var cpt = {};
var pointGripContainer = svgedit.path.getGripContainer(); /* var pointGripContainer = */ svgedit.path.getGripContainer();
// Note that this is intentionally not seg.prev.item // Note that this is intentionally not seg.prev.item
var prev = svgedit.path.path.segs[index-1].item; var prev = svgedit.path.path.segs[index - 1].item;
var seg_items = [prev, item]; var segItems = [prev, item];
var i; var i;
for (i = 1; i < 3; i++) { for (i = 1; i < 3; i++) {
@@ -254,8 +255,8 @@ svgedit.path.getControlPoints = function(seg) {
var ctrlLine = cpt['c' + i + '_line'] = svgedit.path.getCtrlLine(id); var ctrlLine = cpt['c' + i + '_line'] = svgedit.path.getCtrlLine(id);
var pt = svgedit.path.getGripPt(seg, {x:item['x' + i], y:item['y' + i]}); var pt = svgedit.path.getGripPt(seg, {x: item['x' + i], y: item['y' + i]});
var gpt = svgedit.path.getGripPt(seg, {x:seg_items[i-1].x, y:seg_items[i-1].y}); var gpt = svgedit.path.getGripPt(seg, {x: segItems[i - 1].x, y: segItems[i - 1].y});
svgedit.utilities.assignAttributes(ctrlLine, { svgedit.utilities.assignAttributes(ctrlLine, {
'x1': pt.x, 'x1': pt.x,
@@ -281,7 +282,7 @@ svgedit.path.getControlPoints = function(seg) {
}; };
// This replaces the segment at the given index. Type is given as number. // This replaces the segment at the given index. Type is given as number.
svgedit.path.replacePathSeg = function(type, index, pts, elem) { svgedit.path.replacePathSeg = function (type, index, pts, elem) {
var path = elem || svgedit.path.path.elem; var path = elem || svgedit.path.path.elem;
var func = 'createSVGPathSeg' + pathFuncs[type]; var func = 'createSVGPathSeg' + pathFuncs[type];
@@ -295,8 +296,8 @@ svgedit.path.replacePathSeg = function(type, index, pts, elem) {
var arr = []; var arr = [];
var i; var i;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
var cur_seg = segList.getItem(i); var curSeg = segList.getItem(i);
arr.push(cur_seg); arr.push(curSeg);
} }
segList.clear(); segList.clear();
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
@@ -309,7 +310,7 @@ svgedit.path.replacePathSeg = function(type, index, pts, elem) {
} }
}; };
svgedit.path.getSegSelector = function(seg, update) { svgedit.path.getSegSelector = function (seg, update) {
var index = seg.index; var index = seg.index;
var segLine = svgedit.utilities.getElem('segline_' + index); var segLine = svgedit.utilities.getElem('segline_' + index);
if (!segLine) { if (!segLine) {
@@ -322,7 +323,7 @@ svgedit.path.getSegSelector = function(seg, update) {
'fill': 'none', 'fill': 'none',
'stroke': '#0FF', 'stroke': '#0FF',
'stroke-width': 2, 'stroke-width': 2,
'style':'pointer-events:none', 'style': 'pointer-events:none',
'd': 'M0,0 0,0' 'd': 'M0,0 0,0'
}); });
pointGripContainer.appendChild(segLine); pointGripContainer.appendChild(segLine);
@@ -342,9 +343,9 @@ svgedit.path.getSegSelector = function(seg, update) {
var pts = svgedit.path.ptObjToArr(seg.type, seg.item, true); var pts = svgedit.path.ptObjToArr(seg.type, seg.item, true);
var i; var i;
for (i = 0; i < pts.length; i += 2) { for (i = 0; i < pts.length; i += 2) {
pt = svgedit.path.getGripPt(seg, {x:pts[i], y:pts[i+1]}); pt = svgedit.path.getGripPt(seg, {x: pts[i], y: pts[i + 1]});
pts[i] = pt.x; pts[i] = pt.x;
pts[i+1] = pt.y; pts[i + 1] = pt.y;
} }
svgedit.path.replacePathSeg(seg.type, 1, pts, segLine); svgedit.path.replacePathSeg(seg.type, 1, pts, segLine);
@@ -362,48 +363,47 @@ svgedit.path.getSegSelector = function(seg, update) {
// //
// Returns: // Returns:
// Array of two "smoothed" point objects // Array of two "smoothed" point objects
svgedit.path.smoothControlPoints = function(ct1, ct2, pt) { svgedit.path.smoothControlPoints = function (ct1, ct2, pt) {
// each point must not be the origin // each point must not be the origin
var x1 = ct1.x - pt.x, var x1 = ct1.x - pt.x,
y1 = ct1.y - pt.y, y1 = ct1.y - pt.y,
x2 = ct2.x - pt.x, x2 = ct2.x - pt.x,
y2 = ct2.y - pt.y; y2 = ct2.y - pt.y;
if ( (x1 != 0 || y1 != 0) && (x2 != 0 || y2 != 0) ) { if ((x1 != 0 || y1 != 0) && (x2 != 0 || y2 != 0)) {
var anglea = Math.atan2(y1, x1), var anglea = Math.atan2(y1, x1),
angleb = Math.atan2(y2, x2), angleb = Math.atan2(y2, x2),
r1 = Math.sqrt(x1*x1+y1*y1), r1 = Math.sqrt(x1 * x1 + y1 * y1),
r2 = Math.sqrt(x2*x2+y2*y2), r2 = Math.sqrt(x2 * x2 + y2 * y2),
nct1 = editorContext_.getSVGRoot().createSVGPoint(), nct1 = editorContext_.getSVGRoot().createSVGPoint(),
nct2 = editorContext_.getSVGRoot().createSVGPoint(); nct2 = editorContext_.getSVGRoot().createSVGPoint();
if (anglea < 0) { anglea += 2*Math.PI; } if (anglea < 0) { anglea += 2 * Math.PI; }
if (angleb < 0) { angleb += 2*Math.PI; } if (angleb < 0) { angleb += 2 * Math.PI; }
var angleBetween = Math.abs(anglea - angleb), var angleBetween = Math.abs(anglea - angleb),
angleDiff = Math.abs(Math.PI - angleBetween)/2; angleDiff = Math.abs(Math.PI - angleBetween) / 2;
var new_anglea, new_angleb; var newAnglea, newAngleb;
if (anglea - angleb > 0) { if (anglea - angleb > 0) {
new_anglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff); newAnglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff);
new_angleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff); newAngleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff);
} } else {
else { newAnglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff);
new_anglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff); newAngleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);
new_angleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);
} }
// rotate the points // rotate the points
nct1.x = r1 * Math.cos(new_anglea) + pt.x; nct1.x = r1 * Math.cos(newAnglea) + pt.x;
nct1.y = r1 * Math.sin(new_anglea) + pt.y; nct1.y = r1 * Math.sin(newAnglea) + pt.y;
nct2.x = r2 * Math.cos(new_angleb) + pt.x; nct2.x = r2 * Math.cos(newAngleb) + pt.x;
nct2.y = r2 * Math.sin(new_angleb) + pt.y; nct2.y = r2 * Math.sin(newAngleb) + pt.y;
return [nct1, nct2]; return [nct1, nct2];
} }
return undefined; return undefined;
}; };
svgedit.path.Segment = function(index, item) { svgedit.path.Segment = function (index, item) {
this.selected = false; this.selected = false;
this.index = index; this.index = index;
this.item = item; this.item = item;
@@ -414,7 +414,7 @@ svgedit.path.Segment = function(index, item) {
this.segsel = null; this.segsel = null;
}; };
svgedit.path.Segment.prototype.showCtrlPts = function(y) { svgedit.path.Segment.prototype.showCtrlPts = function (y) {
var i; var i;
for (i in this.ctrlpts) { for (i in this.ctrlpts) {
if (this.ctrlpts.hasOwnProperty(i)) { if (this.ctrlpts.hasOwnProperty(i)) {
@@ -423,12 +423,12 @@ svgedit.path.Segment.prototype.showCtrlPts = function(y) {
} }
}; };
svgedit.path.Segment.prototype.selectCtrls = function(y) { svgedit.path.Segment.prototype.selectCtrls = function (y) {
$('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2'). $('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2')
attr('fill', y ? '#0FF' : '#EEE'); .attr('fill', y ? '#0FF' : '#EEE');
}; };
svgedit.path.Segment.prototype.show = function(y) { svgedit.path.Segment.prototype.show = function (y) {
if (this.ptgrip) { if (this.ptgrip) {
this.ptgrip.setAttribute('display', y ? 'inline' : 'none'); this.ptgrip.setAttribute('display', y ? 'inline' : 'none');
this.segsel.setAttribute('display', y ? 'inline' : 'none'); this.segsel.setAttribute('display', y ? 'inline' : 'none');
@@ -437,7 +437,7 @@ svgedit.path.Segment.prototype.show = function(y) {
} }
}; };
svgedit.path.Segment.prototype.select = function(y) { svgedit.path.Segment.prototype.select = function (y) {
if (this.ptgrip) { if (this.ptgrip) {
this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F'); this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F');
this.segsel.setAttribute('display', y ? 'inline' : 'none'); this.segsel.setAttribute('display', y ? 'inline' : 'none');
@@ -448,13 +448,13 @@ svgedit.path.Segment.prototype.select = function(y) {
} }
}; };
svgedit.path.Segment.prototype.addGrip = function() { svgedit.path.Segment.prototype.addGrip = function () {
this.ptgrip = svgedit.path.getPointGrip(this, true); this.ptgrip = svgedit.path.getPointGrip(this, true);
this.ctrlpts = svgedit.path.getControlPoints(this, true); this.ctrlpts = svgedit.path.getControlPoints(this, true);
this.segsel = svgedit.path.getSegSelector(this, true); this.segsel = svgedit.path.getSegSelector(this, true);
}; };
svgedit.path.Segment.prototype.update = function(full) { svgedit.path.Segment.prototype.update = function (full) {
if (this.ptgrip) { if (this.ptgrip) {
var pt = svgedit.path.getGripPt(this); var pt = svgedit.path.getGripPt(this);
svgedit.utilities.assignAttributes(this.ptgrip, { svgedit.utilities.assignAttributes(this.ptgrip, {
@@ -475,23 +475,23 @@ svgedit.path.Segment.prototype.update = function(full) {
} }
}; };
svgedit.path.Segment.prototype.move = function(dx, dy) { svgedit.path.Segment.prototype.move = function (dx, dy) {
var cur_pts, item = this.item; var curPts, item = this.item;
if (this.ctrlpts) { if (this.ctrlpts) {
cur_pts = [item.x += dx, item.y += dy, curPts = [item.x += dx, item.y += dy,
item.x1, item.y1, item.x2 += dx, item.y2 += dy]; item.x1, item.y1, item.x2 += dx, item.y2 += dy];
} else { } else {
cur_pts = [item.x += dx, item.y += dy]; curPts = [item.x += dx, item.y += dy];
} }
svgedit.path.replacePathSeg(this.type, this.index, cur_pts); svgedit.path.replacePathSeg(this.type, this.index, curPts);
if (this.next && this.next.ctrlpts) { if (this.next && this.next.ctrlpts) {
var next = this.next.item; var next = this.next.item;
var next_pts = [next.x, next.y, var nextPts = [next.x, next.y,
next.x1 += dx, next.y1 += dy, next.x2, next.y2]; next.x1 += dx, next.y1 += dy, next.x2, next.y2];
svgedit.path.replacePathSeg(this.next.type, this.next.index, next_pts); svgedit.path.replacePathSeg(this.next.type, this.next.index, nextPts);
} }
if (this.mate) { if (this.mate) {
@@ -504,26 +504,26 @@ svgedit.path.Segment.prototype.move = function(dx, dy) {
} }
this.update(true); this.update(true);
if (this.next) {this.next.update(true);} if (this.next) { this.next.update(true); }
}; };
svgedit.path.Segment.prototype.setLinked = function(num) { svgedit.path.Segment.prototype.setLinked = function (num) {
var seg, anum, pt; var seg, anum, pt;
if (num == 2) { if (num == 2) {
anum = 1; anum = 1;
seg = this.next; seg = this.next;
if (!seg) {return;} if (!seg) { return; }
pt = this.item; pt = this.item;
} else { } else {
anum = 2; anum = 2;
seg = this.prev; seg = this.prev;
if (!seg) {return;} if (!seg) { return; }
pt = seg.item; pt = seg.item;
} }
var item = seg.item; var item = seg.item;
item['x' + anum ] = pt.x + (pt.x - this.item['x' + num]); item['x' + anum] = pt.x + (pt.x - this.item['x' + num]);
item['y' + anum ] = pt.y + (pt.y - this.item['y' + num]); item['y' + anum] = pt.y + (pt.y - this.item['y' + num]);
var pts = [item.x, item.y, var pts = [item.x, item.y,
item.x1, item.y1, item.x1, item.y1,
@@ -533,30 +533,30 @@ svgedit.path.Segment.prototype.setLinked = function(num) {
seg.update(true); seg.update(true);
}; };
svgedit.path.Segment.prototype.moveCtrl = function(num, dx, dy) { svgedit.path.Segment.prototype.moveCtrl = function (num, dx, dy) {
var item = this.item; var item = this.item;
item['x' + num] += dx; item['x' + num] += dx;
item['y' + num] += dy; item['y' + num] += dy;
var pts = [item.x,item.y, var pts = [item.x, item.y,
item.x1,item.y1, item.x2,item.y2]; item.x1, item.y1, item.x2, item.y2];
svgedit.path.replacePathSeg(this.type, this.index, pts); svgedit.path.replacePathSeg(this.type, this.index, pts);
this.update(true); this.update(true);
}; };
svgedit.path.Segment.prototype.setType = function(new_type, pts) { svgedit.path.Segment.prototype.setType = function (newType, pts) {
svgedit.path.replacePathSeg(new_type, this.index, pts); svgedit.path.replacePathSeg(newType, this.index, pts);
this.type = new_type; this.type = newType;
this.item = svgedit.path.path.elem.pathSegList.getItem(this.index); this.item = svgedit.path.path.elem.pathSegList.getItem(this.index);
this.showCtrlPts(new_type === 6); this.showCtrlPts(newType === 6);
this.ctrlpts = svgedit.path.getControlPoints(this); this.ctrlpts = svgedit.path.getControlPoints(this);
this.update(true); this.update(true);
}; };
svgedit.path.Path = function(elem) { svgedit.path.Path = function (elem) {
if (!elem || elem.tagName !== 'path') { if (!elem || elem.tagName !== 'path') {
throw 'svgedit.path.Path constructed without a <path> element'; throw new Error('svgedit.path.Path constructed without a <path> element');
} }
this.elem = elem; this.elem = elem;
@@ -568,11 +568,13 @@ svgedit.path.Path = function(elem) {
}; };
// Reset path data // Reset path data
svgedit.path.Path.prototype.init = function() { svgedit.path.Path.prototype.init = function () {
// Hide all grips, etc // Hide all grips, etc
//fixed, needed to work on all found elements, not just first // fixed, needed to work on all found elements, not just first
$(svgedit.path.getGripContainer()).find('*').each( function() { $(this).attr('display', 'none') }); $(svgedit.path.getGripContainer()).find('*').each(function () {
$(this).attr('display', 'none');
});
var segList = this.elem.pathSegList; var segList = this.elem.pathSegList;
var len = segList.numberOfItems; var len = segList.numberOfItems;
@@ -590,58 +592,58 @@ svgedit.path.Path.prototype.init = function() {
} }
var segs = this.segs; var segs = this.segs;
var start_i = null; var startI = null;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
var seg = segs[i]; var seg = segs[i];
var next_seg = (i+1) >= len ? null : segs[i+1]; var nextSeg = (i + 1) >= len ? null : segs[i + 1];
var prev_seg = (i-1) < 0 ? null : segs[i-1]; var prevSeg = (i - 1) < 0 ? null : segs[i - 1];
var start_seg; var startSeg;
if (seg.type === 2) { if (seg.type === 2) {
if (prev_seg && prev_seg.type !== 1) { if (prevSeg && prevSeg.type !== 1) {
// New sub-path, last one is open, // New sub-path, last one is open,
// so add a grip to last sub-path's first point // so add a grip to last sub-path's first point
start_seg = segs[start_i]; startSeg = segs[startI];
start_seg.next = segs[start_i+1]; startSeg.next = segs[startI + 1];
start_seg.next.prev = start_seg; startSeg.next.prev = startSeg;
start_seg.addGrip(); startSeg.addGrip();
} }
// Remember that this is a starter seg // Remember that this is a starter seg
start_i = i; startI = i;
} else if (next_seg && next_seg.type === 1) { } else if (nextSeg && nextSeg.type === 1) {
// This is the last real segment of a closed sub-path // This is the last real segment of a closed sub-path
// Next is first seg after "M" // Next is first seg after "M"
seg.next = segs[start_i+1]; seg.next = segs[startI + 1];
// First seg after "M"'s prev is this // First seg after "M"'s prev is this
seg.next.prev = seg; seg.next.prev = seg;
seg.mate = segs[start_i]; seg.mate = segs[startI];
seg.addGrip(); seg.addGrip();
if (this.first_seg == null) { if (this.first_seg == null) {
this.first_seg = seg; this.first_seg = seg;
} }
} else if (!next_seg) { } else if (!nextSeg) {
if (seg.type !== 1) { if (seg.type !== 1) {
// Last seg, doesn't close so add a grip // Last seg, doesn't close so add a grip
// to last sub-path's first point // to last sub-path's first point
start_seg = segs[start_i]; startSeg = segs[startI];
start_seg.next = segs[start_i+1]; startSeg.next = segs[startI + 1];
start_seg.next.prev = start_seg; startSeg.next.prev = startSeg;
start_seg.addGrip(); startSeg.addGrip();
seg.addGrip(); seg.addGrip();
if (!this.first_seg) { if (!this.first_seg) {
// Open path, so set first as real first and add grip // Open path, so set first as real first and add grip
this.first_seg = segs[start_i]; this.first_seg = segs[startI];
} }
} }
} else if (seg.type !== 1){ } else if (seg.type !== 1) {
// Regular segment, so add grip and its "next" // Regular segment, so add grip and its "next"
seg.addGrip(); seg.addGrip();
// Don't set its "next" if it's an "M" // Don't set its "next" if it's an "M"
if (next_seg && next_seg.type !== 2) { if (nextSeg && nextSeg.type !== 2) {
seg.next = next_seg; seg.next = nextSeg;
seg.next.prev = seg; seg.next.prev = seg;
} }
} }
@@ -649,44 +651,44 @@ svgedit.path.Path.prototype.init = function() {
return this; return this;
}; };
svgedit.path.Path.prototype.eachSeg = function(fn) { svgedit.path.Path.prototype.eachSeg = function (fn) {
var i; var i;
var len = this.segs.length; var len = this.segs.length;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
var ret = fn.call(this.segs[i], i); var ret = fn.call(this.segs[i], i);
if (ret === false) {break;} if (ret === false) { break; }
} }
}; };
svgedit.path.Path.prototype.addSeg = function(index) { svgedit.path.Path.prototype.addSeg = function (index) {
// Adds a new segment // Adds a new segment
var seg = this.segs[index]; var seg = this.segs[index];
if (!seg.prev) {return;} if (!seg.prev) { return; }
var prev = seg.prev; var prev = seg.prev;
var newseg, new_x, new_y; var newseg, newX, newY;
switch(seg.item.pathSegType) { switch (seg.item.pathSegType) {
case 4: case 4:
new_x = (seg.item.x + prev.item.x) / 2; newX = (seg.item.x + prev.item.x) / 2;
new_y = (seg.item.y + prev.item.y) / 2; newY = (seg.item.y + prev.item.y) / 2;
newseg = this.elem.createSVGPathSegLinetoAbs(new_x, new_y); newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY);
break; break;
case 6: //make it a curved segment to preserve the shape (WRS) case 6: // make it a curved segment to preserve the shape (WRS)
// http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation // http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm#Geometric_interpretation
var p0_x = (prev.item.x + seg.item.x1)/2; var p0x = (prev.item.x + seg.item.x1) / 2;
var p1_x = (seg.item.x1 + seg.item.x2)/2; var p1x = (seg.item.x1 + seg.item.x2) / 2;
var p2_x = (seg.item.x2 + seg.item.x)/2; var p2x = (seg.item.x2 + seg.item.x) / 2;
var p01_x = (p0_x + p1_x)/2; var p01x = (p0x + p1x) / 2;
var p12_x = (p1_x + p2_x)/2; var p12x = (p1x + p2x) / 2;
new_x = (p01_x + p12_x)/2; newX = (p01x + p12x) / 2;
var p0_y = (prev.item.y + seg.item.y1)/2; var p0y = (prev.item.y + seg.item.y1) / 2;
var p1_y = (seg.item.y1 + seg.item.y2)/2; var p1y = (seg.item.y1 + seg.item.y2) / 2;
var p2_y = (seg.item.y2 + seg.item.y)/2; var p2y = (seg.item.y2 + seg.item.y) / 2;
var p01_y = (p0_y + p1_y)/2; var p01y = (p0y + p1y) / 2;
var p12_y = (p1_y + p2_y)/2; var p12y = (p1y + p2y) / 2;
new_y = (p01_y + p12_y)/2; newY = (p01y + p12y) / 2;
newseg = this.elem.createSVGPathSegCurvetoCubicAbs(new_x, new_y, p0_x, p0_y, p01_x, p01_y); newseg = this.elem.createSVGPathSegCurvetoCubicAbs(newX, newY, p0x, p0y, p01x, p01y);
var pts = [seg.item.x, seg.item.y, p12_x, p12_y, p2_x, p2_y]; var pts = [seg.item.x, seg.item.y, p12x, p12y, p2x, p2y];
svgedit.path.replacePathSeg(seg.type, index, pts); svgedit.path.replacePathSeg(seg.type, index, pts);
break; break;
} }
@@ -694,7 +696,7 @@ svgedit.path.Path.prototype.addSeg = function(index) {
svgedit.path.insertItemBefore(this.elem, newseg, index); svgedit.path.insertItemBefore(this.elem, newseg, index);
}; };
svgedit.path.Path.prototype.deleteSeg = function(index) { svgedit.path.Path.prototype.deleteSeg = function (index) {
var seg = this.segs[index]; var seg = this.segs[index];
var list = this.elem.pathSegList; var list = this.elem.pathSegList;
@@ -712,7 +714,7 @@ svgedit.path.Path.prototype.deleteSeg = function(index) {
list.removeItem(seg.mate.index); list.removeItem(seg.mate.index);
} else if (!seg.prev) { } else if (!seg.prev) {
// First node of open path, make next point the M // First node of open path, make next point the M
var item = seg.item; // var item = seg.item;
pt = [next.item.x, next.item.y]; pt = [next.item.x, next.item.y];
svgedit.path.replacePathSeg(2, seg.next.index, pt); svgedit.path.replacePathSeg(2, seg.next.index, pt);
list.removeItem(index); list.removeItem(index);
@@ -721,11 +723,11 @@ svgedit.path.Path.prototype.deleteSeg = function(index) {
} }
}; };
svgedit.path.Path.prototype.subpathIsClosed = function(index) { svgedit.path.Path.prototype.subpathIsClosed = function (index) {
var closed = false; var closed = false;
// Check if subpath is already open // Check if subpath is already open
svgedit.path.path.eachSeg(function(i) { svgedit.path.path.eachSeg(function (i) {
if (i <= index) {return true;} if (i <= index) { return true; }
if (this.type === 2) { if (this.type === 2) {
// Found M first, so open // Found M first, so open
return false; return false;
@@ -740,7 +742,7 @@ svgedit.path.Path.prototype.subpathIsClosed = function(index) {
return closed; return closed;
}; };
svgedit.path.Path.prototype.removePtFromSelection = function(index) { svgedit.path.Path.prototype.removePtFromSelection = function (index) {
var pos = this.selected_pts.indexOf(index); var pos = this.selected_pts.indexOf(index);
if (pos == -1) { if (pos == -1) {
return; return;
@@ -749,21 +751,21 @@ svgedit.path.Path.prototype.removePtFromSelection = function(index) {
this.selected_pts.splice(pos, 1); this.selected_pts.splice(pos, 1);
}; };
svgedit.path.Path.prototype.clearSelection = function() { svgedit.path.Path.prototype.clearSelection = function () {
this.eachSeg(function() { this.eachSeg(function () {
// 'this' is the segment here // 'this' is the segment here
this.select(false); this.select(false);
}); });
this.selected_pts = []; this.selected_pts = [];
}; };
svgedit.path.Path.prototype.storeD = function() { svgedit.path.Path.prototype.storeD = function () {
this.last_d = this.elem.getAttribute('d'); this.last_d = this.elem.getAttribute('d');
}; };
svgedit.path.Path.prototype.show = function(y) { svgedit.path.Path.prototype.show = function (y) {
// Shows this path's segment grips // Shows this path's segment grips
this.eachSeg(function() { this.eachSeg(function () {
// 'this' is the segment here // 'this' is the segment here
this.show(y); this.show(y);
}); });
@@ -774,90 +776,90 @@ svgedit.path.Path.prototype.show = function(y) {
}; };
// Move selected points // Move selected points
svgedit.path.Path.prototype.movePts = function(d_x, d_y) { svgedit.path.Path.prototype.movePts = function (dx, dy) {
var i = this.selected_pts.length; var i = this.selected_pts.length;
while(i--) { while (i--) {
var seg = this.segs[this.selected_pts[i]]; var seg = this.segs[this.selected_pts[i]];
seg.move(d_x, d_y); seg.move(dx, dy);
} }
}; };
svgedit.path.Path.prototype.moveCtrl = function(d_x, d_y) { svgedit.path.Path.prototype.moveCtrl = function (dx, dy) {
var seg = this.segs[this.selected_pts[0]]; var seg = this.segs[this.selected_pts[0]];
seg.moveCtrl(this.dragctrl, d_x, d_y); seg.moveCtrl(this.dragctrl, dx, dy);
if (link_control_pts) { if (linkControlPts) {
seg.setLinked(this.dragctrl); seg.setLinked(this.dragctrl);
} }
}; };
svgedit.path.Path.prototype.setSegType = function(new_type) { svgedit.path.Path.prototype.setSegType = function (newType) {
this.storeD(); this.storeD();
var i = this.selected_pts.length; var i = this.selected_pts.length;
var text; var text;
while(i--) { while (i--) {
var sel_pt = this.selected_pts[i]; var selPt = this.selected_pts[i];
// Selected seg // Selected seg
var cur = this.segs[sel_pt]; var cur = this.segs[selPt];
var prev = cur.prev; var prev = cur.prev;
if (!prev) {continue;} if (!prev) { continue; }
if (!new_type) { // double-click, so just toggle if (!newType) { // double-click, so just toggle
text = 'Toggle Path Segment Type'; text = 'Toggle Path Segment Type';
// Toggle segment to curve/straight line // Toggle segment to curve/straight line
var old_type = cur.type; var oldType = cur.type;
new_type = (old_type == 6) ? 4 : 6; newType = (oldType == 6) ? 4 : 6;
} }
new_type = Number(new_type); newType = Number(newType);
var cur_x = cur.item.x; var curX = cur.item.x;
var cur_y = cur.item.y; var curY = cur.item.y;
var prev_x = prev.item.x; var prevX = prev.item.x;
var prev_y = prev.item.y; var prevY = prev.item.y;
var points; var points;
switch ( new_type ) { switch (newType) {
case 6: case 6:
if (cur.olditem) { if (cur.olditem) {
var old = cur.olditem; var old = cur.olditem;
points = [cur_x, cur_y, old.x1, old.y1, old.x2, old.y2]; points = [curX, curY, old.x1, old.y1, old.x2, old.y2];
} else { } else {
var diff_x = cur_x - prev_x; var diffX = curX - prevX;
var diff_y = cur_y - prev_y; var diffY = curY - prevY;
// get control points from straight line segment // get control points from straight line segment
/* /*
var ct1_x = (prev_x + (diff_y/2)); var ct1x = (prevX + (diffY/2));
var ct1_y = (prev_y - (diff_x/2)); var ct1y = (prevY - (diffX/2));
var ct2_x = (cur_x + (diff_y/2)); var ct2x = (curX + (diffY/2));
var ct2_y = (cur_y - (diff_x/2)); var ct2y = (curY - (diffX/2));
*/ */
//create control points on the line to preserve the shape (WRS) // create control points on the line to preserve the shape (WRS)
var ct1_x = (prev_x + (diff_x/3)); var ct1x = (prevX + (diffX / 3));
var ct1_y = (prev_y + (diff_y/3)); var ct1y = (prevY + (diffY / 3));
var ct2_x = (cur_x - (diff_x/3)); var ct2x = (curX - (diffX / 3));
var ct2_y = (cur_y - (diff_y/3)); var ct2y = (curY - (diffY / 3));
points = [cur_x, cur_y, ct1_x, ct1_y, ct2_x, ct2_y]; points = [curX, curY, ct1x, ct1y, ct2x, ct2y];
} }
break; break;
case 4: case 4:
points = [cur_x, cur_y]; points = [curX, curY];
// Store original prevve segment nums // Store original prevve segment nums
cur.olditem = cur.item; cur.olditem = cur.item;
break; break;
} }
cur.setType(new_type, points); cur.setType(newType, points);
} }
svgedit.path.path.endChanges(text); svgedit.path.path.endChanges(text);
}; };
svgedit.path.Path.prototype.selectPt = function(pt, ctrl_num) { svgedit.path.Path.prototype.selectPt = function (pt, ctrlNum) {
this.clearSelection(); this.clearSelection();
if (pt == null) { if (pt == null) {
this.eachSeg(function(i) { this.eachSeg(function (i) {
// 'this' is the segment here. // 'this' is the segment here.
if (this.prev) { if (this.prev) {
pt = i; pt = i;
@@ -865,17 +867,17 @@ svgedit.path.Path.prototype.selectPt = function(pt, ctrl_num) {
}); });
} }
this.addPtsToSelection(pt); this.addPtsToSelection(pt);
if (ctrl_num) { if (ctrlNum) {
this.dragctrl = ctrl_num; this.dragctrl = ctrlNum;
if (link_control_pts) { if (linkControlPts) {
this.segs[pt].setLinked(ctrl_num); this.segs[pt].setLinked(ctrlNum);
} }
} }
}; };
// Update position of all points // Update position of all points
svgedit.path.Path.prototype.update = function() { svgedit.path.Path.prototype.update = function () {
var elem = this.elem; var elem = this.elem;
if (svgedit.utilities.getRotationAngle(elem)) { if (svgedit.utilities.getRotationAngle(elem)) {
this.matrix = svgedit.math.getMatrix(elem); this.matrix = svgedit.math.getMatrix(elem);
@@ -885,7 +887,7 @@ svgedit.path.Path.prototype.update = function() {
this.imatrix = null; this.imatrix = null;
} }
this.eachSeg(function(i) { this.eachSeg(function (i) {
this.item = elem.pathSegList.getItem(i); this.item = elem.pathSegList.getItem(i);
this.update(); this.update();
}); });
@@ -893,7 +895,7 @@ svgedit.path.Path.prototype.update = function() {
return this; return this;
}; };
svgedit.path.getPath_ = function(elem) { svgedit.path.getPath_ = function (elem) {
var p = pathData[elem.id]; var p = pathData[elem.id];
if (!p) { if (!p) {
p = pathData[elem.id] = new svgedit.path.Path(elem); p = pathData[elem.id] = new svgedit.path.Path(elem);
@@ -901,16 +903,16 @@ svgedit.path.getPath_ = function(elem) {
return p; return p;
}; };
svgedit.path.removePath_ = function(id) { svgedit.path.removePath_ = function (id) {
if (id in pathData) {delete pathData[id];} if (id in pathData) { delete pathData[id]; }
}; };
var newcx, newcy, oldcx, oldcy, angle; var newcx, newcy, oldcx, oldcy, angle;
var getRotVals = function(x, y) { var getRotVals = function (x, y) {
var dx = x - oldcx; var dx = x - oldcx;
var dy = y - oldcy; var dy = y - oldcy;
// rotate the point around the old center // rotate the point around the old center
var r = Math.sqrt(dx*dx + dy*dy); var r = Math.sqrt(dx * dx + dy * dy);
var theta = Math.atan2(dy, dx) + angle; var theta = Math.atan2(dy, dx) + angle;
dx = r * Math.cos(theta) + oldcx; dx = r * Math.cos(theta) + oldcx;
dy = r * Math.sin(theta) + oldcy; dy = r * Math.sin(theta) + oldcy;
@@ -922,7 +924,7 @@ var getRotVals = function(x, y) {
dx -= newcx; dx -= newcx;
dy -= newcy; dy -= newcy;
r = Math.sqrt(dx*dx + dy*dy); r = Math.sqrt(dx * dx + dy * dy);
theta = Math.atan2(dy, dx) - angle; theta = Math.atan2(dy, dx) - angle;
return {'x': r * Math.cos(theta) + newcx, return {'x': r * Math.cos(theta) + newcx,
@@ -936,61 +938,60 @@ var getRotVals = function(x, y) {
// TODO: This is still using ye olde transform methods, can probably // TODO: This is still using ye olde transform methods, can probably
// be optimized or even taken care of by recalculateDimensions // be optimized or even taken care of by recalculateDimensions
svgedit.path.recalcRotatedPath = function() { svgedit.path.recalcRotatedPath = function () {
var current_path = svgedit.path.path.elem; var currentPath = svgedit.path.path.elem;
angle = svgedit.utilities.getRotationAngle(current_path, true); angle = svgedit.utilities.getRotationAngle(currentPath, true);
if (!angle) {return;} if (!angle) { return; }
// selectedBBoxes[0] = svgedit.path.path.oldbbox; // selectedBBoxes[0] = svgedit.path.path.oldbbox;
var box = svgedit.utilities.getBBox(current_path), var box = svgedit.utilities.getBBox(currentPath),
oldbox = svgedit.path.path.oldbbox; //selectedBBoxes[0], oldbox = svgedit.path.path.oldbbox; // selectedBBoxes[0],
oldcx = oldbox.x + oldbox.width/2; oldcx = oldbox.x + oldbox.width / 2;
oldcy = oldbox.y + oldbox.height/2; oldcy = oldbox.y + oldbox.height / 2;
newcx = box.x + box.width/2; newcx = box.x + box.width / 2;
newcy = box.y + box.height/2; newcy = box.y + box.height / 2;
// un-rotate the new center to the proper position // un-rotate the new center to the proper position
var dx = newcx - oldcx, var dx = newcx - oldcx,
dy = newcy - oldcy, dy = newcy - oldcy,
r = Math.sqrt(dx*dx + dy*dy), r = Math.sqrt(dx * dx + dy * dy),
theta = Math.atan2(dy, dx) + angle; theta = Math.atan2(dy, dx) + angle;
newcx = r * Math.cos(theta) + oldcx; newcx = r * Math.cos(theta) + oldcx;
newcy = r * Math.sin(theta) + oldcy; newcy = r * Math.sin(theta) + oldcy;
var list = current_path.pathSegList, var list = currentPath.pathSegList,
i = list.numberOfItems; i = list.numberOfItems;
while (i) { while (i) {
i -= 1; i -= 1;
var seg = list.getItem(i), var seg = list.getItem(i),
type = seg.pathSegType; type = seg.pathSegType;
if (type == 1) {continue;} if (type == 1) { continue; }
var rvals = getRotVals(seg.x, seg.y), var rvals = getRotVals(seg.x, seg.y),
points = [rvals.x, rvals.y]; points = [rvals.x, rvals.y];
if (seg.x1 != null && seg.x2 != null) { if (seg.x1 != null && seg.x2 != null) {
var c_vals1 = getRotVals(seg.x1, seg.y1); var cVals1 = getRotVals(seg.x1, seg.y1);
var c_vals2 = getRotVals(seg.x2, seg.y2); var cVals2 = getRotVals(seg.x2, seg.y2);
points.splice(points.length, 0, c_vals1.x , c_vals1.y, c_vals2.x, c_vals2.y); points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y);
} }
svgedit.path.replacePathSeg(type, i, points); svgedit.path.replacePathSeg(type, i, points);
} // loop for each point } // loop for each point
box = svgedit.utilities.getBBox(current_path); box = svgedit.utilities.getBBox(currentPath);
// selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y; // selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;
// selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height; // selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;
// now we must set the new transform to be rotated around the new center // now we must set the new transform to be rotated around the new center
var R_nc = svgroot.createSVGTransform(), var Rnc = svgroot.createSVGTransform(),
tlist = svgedit.transformlist.getTransformList(current_path); tlist = svgedit.transformlist.getTransformList(currentPath);
R_nc.setRotate((angle * 180.0 / Math.PI), newcx, newcy); Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);
tlist.replaceItem(R_nc,0); tlist.replaceItem(Rnc, 0);
}; };
// ==================================== // ====================================
// Public API starts here // Public API starts here
svgedit.path.clearData = function() { svgedit.path.clearData = function () {
pathData = {}; pathData = {};
}; };
}()); }());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true*/ /* globals $, svgedit */
/** /**
* Package: svgedit.sanitize * Package: svgedit.sanitize
* *
@@ -15,98 +15,99 @@
// 3) browser.js // 3) browser.js
// 4) svgutils.js // 4) svgutils.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.sanitize) { if (!svgedit.sanitize) {
svgedit.sanitize = {}; svgedit.sanitize = {};
} }
var NS = svgedit.NS, var NS = svgedit.NS,
REVERSE_NS = svgedit.getReverseNS(); REVERSE_NS = svgedit.getReverseNS();
// this defines which elements and attributes that we support // this defines which elements and attributes that we support
var svgWhiteList_ = { var svgWhiteList_ = {
// SVG Elements // SVG Elements
"a": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "xlink:href", "xlink:title"], 'a': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],
"circle": ["class", "clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "r", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], 'circle': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
"clipPath": ["class", "clipPathUnits", "id"], 'clipPath': ['class', 'clipPathUnits', 'id'],
"defs": [], 'defs': [],
"style" : ["type"], 'style': ['type'],
"desc": [], 'desc': [],
"ellipse": ["class", "clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], 'ellipse': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
"feGaussianBlur": ["class", "color-interpolation-filters", "id", "requiredFeatures", "stdDeviation"], 'feGaussianBlur': ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
"filter": ["class", "color-interpolation-filters", "filterRes", "filterUnits", "height", "id", "primitiveUnits", "requiredFeatures", "width", "x", "xlink:href", "y"], 'filter': ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
"foreignObject": ["class", "font-size", "height", "id", "opacity", "requiredFeatures", "style", "transform", "width", "x", "y"], 'foreignObject': ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],
"g": ["class", "clip-path", "clip-rule", "id", "display", "fill", "fill-opacity", "fill-rule", "filter", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "font-family", "font-size", "font-style", "font-weight", "text-anchor"], 'g': ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
"image": ["class", "clip-path", "clip-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "style", "systemLanguage", "transform", "width", "x", "xlink:href", "xlink:title", "y"], 'image': ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],
"line": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "x1", "x2", "y1", "y2"], 'line': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],
"linearGradient": ["class", "id", "gradientTransform", "gradientUnits", "requiredFeatures", "spreadMethod", "systemLanguage", "x1", "x2", "xlink:href", "y1", "y2"], 'linearGradient': ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],
"marker": ["id", "class", "markerHeight", "markerUnits", "markerWidth", "orient", "preserveAspectRatio", "refX", "refY", "systemLanguage", "viewBox"], 'marker': ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
"mask": ["class", "height", "id", "maskContentUnits", "maskUnits", "width", "x", "y"], 'mask': ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
"metadata": ["class", "id"], 'metadata': ['class', 'id'],
"path": ["class", "clip-path", "clip-rule", "d", "fill", "fill-opacity", "fill-rule", "filter", "id", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], 'path': ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
"pattern": ["class", "height", "id", "patternContentUnits", "patternTransform", "patternUnits", "requiredFeatures", "style", "systemLanguage", "viewBox", "width", "x", "xlink:href", "y"], 'pattern': ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],
"polygon": ["class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], 'polygon': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
"polyline": ["class", "clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "marker-end", "marker-mid", "marker-start", "mask", "opacity", "points", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"], 'polyline': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
"radialGradient": ["class", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "id", "r", "requiredFeatures", "spreadMethod", "systemLanguage", "xlink:href"], 'radialGradient': ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],
"rect": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "width", "x", "y"], 'rect': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],
"stop": ["class", "id", "offset", "requiredFeatures", "stop-color", "stop-opacity", "style", "systemLanguage"], 'stop': ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],
"svg": ["class", "clip-path", "clip-rule", "filter", "id", "height", "mask", "preserveAspectRatio", "requiredFeatures", "style", "systemLanguage", "viewBox", "width", "x", "xmlns", "xmlns:se", "xmlns:xlink", "y"], 'svg': ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],
"switch": ["class", "id", "requiredFeatures", "systemLanguage"], 'switch': ['class', 'id', 'requiredFeatures', 'systemLanguage'],
"symbol": ["class", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "opacity", "preserveAspectRatio", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "viewBox"], 'symbol': ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],
"text": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "text-anchor", "transform", "x", "xml:space", "y"], 'text': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],
"textPath": ["class", "id", "method", "requiredFeatures", "spacing", "startOffset", "style", "systemLanguage", "transform", "xlink:href"], 'textPath': ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
"title": [], 'title': [],
"tspan": ["class", "clip-path", "clip-rule", "dx", "dy", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "mask", "opacity", "requiredFeatures", "rotate", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "text-anchor", "textLength", "transform", "x", "xml:space", "y"], 'tspan': ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],
"use": ["class", "clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "height", "id", "mask", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "transform", "width", "x", "xlink:href", "y"], 'use': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],
// MathML Elements // MathML Elements
"annotation": ["encoding"], 'annotation': ['encoding'],
"annotation-xml": ["encoding"], 'annotation-xml': ['encoding'],
"maction": ["actiontype", "other", "selection"], 'maction': ['actiontype', 'other', 'selection'],
"math": ["class", "id", "display", "xmlns"], 'math': ['class', 'id', 'display', 'xmlns'],
"menclose": ["notation"], 'menclose': ['notation'],
"merror": [], 'merror': [],
"mfrac": ["linethickness"], 'mfrac': ['linethickness'],
"mi": ["mathvariant"], 'mi': ['mathvariant'],
"mmultiscripts": [], 'mmultiscripts': [],
"mn": [], 'mn': [],
"mo": ["fence", "lspace", "maxsize", "minsize", "rspace", "stretchy"], 'mo': ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],
"mover": [], 'mover': [],
"mpadded": ["lspace", "width", "height", "depth", "voffset"], 'mpadded': ['lspace', 'width', 'height', 'depth', 'voffset'],
"mphantom": [], 'mphantom': [],
"mprescripts": [], 'mprescripts': [],
"mroot": [], 'mroot': [],
"mrow": ["xlink:href", "xlink:type", "xmlns:xlink"], 'mrow': ['xlink:href', 'xlink:type', 'xmlns:xlink'],
"mspace": ["depth", "height", "width"], 'mspace': ['depth', 'height', 'width'],
"msqrt": [], 'msqrt': [],
"mstyle": ["displaystyle", "mathbackground", "mathcolor", "mathvariant", "scriptlevel"], 'mstyle': ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],
"msub": [], 'msub': [],
"msubsup": [], 'msubsup': [],
"msup": [], 'msup': [],
"mtable": ["align", "columnalign", "columnlines", "columnspacing", "displaystyle", "equalcolumns", "equalrows", "frame", "rowalign", "rowlines", "rowspacing", "width"], 'mtable': ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],
"mtd": ["columnalign", "columnspan", "rowalign", "rowspan"], 'mtd': ['columnalign', 'columnspan', 'rowalign', 'rowspan'],
"mtext": [], 'mtext': [],
"mtr": ["columnalign", "rowalign"], 'mtr': ['columnalign', 'rowalign'],
"munder": [], 'munder': [],
"munderover": [], 'munderover': [],
"none": [], 'none': [],
"semantics": [] 'semantics': []
}; };
// Produce a Namespace-aware version of svgWhitelist // Produce a Namespace-aware version of svgWhitelist
var svgWhiteListNS_ = {}; var svgWhiteListNS_ = {};
$.each(svgWhiteList_, function(elt, atts){ $.each(svgWhiteList_, function (elt, atts) {
var attNS = {}; var attNS = {};
$.each(atts, function(i, att){ $.each(atts, function (i, att) {
if (att.indexOf(':') >= 0) { if (att.indexOf(':') >= 0) {
var v = att.split(':'); var v = att.split(':');
attNS[v[1]] = NS[(v[0]).toUpperCase()]; attNS[v[1]] = NS[(v[0]).toUpperCase()];
} else { } else {
attNS[att] = att == 'xmlns' ? NS.XMLNS : null; attNS[att] = att == 'xmlns' ? NS.XMLNS : null;
} }
}); });
svgWhiteListNS_[elt] = attNS; svgWhiteListNS_[elt] = attNS;
}); });
// Function: svgedit.sanitize.sanitizeSvg // Function: svgedit.sanitize.sanitizeSvg
@@ -115,145 +116,141 @@ $.each(svgWhiteList_, function(elt, atts){
// //
// Parameters: // Parameters:
// node - The DOM element to be checked (we'll also check its children) // node - The DOM element to be checked (we'll also check its children)
svgedit.sanitize.sanitizeSvg = function(node) { svgedit.sanitize.sanitizeSvg = function (node) {
// Cleanup text nodes // Cleanup text nodes
if (node.nodeType == 3) { // 3 == TEXT_NODE if (node.nodeType == 3) { // 3 == TEXT_NODE
// Trim whitespace // Trim whitespace
node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, ''); node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, '');
// Remove if empty // Remove if empty
if (node.nodeValue.length === 0) { if (node.nodeValue.length === 0) {
node.parentNode.removeChild(node); node.parentNode.removeChild(node);
} }
} }
// We only care about element nodes. // We only care about element nodes.
// Automatically return for all non-element nodes, such as comments, etc. // Automatically return for all non-element nodes, such as comments, etc.
if (node.nodeType != 1) { // 1 == ELEMENT_NODE if (node.nodeType != 1) { // 1 == ELEMENT_NODE
return; return;
} }
var doc = node.ownerDocument; var doc = node.ownerDocument;
var parent = node.parentNode; var parent = node.parentNode;
// can parent ever be null here? I think the root node's parent is the document... // can parent ever be null here? I think the root node's parent is the document...
if (!doc || !parent) { if (!doc || !parent) {
return; return;
} }
var allowedAttrs = svgWhiteList_[node.nodeName]; var allowedAttrs = svgWhiteList_[node.nodeName];
var allowedAttrsNS = svgWhiteListNS_[node.nodeName]; var allowedAttrsNS = svgWhiteListNS_[node.nodeName];
var i; var i;
// if this element is supported, sanitize it // if this element is supported, sanitize it
if (typeof allowedAttrs !== 'undefined') { if (typeof allowedAttrs !== 'undefined') {
var seAttrs = [];
i = node.attributes.length;
while (i--) {
// if the attribute is not in our whitelist, then remove it
// could use jQuery's inArray(), but I don't know if that's any better
var attr = node.attributes.item(i);
var attrName = attr.nodeName;
var attrLocalName = attr.localName;
var attrNsURI = attr.namespaceURI;
// Check that an attribute with the correct localName in the correct namespace is on
// our whitelist or is a namespace declaration for one of our allowed namespaces
if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI == allowedAttrsNS[attrLocalName] && attrNsURI != NS.XMLNS) &&
!(attrNsURI == NS.XMLNS && REVERSE_NS[attr.value])) {
// TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.
// Bypassing the whitelist to allow se: prefixes.
// Is there a more appropriate way to do this?
if (attrName.indexOf('se:') === 0 || attrName.indexOf('data-') === 0) {
seAttrs.push([attrName, attr.value]);
}
node.removeAttributeNS(attrNsURI, attrLocalName);
}
var seAttrs = []; // Add spaces before negative signs where necessary
i = node.attributes.length; if (svgedit.browser.isGecko()) {
while (i--) { switch (attrName) {
// if the attribute is not in our whitelist, then remove it case 'transform':
// could use jQuery's inArray(), but I don't know if that's any better case 'gradientTransform':
var attr = node.attributes.item(i); case 'patternTransform':
var attrName = attr.nodeName; var val = attr.value.replace(/(\d)-/g, '$1 -');
var attrLocalName = attr.localName; node.setAttribute(attrName, val);
var attrNsURI = attr.namespaceURI; break;
// Check that an attribute with the correct localName in the correct namespace is on }
// our whitelist or is a namespace declaration for one of our allowed namespaces }
if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI == allowedAttrsNS[attrLocalName] && attrNsURI != NS.XMLNS) &&
!(attrNsURI == NS.XMLNS && REVERSE_NS[attr.value]) )
{
// TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.
// Bypassing the whitelist to allow se: prefixes.
// Is there a more appropriate way to do this?
if (attrName.indexOf('se:') === 0 || attrName.indexOf('data-') === 0) {
seAttrs.push([attrName, attr.value]);
}
node.removeAttributeNS(attrNsURI, attrLocalName);
}
// Add spaces before negative signs where necessary // For the style attribute, rewrite it in terms of XML presentational attributes
if (svgedit.browser.isGecko()) { if (attrName == 'style') {
switch (attrName) { var props = attr.value.split(';'),
case 'transform': p = props.length;
case 'gradientTransform': while (p--) {
case 'patternTransform': var nv = props[p].split(':');
var val = attr.value.replace(/(\d)-/g, '$1 -'); var styleAttrName = $.trim(nv[0]);
node.setAttribute(attrName, val); var styleAttrVal = $.trim(nv[1]);
break; // Now check that this attribute is supported
} if (allowedAttrs.indexOf(styleAttrName) >= 0) {
} node.setAttribute(styleAttrName, styleAttrVal);
}
}
node.removeAttribute('style');
}
}
// For the style attribute, rewrite it in terms of XML presentational attributes $.each(seAttrs, function (i, attr) {
if (attrName == 'style') { node.setAttributeNS(NS.SE, attr[0], attr[1]);
var props = attr.value.split(';'), });
p = props.length;
while (p--) {
var nv = props[p].split(':');
var styleAttrName = $.trim(nv[0]);
var styleAttrVal = $.trim(nv[1]);
// Now check that this attribute is supported
if (allowedAttrs.indexOf(styleAttrName) >= 0) {
node.setAttribute(styleAttrName, styleAttrVal);
}
}
node.removeAttribute('style');
}
}
$.each(seAttrs, function(i, attr) { // for some elements that have a xlink:href, ensure the URI refers to a local element
node.setAttributeNS(NS.SE, attr[0], attr[1]); // (but not for links)
}); var href = svgedit.utilities.getHref(node);
if (href &&
['filter', 'linearGradient', 'pattern',
'radialGradient', 'textPath', 'use'].indexOf(node.nodeName) >= 0) {
// TODO: we simply check if the first character is a #, is this bullet-proof?
if (href[0] != '#') {
// remove the attribute (but keep the element)
svgedit.utilities.setHref(node, '');
node.removeAttributeNS(NS.XLINK, 'href');
}
}
// for some elements that have a xlink:href, ensure the URI refers to a local element // Safari crashes on a <use> without a xlink:href, so we just remove the node here
// (but not for links) if (node.nodeName == 'use' && !svgedit.utilities.getHref(node)) {
var href = svgedit.utilities.getHref(node); parent.removeChild(node);
if (href && return;
['filter', 'linearGradient', 'pattern', }
'radialGradient', 'textPath', 'use'].indexOf(node.nodeName) >= 0) { // if the element has attributes pointing to a non-local reference,
// TODO: we simply check if the first character is a #, is this bullet-proof? // need to remove the attribute
if (href[0] != '#') { $.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (i, attr) {
// remove the attribute (but keep the element) var val = node.getAttribute(attr);
svgedit.utilities.setHref(node, ''); if (val) {
node.removeAttributeNS(NS.XLINK, 'href'); val = svgedit.utilities.getUrlFromAttr(val);
} // simply check for first character being a '#'
} if (val && val[0] !== '#') {
node.setAttribute(attr, '');
node.removeAttribute(attr);
}
}
});
// Safari crashes on a <use> without a xlink:href, so we just remove the node here // recurse to children
if (node.nodeName == 'use' && !svgedit.utilities.getHref(node)) { i = node.childNodes.length;
parent.removeChild(node); while (i--) { svgedit.sanitize.sanitizeSvg(node.childNodes.item(i)); }
return; // else (element not supported), remove it
} } else {
// if the element has attributes pointing to a non-local reference, // remove all children from this node and insert them before this node
// need to remove the attribute // FIXME: in the case of animation elements this will hardly ever be correct
$.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function(i, attr) { var children = [];
var val = node.getAttribute(attr); while (node.hasChildNodes()) {
if (val) { children.push(parent.insertBefore(node.firstChild, node));
val = svgedit.utilities.getUrlFromAttr(val); }
// simply check for first character being a '#'
if (val && val[0] !== '#') {
node.setAttribute(attr, '');
node.removeAttribute(attr);
}
}
});
// recurse to children // remove this node from the document altogether
i = node.childNodes.length; parent.removeChild(node);
while (i--) { svgedit.sanitize.sanitizeSvg(node.childNodes.item(i)); }
}
// else (element not supported), remove it
else {
// remove all children from this node and insert them before this node
// FIXME: in the case of animation elements this will hardly ever be correct
var children = [];
while (node.hasChildNodes()) {
children.push(parent.insertBefore(node.firstChild, node));
}
// remove this node from the document altogether // call sanitizeSvg on each of those children
parent.removeChild(node); i = children.length;
while (i--) { svgedit.sanitize.sanitizeSvg(children[i]); }
// call sanitizeSvg on each of those children }
i = children.length;
while (i--) { svgedit.sanitize.sanitizeSvg(children[i]); }
}
}; };
}()); }());

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true, forin: true*/ /* globals $, svgedit */
/** /**
* Package: svedit.select * Package: svedit.select
* *
@@ -16,7 +16,8 @@
// 4) math.js // 4) math.js
// 5) svgutils.js // 5) svgutils.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.select) { if (!svgedit.select) {
svgedit.select = {}; svgedit.select = {};
@@ -34,7 +35,7 @@ var gripRadius = svgedit.browser.isTouch() ? 10 : 4;
// id - integer to internally indentify the selector // id - integer to internally indentify the selector
// elem - DOM element associated with this selector // elem - DOM element associated with this selector
// bbox - Optional bbox to use for initialization (prevents duplicate getBBox call). // bbox - Optional bbox to use for initialization (prevents duplicate getBBox call).
svgedit.select.Selector = function(id, elem, bbox) { svgedit.select.Selector = function (id, elem, bbox) {
// this is the selector's unique number // this is the selector's unique number
this.id = id; this.id = id;
@@ -69,53 +70,51 @@ svgedit.select.Selector = function(id, elem, bbox) {
// this holds a reference to the grip coordinates for this selector // this holds a reference to the grip coordinates for this selector
this.gripCoords = { this.gripCoords = {
'nw': null, 'nw': null,
'n' : null, 'n': null,
'ne': null, 'ne': null,
'e' : null, 'e': null,
'se': null, 'se': null,
's' : null, 's': null,
'sw': null, 'sw': null,
'w' : null 'w': null
}; };
this.reset(this.selectedElement, bbox); this.reset(this.selectedElement, bbox);
}; };
// Function: svgedit.select.Selector.reset // Function: svgedit.select.Selector.reset
// Used to reset the id and element that the selector is attached to // Used to reset the id and element that the selector is attached to
// //
// Parameters: // Parameters:
// e - DOM element associated with this selector // e - DOM element associated with this selector
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call). // bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
svgedit.select.Selector.prototype.reset = function(e, bbox) { svgedit.select.Selector.prototype.reset = function (e, bbox) {
this.locked = true; this.locked = true;
this.selectedElement = e; this.selectedElement = e;
this.resize(bbox); this.resize(bbox);
this.selectorGroup.setAttribute('display', 'inline'); this.selectorGroup.setAttribute('display', 'inline');
}; };
// Function: svgedit.select.Selector.updateGripCursors // Function: svgedit.select.Selector.updateGripCursors
// Updates cursors for corner grips on rotation so arrows point the right way // Updates cursors for corner grips on rotation so arrows point the right way
// //
// Parameters: // Parameters:
// angle - Float indicating current rotation angle in degrees // angle - Float indicating current rotation angle in degrees
svgedit.select.Selector.prototype.updateGripCursors = function(angle) { svgedit.select.Selector.prototype.updateGripCursors = function (angle) {
var dir, var dir,
dir_arr = [], dirArr = [],
steps = Math.round(angle / 45); steps = Math.round(angle / 45);
if (steps < 0) {steps += 8;} if (steps < 0) { steps += 8; }
for (dir in selectorManager_.selectorGrips) { for (dir in selectorManager_.selectorGrips) {
dir_arr.push(dir); dirArr.push(dir);
} }
while (steps > 0) { while (steps > 0) {
dir_arr.push(dir_arr.shift()); dirArr.push(dirArr.shift());
steps--; steps--;
} }
var i = 0; var i = 0;
for (dir in selectorManager_.selectorGrips) { for (dir in selectorManager_.selectorGrips) {
selectorManager_.selectorGrips[dir].setAttribute('style', ('cursor:' + dir_arr[i] + '-resize')); selectorManager_.selectorGrips[dir].setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));
i++; i++;
} }
}; };
@@ -125,7 +124,7 @@ svgedit.select.Selector.prototype.updateGripCursors = function(angle) {
// //
// Parameters: // Parameters:
// show - boolean indicating whether grips should be shown or not // show - boolean indicating whether grips should be shown or not
svgedit.select.Selector.prototype.showGrips = function(show) { svgedit.select.Selector.prototype.showGrips = function (show) {
var bShow = show ? 'inline' : 'none'; var bShow = show ? 'inline' : 'none';
selectorManager_.selectorGripsGroup.setAttribute('display', bShow); selectorManager_.selectorGripsGroup.setAttribute('display', bShow);
var elem = this.selectedElement; var elem = this.selectedElement;
@@ -139,21 +138,21 @@ svgedit.select.Selector.prototype.showGrips = function(show) {
// Function: svgedit.select.Selector.resize // Function: svgedit.select.Selector.resize
// Updates the selector to match the element's size // Updates the selector to match the element's size
// bbox - Optional bbox to use for resize (prevents duplicate getBBox call). // bbox - Optional bbox to use for resize (prevents duplicate getBBox call).
svgedit.select.Selector.prototype.resize = function(bbox) { svgedit.select.Selector.prototype.resize = function (bbox) {
var selectedBox = this.selectorRect, var selectedBox = this.selectorRect,
mgr = selectorManager_, mgr = selectorManager_,
selectedGrips = mgr.selectorGrips, selectedGrips = mgr.selectorGrips,
selected = this.selectedElement, selected = this.selectedElement,
sw = selected.getAttribute('stroke-width'), sw = selected.getAttribute('stroke-width'),
current_zoom = svgFactory_.currentZoom(); currentZoom = svgFactory_.currentZoom();
var offset = 1/current_zoom; var offset = 1 / currentZoom;
if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) { if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {
offset += (sw/2); offset += (sw / 2);
} }
var tagName = selected.tagName; var tagName = selected.tagName;
if (tagName === 'text') { if (tagName === 'text') {
offset += 2/current_zoom; offset += 2 / currentZoom;
} }
// loop and transform our bounding box until we reach our first rotation // loop and transform our bounding box until we reach our first rotation
@@ -162,8 +161,8 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
// This should probably be handled somewhere else, but for now // This should probably be handled somewhere else, but for now
// it keeps the selection box correctly positioned when zoomed // it keeps the selection box correctly positioned when zoomed
m.e *= current_zoom; m.e *= currentZoom;
m.f *= current_zoom; m.f *= currentZoom;
if (!bbox) { if (!bbox) {
bbox = svgedit.utilities.getBBox(selected); bbox = svgedit.utilities.getBBox(selected);
@@ -173,23 +172,23 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
if (tagName === 'g' && !$.data(selected, 'gsvg')) { if (tagName === 'g' && !$.data(selected, 'gsvg')) {
// The bbox for a group does not include stroke vals, so we // The bbox for a group does not include stroke vals, so we
// get the bbox based on its children. // get the bbox based on its children.
var stroked_bbox = svgFactory_.getStrokedBBox(selected.childNodes); var strokedBbox = svgFactory_.getStrokedBBox(selected.childNodes);
if (stroked_bbox) { if (strokedBbox) {
bbox = stroked_bbox; bbox = strokedBbox;
} }
} }
// apply the transforms // apply the transforms
var l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height; var l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height;
bbox = {x:l, y:t, width:w, height:h}; bbox = {x: l, y: t, width: w, height: h};
// we need to handle temporary transforms too // we need to handle temporary transforms too
// if skewed, get its transformed box, then find its axis-aligned bbox // if skewed, get its transformed box, then find its axis-aligned bbox
//* // *
offset *= current_zoom; offset *= currentZoom;
var nbox = svgedit.math.transformBox(l*current_zoom, t*current_zoom, w*current_zoom, h*current_zoom, m), var nbox = svgedit.math.transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),
aabox = nbox.aabox, aabox = nbox.aabox,
nbax = aabox.x - offset, nbax = aabox.x - offset,
nbay = aabox.y - offset, nbay = aabox.y - offset,
@@ -197,8 +196,8 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
nbah = aabox.height + (offset * 2); nbah = aabox.height + (offset * 2);
// now if the shape is rotated, un-rotate it // now if the shape is rotated, un-rotate it
var cx = nbax + nbaw/2, var cx = nbax + nbaw / 2,
cy = nbay + nbah/2; cy = nbay + nbah / 2;
var angle = svgedit.utilities.getRotationAngle(selected); var angle = svgedit.utilities.getRotationAngle(selected);
if (angle) { if (angle) {
@@ -219,59 +218,58 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
var min = Math.min, max = Math.max; var min = Math.min, max = Math.max;
minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x) ) ) - offset; minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;
miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y) ) ) - offset; miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;
maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x) ) ) + offset; maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset;
maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y) ) ) + offset; maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset;
nbax = minx; nbax = minx;
nbay = miny; nbay = miny;
nbaw = (maxx-minx); nbaw = (maxx - minx);
nbah = (maxy-miny); nbah = (maxy - miny);
} }
var dstr = 'M' + nbax + ',' + nbay var dstr = 'M' + nbax + ',' + nbay +
+ ' L' + (nbax+nbaw) + ',' + nbay ' L' + (nbax + nbaw) + ',' + nbay +
+ ' ' + (nbax+nbaw) + ',' + (nbay+nbah) ' ' + (nbax + nbaw) + ',' + (nbay + nbah) +
+ ' ' + nbax + ',' + (nbay+nbah) + 'z'; ' ' + nbax + ',' + (nbay + nbah) + 'z';
selectedBox.setAttribute('d', dstr); selectedBox.setAttribute('d', dstr);
var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : ''; var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';
this.selectorGroup.setAttribute('transform', xform); this.selectorGroup.setAttribute('transform', xform);
// TODO(codedread): Is this if needed? // TODO(codedread): Is this if needed?
// if (selected === selectedElements[0]) { // if (selected === selectedElements[0]) {
this.gripCoords = { this.gripCoords = {
'nw': [nbax, nbay], 'nw': [nbax, nbay],
'ne': [nbax+nbaw, nbay], 'ne': [nbax + nbaw, nbay],
'sw': [nbax, nbay+nbah], 'sw': [nbax, nbay + nbah],
'se': [nbax+nbaw, nbay+nbah], 'se': [nbax + nbaw, nbay + nbah],
'n': [nbax + (nbaw)/2, nbay], 'n': [nbax + (nbaw) / 2, nbay],
'w': [nbax, nbay + (nbah)/2], 'w': [nbax, nbay + (nbah) / 2],
'e': [nbax + nbaw, nbay + (nbah)/2], 'e': [nbax + nbaw, nbay + (nbah) / 2],
's': [nbax + (nbaw)/2, nbay + nbah] 's': [nbax + (nbaw) / 2, nbay + nbah]
}; };
var dir; var dir;
for (dir in this.gripCoords) { for (dir in this.gripCoords) {
var coords = this.gripCoords[dir]; var coords = this.gripCoords[dir];
selectedGrips[dir].setAttribute('cx', coords[0]); selectedGrips[dir].setAttribute('cx', coords[0]);
selectedGrips[dir].setAttribute('cy', coords[1]); selectedGrips[dir].setAttribute('cy', coords[1]);
} }
// we want to go 20 pixels in the negative transformed y direction, ignoring scale // we want to go 20 pixels in the negative transformed y direction, ignoring scale
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw)/2); mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);
mgr.rotateGripConnector.setAttribute('y1', nbay); mgr.rotateGripConnector.setAttribute('y1', nbay);
mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw)/2); mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);
mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius*5)); mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));
mgr.rotateGrip.setAttribute('cx', nbax + (nbaw)/2); mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);
mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius*5)); mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));
// } // }
}; };
// Class: svgedit.select.SelectorManager // Class: svgedit.select.SelectorManager
svgedit.select.SelectorManager = function() { svgedit.select.SelectorManager = function () {
// this will hold the <g> element that contains all selector rects/grips // this will hold the <g> element that contains all selector rects/grips
this.selectorParentGroup = null; this.selectorParentGroup = null;
@@ -287,13 +285,13 @@ svgedit.select.SelectorManager = function() {
// this holds a reference to the grip elements // this holds a reference to the grip elements
this.selectorGrips = { this.selectorGrips = {
'nw': null, 'nw': null,
'n' : null, 'n': null,
'ne': null, 'ne': null,
'e' : null, 'e': null,
'se': null, 'se': null,
's' : null, 's': null,
'sw': null, 'sw': null,
'w' : null 'w': null
}; };
this.selectorGripsGroup = null; this.selectorGripsGroup = null;
@@ -305,7 +303,7 @@ svgedit.select.SelectorManager = function() {
// Function: svgedit.select.SelectorManager.initGroup // Function: svgedit.select.SelectorManager.initGroup
// Resets the parent selector group element // Resets the parent selector group element
svgedit.select.SelectorManager.prototype.initGroup = function() { svgedit.select.SelectorManager.prototype.initGroup = function () {
// remove old selector parent group if it existed // remove old selector parent group if it existed
if (this.selectorParentGroup && this.selectorParentGroup.parentNode) { if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {
this.selectorParentGroup.parentNode.removeChild(this.selectorParentGroup); this.selectorParentGroup.parentNode.removeChild(this.selectorParentGroup);
@@ -378,7 +376,7 @@ svgedit.select.SelectorManager.prototype.initGroup = function() {
); );
$.data(this.rotateGrip, 'type', 'rotate'); $.data(this.rotateGrip, 'type', 'rotate');
if ($('#canvasBackground').length) {return;} if ($('#canvasBackground').length) { return; }
var dims = config_.dimensions; var dims = config_.dimensions;
var canvasbg = svgFactory_.createSVGElement({ var canvasbg = svgFactory_.createSVGElement({
@@ -410,7 +408,7 @@ svgedit.select.SelectorManager.prototype.initGroup = function() {
// Both Firefox and WebKit are too slow with this filter region (especially at higher // Both Firefox and WebKit are too slow with this filter region (especially at higher
// zoom levels) and Opera has at least one bug // zoom levels) and Opera has at least one bug
// if (!svgedit.browser.isOpera()) rect.setAttribute('filter', 'url(#canvashadow)'); // if (!svgedit.browser.isOpera()) rect.setAttribute('filter', 'url(#canvashadow)');
canvasbg.appendChild(rect); canvasbg.appendChild(rect);
svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent()); svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());
}; };
@@ -421,12 +419,12 @@ svgedit.select.SelectorManager.prototype.initGroup = function() {
// Parameters: // Parameters:
// elem - DOM element to get the selector for // elem - DOM element to get the selector for
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call). // bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
svgedit.select.SelectorManager.prototype.requestSelector = function(elem, bbox) { svgedit.select.SelectorManager.prototype.requestSelector = function (elem, bbox) {
if (elem == null) {return null;} if (elem == null) { return null; }
var i, var i,
N = this.selectors.length; N = this.selectors.length;
// If we've already acquired one for this element, return it. // If we've already acquired one for this element, return it.
if (typeof(this.selectorMap[elem.id]) == 'object') { if (typeof this.selectorMap[elem.id] === 'object') {
this.selectorMap[elem.id].locked = true; this.selectorMap[elem.id].locked = true;
return this.selectorMap[elem.id]; return this.selectorMap[elem.id];
} }
@@ -450,8 +448,8 @@ svgedit.select.SelectorManager.prototype.requestSelector = function(elem, bbox)
// //
// Parameters: // Parameters:
// elem - DOM element to remove the selector for // elem - DOM element to remove the selector for
svgedit.select.SelectorManager.prototype.releaseSelector = function(elem) { svgedit.select.SelectorManager.prototype.releaseSelector = function (elem) {
if (elem == null) {return;} if (elem == null) { return; }
var i, var i,
N = this.selectors.length, N = this.selectors.length,
sel = this.selectorMap[elem.id]; sel = this.selectorMap[elem.id];
@@ -469,7 +467,7 @@ svgedit.select.SelectorManager.prototype.releaseSelector = function(elem) {
// remove from DOM and store reference in JS but only if it exists in the DOM // remove from DOM and store reference in JS but only if it exists in the DOM
try { try {
sel.selectorGroup.setAttribute('display', 'none'); sel.selectorGroup.setAttribute('display', 'none');
} catch(e) { } } catch (e) {}
break; break;
} }
@@ -478,7 +476,7 @@ svgedit.select.SelectorManager.prototype.releaseSelector = function(elem) {
// Function: svgedit.select.SelectorManager.getRubberBandBox // Function: svgedit.select.SelectorManager.getRubberBandBox
// Returns the rubberBandBox DOM element. This is the rectangle drawn by the user for selecting/zooming // Returns the rubberBandBox DOM element. This is the rectangle drawn by the user for selecting/zooming
svgedit.select.SelectorManager.prototype.getRubberBandBox = function() { svgedit.select.SelectorManager.prototype.getRubberBandBox = function () {
if (!this.rubberBandBox) { if (!this.rubberBandBox) {
this.rubberBandBox = this.selectorParentGroup.appendChild( this.rubberBandBox = this.selectorParentGroup.appendChild(
svgFactory_.createSVGElement({ svgFactory_.createSVGElement({
@@ -498,7 +496,6 @@ svgedit.select.SelectorManager.prototype.getRubberBandBox = function() {
return this.rubberBandBox; return this.rubberBandBox;
}; };
/** /**
* Interface: svgedit.select.SVGFactory * Interface: svgedit.select.SVGFactory
* An object that creates SVG elements for the canvas. * An object that creates SVG elements for the canvas.
@@ -521,7 +518,7 @@ svgedit.select.SelectorManager.prototype.getRubberBandBox = function() {
* config - an object containing configurable parameters (imgPath) * config - an object containing configurable parameters (imgPath)
* svgFactory - an object implementing the SVGFactory interface (see above). * svgFactory - an object implementing the SVGFactory interface (see above).
*/ */
svgedit.select.init = function(config, svgFactory) { svgedit.select.init = function (config, svgFactory) {
config_ = config; config_ = config;
svgFactory_ = svgFactory; svgFactory_ = svgFactory;
selectorManager_ = new svgedit.select.SelectorManager(); selectorManager_ = new svgedit.select.SelectorManager();
@@ -533,8 +530,7 @@ svgedit.select.init = function(config, svgFactory) {
* Returns: * Returns:
* The SelectorManager instance. * The SelectorManager instance.
*/ */
svgedit.select.getSelectorManager = function() { svgedit.select.getSelectorManager = function () {
return selectorManager_; return selectorManager_;
}; };
}()); }());

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var */
/* globals $, svgedit:true */
/** /**
* *
* Licensed under the MIT License * Licensed under the MIT License
@@ -19,9 +20,10 @@ svgedit = {
}; };
// return the svgedit.NS with key values switched and lowercase // return the svgedit.NS with key values switched and lowercase
svgedit.getReverseNS = function() {'use strict'; svgedit.getReverseNS = function () {
'use strict';
var reverseNS = {}; var reverseNS = {};
$.each(this.NS, function(name, URI) { $.each(this.NS, function (name, URI) {
reverseNS[URI] = name.toLowerCase(); reverseNS[URI] = name.toLowerCase();
}); });
return reverseNS; return reverseNS;

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var, eqeqeq */
/*jslint vars: true, eqeq: true*/ /* globals $, svgedit */
/** /**
* SVGTransformList * SVGTransformList
* *
@@ -12,7 +12,8 @@
// Dependencies: // Dependencies:
// 1) browser.js // 1) browser.js
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.transformlist) { if (!svgedit.transformlist) {
svgedit.transformlist = {}; svgedit.transformlist = {};
@@ -21,41 +22,42 @@ if (!svgedit.transformlist) {
var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg'); var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
// Helper function. // Helper function.
function transformToString(xform) { function transformToString (xform) {
var m = xform.matrix, var m = xform.matrix,
text = ''; text = '';
switch(xform.type) { switch (xform.type) {
case 1: // MATRIX case 1: // MATRIX
text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')'; text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
break; break;
case 2: // TRANSLATE case 2: // TRANSLATE
text = 'translate(' + m.e + ',' + m.f + ')'; text = 'translate(' + m.e + ',' + m.f + ')';
break; break;
case 3: // SCALE case 3: // SCALE
if (m.a == m.d) {text = 'scale(' + m.a + ')';} if (m.a == m.d) {
else {text = 'scale(' + m.a + ',' + m.d + ')';} text = 'scale(' + m.a + ')';
break; } else {
case 4: // ROTATE text = 'scale(' + m.a + ',' + m.d + ')';
var cx = 0, cy = 0; }
// this prevents divide by zero break;
if (xform.angle != 0) { case 4: // ROTATE
var K = 1 - m.a; var cx = 0, cy = 0;
cy = ( K * m.f + m.b*m.e ) / ( K*K + m.b*m.b ); // this prevents divide by zero
cx = ( m.e - m.b * cy ) / K; if (xform.angle != 0) {
} var K = 1 - m.a;
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')'; cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);
break; cx = (m.e - m.b * cy) / K;
}
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
break;
} }
return text; return text;
} }
/** /**
* Map of SVGTransformList objects. * Map of SVGTransformList objects.
*/ */
var listMap_ = {}; var listMap_ = {};
// ************************************************************************************** // **************************************************************************************
// SVGTransformList implementation for Webkit // SVGTransformList implementation for Webkit
// These methods do not currently raise any exceptions. // These methods do not currently raise any exceptions.
@@ -75,13 +77,13 @@ var listMap_ = {};
// NOT IMPLEMENTED: SVGTransform consolidate ( ); // NOT IMPLEMENTED: SVGTransform consolidate ( );
// } // }
// ************************************************************************************** // **************************************************************************************
svgedit.transformlist.SVGTransformList = function(elem) { svgedit.transformlist.SVGTransformList = function (elem) {
this._elem = elem || null; this._elem = elem || null;
this._xforms = []; this._xforms = [];
// TODO: how do we capture the undo-ability in the changed transform list? // TODO: how do we capture the undo-ability in the changed transform list?
this._update = function() { this._update = function () {
var tstr = ''; var tstr = '';
var concatMatrix = svgroot.createSVGMatrix(); /* var concatMatrix = */ svgroot.createSVGMatrix();
var i; var i;
for (i = 0; i < this.numberOfItems; ++i) { for (i = 0; i < this.numberOfItems; ++i) {
var xform = this._list.getItem(i); var xform = this._list.getItem(i);
@@ -90,10 +92,10 @@ svgedit.transformlist.SVGTransformList = function(elem) {
this._elem.setAttribute('transform', tstr); this._elem.setAttribute('transform', tstr);
}; };
this._list = this; this._list = this;
this._init = function() { this._init = function () {
// Transform attribute parser // Transform attribute parser
var str = this._elem.getAttribute('transform'); var str = this._elem.getAttribute('transform');
if (!str) {return;} if (!str) { return; }
// TODO: Add skew support in future // TODO: Add skew support in future
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/; var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
@@ -105,20 +107,20 @@ svgedit.transformlist.SVGTransformList = function(elem) {
var x = m[1]; var x = m[1];
var bits = x.split(/\s*\(/); var bits = x.split(/\s*\(/);
var name = bits[0]; var name = bits[0];
var val_bits = bits[1].match(/\s*(.*?)\s*\)/); var valBits = bits[1].match(/\s*(.*?)\s*\)/);
val_bits[1] = val_bits[1].replace(/(\d)-/g, '$1 -'); valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
var val_arr = val_bits[1].split(/[, ]+/); var valArr = valBits[1].split(/[, ]+/);
var letters = 'abcdef'.split(''); var letters = 'abcdef'.split('');
var mtx = svgroot.createSVGMatrix(); var mtx = svgroot.createSVGMatrix();
$.each(val_arr, function(i, item) { $.each(valArr, function (i, item) {
val_arr[i] = parseFloat(item); valArr[i] = parseFloat(item);
if (name == 'matrix') { if (name == 'matrix') {
mtx[letters[i]] = val_arr[i]; mtx[letters[i]] = valArr[i];
} }
}); });
var xform = svgroot.createSVGTransform(); var xform = svgroot.createSVGTransform();
var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1); var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
var values = name == 'matrix' ? [mtx] : val_arr; var values = name == 'matrix' ? [mtx] : valArr;
if (name == 'scale' && values.length == 1) { if (name == 'scale' && values.length == 1) {
values.push(values[0]); values.push(values[0]);
@@ -132,7 +134,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
} }
} }
}; };
this._removeFromOtherLists = function(item) { this._removeFromOtherLists = function (item) {
if (item) { if (item) {
// Check if this transform is already in a transformlist, and // Check if this transform is already in a transformlist, and
// remove it if so. // remove it if so.
@@ -156,25 +158,27 @@ svgedit.transformlist.SVGTransformList = function(elem) {
}; };
this.numberOfItems = 0; this.numberOfItems = 0;
this.clear = function() { this.clear = function () {
this.numberOfItems = 0; this.numberOfItems = 0;
this._xforms = []; this._xforms = [];
}; };
this.initialize = function(newItem) { this.initialize = function (newItem) {
this.numberOfItems = 1; this.numberOfItems = 1;
this._removeFromOtherLists(newItem); this._removeFromOtherLists(newItem);
this._xforms = [newItem]; this._xforms = [newItem];
}; };
this.getItem = function(index) { this.getItem = function (index) {
if (index < this.numberOfItems && index >= 0) { if (index < this.numberOfItems && index >= 0) {
return this._xforms[index]; return this._xforms[index];
} }
throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR var err = new Error('DOMException with code=INDEX_SIZE_ERR');
err.code = 1;
throw err;
}; };
this.insertItemBefore = function(newItem, index) { this.insertItemBefore = function (newItem, index) {
var retValue = null; var retValue = null;
if (index >= 0) { if (index >= 0) {
if (index < this.numberOfItems) { if (index < this.numberOfItems) {
@@ -187,22 +191,21 @@ svgedit.transformlist.SVGTransformList = function(elem) {
} }
newxforms[i] = newItem; newxforms[i] = newItem;
var j; var j;
for (j = i+1; i < this.numberOfItems; ++j, ++i) { for (j = i + 1; i < this.numberOfItems; ++j, ++i) {
newxforms[j] = this._xforms[i]; newxforms[j] = this._xforms[i];
} }
this.numberOfItems++; this.numberOfItems++;
this._xforms = newxforms; this._xforms = newxforms;
retValue = newItem; retValue = newItem;
this._list._update(); this._list._update();
} } else {
else {
retValue = this._list.appendItem(newItem); retValue = this._list.appendItem(newItem);
} }
} }
return retValue; return retValue;
}; };
this.replaceItem = function(newItem, index) { this.replaceItem = function (newItem, index) {
var retValue = null; var retValue = null;
if (index < this.numberOfItems && index >= 0) { if (index < this.numberOfItems && index >= 0) {
this._removeFromOtherLists(newItem); this._removeFromOtherLists(newItem);
@@ -213,7 +216,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
return retValue; return retValue;
}; };
this.removeItem = function(index) { this.removeItem = function (index) {
if (index < this.numberOfItems && index >= 0) { if (index < this.numberOfItems && index >= 0) {
var retValue = this._xforms[index]; var retValue = this._xforms[index];
var newxforms = new Array(this.numberOfItems - 1); var newxforms = new Array(this.numberOfItems - 1);
@@ -221,18 +224,20 @@ svgedit.transformlist.SVGTransformList = function(elem) {
for (i = 0; i < index; ++i) { for (i = 0; i < index; ++i) {
newxforms[i] = this._xforms[i]; newxforms[i] = this._xforms[i];
} }
for (j = i; j < this.numberOfItems-1; ++j, ++i) { for (j = i; j < this.numberOfItems - 1; ++j, ++i) {
newxforms[j] = this._xforms[i+1]; newxforms[j] = this._xforms[i + 1];
} }
this.numberOfItems--; this.numberOfItems--;
this._xforms = newxforms; this._xforms = newxforms;
this._list._update(); this._list._update();
return retValue; return retValue;
} }
throw {code: 1}; // DOMException with code=INDEX_SIZE_ERR var err = new Error('DOMException with code=INDEX_SIZE_ERR');
err.code = 1;
throw err;
}; };
this.appendItem = function(newItem) { this.appendItem = function (newItem) {
this._removeFromOtherLists(newItem); this._removeFromOtherLists(newItem);
this._xforms.push(newItem); this._xforms.push(newItem);
this.numberOfItems++; this.numberOfItems++;
@@ -241,8 +246,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
}; };
}; };
svgedit.transformlist.resetListMap = function () {
svgedit.transformlist.resetListMap = function() {
listMap_ = {}; listMap_ = {};
}; };
@@ -251,7 +255,7 @@ svgedit.transformlist.resetListMap = function() {
* Parameters: * Parameters:
* elem - a DOM Element * elem - a DOM Element
*/ */
svgedit.transformlist.removeElementFromListMap = function(elem) { svgedit.transformlist.removeElementFromListMap = function (elem) {
if (elem.id && listMap_[elem.id]) { if (elem.id && listMap_[elem.id]) {
delete listMap_[elem.id]; delete listMap_[elem.id];
} }
@@ -262,7 +266,7 @@ svgedit.transformlist.removeElementFromListMap = function(elem) {
// //
// Parameters: // Parameters:
// elem - DOM element to get a transformlist from // elem - DOM element to get a transformlist from
svgedit.transformlist.getTransformList = function(elem) { svgedit.transformlist.getTransformList = function (elem) {
if (!svgedit.browser.supportsNativeTransformLists()) { if (!svgedit.browser.supportsNativeTransformLists()) {
var id = elem.id || 'temp'; var id = elem.id || 'temp';
var t = listMap_[id]; var t = listMap_[id];
@@ -285,5 +289,4 @@ svgedit.transformlist.getTransformList = function(elem) {
return null; return null;
}; };
}()); }());

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +1,28 @@
/* eslint-disable no-var */
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/ // http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
function touchHandler(event) {'use strict'; function touchHandler (event) {
'use strict';
var simulatedEvent, var simulatedEvent,
touches = event.changedTouches, touches = event.changedTouches,
first = touches[0], first = touches[0],
type = ""; type = '';
switch (event.type) { switch (event.type) {
case "touchstart": type = "mousedown"; break; case 'touchstart': type = 'mousedown'; break;
case "touchmove": type = "mousemove"; break; case 'touchmove': type = 'mousemove'; break;
case "touchend": type = "mouseup"; break; case 'touchend': type = 'mouseup'; break;
default: return; default: return;
} }
// initMouseEvent(type, canBubble, cancelable, view, clickCount, // initMouseEvent(type, canBubble, cancelable, view, clickCount,
// screenX, screenY, clientX, clientY, ctrlKey, // screenX, screenY, clientX, clientY, ctrlKey,
// altKey, shiftKey, metaKey, button, relatedTarget); // altKey, shiftKey, metaKey, button, relatedTarget);
simulatedEvent = document.createEvent("MouseEvent"); simulatedEvent = document.createEvent('MouseEvent');
simulatedEvent.initMouseEvent(type, true, true, window, 1, simulatedEvent.initMouseEvent(type, true, true, window, 1,
first.screenX, first.screenY, first.screenX, first.screenY,
first.clientX, first.clientY, false, first.clientX, first.clientY, false,
false, false, false, 0/*left*/, null); false, false, false, 0/* left */, null);
if (touches.length < 2) { if (touches.length < 2) {
first.target.dispatchEvent(simulatedEvent); first.target.dispatchEvent(simulatedEvent);
event.preventDefault(); event.preventDefault();

View File

@@ -1,5 +1,5 @@
/*globals $, svgedit*/ /* eslint-disable no-var */
/*jslint vars: true, eqeq: true*/ /* globals $, svgedit */
/** /**
* Package: svgedit.units * Package: svgedit.units
* *
@@ -12,7 +12,8 @@
// Dependencies: // Dependencies:
// 1) jQuery // 1) jQuery
(function() {'use strict'; (function () {
'use strict';
if (!svgedit.units) { if (!svgedit.units) {
svgedit.units = {}; svgedit.units = {};
@@ -23,8 +24,9 @@ var wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];
var hAttrs = ['y', 'y1', 'cy', 'ry', 'height']; var hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];
var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs); var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs);
// unused // unused
/*
var unitNumMap = { var unitNumMap = {
'%': 2, '%': 2,
'em': 3, 'em': 3,
'ex': 4, 'ex': 4,
'px': 5, 'px': 5,
@@ -34,7 +36,7 @@ var unitNumMap = {
'pt': 9, 'pt': 9,
'pc': 10 'pc': 10
}; };
*/
// Container of elements. // Container of elements.
var elementContainer_; var elementContainer_;
@@ -60,7 +62,7 @@ var typeMap_ = {};
* Parameters: * Parameters:
* elementContainer - an object implementing the ElementContainer interface. * elementContainer - an object implementing the ElementContainer interface.
*/ */
svgedit.units.init = function(elementContainer) { svgedit.units.init = function (elementContainer) {
elementContainer_ = elementContainer; elementContainer_ = elementContainer;
// Get correct em/ex values by creating a temporary SVG. // Get correct em/ex values by creating a temporary SVG.
@@ -92,7 +94,7 @@ svgedit.units.init = function(elementContainer) {
// Function: svgedit.units.getTypeMap // Function: svgedit.units.getTypeMap
// Returns the unit object with values for each unit // Returns the unit object with values for each unit
svgedit.units.getTypeMap = function() { svgedit.units.getTypeMap = function () {
return typeMap_; return typeMap_;
}; };
@@ -105,7 +107,7 @@ svgedit.units.getTypeMap = function() {
// Returns: // Returns:
// If a string/number was given, returns a Float. If an array, return a string // If a string/number was given, returns a Float. If an array, return a string
// with comma-seperated floats // with comma-seperated floats
svgedit.units.shortFloat = function(val) { svgedit.units.shortFloat = function (val) {
var digits = elementContainer_.getRoundDigits(); var digits = elementContainer_.getRoundDigits();
if (!isNaN(val)) { if (!isNaN(val)) {
// Note that + converts to Number // Note that + converts to Number
@@ -119,11 +121,11 @@ svgedit.units.shortFloat = function(val) {
// Function: svgedit.units.convertUnit // Function: svgedit.units.convertUnit
// Converts the number to given unit or baseUnit // Converts the number to given unit or baseUnit
svgedit.units.convertUnit = function(val, unit) { svgedit.units.convertUnit = function (val, unit) {
unit = unit || elementContainer_.getBaseUnit(); unit = unit || elementContainer_.getBaseUnit();
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]); // baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
// var val = baseVal.valueInSpecifiedUnits; // var val = baseVal.valueInSpecifiedUnits;
// baseVal.convertToSpecifiedUnits(1); // baseVal.convertToSpecifiedUnits(1);
return svgedit.units.shortFloat(val / typeMap_[unit]); return svgedit.units.shortFloat(val / typeMap_[unit]);
}; };
@@ -134,38 +136,38 @@ svgedit.units.convertUnit = function(val, unit) {
// elem - DOM element to be changed // elem - DOM element to be changed
// attr - String with the name of the attribute associated with the value // attr - String with the name of the attribute associated with the value
// val - String with the attribute value to convert // val - String with the attribute value to convert
svgedit.units.setUnitAttr = function(elem, attr, val) { svgedit.units.setUnitAttr = function (elem, attr, val) {
// if (!isNaN(val)) { // if (!isNaN(val)) {
// New value is a number, so check currently used unit // New value is a number, so check currently used unit
// var old_val = elem.getAttribute(attr); // var old_val = elem.getAttribute(attr);
// Enable this for alternate mode // Enable this for alternate mode
// if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) { // if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) {
// // Old value was a number, so get unit, then convert // // Old value was a number, so get unit, then convert
// var unit; // var unit;
// if (old_val.substr(-1) === '%') { // if (old_val.substr(-1) === '%') {
// var res = getResolution(); // var res = getResolution();
// unit = '%'; // unit = '%';
// val *= 100; // val *= 100;
// if (wAttrs.indexOf(attr) >= 0) { // if (wAttrs.indexOf(attr) >= 0) {
// val = val / res.w; // val = val / res.w;
// } else if (hAttrs.indexOf(attr) >= 0) { // } else if (hAttrs.indexOf(attr) >= 0) {
// val = val / res.h; // val = val / res.h;
// } else { // } else {
// return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2); // return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
// } // }
// } else { // } else {
// if (elementContainer_.getBaseUnit() !== 'px') { // if (elementContainer_.getBaseUnit() !== 'px') {
// unit = elementContainer_.getBaseUnit(); // unit = elementContainer_.getBaseUnit();
// } else { // } else {
// unit = old_val.substr(-2); // unit = old_val.substr(-2);
// } // }
// val = val / typeMap_[unit]; // val = val / typeMap_[unit];
// } // }
// //
// val += unit; // val += unit;
// } // }
// } // }
elem.setAttribute(attr, val); elem.setAttribute(attr, val);
}; };
@@ -185,11 +187,11 @@ var attrsToConvert = {
// //
// Parameters: // Parameters:
// element - a DOM element whose attributes should be converted // element - a DOM element whose attributes should be converted
svgedit.units.convertAttrs = function(element) { svgedit.units.convertAttrs = function (element) {
var elName = element.tagName; var elName = element.tagName;
var unit = elementContainer_.getBaseUnit(); var unit = elementContainer_.getBaseUnit();
var attrs = attrsToConvert[elName]; var attrs = attrsToConvert[elName];
if (!attrs) {return;} if (!attrs) { return; }
var len = attrs.length; var len = attrs.length;
var i; var i;
@@ -201,7 +203,7 @@ svgedit.units.convertAttrs = function(element) {
element.setAttribute(attr, (cur / typeMap_[unit]) + unit); element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
} }
// else { // else {
// Convert existing? // Convert existing?
// } // }
} }
} }
@@ -214,13 +216,13 @@ svgedit.units.convertAttrs = function(element) {
// Parameters: // Parameters:
// attr - String with the name of the attribute associated with the value // attr - String with the name of the attribute associated with the value
// val - String with the attribute value to convert // val - String with the attribute value to convert
svgedit.units.convertToNum = function(attr, val) { svgedit.units.convertToNum = function (attr, val) {
// Return a number if that's what it already is // Return a number if that's what it already is
if (!isNaN(val)) {return val-0;} if (!isNaN(val)) { return val - 0; }
var num; var num;
if (val.substr(-1) === '%') { if (val.substr(-1) === '%') {
// Deal with percentage, depends on attribute // Deal with percentage, depends on attribute
num = val.substr(0, val.length-1)/100; num = val.substr(0, val.length - 1) / 100;
var width = elementContainer_.getWidth(); var width = elementContainer_.getWidth();
var height = elementContainer_.getHeight(); var height = elementContainer_.getHeight();
@@ -230,10 +232,10 @@ svgedit.units.convertToNum = function(attr, val) {
if (hAttrs.indexOf(attr) >= 0) { if (hAttrs.indexOf(attr) >= 0) {
return num * height; return num * height;
} }
return num * Math.sqrt((width*width) + (height*height))/Math.sqrt(2); return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);
} }
var unit = val.substr(-2); var unit = val.substr(-2);
num = val.substr(0, val.length-2); num = val.substr(0, val.length - 2);
// Note that this multiplication turns the string into a number // Note that this multiplication turns the string into a number
return num * typeMap_[unit]; return num * typeMap_[unit];
}; };
@@ -244,7 +246,7 @@ svgedit.units.convertToNum = function(attr, val) {
// Parameters: // Parameters:
// attr - String with the name of the attribute associated with the value // attr - String with the name of the attribute associated with the value
// val - String with the attribute value to check // val - String with the attribute value to check
svgedit.units.isValidUnit = function(attr, val, selectedElement) { svgedit.units.isValidUnit = function (attr, val, selectedElement) {
var valid = false; var valid = false;
if (unitAttrs.indexOf(attr) >= 0) { if (unitAttrs.indexOf(attr) >= 0) {
// True if it's just a number // True if it's just a number
@@ -253,13 +255,13 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
} else { } else {
// Not a number, check if it has a valid unit // Not a number, check if it has a valid unit
val = val.toLowerCase(); val = val.toLowerCase();
$.each(typeMap_, function(unit) { $.each(typeMap_, function (unit) {
if (valid) {return;} if (valid) { return; }
var re = new RegExp('^-?[\\d\\.]+' + unit + '$'); var re = new RegExp('^-?[\\d\\.]+' + unit + '$');
if (re.test(val)) {valid = true;} if (re.test(val)) { valid = true; }
}); });
} }
} else if (attr == 'id') { } else if (attr === 'id') {
// if we're trying to change the id, make sure it's not already present in the doc // if we're trying to change the id, make sure it's not already present in the doc
// and the id value is valid. // and the id value is valid.
@@ -271,12 +273,11 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
try { try {
var elem = elementContainer_.getElement(val); var elem = elementContainer_.getElement(val);
result = (elem == null || elem === selectedElement); result = (elem == null || elem === selectedElement);
} catch(e) {} } catch (e) {}
return result; return result;
} }
valid = true; valid = true;
return valid; return valid;
}; };
}()); }());