- 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:
@@ -1,13 +1,14 @@
|
||||
node_modules
|
||||
|
||||
editor/jquery.js
|
||||
editor/jspdf/jspdf.min.js
|
||||
editor/jspdf/underscore-min.js
|
||||
jgraduate/jpicker.min.js
|
||||
jgraduate/jquery.jgraduate.js
|
||||
jquery-ui
|
||||
jquerybbq
|
||||
js-hotkeys
|
||||
spinbtn/JQuerySpinBtn.min.js
|
||||
editor/jgraduate/jpicker.min.js
|
||||
editor/jgraduate/jquery.jgraduate.min.js
|
||||
editor/jquery-ui
|
||||
editor/jquerybbq
|
||||
editor/js-hotkeys
|
||||
editor/spinbtn/JQuerySpinBtn.min.js
|
||||
test/qunit
|
||||
test/sinon
|
||||
wave/json2.js
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* Package: svgedit.browser
|
||||
*
|
||||
@@ -12,7 +12,8 @@
|
||||
// Dependencies:
|
||||
// 1) jQuery (for $.alert())
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.browser) {
|
||||
svgedit.browser = {};
|
||||
@@ -21,12 +22,12 @@ if (!svgedit.browser) {
|
||||
// alias
|
||||
var NS = svgedit.NS;
|
||||
|
||||
var supportsSvg_ = (function() {
|
||||
var supportsSvg_ = (function () {
|
||||
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
|
||||
}());
|
||||
|
||||
svgedit.browser.supportsSvg = function() { return supportsSvg_; };
|
||||
if(!svgedit.browser.supportsSvg()) {
|
||||
svgedit.browser.supportsSvg = function () { return supportsSvg_; };
|
||||
if (!svgedit.browser.supportsSvg()) {
|
||||
window.location = 'browser-not-supported.html';
|
||||
return;
|
||||
}
|
||||
@@ -44,41 +45,41 @@ var isWindows_ = userAgent.indexOf('Windows') >= 0;
|
||||
var isMac_ = userAgent.indexOf('Macintosh') >= 0;
|
||||
var isTouch_ = 'ontouchstart' in window;
|
||||
|
||||
var supportsSelectors_ = (function() {
|
||||
var supportsSelectors_ = (function () {
|
||||
return !!svg.querySelector;
|
||||
}());
|
||||
|
||||
var supportsXpath_ = (function() {
|
||||
var supportsXpath_ = (function () {
|
||||
return !!document.evaluate;
|
||||
}());
|
||||
|
||||
// segList functions (for FF1.5 and 2.0)
|
||||
var supportsPathReplaceItem_ = (function() {
|
||||
var supportsPathReplaceItem_ = (function () {
|
||||
var path = document.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'M0,0 10,10');
|
||||
var seglist = path.pathSegList;
|
||||
var seg = path.createSVGPathSegLinetoAbs(5,5);
|
||||
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||
try {
|
||||
seglist.replaceItem(seg, 1);
|
||||
return true;
|
||||
} catch(err) {}
|
||||
} catch (err) {}
|
||||
return false;
|
||||
}());
|
||||
|
||||
var supportsPathInsertItemBefore_ = (function() {
|
||||
var supportsPathInsertItemBefore_ = (function () {
|
||||
var path = document.createElementNS(NS.SVG, 'path');
|
||||
path.setAttribute('d', 'M0,0 10,10');
|
||||
var seglist = path.pathSegList;
|
||||
var seg = path.createSVGPathSegLinetoAbs(5,5);
|
||||
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||
try {
|
||||
seglist.insertItemBefore(seg, 1);
|
||||
return true;
|
||||
} catch(err) {}
|
||||
} catch (err) {}
|
||||
return false;
|
||||
}());
|
||||
|
||||
// text character positioning (for IE9)
|
||||
var supportsGoodTextCharPos_ = (function() {
|
||||
var supportsGoodTextCharPos_ = (function () {
|
||||
var svgroot = document.createElementNS(NS.SVG, 'svg');
|
||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||
document.documentElement.appendChild(svgroot);
|
||||
@@ -92,7 +93,7 @@ var supportsGoodTextCharPos_ = (function() {
|
||||
return (pos === 0);
|
||||
}());
|
||||
|
||||
var supportsPathBBox_ = (function() {
|
||||
var supportsPathBBox_ = (function () {
|
||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||
document.documentElement.appendChild(svgcontent);
|
||||
var path = document.createElementNS(NS.SVG, 'path');
|
||||
@@ -104,7 +105,7 @@ var supportsPathBBox_ = (function() {
|
||||
}());
|
||||
|
||||
// Support for correct bbox sizing on groups with horizontal/vertical lines
|
||||
var supportsHVLineContainerBBox_ = (function() {
|
||||
var supportsHVLineContainerBBox_ = (function () {
|
||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||
document.documentElement.appendChild(svgcontent);
|
||||
var path = document.createElementNS(NS.SVG, 'path');
|
||||
@@ -121,31 +122,31 @@ var supportsHVLineContainerBBox_ = (function() {
|
||||
return (bbox.width == 15);
|
||||
}());
|
||||
|
||||
var supportsEditableText_ = (function() {
|
||||
var supportsEditableText_ = (function () {
|
||||
// TODO: Find better way to check support for this
|
||||
return isOpera_;
|
||||
}());
|
||||
|
||||
var supportsGoodDecimals_ = (function() {
|
||||
var supportsGoodDecimals_ = (function () {
|
||||
// Correct decimals on clone attributes (Opera < 10.5/win/non-en)
|
||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||
rect.setAttribute('x', 0.1);
|
||||
var crect = rect.cloneNode(false);
|
||||
var retValue = (crect.getAttribute('x').indexOf(',') == -1);
|
||||
if(!retValue) {
|
||||
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n'+
|
||||
var retValue = (crect.getAttribute('x').indexOf(',') === -1);
|
||||
if (!retValue) {
|
||||
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' +
|
||||
'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.');
|
||||
}
|
||||
return retValue;
|
||||
}());
|
||||
|
||||
var supportsNonScalingStroke_ = (function() {
|
||||
var supportsNonScalingStroke_ = (function () {
|
||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||
rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
|
||||
return rect.style.vectorEffect === 'non-scaling-stroke';
|
||||
}());
|
||||
|
||||
var supportsNativeSVGTransformLists_ = (function() {
|
||||
var supportsNativeSVGTransformLists_ = (function () {
|
||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||
var rxform = rect.transform.baseVal;
|
||||
var t1 = svg.createSVGTransform();
|
||||
@@ -163,26 +164,25 @@ var supportsNativeSVGTransformLists_ = (function() {
|
||||
|
||||
// Public API
|
||||
|
||||
svgedit.browser.isOpera = function() { return isOpera_; };
|
||||
svgedit.browser.isWebkit = function() { return isWebkit_; };
|
||||
svgedit.browser.isGecko = function() { return isGecko_; };
|
||||
svgedit.browser.isIE = function() { return isIE_; };
|
||||
svgedit.browser.isChrome = function() { return isChrome_; };
|
||||
svgedit.browser.isWindows = function() { return isWindows_; };
|
||||
svgedit.browser.isMac = function() { return isMac_; };
|
||||
svgedit.browser.isTouch = function() { return isTouch_; };
|
||||
svgedit.browser.isOpera = function () { return isOpera_; };
|
||||
svgedit.browser.isWebkit = function () { return isWebkit_; };
|
||||
svgedit.browser.isGecko = function () { return isGecko_; };
|
||||
svgedit.browser.isIE = function () { return isIE_; };
|
||||
svgedit.browser.isChrome = function () { return isChrome_; };
|
||||
svgedit.browser.isWindows = function () { return isWindows_; };
|
||||
svgedit.browser.isMac = function () { return isMac_; };
|
||||
svgedit.browser.isTouch = function () { return isTouch_; };
|
||||
|
||||
svgedit.browser.supportsSelectors = function() { return supportsSelectors_; };
|
||||
svgedit.browser.supportsXpath = function() { return supportsXpath_; };
|
||||
|
||||
svgedit.browser.supportsPathReplaceItem = function() { return supportsPathReplaceItem_; };
|
||||
svgedit.browser.supportsPathInsertItemBefore = function() { return supportsPathInsertItemBefore_; };
|
||||
svgedit.browser.supportsPathBBox = function() { return supportsPathBBox_; };
|
||||
svgedit.browser.supportsHVLineContainerBBox = function() { return supportsHVLineContainerBBox_; };
|
||||
svgedit.browser.supportsGoodTextCharPos = function() { return supportsGoodTextCharPos_; };
|
||||
svgedit.browser.supportsEditableText = function() { return supportsEditableText_; };
|
||||
svgedit.browser.supportsGoodDecimals = function() { return supportsGoodDecimals_; };
|
||||
svgedit.browser.supportsNonScalingStroke = function() { return supportsNonScalingStroke_; };
|
||||
svgedit.browser.supportsNativeTransformLists = function() { return supportsNativeSVGTransformLists_; };
|
||||
svgedit.browser.supportsSelectors = function () { return supportsSelectors_; };
|
||||
svgedit.browser.supportsXpath = function () { return supportsXpath_; };
|
||||
|
||||
svgedit.browser.supportsPathReplaceItem = function () { return supportsPathReplaceItem_; };
|
||||
svgedit.browser.supportsPathInsertItemBefore = function () { return supportsPathInsertItemBefore_; };
|
||||
svgedit.browser.supportsPathBBox = function () { return supportsPathBBox_; };
|
||||
svgedit.browser.supportsHVLineContainerBBox = function () { return supportsHVLineContainerBBox_; };
|
||||
svgedit.browser.supportsGoodTextCharPos = function () { return supportsGoodTextCharPos_; };
|
||||
svgedit.browser.supportsEditableText = function () { return supportsEditableText_; };
|
||||
svgedit.browser.supportsGoodDecimals = function () { return supportsGoodDecimals_; };
|
||||
svgedit.browser.supportsNonScalingStroke = function () { return supportsNonScalingStroke_; };
|
||||
svgedit.browser.supportsNativeTransformLists = function () { return supportsNativeSVGTransformLists_; };
|
||||
}());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// CREATE A NEW FILE config.js AND ADD CONTENTS
|
||||
// SUCH AS SHOWN BELOW INTO THAT FILE.
|
||||
|
||||
/*globals svgEditor*/
|
||||
/* globals svgEditor */
|
||||
/*
|
||||
The config.js file is intended for the setting of configuration or
|
||||
preferences which must run early on; if this is not needed, it is
|
||||
@@ -56,17 +56,17 @@ svgEditor.setConfig({
|
||||
});
|
||||
|
||||
// OTHER CONFIG
|
||||
svgEditor.setConfig({
|
||||
svgEditor.setConfig({
|
||||
// canvasName: 'default',
|
||||
// canvas_expansion: 3,
|
||||
// initFill: {
|
||||
// color: 'FF0000', // solid red
|
||||
// opacity: 1
|
||||
// color: 'FF0000', // solid red
|
||||
// opacity: 1
|
||||
// },
|
||||
// initStroke: {
|
||||
// width: 5,
|
||||
// color: '000000', // solid black
|
||||
// opacity: 1
|
||||
// width: 5,
|
||||
// color: '000000', // solid black
|
||||
// opacity: 1
|
||||
// },
|
||||
// initOpacity: 1,
|
||||
// colorPickerCSS: null,
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
/*globals $, svgEditor*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgEditor */
|
||||
/**
|
||||
* Package: svgedit.contextmenu
|
||||
*
|
||||
*
|
||||
* Licensed under the Apache License, Version 2
|
||||
*
|
||||
*
|
||||
* Author: Adam Bender
|
||||
*/
|
||||
// Dependencies:
|
||||
// 1) jQuery (for dom injection of context menus)
|
||||
var svgedit = svgedit || {};
|
||||
(function() {
|
||||
var self = this;
|
||||
if (!svgedit.contextmenu) {
|
||||
svgedit.contextmenu = {};
|
||||
var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define
|
||||
(function () {
|
||||
var self = this;
|
||||
if (!svgedit.contextmenu) {
|
||||
svgedit.contextmenu = {};
|
||||
}
|
||||
self.contextMenuExtensions = {};
|
||||
var menuItemIsValid = function (menuItem) {
|
||||
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function';
|
||||
};
|
||||
var addContextMenuItem = function (menuItem) {
|
||||
// menuItem: {id, label, shortcut, action}
|
||||
if (!menuItemIsValid(menuItem)) {
|
||||
console.error('Menu items must be defined and have at least properties: id, label, action, where action must be a function');
|
||||
return;
|
||||
}
|
||||
self.contextMenuExtensions = {};
|
||||
var menuItemIsValid = function(menuItem) {
|
||||
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function';
|
||||
};
|
||||
var addContextMenuItem = function(menuItem) {
|
||||
// menuItem: {id, label, shortcut, action}
|
||||
if (!menuItemIsValid(menuItem)) {
|
||||
console.error("Menu items must be defined and have at least properties: id, label, action, where action must be a function");
|
||||
return;
|
||||
}
|
||||
if (menuItem.id in self.contextMenuExtensions) {
|
||||
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
|
||||
return;
|
||||
}
|
||||
// Register menuItem action, see below for deferred menu dom injection
|
||||
console.log("Registed contextmenu item: {id:"+ menuItem.id+", label:"+menuItem.label+"}");
|
||||
self.contextMenuExtensions[menuItem.id] = menuItem;
|
||||
//TODO: Need to consider how to handle custom enable/disable behavior
|
||||
};
|
||||
var hasCustomHandler = function(handlerKey) {
|
||||
return self.contextMenuExtensions[handlerKey] && true;
|
||||
};
|
||||
var getCustomHandler = function(handlerKey) {
|
||||
return self.contextMenuExtensions[handlerKey].action;
|
||||
};
|
||||
var injectExtendedContextMenuItemIntoDom = function(menuItem) {
|
||||
if (Object.keys(self.contextMenuExtensions).length === 0) {
|
||||
// all menuItems appear at the bottom of the menu in their own container.
|
||||
// if this is the first extension menu we need to add the separator.
|
||||
$("#cmenu_canvas").append("<li class='separator'>");
|
||||
}
|
||||
var shortcut = menuItem.shortcut || "";
|
||||
$("#cmenu_canvas").append("<li class='disabled'><a href='#" + menuItem.id + "'>"
|
||||
+ menuItem.label + "<span class='shortcut'>"
|
||||
+ shortcut + "</span></a></li>");
|
||||
};
|
||||
// Defer injection to wait out initial menu processing. This probably goes away once all context
|
||||
// menu behavior is brought here.
|
||||
svgEditor.ready(function() {
|
||||
var menuItem;
|
||||
for (menuItem in contextMenuExtensions) {
|
||||
injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]);
|
||||
}
|
||||
});
|
||||
svgedit.contextmenu.resetCustomMenus = function(){self.contextMenuExtensions = {};};
|
||||
svgedit.contextmenu.add = addContextMenuItem;
|
||||
svgedit.contextmenu.hasCustomHandler = hasCustomHandler;
|
||||
svgedit.contextmenu.getCustomHandler = getCustomHandler;
|
||||
if (menuItem.id in self.contextMenuExtensions) {
|
||||
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
|
||||
return;
|
||||
}
|
||||
// Register menuItem action, see below for deferred menu dom injection
|
||||
console.log('Registed contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}');
|
||||
self.contextMenuExtensions[menuItem.id] = menuItem;
|
||||
// TODO: Need to consider how to handle custom enable/disable behavior
|
||||
};
|
||||
var hasCustomHandler = function (handlerKey) {
|
||||
return self.contextMenuExtensions[handlerKey] && true;
|
||||
};
|
||||
var getCustomHandler = function (handlerKey) {
|
||||
return self.contextMenuExtensions[handlerKey].action;
|
||||
};
|
||||
var injectExtendedContextMenuItemIntoDom = function (menuItem) {
|
||||
if (Object.keys(self.contextMenuExtensions).length === 0) {
|
||||
// all menuItems appear at the bottom of the menu in their own container.
|
||||
// if this is the first extension menu we need to add the separator.
|
||||
$('#cmenu_canvas').append("<li class='separator'>");
|
||||
}
|
||||
var shortcut = menuItem.shortcut || '';
|
||||
$('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" +
|
||||
menuItem.label + "<span class='shortcut'>" +
|
||||
shortcut + '</span></a></li>');
|
||||
};
|
||||
// Defer injection to wait out initial menu processing. This probably goes away once all context
|
||||
// menu behavior is brought here.
|
||||
svgEditor.ready(function () {
|
||||
var menuItem;
|
||||
for (menuItem in self.contextMenuExtensions) {
|
||||
injectExtendedContextMenuItemIntoDom(self.contextMenuExtensions[menuItem]);
|
||||
}
|
||||
});
|
||||
svgedit.contextmenu.resetCustomMenus = function () { self.contextMenuExtensions = {}; };
|
||||
svgedit.contextmenu.add = addContextMenuItem;
|
||||
svgedit.contextmenu.hasCustomHandler = hasCustomHandler;
|
||||
svgedit.contextmenu.getCustomHandler = getCustomHandler;
|
||||
}());
|
||||
|
||||
527
editor/coords.js
527
editor/coords.js
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgroot */
|
||||
/*jslint vars: true, eqeq: true, forin: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgroot */
|
||||
/**
|
||||
* Coords.
|
||||
*
|
||||
@@ -16,17 +16,18 @@
|
||||
// 6) units.js
|
||||
// 7) svgtransformlist.js
|
||||
|
||||
var svgedit = svgedit || {};
|
||||
var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.coords) {
|
||||
svgedit.coords = {};
|
||||
svgedit.coords = {};
|
||||
}
|
||||
|
||||
// this is how we map paths to our preferred relative segment types
|
||||
var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
||||
var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
||||
|
||||
/**
|
||||
* @typedef editorContext
|
||||
@@ -39,8 +40,8 @@ var editorContext_ = null;
|
||||
/**
|
||||
* @param {editorContext} editorContext
|
||||
*/
|
||||
svgedit.coords.init = function(editorContext) {
|
||||
editorContext_ = editorContext;
|
||||
svgedit.coords.init = function (editorContext) {
|
||||
editorContext_ = editorContext;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -49,269 +50,267 @@ svgedit.coords.init = function(editorContext) {
|
||||
* @param {object} changes - Object with changes to be remapped
|
||||
* @param {SVGMatrix} m - Matrix object to use for remapping coordinates
|
||||
*/
|
||||
svgedit.coords.remapElement = function(selected, changes, m) {
|
||||
var i, type,
|
||||
remap = function(x, y) { return svgedit.math.transformPoint(x, y, m); },
|
||||
scalew = function(w) { return m.a * w; },
|
||||
scaleh = function(h) { return m.d * h; },
|
||||
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
|
||||
finishUp = function() {
|
||||
var o;
|
||||
if (doSnapping) {
|
||||
for (o in changes) {
|
||||
changes[o] = svgedit.utilities.snapToGrid(changes[o]);
|
||||
}
|
||||
}
|
||||
svgedit.utilities.assignAttributes(selected, changes, 1000, true);
|
||||
},
|
||||
box = svgedit.utilities.getBBox(selected);
|
||||
svgedit.coords.remapElement = function (selected, changes, m) {
|
||||
var i, type,
|
||||
remap = function (x, y) { return svgedit.math.transformPoint(x, y, m); },
|
||||
scalew = function (w) { return m.a * w; },
|
||||
scaleh = function (h) { return m.d * h; },
|
||||
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
|
||||
finishUp = function () {
|
||||
var o;
|
||||
if (doSnapping) {
|
||||
for (o in changes) {
|
||||
changes[o] = svgedit.utilities.snapToGrid(changes[o]);
|
||||
}
|
||||
}
|
||||
svgedit.utilities.assignAttributes(selected, changes, 1000, true);
|
||||
},
|
||||
box = svgedit.utilities.getBBox(selected);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
type = i === 0 ? 'fill' : 'stroke';
|
||||
var attrVal = selected.getAttribute(type);
|
||||
if (attrVal && attrVal.indexOf('url(') === 0) {
|
||||
if (m.a < 0 || m.d < 0) {
|
||||
var grad = svgedit.utilities.getRefElem(attrVal);
|
||||
var newgrad = grad.cloneNode(true);
|
||||
if (m.a < 0) {
|
||||
// flip x
|
||||
var x1 = newgrad.getAttribute('x1');
|
||||
var x2 = newgrad.getAttribute('x2');
|
||||
newgrad.setAttribute('x1', -(x1 - 1));
|
||||
newgrad.setAttribute('x2', -(x2 - 1));
|
||||
}
|
||||
for (i = 0; i < 2; i++) {
|
||||
type = i === 0 ? 'fill' : 'stroke';
|
||||
var attrVal = selected.getAttribute(type);
|
||||
if (attrVal && attrVal.indexOf('url(') === 0) {
|
||||
if (m.a < 0 || m.d < 0) {
|
||||
var grad = svgedit.utilities.getRefElem(attrVal);
|
||||
var newgrad = grad.cloneNode(true);
|
||||
if (m.a < 0) {
|
||||
// flip x
|
||||
var x1 = newgrad.getAttribute('x1');
|
||||
var x2 = newgrad.getAttribute('x2');
|
||||
newgrad.setAttribute('x1', -(x1 - 1));
|
||||
newgrad.setAttribute('x2', -(x2 - 1));
|
||||
}
|
||||
|
||||
if (m.d < 0) {
|
||||
// flip y
|
||||
var y1 = newgrad.getAttribute('y1');
|
||||
var y2 = newgrad.getAttribute('y2');
|
||||
newgrad.setAttribute('y1', -(y1 - 1));
|
||||
newgrad.setAttribute('y2', -(y2 - 1));
|
||||
}
|
||||
newgrad.id = editorContext_.getDrawing().getNextId();
|
||||
svgedit.utilities.findDefs().appendChild(newgrad);
|
||||
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
||||
}
|
||||
if (m.d < 0) {
|
||||
// flip y
|
||||
var y1 = newgrad.getAttribute('y1');
|
||||
var y2 = newgrad.getAttribute('y2');
|
||||
newgrad.setAttribute('y1', -(y1 - 1));
|
||||
newgrad.setAttribute('y2', -(y2 - 1));
|
||||
}
|
||||
newgrad.id = editorContext_.getDrawing().getNextId();
|
||||
svgedit.utilities.findDefs().appendChild(newgrad);
|
||||
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
||||
}
|
||||
|
||||
// Not really working :(
|
||||
// if (selected.tagName === 'path') {
|
||||
// reorientGrads(selected, m);
|
||||
// }
|
||||
}
|
||||
}
|
||||
// Not really working :(
|
||||
// if (selected.tagName === 'path') {
|
||||
// reorientGrads(selected, m);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
var elName = selected.tagName;
|
||||
var chlist, mt;
|
||||
if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') {
|
||||
// if it was a translate, then just update x,y
|
||||
if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0) ) {
|
||||
// [T][M] = [M][T']
|
||||
// therefore [T'] = [M_inv][T][M]
|
||||
var existing = svgedit.math.transformListToTransform(selected).matrix,
|
||||
t_new = svgedit.math.matrixMultiply(existing.inverse(), m, existing);
|
||||
changes.x = parseFloat(changes.x) + t_new.e;
|
||||
changes.y = parseFloat(changes.y) + t_new.f;
|
||||
} else {
|
||||
// we just absorb all matrices into the element and don't do any remapping
|
||||
chlist = svgedit.transformlist.getTransformList(selected);
|
||||
mt = svgroot.createSVGTransform();
|
||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
}
|
||||
}
|
||||
var c, pt, pt1, pt2, len;
|
||||
// now we have a set of changes and an applied reduced transform list
|
||||
// we apply the changes directly to the DOM
|
||||
switch (elName) {
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image':
|
||||
// Allow images to be inverted (give them matrix when flipped)
|
||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||
// Convert to matrix
|
||||
chlist = svgedit.transformlist.getTransformList(selected);
|
||||
mt = svgroot.createSVGTransform();
|
||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
} else {
|
||||
pt1 = remap(changes.x, changes.y);
|
||||
changes.width = scalew(changes.width);
|
||||
changes.height = scaleh(changes.height);
|
||||
changes.x = pt1.x + Math.min(0, changes.width);
|
||||
changes.y = pt1.y + Math.min(0, changes.height);
|
||||
changes.width = Math.abs(changes.width);
|
||||
changes.height = Math.abs(changes.height);
|
||||
}
|
||||
finishUp();
|
||||
break;
|
||||
case 'ellipse':
|
||||
c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
changes.rx = scalew(changes.rx);
|
||||
changes.ry = scaleh(changes.ry);
|
||||
changes.rx = Math.abs(changes.rx);
|
||||
changes.ry = Math.abs(changes.ry);
|
||||
finishUp();
|
||||
break;
|
||||
case 'circle':
|
||||
c = remap(changes.cx,changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
// take the minimum of the new selected box's dimensions for the new circle radius
|
||||
var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m);
|
||||
var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
||||
changes.r = Math.min(w/2, h/2);
|
||||
var elName = selected.tagName;
|
||||
var chlist, mt;
|
||||
if (elName === 'g' || elName === 'text' || elName == 'tspan' || elName === 'use') {
|
||||
// if it was a translate, then just update x,y
|
||||
if (m.a == 1 && m.b == 0 && m.c == 0 && m.d == 1 && (m.e != 0 || m.f != 0)) {
|
||||
// [T][M] = [M][T']
|
||||
// therefore [T'] = [M_inv][T][M]
|
||||
var existing = svgedit.math.transformListToTransform(selected).matrix,
|
||||
tNew = svgedit.math.matrixMultiply(existing.inverse(), m, existing);
|
||||
changes.x = parseFloat(changes.x) + tNew.e;
|
||||
changes.y = parseFloat(changes.y) + tNew.f;
|
||||
} else {
|
||||
// we just absorb all matrices into the element and don't do any remapping
|
||||
chlist = svgedit.transformlist.getTransformList(selected);
|
||||
mt = svgroot.createSVGTransform();
|
||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
}
|
||||
}
|
||||
var c, pt, pt1, pt2, len;
|
||||
// now we have a set of changes and an applied reduced transform list
|
||||
// we apply the changes directly to the DOM
|
||||
switch (elName) {
|
||||
case 'foreignObject':
|
||||
case 'rect':
|
||||
case 'image':
|
||||
// Allow images to be inverted (give them matrix when flipped)
|
||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||
// Convert to matrix
|
||||
chlist = svgedit.transformlist.getTransformList(selected);
|
||||
mt = svgroot.createSVGTransform();
|
||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||
chlist.clear();
|
||||
chlist.appendItem(mt);
|
||||
} else {
|
||||
pt1 = remap(changes.x, changes.y);
|
||||
changes.width = scalew(changes.width);
|
||||
changes.height = scaleh(changes.height);
|
||||
changes.x = pt1.x + Math.min(0, changes.width);
|
||||
changes.y = pt1.y + Math.min(0, changes.height);
|
||||
changes.width = Math.abs(changes.width);
|
||||
changes.height = Math.abs(changes.height);
|
||||
}
|
||||
finishUp();
|
||||
break;
|
||||
case 'ellipse':
|
||||
c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
changes.rx = scalew(changes.rx);
|
||||
changes.ry = scaleh(changes.ry);
|
||||
changes.rx = Math.abs(changes.rx);
|
||||
changes.ry = Math.abs(changes.ry);
|
||||
finishUp();
|
||||
break;
|
||||
case 'circle':
|
||||
c = remap(changes.cx, changes.cy);
|
||||
changes.cx = c.x;
|
||||
changes.cy = c.y;
|
||||
// take the minimum of the new selected box's dimensions for the new circle radius
|
||||
var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m);
|
||||
var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
||||
changes.r = Math.min(w / 2, h / 2);
|
||||
|
||||
if (changes.r) {changes.r = Math.abs(changes.r);}
|
||||
finishUp();
|
||||
break;
|
||||
case 'line':
|
||||
pt1 = remap(changes.x1, changes.y1);
|
||||
pt2 = remap(changes.x2, changes.y2);
|
||||
changes.x1 = pt1.x;
|
||||
changes.y1 = pt1.y;
|
||||
changes.x2 = pt2.x;
|
||||
changes.y2 = pt2.y;
|
||||
// deliberately fall through here
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
case 'use':
|
||||
finishUp();
|
||||
break;
|
||||
case 'g':
|
||||
var gsvg = $(selected).data('gsvg');
|
||||
if (gsvg) {
|
||||
svgedit.utilities.assignAttributes(gsvg, changes, 1000, true);
|
||||
}
|
||||
break;
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
len = changes.points.length;
|
||||
for (i = 0; i < len; ++i) {
|
||||
pt = changes.points[i];
|
||||
pt = remap(pt.x, pt.y);
|
||||
changes.points[i].x = pt.x;
|
||||
changes.points[i].y = pt.y;
|
||||
}
|
||||
if (changes.r) { changes.r = Math.abs(changes.r); }
|
||||
finishUp();
|
||||
break;
|
||||
case 'line':
|
||||
pt1 = remap(changes.x1, changes.y1);
|
||||
pt2 = remap(changes.x2, changes.y2);
|
||||
changes.x1 = pt1.x;
|
||||
changes.y1 = pt1.y;
|
||||
changes.x2 = pt2.x;
|
||||
changes.y2 = pt2.y;
|
||||
// deliberately fall through here
|
||||
case 'text':
|
||||
case 'tspan':
|
||||
case 'use':
|
||||
finishUp();
|
||||
break;
|
||||
case 'g':
|
||||
var gsvg = $(selected).data('gsvg');
|
||||
if (gsvg) {
|
||||
svgedit.utilities.assignAttributes(gsvg, changes, 1000, true);
|
||||
}
|
||||
break;
|
||||
case 'polyline':
|
||||
case 'polygon':
|
||||
len = changes.points.length;
|
||||
for (i = 0; i < len; ++i) {
|
||||
pt = changes.points[i];
|
||||
pt = remap(pt.x, pt.y);
|
||||
changes.points[i].x = pt.x;
|
||||
changes.points[i].y = pt.y;
|
||||
}
|
||||
|
||||
len = changes.points.length;
|
||||
var pstr = '';
|
||||
for (i = 0; i < len; ++i) {
|
||||
pt = changes.points[i];
|
||||
pstr += pt.x + ',' + pt.y + ' ';
|
||||
}
|
||||
selected.setAttribute('points', pstr);
|
||||
break;
|
||||
case 'path':
|
||||
var seg;
|
||||
var segList = selected.pathSegList;
|
||||
len = segList.numberOfItems;
|
||||
changes.d = [];
|
||||
for (i = 0; i < len; ++i) {
|
||||
seg = segList.getItem(i);
|
||||
changes.d[i] = {
|
||||
type: seg.pathSegType,
|
||||
x: seg.x,
|
||||
y: seg.y,
|
||||
x1: seg.x1,
|
||||
y1: seg.y1,
|
||||
x2: seg.x2,
|
||||
y2: seg.y2,
|
||||
r1: seg.r1,
|
||||
r2: seg.r2,
|
||||
angle: seg.angle,
|
||||
largeArcFlag: seg.largeArcFlag,
|
||||
sweepFlag: seg.sweepFlag
|
||||
};
|
||||
}
|
||||
len = changes.points.length;
|
||||
var pstr = '';
|
||||
for (i = 0; i < len; ++i) {
|
||||
pt = changes.points[i];
|
||||
pstr += pt.x + ',' + pt.y + ' ';
|
||||
}
|
||||
selected.setAttribute('points', pstr);
|
||||
break;
|
||||
case 'path':
|
||||
var seg;
|
||||
var segList = selected.pathSegList;
|
||||
len = segList.numberOfItems;
|
||||
changes.d = [];
|
||||
for (i = 0; i < len; ++i) {
|
||||
seg = segList.getItem(i);
|
||||
changes.d[i] = {
|
||||
type: seg.pathSegType,
|
||||
x: seg.x,
|
||||
y: seg.y,
|
||||
x1: seg.x1,
|
||||
y1: seg.y1,
|
||||
x2: seg.x2,
|
||||
y2: seg.y2,
|
||||
r1: seg.r1,
|
||||
r2: seg.r2,
|
||||
angle: seg.angle,
|
||||
largeArcFlag: seg.largeArcFlag,
|
||||
sweepFlag: seg.sweepFlag
|
||||
};
|
||||
}
|
||||
|
||||
len = changes.d.length;
|
||||
var firstseg = changes.d[0],
|
||||
currentpt = remap(firstseg.x, firstseg.y);
|
||||
changes.d[0].x = currentpt.x;
|
||||
changes.d[0].y = currentpt.y;
|
||||
for (i = 1; i < len; ++i) {
|
||||
seg = changes.d[i];
|
||||
type = seg.type;
|
||||
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
||||
// if relative, we want to scalew, scaleh
|
||||
if (type % 2 == 0) { // absolute
|
||||
var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands
|
||||
thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands
|
||||
pt = remap(thisx,thisy);
|
||||
pt1 = remap(seg.x1, seg.y1);
|
||||
pt2 = remap(seg.x2, seg.y2);
|
||||
seg.x = pt.x;
|
||||
seg.y = pt.y;
|
||||
seg.x1 = pt1.x;
|
||||
seg.y1 = pt1.y;
|
||||
seg.x2 = pt2.x;
|
||||
seg.y2 = pt2.y;
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
}
|
||||
else { // relative
|
||||
seg.x = scalew(seg.x);
|
||||
seg.y = scaleh(seg.y);
|
||||
seg.x1 = scalew(seg.x1);
|
||||
seg.y1 = scaleh(seg.y1);
|
||||
seg.x2 = scalew(seg.x2);
|
||||
seg.y2 = scaleh(seg.y2);
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
}
|
||||
} // for each segment
|
||||
len = changes.d.length;
|
||||
var firstseg = changes.d[0],
|
||||
currentpt = remap(firstseg.x, firstseg.y);
|
||||
changes.d[0].x = currentpt.x;
|
||||
changes.d[0].y = currentpt.y;
|
||||
for (i = 1; i < len; ++i) {
|
||||
seg = changes.d[i];
|
||||
type = seg.type;
|
||||
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
||||
// if relative, we want to scalew, scaleh
|
||||
if (type % 2 == 0) { // absolute
|
||||
var thisx = (seg.x != undefined) ? seg.x : currentpt.x, // for V commands
|
||||
thisy = (seg.y != undefined) ? seg.y : currentpt.y; // for H commands
|
||||
pt = remap(thisx, thisy);
|
||||
pt1 = remap(seg.x1, seg.y1);
|
||||
pt2 = remap(seg.x2, seg.y2);
|
||||
seg.x = pt.x;
|
||||
seg.y = pt.y;
|
||||
seg.x1 = pt1.x;
|
||||
seg.y1 = pt1.y;
|
||||
seg.x2 = pt2.x;
|
||||
seg.y2 = pt2.y;
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
} else { // relative
|
||||
seg.x = scalew(seg.x);
|
||||
seg.y = scaleh(seg.y);
|
||||
seg.x1 = scalew(seg.x1);
|
||||
seg.y1 = scaleh(seg.y1);
|
||||
seg.x2 = scalew(seg.x2);
|
||||
seg.y2 = scaleh(seg.y2);
|
||||
seg.r1 = scalew(seg.r1);
|
||||
seg.r2 = scaleh(seg.r2);
|
||||
}
|
||||
} // for each segment
|
||||
|
||||
var dstr = '';
|
||||
len = changes.d.length;
|
||||
for (i = 0; i < len; ++i) {
|
||||
seg = changes.d[i];
|
||||
type = seg.type;
|
||||
dstr += pathMap[type];
|
||||
switch (type) {
|
||||
case 13: // relative horizontal line (h)
|
||||
case 12: // absolute horizontal line (H)
|
||||
dstr += seg.x + ' ';
|
||||
break;
|
||||
case 15: // relative vertical line (v)
|
||||
case 14: // absolute vertical line (V)
|
||||
dstr += seg.y + ' ';
|
||||
break;
|
||||
case 3: // relative move (m)
|
||||
case 5: // relative line (l)
|
||||
case 19: // relative smooth quad (t)
|
||||
case 2: // absolute move (M)
|
||||
case 4: // absolute line (L)
|
||||
case 18: // absolute smooth quad (T)
|
||||
dstr += seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 7: // relative cubic (c)
|
||||
case 6: // absolute cubic (C)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
||||
seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 9: // relative quad (q)
|
||||
case 8: // absolute quad (Q)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
|
||||
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 16: // absolute smooth cubic (S)
|
||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
var dstr = '';
|
||||
len = changes.d.length;
|
||||
for (i = 0; i < len; ++i) {
|
||||
seg = changes.d[i];
|
||||
type = seg.type;
|
||||
dstr += pathMap[type];
|
||||
switch (type) {
|
||||
case 13: // relative horizontal line (h)
|
||||
case 12: // absolute horizontal line (H)
|
||||
dstr += seg.x + ' ';
|
||||
break;
|
||||
case 15: // relative vertical line (v)
|
||||
case 14: // absolute vertical line (V)
|
||||
dstr += seg.y + ' ';
|
||||
break;
|
||||
case 3: // relative move (m)
|
||||
case 5: // relative line (l)
|
||||
case 19: // relative smooth quad (t)
|
||||
case 2: // absolute move (M)
|
||||
case 4: // absolute line (L)
|
||||
case 18: // absolute smooth quad (T)
|
||||
dstr += seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 7: // relative cubic (c)
|
||||
case 6: // absolute cubic (C)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
||||
seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 9: // relative quad (q)
|
||||
case 8: // absolute quad (Q)
|
||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 11: // relative elliptical arc (a)
|
||||
case 10: // absolute elliptical arc (A)
|
||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
|
||||
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
case 17: // relative smooth cubic (s)
|
||||
case 16: // absolute smooth cubic (S)
|
||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
selected.setAttribute('d', dstr);
|
||||
break;
|
||||
}
|
||||
selected.setAttribute('d', dstr);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
172
editor/draw.js
172
editor/draw.js
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true, todo: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* Package: svgedit.draw
|
||||
*
|
||||
@@ -13,7 +13,8 @@
|
||||
// 2) browser.js
|
||||
// 3) svgutils.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.draw) {
|
||||
svgedit.draw = {};
|
||||
@@ -28,25 +29,22 @@ var RandomizeModes = {
|
||||
ALWAYS_RANDOMIZE: 1,
|
||||
NEVER_RANDOMIZE: 2
|
||||
};
|
||||
var randomize_ids = RandomizeModes.LET_DOCUMENT_DECIDE;
|
||||
var randomizeIds = RandomizeModes.LET_DOCUMENT_DECIDE;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Called to ensure that drawings will or will not have randomized ids.
|
||||
* The currentDrawing will have its nonce set if it doesn't already.
|
||||
* @param {boolean} enableRandomization - flag indicating if documents should have randomized ids
|
||||
* @param {svgedit.draw.Drawing} currentDrawing
|
||||
*/
|
||||
svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) {
|
||||
randomize_ids = enableRandomization === false ?
|
||||
RandomizeModes.NEVER_RANDOMIZE :
|
||||
RandomizeModes.ALWAYS_RANDOMIZE;
|
||||
svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) {
|
||||
randomizeIds = enableRandomization === false
|
||||
? RandomizeModes.NEVER_RANDOMIZE
|
||||
: RandomizeModes.ALWAYS_RANDOMIZE;
|
||||
|
||||
if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {
|
||||
if (randomizeIds == RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {
|
||||
currentDrawing.setNonce(Math.floor(Math.random() * 100001));
|
||||
} else if (randomize_ids == RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {
|
||||
} else if (randomizeIds == RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {
|
||||
currentDrawing.clearNonce();
|
||||
}
|
||||
};
|
||||
@@ -56,12 +54,12 @@ svgedit.draw.randomizeIds = function(enableRandomization, currentDrawing) {
|
||||
* @param {SVGSVGElement} svgElem - The SVG DOM Element that this JS object
|
||||
* encapsulates. If the svgElem has a se:nonce attribute on it, then
|
||||
* IDs will use the nonce as they are generated.
|
||||
* @param {String=svg_} [opt_idPrefix] - The ID prefix to use.
|
||||
* @param {String=svg_} [optIdPrefix] - The ID prefix to use.
|
||||
*/
|
||||
svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
|
||||
svgedit.draw.Drawing = function (svgElem, optIdPrefix) {
|
||||
if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||
|
||||
svgElem.tagName != 'svg' || svgElem.namespaceURI != NS.SVG) {
|
||||
throw "Error: svgedit.draw.Drawing instance initialized without a <svg> element";
|
||||
throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,19 +67,19 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
|
||||
* @type {SVGSVGElement}
|
||||
*/
|
||||
this.svgElem_ = svgElem;
|
||||
|
||||
|
||||
/**
|
||||
* The latest object number used in this drawing.
|
||||
* @type {number}
|
||||
*/
|
||||
this.obj_num = 0;
|
||||
|
||||
|
||||
/**
|
||||
* The prefix to prepend to each element id in the drawing.
|
||||
* @type {String}
|
||||
*/
|
||||
this.idPrefix = opt_idPrefix || "svg_";
|
||||
|
||||
this.idPrefix = optIdPrefix || 'svg_';
|
||||
|
||||
/**
|
||||
* An array of released element ids to immediately reuse.
|
||||
* @type {Array.<number>}
|
||||
@@ -120,9 +118,9 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) {
|
||||
var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');
|
||||
// If already set in the DOM, use the nonce throughout the document
|
||||
// else, if randomizeIds(true) has been called, create and set the nonce.
|
||||
if (!!n && randomize_ids != RandomizeModes.NEVER_RANDOMIZE) {
|
||||
if (!!n && randomizeIds != RandomizeModes.NEVER_RANDOMIZE) {
|
||||
this.nonce_ = n;
|
||||
} else if (randomize_ids == RandomizeModes.ALWAYS_RANDOMIZE) {
|
||||
} else if (randomizeIds == RandomizeModes.ALWAYS_RANDOMIZE) {
|
||||
this.setNonce(Math.floor(Math.random() * 100001));
|
||||
}
|
||||
};
|
||||
@@ -150,14 +148,14 @@ svgedit.draw.Drawing.prototype.getSvgElem = function () {
|
||||
/**
|
||||
* @returns {!string|number} The previously set nonce
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getNonce = function() {
|
||||
svgedit.draw.Drawing.prototype.getNonce = function () {
|
||||
return this.nonce_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!string|number} n The nonce to set
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.setNonce = function(n) {
|
||||
svgedit.draw.Drawing.prototype.setNonce = function (n) {
|
||||
this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE);
|
||||
this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);
|
||||
this.nonce_ = n;
|
||||
@@ -177,9 +175,9 @@ svgedit.draw.Drawing.prototype.clearNonce = function () {
|
||||
* @return {String} The latest object Id.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getId = function () {
|
||||
return this.nonce_ ?
|
||||
this.idPrefix + this.nonce_ + '_' + this.obj_num :
|
||||
this.idPrefix + this.obj_num;
|
||||
return this.nonce_
|
||||
? this.idPrefix + this.nonce_ + '_' + this.obj_num
|
||||
: this.idPrefix + this.obj_num;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -190,7 +188,7 @@ svgedit.draw.Drawing.prototype.getNextId = function () {
|
||||
var oldObjNum = this.obj_num;
|
||||
var restoreOldObjNum = false;
|
||||
|
||||
// If there are any released numbers in the release stack,
|
||||
// If there are any released numbers in the release stack,
|
||||
// use the last one instead of the next obj_num.
|
||||
// We need to temporarily use obj_num as that is what getId() depends on.
|
||||
if (this.releasedNums.length > 0) {
|
||||
@@ -239,7 +237,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) {
|
||||
if (typeof num !== 'number' || num <= 0 || this.releasedNums.indexOf(num) != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// push the released number into the released queue
|
||||
this.releasedNums.push(num);
|
||||
|
||||
@@ -250,7 +248,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) {
|
||||
* Returns the number of layers in the current drawing.
|
||||
* @returns {integer} The number of layers in the current drawing.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getNumLayers = function() {
|
||||
svgedit.draw.Drawing.prototype.getNumLayers = function () {
|
||||
return this.all_layers.length;
|
||||
};
|
||||
|
||||
@@ -262,7 +260,6 @@ svgedit.draw.Drawing.prototype.hasLayer = function (name) {
|
||||
return this.layer_map[name] !== undefined;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the ith layer. If the index is out of range, an empty string is returned.
|
||||
* @param {integer} i - The zero-based index of the layer you are querying.
|
||||
@@ -275,7 +272,7 @@ svgedit.draw.Drawing.prototype.getLayerName = function (i) {
|
||||
/**
|
||||
* @returns {SVGGElement} The SVGGElement representing the current layer.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getCurrentLayer = function() {
|
||||
svgedit.draw.Drawing.prototype.getCurrentLayer = function () {
|
||||
return this.current_layer ? this.current_layer.getGroup() : null;
|
||||
};
|
||||
|
||||
@@ -283,13 +280,13 @@ svgedit.draw.Drawing.prototype.getCurrentLayer = function() {
|
||||
* Get a layer by name.
|
||||
* @returns {SVGGElement} The SVGGElement representing the named layer or null.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getLayerByName = function(name) {
|
||||
svgedit.draw.Drawing.prototype.getLayerByName = function (name) {
|
||||
var layer = this.layer_map[name];
|
||||
return layer ? layer.getGroup() : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the name of the currently selected layer. If an error occurs, an empty string
|
||||
* Returns the name of the currently selected layer. If an error occurs, an empty string
|
||||
* is returned.
|
||||
* @returns {string} The name of the currently active layer (or the empty string if none found).
|
||||
*/
|
||||
@@ -322,39 +319,38 @@ svgedit.draw.Drawing.prototype.setCurrentLayerName = function (name, hrService)
|
||||
* @returns {Object} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
|
||||
var layer_count = this.getNumLayers();
|
||||
if (!this.current_layer || newpos < 0 || newpos >= layer_count) {
|
||||
var layerCount = this.getNumLayers();
|
||||
if (!this.current_layer || newpos < 0 || newpos >= layerCount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var oldpos;
|
||||
for (oldpos = 0; oldpos < layer_count; ++oldpos) {
|
||||
if (this.all_layers[oldpos] == this.current_layer) {break;}
|
||||
for (oldpos = 0; oldpos < layerCount; ++oldpos) {
|
||||
if (this.all_layers[oldpos] == this.current_layer) { break; }
|
||||
}
|
||||
// some unknown error condition (current_layer not in all_layers)
|
||||
if (oldpos == layer_count) { return null; }
|
||||
if (oldpos == layerCount) { return null; }
|
||||
|
||||
if (oldpos != newpos) {
|
||||
// if our new position is below us, we need to insert before the node after newpos
|
||||
var refGroup = null;
|
||||
var current_group = this.current_layer.getGroup();
|
||||
var oldNextSibling = current_group.nextSibling;
|
||||
if (newpos > oldpos ) {
|
||||
if (newpos < layer_count-1) {
|
||||
refGroup = this.all_layers[newpos+1].getGroup();
|
||||
var currentGroup = this.current_layer.getGroup();
|
||||
var oldNextSibling = currentGroup.nextSibling;
|
||||
if (newpos > oldpos) {
|
||||
if (newpos < layerCount - 1) {
|
||||
refGroup = this.all_layers[newpos + 1].getGroup();
|
||||
}
|
||||
}
|
||||
// if our new position is above us, we need to insert before the node at newpos
|
||||
else {
|
||||
} else {
|
||||
refGroup = this.all_layers[newpos].getGroup();
|
||||
}
|
||||
this.svgElem_.insertBefore(current_group, refGroup);
|
||||
this.svgElem_.insertBefore(currentGroup, refGroup);
|
||||
|
||||
this.identifyLayers();
|
||||
this.setCurrentLayer(this.getLayerName(newpos));
|
||||
|
||||
return {
|
||||
currentGroup: current_group,
|
||||
currentGroup: currentGroup,
|
||||
oldNextSibling: oldNextSibling
|
||||
};
|
||||
}
|
||||
@@ -362,25 +358,25 @@ svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
|
||||
};
|
||||
|
||||
svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
|
||||
var current_group = this.current_layer.getGroup();
|
||||
var prevGroup = $(current_group).prev()[0];
|
||||
if (!prevGroup) {return;}
|
||||
var currentGroup = this.current_layer.getGroup();
|
||||
var prevGroup = $(currentGroup).prev()[0];
|
||||
if (!prevGroup) { return; }
|
||||
|
||||
hrService.startBatchCommand('Merge Layer');
|
||||
|
||||
var layerNextSibling = current_group.nextSibling;
|
||||
hrService.removeElement(current_group, layerNextSibling, this.svgElem_);
|
||||
var layerNextSibling = currentGroup.nextSibling;
|
||||
hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);
|
||||
|
||||
while (current_group.firstChild) {
|
||||
var child = current_group.firstChild;
|
||||
while (currentGroup.firstChild) {
|
||||
var child = currentGroup.firstChild;
|
||||
if (child.localName == 'title') {
|
||||
hrService.removeElement(child, child.nextSibling, current_group);
|
||||
current_group.removeChild(child);
|
||||
hrService.removeElement(child, child.nextSibling, currentGroup);
|
||||
currentGroup.removeChild(child);
|
||||
continue;
|
||||
}
|
||||
var oldNextSibling = child.nextSibling;
|
||||
prevGroup.appendChild(child);
|
||||
hrService.moveElement(child, oldNextSibling, current_group);
|
||||
hrService.moveElement(child, oldNextSibling, currentGroup);
|
||||
}
|
||||
|
||||
// Remove current layer's group
|
||||
@@ -389,7 +385,7 @@ svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
|
||||
var index = this.all_layers.indexOf(this.current_layer);
|
||||
if (index > 0) {
|
||||
var name = this.current_layer.getName();
|
||||
this.current_layer = this.all_layers[index-1]
|
||||
this.current_layer = this.all_layers[index - 1];
|
||||
this.all_layers.splice(index, 1);
|
||||
delete this.layer_map[name];
|
||||
}
|
||||
@@ -399,7 +395,7 @@ svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
|
||||
|
||||
svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
|
||||
// Set the current layer to the last layer.
|
||||
this.current_layer = this.all_layers[this.all_layers.length-1];
|
||||
this.current_layer = this.all_layers[this.all_layers.length - 1];
|
||||
|
||||
hrService.startBatchCommand('Merge all Layers');
|
||||
while (this.all_layers.length > 1) {
|
||||
@@ -415,7 +411,7 @@ svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
|
||||
* @param {string} name - The name of the layer you want to switch to.
|
||||
* @returns {boolean} true if the current layer was switched, otherwise false
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) {
|
||||
svgedit.draw.Drawing.prototype.setCurrentLayer = function (name) {
|
||||
var layer = this.layer_map[name];
|
||||
if (layer) {
|
||||
if (this.current_layer) {
|
||||
@@ -428,13 +424,12 @@ svgedit.draw.Drawing.prototype.setCurrentLayer = function(name) {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the current layer from the drawing and then clears the selection.
|
||||
* This function then calls the 'changed' handler. This is an undoable action.
|
||||
* @returns {SVGGElement} The SVGGElement of the layer removed or null.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() {
|
||||
svgedit.draw.Drawing.prototype.deleteCurrentLayer = function () {
|
||||
if (this.current_layer && this.getNumLayers() > 1) {
|
||||
var oldLayerGroup = this.current_layer.removeGroup();
|
||||
this.identifyLayers();
|
||||
@@ -448,8 +443,8 @@ svgedit.draw.Drawing.prototype.deleteCurrentLayer = function() {
|
||||
* @param group The group element to search in.
|
||||
* @returns {string} The layer name or empty string.
|
||||
*/
|
||||
function findLayerNameInGroup(group) {
|
||||
var name = $("title", group).text();
|
||||
function findLayerNameInGroup (group) {
|
||||
var name = $('title', group).text();
|
||||
|
||||
// Hack for Opera 10.60
|
||||
if (!name && svgedit.browser.isOpera() && group.querySelectorAll) {
|
||||
@@ -463,18 +458,18 @@ function findLayerNameInGroup(group) {
|
||||
* @param {Array.<string>} existingLayerNames - Existing layer names.
|
||||
* @returns {string} - The new name.
|
||||
*/
|
||||
function getNewLayerName(existingLayerNames) {
|
||||
function getNewLayerName (existingLayerNames) {
|
||||
var i = 1;
|
||||
// TODO(codedread): What about internationalization of "Layer"?
|
||||
while (existingLayerNames.indexOf(("Layer " + i)) >= 0) { i++; }
|
||||
return "Layer " + i;
|
||||
while (existingLayerNames.indexOf(('Layer ' + i)) >= 0) { i++; }
|
||||
return 'Layer ' + i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates layer system and sets the current layer to the
|
||||
* top-most layer (last <g> child of this drawing).
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.identifyLayers = function() {
|
||||
svgedit.draw.Drawing.prototype.identifyLayers = function () {
|
||||
this.all_layers = [];
|
||||
this.layer_map = {};
|
||||
var numchildren = this.svgElem_.childNodes.length;
|
||||
@@ -486,7 +481,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
|
||||
var child = this.svgElem_.childNodes.item(i);
|
||||
// for each g, find its layer name
|
||||
if (child && child.nodeType == 1) {
|
||||
if (child.tagName == "g") {
|
||||
if (child.tagName === 'g') {
|
||||
childgroups = true;
|
||||
var name = findLayerNameInGroup(child);
|
||||
if (name) {
|
||||
@@ -504,7 +499,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If orphans or no layers found, create a new layer and add all the orphans to it
|
||||
if (orphans.length > 0 || !childgroups) {
|
||||
layer = new svgedit.draw.Layer(getNewLayerName(layernames), null, this.svgElem_);
|
||||
@@ -525,7 +520,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() {
|
||||
* @returns {SVGGElement} The SVGGElement of the new layer, which is
|
||||
* also the current layer of this drawing.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.createLayer = function(name, hrService) {
|
||||
svgedit.draw.Drawing.prototype.createLayer = function (name, hrService) {
|
||||
if (this.current_layer) {
|
||||
this.current_layer.deactivate();
|
||||
}
|
||||
@@ -556,8 +551,8 @@ svgedit.draw.Drawing.prototype.createLayer = function(name, hrService) {
|
||||
* @returns {SVGGElement} The SVGGElement of the new layer, which is
|
||||
* also the current layer of this drawing.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) {
|
||||
if (!this.current_layer) {return null;}
|
||||
svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) {
|
||||
if (!this.current_layer) { return null; }
|
||||
this.current_layer.deactivate();
|
||||
// Check for duplicate name.
|
||||
if (name === undefined || name === null || name === '' || this.layer_map[name]) {
|
||||
@@ -567,14 +562,14 @@ svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) {
|
||||
// Create new group and add to DOM just after current_layer
|
||||
var currentGroup = this.current_layer.getGroup();
|
||||
var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_);
|
||||
var group = layer.getGroup();
|
||||
var group = layer.getGroup();
|
||||
|
||||
// Clone children
|
||||
var children = currentGroup.childNodes;
|
||||
var index;
|
||||
for (index = 0; index < children.length; index++) {
|
||||
var ch = children[index];
|
||||
if (ch.localName == 'title') {continue;}
|
||||
if (ch.localName == 'title') { continue; }
|
||||
group.appendChild(this.copyElem(ch));
|
||||
}
|
||||
|
||||
@@ -602,7 +597,7 @@ svgedit.draw.Drawing.prototype.cloneLayer = function(name, hrService) {
|
||||
* @param {string} layername - The name of the layer which you want to query.
|
||||
* @returns {boolean} The visibility state of the layer, or false if the layer name was invalid.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) {
|
||||
svgedit.draw.Drawing.prototype.getLayerVisibility = function (layername) {
|
||||
var layer = this.layer_map[layername];
|
||||
return layer ? layer.isVisible() : false;
|
||||
};
|
||||
@@ -616,26 +611,25 @@ svgedit.draw.Drawing.prototype.getLayerVisibility = function(layername) {
|
||||
* @returns {?SVGGElement} The SVGGElement representing the layer if the
|
||||
* layername was valid, otherwise null.
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.setLayerVisibility = function(layername, bVisible) {
|
||||
svgedit.draw.Drawing.prototype.setLayerVisibility = function (layername, bVisible) {
|
||||
if (typeof bVisible !== 'boolean') {
|
||||
return null;
|
||||
}
|
||||
var layer = this.layer_map[layername];
|
||||
if (!layer) {return null;}
|
||||
if (!layer) { return null; }
|
||||
layer.setVisible(bVisible);
|
||||
return layer.getGroup();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the opacity of the given layer. If the input name is not a layer, null is returned.
|
||||
* @param {string} layername - name of the layer on which to get the opacity
|
||||
* @returns {?number} The opacity value of the given layer. This will be a value between 0.0 and 1.0, or null
|
||||
* if layername is not a valid layer
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) {
|
||||
svgedit.draw.Drawing.prototype.getLayerOpacity = function (layername) {
|
||||
var layer = this.layer_map[layername];
|
||||
if (!layer) {return null;}
|
||||
if (!layer) { return null; }
|
||||
return layer.getOpacity();
|
||||
};
|
||||
|
||||
@@ -646,7 +640,7 @@ svgedit.draw.Drawing.prototype.getLayerOpacity = function(layername) {
|
||||
* @param {string} layername - Name of the layer on which to set the opacity
|
||||
* @param {number} opacity - A float value in the range 0.0-1.0
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) {
|
||||
svgedit.draw.Drawing.prototype.setLayerOpacity = function (layername, opacity) {
|
||||
if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {
|
||||
return;
|
||||
}
|
||||
@@ -661,11 +655,9 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function(layername, opacity) {
|
||||
* @param {Element} el - DOM element to clone
|
||||
* @returns {Element}
|
||||
*/
|
||||
svgedit.draw.Drawing.prototype.copyElem = function(el) {
|
||||
svgedit.draw.Drawing.prototype.copyElem = function (el) {
|
||||
var self = this;
|
||||
var getNextIdClosure = function() { return self.getNextId();}
|
||||
return svgedit.utilities.copyElem(el, getNextIdClosure)
|
||||
}
|
||||
|
||||
|
||||
var getNextIdClosure = function () { return self.getNextId(); };
|
||||
return svgedit.utilities.copyElem(el, getNextIdClosure);
|
||||
};
|
||||
}());
|
||||
|
||||
@@ -1,79 +1,80 @@
|
||||
/*globals $, EmbeddedSVGEdit*/
|
||||
/*jslint vars: true */
|
||||
var initEmbed;
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, EmbeddedSVGEdit */
|
||||
var initEmbed; // eslint-disable-line no-unused-vars
|
||||
|
||||
// Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
|
||||
|
||||
$(function () {'use strict';
|
||||
|
||||
var svgCanvas = null;
|
||||
var frame;
|
||||
$(function () {
|
||||
'use strict';
|
||||
|
||||
initEmbed = function () {
|
||||
var doc, mainButton;
|
||||
svgCanvas = new EmbeddedSVGEdit(frame);
|
||||
// Hide main button, as we will be controlling new, load, save, etc. from the host document
|
||||
doc = frame.contentDocument || frame.contentWindow.document;
|
||||
mainButton = doc.getElementById('main_button');
|
||||
mainButton.style.display = 'none';
|
||||
};
|
||||
var svgCanvas = null;
|
||||
var frame;
|
||||
|
||||
function handleSvgData(data, error) {
|
||||
if (error) {
|
||||
alert('error ' + error);
|
||||
} else {
|
||||
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
|
||||
}
|
||||
}
|
||||
initEmbed = function () {
|
||||
var doc, mainButton;
|
||||
svgCanvas = new EmbeddedSVGEdit(frame);
|
||||
// Hide main button, as we will be controlling new, load, save, etc. from the host document
|
||||
doc = frame.contentDocument || frame.contentWindow.document;
|
||||
mainButton = doc.getElementById('main_button');
|
||||
mainButton.style.display = 'none';
|
||||
};
|
||||
|
||||
function loadSvg() {
|
||||
var svgexample = '<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);
|
||||
}
|
||||
function handleSvgData (data, error) {
|
||||
if (error) {
|
||||
alert('error ' + error);
|
||||
} else {
|
||||
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
|
||||
}
|
||||
}
|
||||
|
||||
function saveSvg() {
|
||||
svgCanvas.getSvgString()(handleSvgData);
|
||||
}
|
||||
|
||||
function exportPNG() {
|
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||
function loadSvg () {
|
||||
var svgexample = '<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);
|
||||
}
|
||||
|
||||
function saveSvg () {
|
||||
svgCanvas.getSvgString()(handleSvgData);
|
||||
}
|
||||
|
||||
function exportPNG () {
|
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||
|
||||
var exportWindow = window.open(
|
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||
'svg-edit-exportWindow'
|
||||
);
|
||||
svgCanvas.rasterExport('PNG', null, exportWindow.name);
|
||||
}
|
||||
|
||||
function exportPDF () {
|
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||
|
||||
var exportWindow = window.open(
|
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||
'svg-edit-exportWindow'
|
||||
);
|
||||
svgCanvas.rasterExport('PNG', null, exportWindow.name);
|
||||
}
|
||||
|
||||
function exportPDF() {
|
||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||
|
||||
/**
|
||||
// If you want to handle the PDF blob yourself, do as follows
|
||||
// If you want to handle the PDF blob yourself, do as follows
|
||||
svgCanvas.bind('exportedPDF', function (win, data) {
|
||||
alert(data.dataurlstring);
|
||||
});
|
||||
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
|
||||
return;
|
||||
*/
|
||||
|
||||
var exportWindow = window.open(
|
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||
'svg-edit-exportWindow'
|
||||
);
|
||||
return;
|
||||
*/
|
||||
|
||||
var exportWindow = window.open(
|
||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||
'svg-edit-exportWindow'
|
||||
);
|
||||
svgCanvas.exportPDF(exportWindow.name);
|
||||
}
|
||||
|
||||
// Add event handlers
|
||||
$('#load').click(loadSvg);
|
||||
$('#save').click(saveSvg);
|
||||
$('#exportPNG').click(exportPNG);
|
||||
$('#exportPDF').click(exportPDF);
|
||||
$('body').append(
|
||||
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
|
||||
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
|
||||
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
|
||||
)
|
||||
);
|
||||
frame = document.getElementById('svgedit');
|
||||
}
|
||||
|
||||
// Add event handlers
|
||||
$('#load').click(loadSvg);
|
||||
$('#save').click(saveSvg);
|
||||
$('#exportPNG').click(exportPNG);
|
||||
$('#exportPDF').click(exportPDF);
|
||||
$('body').append(
|
||||
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
|
||||
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
|
||||
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
|
||||
)
|
||||
);
|
||||
frame = document.getElementById('svgedit');
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/*
|
||||
/* eslint-disable no-var */
|
||||
/*
|
||||
Embedded SVG-edit API
|
||||
|
||||
General usage:
|
||||
@@ -9,11 +10,11 @@ var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit);
|
||||
svgCanvas.setSvgString('string')
|
||||
- Or if a callback is needed:
|
||||
svgCanvas.setSvgString('string')(function(data, error){
|
||||
if (error){
|
||||
if (error){
|
||||
// There was an error
|
||||
} else{
|
||||
} else{
|
||||
// Handle data
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Everything is done with the same API as the real svg-edit,
|
||||
@@ -35,20 +36,21 @@ var blah = new EmbeddedSVGEdit(window.frames.svgedit);
|
||||
blah.clearSelection('woot', 'blah', 1337, [1, 2, 3, 4, 5, 'moo'], -42, {a: 'tree',b:6, c: 9})(function(){console.log('GET DATA',arguments)})
|
||||
*/
|
||||
|
||||
(function () {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var cbid = 0;
|
||||
|
||||
function getCallbackSetter (d) {
|
||||
return function () {
|
||||
var t = this, // New callback
|
||||
args = [].slice.call(arguments),
|
||||
cbid = t.send(d, args, function(){}); // The callback (currently it's nothing, but will be set later)
|
||||
return function () {
|
||||
var t = this, // New callback
|
||||
args = [].slice.call(arguments),
|
||||
cbid = t.send(d, args, function () {}); // The callback (currently it's nothing, but will be set later)
|
||||
|
||||
return function(newcallback){
|
||||
t.callbacks[cbid] = newcallback; // Set callback
|
||||
return function (newcallback) {
|
||||
t.callbacks[cbid] = newcallback; // Set callback
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -57,32 +59,32 @@ function getCallbackSetter (d) {
|
||||
* of same domain control
|
||||
*/
|
||||
function addCallback (t, data) {
|
||||
var result = data.result || data.error,
|
||||
cbid = data.id;
|
||||
if (t.callbacks[cbid]) {
|
||||
if (data.result) {
|
||||
t.callbacks[cbid](result);
|
||||
} else {
|
||||
t.callbacks[cbid](result, 'error');
|
||||
var result = data.result || data.error,
|
||||
cbid = data.id;
|
||||
if (t.callbacks[cbid]) {
|
||||
if (data.result) {
|
||||
t.callbacks[cbid](result);
|
||||
} else {
|
||||
t.callbacks[cbid](result, 'error');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function messageListener (e) {
|
||||
// We accept and post strings as opposed to objects for the sake of IE9 support; this
|
||||
// will most likely be changed in the future
|
||||
if (typeof e.data !== 'string') {
|
||||
return;
|
||||
}
|
||||
var allowedOrigins = this.allowedOrigins,
|
||||
data = e.data && JSON.parse(e.data);
|
||||
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
|
||||
e.source !== this.frame.contentWindow ||
|
||||
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
addCallback(this, data);
|
||||
// We accept and post strings as opposed to objects for the sake of IE9 support; this
|
||||
// will most likely be changed in the future
|
||||
if (typeof e.data !== 'string') {
|
||||
return;
|
||||
}
|
||||
var allowedOrigins = this.allowedOrigins,
|
||||
data = e.data && JSON.parse(e.data);
|
||||
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
|
||||
e.source !== this.frame.contentWindow ||
|
||||
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
addCallback(this, data);
|
||||
}
|
||||
|
||||
function getMessageListener (t) {
|
||||
@@ -98,82 +100,79 @@ function getMessageListener (t) {
|
||||
* If supplied, it should probably be the same as svgEditor's allowedOrigins
|
||||
*/
|
||||
function EmbeddedSVGEdit (frame, allowedOrigins) {
|
||||
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
|
||||
return new EmbeddedSVGEdit(frame);
|
||||
}
|
||||
this.allowedOrigins = allowedOrigins || [];
|
||||
// Initialize communication
|
||||
this.frame = frame;
|
||||
this.callbacks = {};
|
||||
// List of functions extracted with this:
|
||||
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
|
||||
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
|
||||
return new EmbeddedSVGEdit(frame);
|
||||
}
|
||||
this.allowedOrigins = allowedOrigins || [];
|
||||
// Initialize communication
|
||||
this.frame = frame;
|
||||
this.callbacks = {};
|
||||
// List of functions extracted with this:
|
||||
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
|
||||
|
||||
// for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q
|
||||
// var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
|
||||
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
|
||||
// 'moveSelectedToLayer', 'clear'];
|
||||
// for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q
|
||||
// var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
|
||||
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
|
||||
// 'moveSelectedToLayer', 'clear'];
|
||||
|
||||
// Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
|
||||
// var svgCanvas = frame.contentWindow.svgCanvas;
|
||||
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
|
||||
// alert("['" + l.join("', '") + "']");
|
||||
// Run in svgedit itself
|
||||
var i,
|
||||
functions = [
|
||||
'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready'
|
||||
];
|
||||
// Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
|
||||
// var svgCanvas = frame.contentWindow.svgCanvas;
|
||||
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
|
||||
// alert("['" + l.join("', '") + "']");
|
||||
// Run in svgedit itself
|
||||
var i,
|
||||
functions = [
|
||||
'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready'
|
||||
];
|
||||
|
||||
// TODO: rewrite the following, it's pretty scary.
|
||||
for (i = 0; i < functions.length; i++) {
|
||||
this[functions[i]] = getCallbackSetter(functions[i]);
|
||||
}
|
||||
|
||||
// Older IE may need a polyfill for addEventListener, but so it would for SVG
|
||||
window.addEventListener('message', getMessageListener(this), false);
|
||||
// TODO: rewrite the following, it's pretty scary.
|
||||
for (i = 0; i < functions.length; i++) {
|
||||
this[functions[i]] = getCallbackSetter(functions[i]);
|
||||
}
|
||||
|
||||
// Older IE may need a polyfill for addEventListener, but so it would for SVG
|
||||
window.addEventListener('message', getMessageListener(this), false);
|
||||
}
|
||||
|
||||
EmbeddedSVGEdit.prototype.send = function (name, args, callback){
|
||||
var t = this;
|
||||
cbid++;
|
||||
EmbeddedSVGEdit.prototype.send = function (name, args, callback) {
|
||||
var t = this;
|
||||
cbid++;
|
||||
|
||||
this.callbacks[cbid] = callback;
|
||||
setTimeout((function (cbid) {
|
||||
return function () { // Delay for the callback to be set in case its synchronous
|
||||
/*
|
||||
* Todo: Handle non-JSON arguments and return values (undefined,
|
||||
* nonfinite numbers, functions, and built-in objects like Date,
|
||||
* RegExp), etc.? Allow promises instead of callbacks? Review
|
||||
* SVG-Edit functions for whether JSON-able parameters can be
|
||||
* made compatile with all API functionality
|
||||
*/
|
||||
// We accept and post strings for the sake of IE9 support
|
||||
if (window.location.origin === t.frame.contentWindow.location.origin) {
|
||||
// Although we do not really need this API if we are working same
|
||||
// domain, it could allow us to write in a way that would work
|
||||
// cross-domain as well, assuming we stick to the argument limitations
|
||||
// of the current JSON-based communication API (e.g., not passing
|
||||
// callbacks). We might be able to address these shortcomings; see
|
||||
// the todo elsewhere in this file.
|
||||
var message = {id: cbid},
|
||||
svgCanvas = t.frame.contentWindow.svgCanvas;
|
||||
try {
|
||||
message.result = svgCanvas[name].apply(svgCanvas, args);
|
||||
}
|
||||
catch (err) {
|
||||
message.error = err.message;
|
||||
}
|
||||
addCallback(t, message);
|
||||
}
|
||||
else { // Requires the ext-xdomain-messaging.js extension
|
||||
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*');
|
||||
}
|
||||
};
|
||||
}(cbid)), 0);
|
||||
this.callbacks[cbid] = callback;
|
||||
setTimeout((function (cbid) {
|
||||
return function () { // Delay for the callback to be set in case its synchronous
|
||||
/*
|
||||
* Todo: Handle non-JSON arguments and return values (undefined,
|
||||
* nonfinite numbers, functions, and built-in objects like Date,
|
||||
* RegExp), etc.? Allow promises instead of callbacks? Review
|
||||
* SVG-Edit functions for whether JSON-able parameters can be
|
||||
* made compatile with all API functionality
|
||||
*/
|
||||
// We accept and post strings for the sake of IE9 support
|
||||
if (window.location.origin === t.frame.contentWindow.location.origin) {
|
||||
// Although we do not really need this API if we are working same
|
||||
// domain, it could allow us to write in a way that would work
|
||||
// cross-domain as well, assuming we stick to the argument limitations
|
||||
// of the current JSON-based communication API (e.g., not passing
|
||||
// callbacks). We might be able to address these shortcomings; see
|
||||
// the todo elsewhere in this file.
|
||||
var message = {id: cbid},
|
||||
svgCanvas = t.frame.contentWindow.svgCanvas;
|
||||
try {
|
||||
message.result = svgCanvas[name].apply(svgCanvas, args);
|
||||
} catch (err) {
|
||||
message.error = err.message;
|
||||
}
|
||||
addCallback(t, message);
|
||||
} else { // Requires the ext-xdomain-messaging.js extension
|
||||
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*');
|
||||
}
|
||||
};
|
||||
}(cbid)), 0);
|
||||
|
||||
return cbid;
|
||||
return cbid;
|
||||
};
|
||||
|
||||
window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API
|
||||
window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors
|
||||
|
||||
}());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgCanvas, $*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-arrows.js
|
||||
*
|
||||
@@ -9,65 +9,64 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension('Arrows', function(S) {
|
||||
var svgcontent = S.svgcontent,
|
||||
svgEditor.addExtension('Arrows', function (S) {
|
||||
var // svgcontent = S.svgcontent,
|
||||
addElem = S.addSvgElementFromJson,
|
||||
nonce = S.nonce,
|
||||
randomize_ids = S.randomize_ids,
|
||||
randomizeIds = S.randomize_ids,
|
||||
selElems, pathdata,
|
||||
lang_list = {
|
||||
'en':[
|
||||
{'id': 'arrow_none', 'textContent': 'No arrow' }
|
||||
langList = {
|
||||
'en': [
|
||||
{'id': 'arrow_none', 'textContent': 'No arrow'}
|
||||
],
|
||||
'fr':[
|
||||
{'id': 'arrow_none', 'textContent': 'Sans flèche' }
|
||||
'fr': [
|
||||
{'id': 'arrow_none', 'textContent': 'Sans flèche'}
|
||||
]
|
||||
},
|
||||
arrowprefix,
|
||||
prefix = 'se_arrow_';
|
||||
|
||||
function setArrowNonce(window, n) {
|
||||
randomize_ids = true;
|
||||
function setArrowNonce (window, n) {
|
||||
randomizeIds = true;
|
||||
arrowprefix = prefix + n + '_';
|
||||
pathdata.fw.id = arrowprefix + 'fw';
|
||||
pathdata.bk.id = arrowprefix + 'bk';
|
||||
}
|
||||
|
||||
function unsetArrowNonce(window) {
|
||||
randomize_ids = false;
|
||||
function unsetArrowNonce (window) {
|
||||
randomizeIds = false;
|
||||
arrowprefix = prefix;
|
||||
pathdata.fw.id = arrowprefix + 'fw';
|
||||
pathdata.bk.id = arrowprefix + 'bk';
|
||||
}
|
||||
|
||||
|
||||
svgCanvas.bind('setnonce', setArrowNonce);
|
||||
svgCanvas.bind('unsetnonce', unsetArrowNonce);
|
||||
|
||||
if (randomize_ids) {
|
||||
if (randomizeIds) {
|
||||
arrowprefix = prefix + nonce + '_';
|
||||
} else {
|
||||
arrowprefix = prefix;
|
||||
}
|
||||
|
||||
pathdata = {
|
||||
fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'},
|
||||
fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'},
|
||||
bk: {d: 'm10,0l-10,5l10,5l-5,-5l5,-5z', refx: 2, id: arrowprefix + 'bk'}
|
||||
};
|
||||
|
||||
function getLinked(elem, attr) {
|
||||
function getLinked (elem, attr) {
|
||||
var str = elem.getAttribute(attr);
|
||||
if(!str) {return null;}
|
||||
var m = str.match(/\(\#(.*)\)/);
|
||||
if(!m || m.length !== 2) {
|
||||
if (!str) { return null; }
|
||||
var m = str.match(/\(#(.*)\)/);
|
||||
if (!m || m.length !== 2) {
|
||||
return null;
|
||||
}
|
||||
return S.getElem(m[1]);
|
||||
}
|
||||
|
||||
function showPanel(on) {
|
||||
function showPanel (on) {
|
||||
$('#arrow_panel').toggle(on);
|
||||
if(on) {
|
||||
if (on) {
|
||||
var el = selElems[0];
|
||||
var end = el.getAttribute('marker-end');
|
||||
var start = el.getAttribute('marker-start');
|
||||
@@ -95,21 +94,21 @@ svgEditor.addExtension('Arrows', function(S) {
|
||||
}
|
||||
}
|
||||
|
||||
function resetMarker() {
|
||||
function resetMarker () {
|
||||
var el = selElems[0];
|
||||
el.removeAttribute('marker-start');
|
||||
el.removeAttribute('marker-mid');
|
||||
el.removeAttribute('marker-end');
|
||||
}
|
||||
|
||||
function addMarker(dir, type, id) {
|
||||
function addMarker (dir, type, id) {
|
||||
// TODO: Make marker (or use?) per arrow type, since refX can be different
|
||||
id = id || arrowprefix + dir;
|
||||
|
||||
var marker = S.getElem(id);
|
||||
var data = pathdata[dir];
|
||||
|
||||
if (type == 'mid') {
|
||||
if (type === 'mid') {
|
||||
data.refx = 5;
|
||||
}
|
||||
|
||||
@@ -143,25 +142,25 @@ svgEditor.addExtension('Arrows', function(S) {
|
||||
return marker;
|
||||
}
|
||||
|
||||
function setArrow() {
|
||||
function setArrow () {
|
||||
var type = this.value;
|
||||
resetMarker();
|
||||
|
||||
if (type == 'none') {
|
||||
if (type === 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set marker on element
|
||||
var dir = 'fw';
|
||||
if (type == 'mid_bk') {
|
||||
if (type === 'mid_bk') {
|
||||
type = 'mid';
|
||||
dir = 'bk';
|
||||
} else if (type == 'both') {
|
||||
} else if (type === 'both') {
|
||||
addMarker('bk', type);
|
||||
svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')');
|
||||
type = 'end';
|
||||
dir = 'fw';
|
||||
} else if (type == 'start') {
|
||||
} else if (type === 'start') {
|
||||
dir = 'bk';
|
||||
}
|
||||
|
||||
@@ -170,57 +169,57 @@ svgEditor.addExtension('Arrows', function(S) {
|
||||
S.call('changed', selElems);
|
||||
}
|
||||
|
||||
function colorChanged(elem) {
|
||||
function colorChanged (elem) {
|
||||
var color = elem.getAttribute('stroke');
|
||||
var mtypes = ['start', 'mid', 'end'];
|
||||
var defs = S.findDefs();
|
||||
|
||||
$.each(mtypes, function(i, type) {
|
||||
var marker = getLinked(elem, 'marker-'+type);
|
||||
if(!marker) {return;}
|
||||
$.each(mtypes, function (i, type) {
|
||||
var marker = getLinked(elem, 'marker-' + type);
|
||||
if (!marker) { return; }
|
||||
|
||||
var cur_color = $(marker).children().attr('fill');
|
||||
var cur_d = $(marker).children().attr('d');
|
||||
var new_marker = null;
|
||||
if(cur_color === color) {return;}
|
||||
var curColor = $(marker).children().attr('fill');
|
||||
var curD = $(marker).children().attr('d');
|
||||
var newMarker = null;
|
||||
if (curColor === color) { return; }
|
||||
|
||||
var all_markers = $(defs).find('marker');
|
||||
var allMarkers = $(defs).find('marker');
|
||||
// Different color, check if already made
|
||||
all_markers.each(function() {
|
||||
allMarkers.each(function () {
|
||||
var attrs = $(this).children().attr(['fill', 'd']);
|
||||
if(attrs.fill === color && attrs.d === cur_d) {
|
||||
if (attrs.fill === color && attrs.d === curD) {
|
||||
// Found another marker with this color and this path
|
||||
new_marker = this;
|
||||
newMarker = this;
|
||||
}
|
||||
});
|
||||
|
||||
if(!new_marker) {
|
||||
if (!newMarker) {
|
||||
// Create a new marker with this color
|
||||
var last_id = marker.id;
|
||||
var dir = last_id.indexOf('_fw') !== -1?'fw':'bk';
|
||||
var lastId = marker.id;
|
||||
var dir = lastId.indexOf('_fw') !== -1 ? 'fw' : 'bk';
|
||||
|
||||
new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length);
|
||||
newMarker = addMarker(dir, type, arrowprefix + dir + allMarkers.length);
|
||||
|
||||
$(new_marker).children().attr('fill', color);
|
||||
$(newMarker).children().attr('fill', color);
|
||||
}
|
||||
|
||||
$(elem).attr('marker-'+type, 'url(#' + new_marker.id + ')');
|
||||
$(elem).attr('marker-' + type, 'url(#' + newMarker.id + ')');
|
||||
|
||||
// Check if last marker can be removed
|
||||
var remove = true;
|
||||
$(S.svgcontent).find('line, polyline, path, polygon').each(function() {
|
||||
$(S.svgcontent).find('line, polyline, path, polygon').each(function () {
|
||||
var elem = this;
|
||||
$.each(mtypes, function(j, mtype) {
|
||||
if($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') {
|
||||
$.each(mtypes, function (j, mtype) {
|
||||
if ($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') {
|
||||
remove = false;
|
||||
return remove;
|
||||
}
|
||||
});
|
||||
if(!remove) {return false;}
|
||||
if (!remove) { return false; }
|
||||
});
|
||||
|
||||
// Not found, so can safely remove
|
||||
if(remove) {
|
||||
if (remove) {
|
||||
$(marker).remove();
|
||||
}
|
||||
});
|
||||
@@ -246,26 +245,26 @@ svgEditor.addExtension('Arrows', function(S) {
|
||||
change: setArrow
|
||||
}
|
||||
}],
|
||||
callback: function() {
|
||||
callback: function () {
|
||||
$('#arrow_panel').hide();
|
||||
// Set ID so it can be translated in locale file
|
||||
$('#arrow_list option')[0].id = 'connector_no_arrow';
|
||||
},
|
||||
addLangData: function(lang) {
|
||||
addLangData: function (lang) {
|
||||
return {
|
||||
data: lang_list[lang]
|
||||
data: langList[lang]
|
||||
};
|
||||
},
|
||||
selectedChanged: function(opts) {
|
||||
selectedChanged: function (opts) {
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
|
||||
var i = selElems.length;
|
||||
var marker_elems = ['line', 'path', 'polyline', 'polygon'];
|
||||
while(i--) {
|
||||
var markerElems = ['line', 'path', 'polyline', 'polygon'];
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if(elem && $.inArray(elem.tagName, marker_elems) !== -1) {
|
||||
if(opts.selectedElement && !opts.multiselected) {
|
||||
if (elem && $.inArray(elem.tagName, markerElems) !== -1) {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
showPanel(true);
|
||||
} else {
|
||||
showPanel(false);
|
||||
@@ -275,16 +274,16 @@ svgEditor.addExtension('Arrows', function(S) {
|
||||
}
|
||||
}
|
||||
},
|
||||
elementChanged: function(opts) {
|
||||
elementChanged: function (opts) {
|
||||
var elem = opts.elems[0];
|
||||
if(elem && (
|
||||
if (elem && (
|
||||
elem.getAttribute('marker-start') ||
|
||||
elem.getAttribute('marker-mid') ||
|
||||
elem.getAttribute('marker-end')
|
||||
)) {
|
||||
// var start = elem.getAttribute('marker-start');
|
||||
// var mid = elem.getAttribute('marker-mid');
|
||||
// var end = elem.getAttribute('marker-end');
|
||||
// var start = elem.getAttribute('marker-start');
|
||||
// var mid = elem.getAttribute('marker-mid');
|
||||
// var end = elem.getAttribute('marker-end');
|
||||
// Has marker, so see if it should match color
|
||||
colorChanged(elem);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, $*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, $ */
|
||||
/*
|
||||
* ext-closepath.js
|
||||
*
|
||||
@@ -11,30 +11,31 @@
|
||||
|
||||
// This extension adds a simple button to the contextual panel for paths
|
||||
// The button toggles whether the path is open or closed
|
||||
svgEditor.addExtension('ClosePath', function() {'use strict';
|
||||
svgEditor.addExtension('ClosePath', function () {
|
||||
'use strict';
|
||||
var selElems,
|
||||
updateButton = function(path) {
|
||||
updateButton = function (path) {
|
||||
var seglist = path.pathSegList,
|
||||
closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType == 1,
|
||||
closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType === 1,
|
||||
showbutton = closed ? '#tool_openpath' : '#tool_closepath',
|
||||
hidebutton = closed ? '#tool_closepath' : '#tool_openpath';
|
||||
$(hidebutton).hide();
|
||||
$(showbutton).show();
|
||||
$(hidebutton).hide();
|
||||
$(showbutton).show();
|
||||
},
|
||||
showPanel = function(on) {
|
||||
showPanel = function (on) {
|
||||
$('#closepath_panel').toggle(on);
|
||||
if (on) {
|
||||
var path = selElems[0];
|
||||
if (path) {updateButton(path);}
|
||||
if (path) { updateButton(path); }
|
||||
}
|
||||
},
|
||||
toggleClosed = function() {
|
||||
toggleClosed = function () {
|
||||
var path = selElems[0];
|
||||
if (path) {
|
||||
var seglist = path.pathSegList,
|
||||
last = seglist.numberOfItems - 1;
|
||||
// is closed
|
||||
if (seglist.getItem(last).pathSegType == 1) {
|
||||
if (seglist.getItem(last).pathSegType === 1) {
|
||||
seglist.removeItem(last);
|
||||
} else {
|
||||
seglist.appendItem(path.createSVGPathSegClosePath());
|
||||
@@ -52,7 +53,7 @@ svgEditor.addExtension('ClosePath', function() {'use strict';
|
||||
panel: 'closepath_panel',
|
||||
title: 'Open path',
|
||||
events: {
|
||||
click: function() {
|
||||
click: function () {
|
||||
toggleClosed();
|
||||
}
|
||||
}
|
||||
@@ -63,20 +64,20 @@ svgEditor.addExtension('ClosePath', function() {'use strict';
|
||||
panel: 'closepath_panel',
|
||||
title: 'Close path',
|
||||
events: {
|
||||
click: function() {
|
||||
click: function () {
|
||||
toggleClosed();
|
||||
}
|
||||
}
|
||||
}],
|
||||
callback: function() {
|
||||
callback: function () {
|
||||
$('#closepath_panel').hide();
|
||||
},
|
||||
selectedChanged: function(opts) {
|
||||
selectedChanged: function (opts) {
|
||||
selElems = opts.elems;
|
||||
var i = selElems.length;
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if (elem && elem.tagName == 'path') {
|
||||
if (elem && elem.tagName === 'path') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
showPanel(true);
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgCanvas, $*/
|
||||
/*jslint vars: true, continue: true, eqeq: true, todo: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-connector.js
|
||||
*
|
||||
@@ -8,8 +8,8 @@
|
||||
* Copyright(c) 2010 Alexis Deveria
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("Connector", function(S) {
|
||||
|
||||
svgEditor.addExtension('Connector', function (S) {
|
||||
var svgcontent = S.svgcontent,
|
||||
svgroot = S.svgroot,
|
||||
getNextId = S.getNextId,
|
||||
@@ -18,153 +18,151 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
selManager = S.selectorManager,
|
||||
curConfig = svgEditor.curConfig,
|
||||
started = false,
|
||||
start_x,
|
||||
start_y,
|
||||
cur_line,
|
||||
start_elem,
|
||||
end_elem,
|
||||
startX,
|
||||
startY,
|
||||
curLine,
|
||||
startElem,
|
||||
endElem,
|
||||
connections = [],
|
||||
conn_sel = ".se_connector",
|
||||
se_ns,
|
||||
// connect_str = "-SE_CONNECT-",
|
||||
connSel = '.se_connector',
|
||||
seNs,
|
||||
// connect_str = '-SE_CONNECT-',
|
||||
selElems = [],
|
||||
elData = $.data;
|
||||
|
||||
var lang_list = {
|
||||
"en":[
|
||||
{"id": "mode_connect", "title": "Connect two objects" }
|
||||
|
||||
var langList = {
|
||||
'en': [
|
||||
{'id': 'mode_connect', 'title': 'Connect two objects'}
|
||||
],
|
||||
"fr":[
|
||||
{"id": "mode_connect", "title": "Connecter deux objets"}
|
||||
'fr': [
|
||||
{'id': 'mode_connect', 'title': 'Connecter deux objets'}
|
||||
]
|
||||
};
|
||||
|
||||
function getBBintersect(x, y, bb, offset) {
|
||||
if(offset) {
|
||||
function getBBintersect (x, y, bb, offset) {
|
||||
if (offset) {
|
||||
offset -= 0;
|
||||
bb = $.extend({}, bb);
|
||||
bb.width += offset;
|
||||
bb.height += offset;
|
||||
bb.x -= offset/2;
|
||||
bb.y -= offset/2;
|
||||
bb.x -= offset / 2;
|
||||
bb.y -= offset / 2;
|
||||
}
|
||||
|
||||
var mid_x = bb.x + bb.width/2;
|
||||
var mid_y = bb.y + bb.height/2;
|
||||
var len_x = x - mid_x;
|
||||
var len_y = y - mid_y;
|
||||
|
||||
var slope = Math.abs(len_y/len_x);
|
||||
|
||||
|
||||
var midX = bb.x + bb.width / 2;
|
||||
var midY = bb.y + bb.height / 2;
|
||||
var lenX = x - midX;
|
||||
var lenY = y - midY;
|
||||
|
||||
var slope = Math.abs(lenY / lenX);
|
||||
|
||||
var ratio;
|
||||
|
||||
if(slope < bb.height/bb.width) {
|
||||
ratio = (bb.width/2) / Math.abs(len_x);
|
||||
|
||||
if (slope < bb.height / bb.width) {
|
||||
ratio = (bb.width / 2) / Math.abs(lenX);
|
||||
} else {
|
||||
ratio = (bb.height/2) / Math.abs(len_y);
|
||||
ratio = (bb.height / 2) / Math.abs(lenY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
return {
|
||||
x: mid_x + len_x * ratio,
|
||||
y: mid_y + len_y * ratio
|
||||
x: midX + lenX * ratio,
|
||||
y: midY + lenY * ratio
|
||||
};
|
||||
}
|
||||
|
||||
function getOffset(side, line) {
|
||||
var give_offset = !!line.getAttribute('marker-' + side);
|
||||
// var give_offset = $(line).data(side+'_off');
|
||||
function getOffset (side, line) {
|
||||
var giveOffset = !!line.getAttribute('marker-' + side);
|
||||
// var giveOffset = $(line).data(side+'_off');
|
||||
|
||||
// TODO: Make this number (5) be based on marker width/height
|
||||
var size = line.getAttribute('stroke-width') * 5;
|
||||
return give_offset ? size : 0;
|
||||
return giveOffset ? size : 0;
|
||||
}
|
||||
|
||||
function showPanel(on) {
|
||||
var conn_rules = $('#connector_rules');
|
||||
if(!conn_rules.length) {
|
||||
conn_rules = $('<style id="connector_rules"></style>').appendTo('head');
|
||||
}
|
||||
conn_rules.text(!on?"":"#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }");
|
||||
|
||||
function showPanel (on) {
|
||||
var connRules = $('#connector_rules');
|
||||
if (!connRules.length) {
|
||||
connRules = $('<style id="connector_rules"></style>').appendTo('head');
|
||||
}
|
||||
connRules.text(!on ? '' : '#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }');
|
||||
$('#connector_panel').toggle(on);
|
||||
}
|
||||
|
||||
function setPoint(elem, pos, x, y, setMid) {
|
||||
|
||||
function setPoint (elem, pos, x, y, setMid) {
|
||||
var i, pts = elem.points;
|
||||
var pt = svgroot.createSVGPoint();
|
||||
pt.x = x;
|
||||
pt.y = y;
|
||||
if (pos === 'end') {pos = pts.numberOfItems - 1;}
|
||||
if (pos === 'end') { pos = pts.numberOfItems - 1; }
|
||||
// TODO: Test for this on init, then use alt only if needed
|
||||
try {
|
||||
pts.replaceItem(pt, pos);
|
||||
} catch(err) {
|
||||
} catch (err) {
|
||||
// Should only occur in FF which formats points attr as "n,n n,n", so just split
|
||||
var pt_arr = elem.getAttribute("points").split(" ");
|
||||
for (i = 0; i < pt_arr.length; i++) {
|
||||
var ptArr = elem.getAttribute('points').split(' ');
|
||||
for (i = 0; i < ptArr.length; i++) {
|
||||
if (i === pos) {
|
||||
pt_arr[i] = x + ',' + y;
|
||||
ptArr[i] = x + ',' + y;
|
||||
}
|
||||
}
|
||||
elem.setAttribute("points",pt_arr.join(" "));
|
||||
elem.setAttribute('points', ptArr.join(' '));
|
||||
}
|
||||
|
||||
if(setMid) {
|
||||
|
||||
if (setMid) {
|
||||
// Add center point
|
||||
var pt_start = pts.getItem(0);
|
||||
var pt_end = pts.getItem(pts.numberOfItems-1);
|
||||
setPoint(elem, 1, (pt_end.x + pt_start.x)/2, (pt_end.y + pt_start.y)/2);
|
||||
var ptStart = pts.getItem(0);
|
||||
var ptEnd = pts.getItem(pts.numberOfItems - 1);
|
||||
setPoint(elem, 1, (ptEnd.x + ptStart.x) / 2, (ptEnd.y + ptStart.y) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
function updateLine(diff_x, diff_y) {
|
||||
|
||||
function updateLine (diffX, diffY) {
|
||||
// Update line with element
|
||||
var i = connections.length;
|
||||
while(i--) {
|
||||
while (i--) {
|
||||
var conn = connections[i];
|
||||
var line = conn.connector;
|
||||
var elem = conn.elem;
|
||||
|
||||
var pre = conn.is_start?'start':'end';
|
||||
// var sw = line.getAttribute('stroke-width') * 5;
|
||||
|
||||
// Update bbox for this element
|
||||
var bb = elData(line, pre+'_bb');
|
||||
bb.x = conn.start_x + diff_x;
|
||||
bb.y = conn.start_y + diff_y;
|
||||
elData(line, pre+'_bb', bb);
|
||||
|
||||
var alt_pre = conn.is_start?'end':'start';
|
||||
|
||||
// Get center pt of connected element
|
||||
var bb2 = elData(line, alt_pre+'_bb');
|
||||
var src_x = bb2.x + bb2.width/2;
|
||||
var src_y = bb2.y + bb2.height/2;
|
||||
|
||||
// Set point of element being moved
|
||||
var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0
|
||||
setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
|
||||
|
||||
// Set point of connected element
|
||||
var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line));
|
||||
setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
|
||||
// var elem = conn.elem;
|
||||
|
||||
var pre = conn.is_start ? 'start' : 'end';
|
||||
// var sw = line.getAttribute('stroke-width') * 5;
|
||||
|
||||
// Update bbox for this element
|
||||
var bb = elData(line, pre + '_bb');
|
||||
bb.x = conn.start_x + diffX;
|
||||
bb.y = conn.start_y + diffY;
|
||||
elData(line, pre + '_bb', bb);
|
||||
|
||||
var altPre = conn.is_start ? 'end' : 'start';
|
||||
|
||||
// Get center pt of connected element
|
||||
var bb2 = elData(line, altPre + '_bb');
|
||||
var srcX = bb2.x + bb2.width / 2;
|
||||
var srcY = bb2.y + bb2.height / 2;
|
||||
|
||||
// Set point of element being moved
|
||||
var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line)); // $(line).data(pre+'_off')?sw:0
|
||||
setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
|
||||
|
||||
// Set point of connected element
|
||||
var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line));
|
||||
setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
|
||||
}
|
||||
}
|
||||
|
||||
function findConnectors(elems) {
|
||||
|
||||
function findConnectors (elems) {
|
||||
var i;
|
||||
if (!elems) {elems = selElems;}
|
||||
var connectors = $(svgcontent).find(conn_sel);
|
||||
if (!elems) { elems = selElems; }
|
||||
var connectors = $(svgcontent).find(connSel);
|
||||
connections = [];
|
||||
|
||||
// Loop through connectors to see if one is connected to the element
|
||||
connectors.each(function() {
|
||||
var add_this;
|
||||
connectors.each(function () {
|
||||
var addThis;
|
||||
function add () {
|
||||
if ($.inArray(this, elems) !== -1) {
|
||||
// Pretend this element is selected
|
||||
add_this = true;
|
||||
addThis = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,42 +171,42 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
['start', 'end'].forEach(function (pos, i) {
|
||||
var key = 'c_' + pos;
|
||||
var part = elData(this, key);
|
||||
if(part == null) {
|
||||
if (part == null) {
|
||||
part = document.getElementById(
|
||||
this.attributes['se:connector'].value.split(' ')[i]
|
||||
);
|
||||
elData(this, 'c_'+pos, part.id);
|
||||
elData(this, pos+'_bb', svgCanvas.getStrokedBBox([part]));
|
||||
elData(this, 'c_' + pos, part.id);
|
||||
elData(this, pos + '_bb', svgCanvas.getStrokedBBox([part]));
|
||||
} else part = document.getElementById(part);
|
||||
parts.push(part);
|
||||
}.bind(this));
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
var c_elem = parts[i];
|
||||
var cElem = parts[i];
|
||||
|
||||
add_this = false;
|
||||
addThis = false;
|
||||
// The connected element might be part of a selected group
|
||||
$(c_elem).parents().each(add);
|
||||
|
||||
if(!c_elem || !c_elem.parentNode) {
|
||||
$(cElem).parents().each(add);
|
||||
|
||||
if (!cElem || !cElem.parentNode) {
|
||||
$(this).remove();
|
||||
continue;
|
||||
}
|
||||
if($.inArray(c_elem, elems) !== -1 || add_this) {
|
||||
var bb = svgCanvas.getStrokedBBox([c_elem]);
|
||||
if ($.inArray(cElem, elems) !== -1 || addThis) {
|
||||
var bb = svgCanvas.getStrokedBBox([cElem]);
|
||||
connections.push({
|
||||
elem: c_elem,
|
||||
elem: cElem,
|
||||
connector: this,
|
||||
is_start: (i === 0),
|
||||
start_x: bb.x,
|
||||
start_y: bb.y
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateConnectors(elems) {
|
||||
|
||||
function updateConnectors (elems) {
|
||||
// Updates connector lines based on selected elements
|
||||
// Is not used on mousemove, as it runs getStrokedBBox every time,
|
||||
// which isn't necessary there.
|
||||
@@ -222,227 +220,222 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
var line = conn.connector;
|
||||
var elem = conn.elem;
|
||||
|
||||
var sw = line.getAttribute('stroke-width') * 5;
|
||||
var pre = conn.is_start?'start':'end';
|
||||
|
||||
// var sw = line.getAttribute('stroke-width') * 5;
|
||||
var pre = conn.is_start ? 'start' : 'end';
|
||||
|
||||
// Update bbox for this element
|
||||
var bb = svgCanvas.getStrokedBBox([elem]);
|
||||
bb.x = conn.start_x;
|
||||
bb.y = conn.start_y;
|
||||
elData(line, pre+'_bb', bb);
|
||||
var add_offset = elData(line, pre+'_off');
|
||||
|
||||
var alt_pre = conn.is_start?'end':'start';
|
||||
|
||||
elData(line, pre + '_bb', bb);
|
||||
/* var addOffset = */ elData(line, pre + '_off');
|
||||
|
||||
var altPre = conn.is_start ? 'end' : 'start';
|
||||
|
||||
// Get center pt of connected element
|
||||
var bb2 = elData(line, alt_pre+'_bb');
|
||||
var src_x = bb2.x + bb2.width/2;
|
||||
var src_y = bb2.y + bb2.height/2;
|
||||
|
||||
var bb2 = elData(line, altPre + '_bb');
|
||||
var srcX = bb2.x + bb2.width / 2;
|
||||
var srcY = bb2.y + bb2.height / 2;
|
||||
|
||||
// Set point of element being moved
|
||||
var pt = getBBintersect(src_x, src_y, bb, getOffset(pre, line));
|
||||
var pt = getBBintersect(srcX, srcY, bb, getOffset(pre, line));
|
||||
setPoint(line, conn.is_start ? 0 : 'end', pt.x, pt.y, true);
|
||||
|
||||
|
||||
// Set point of connected element
|
||||
var pt2 = getBBintersect(pt.x, pt.y, elData(line, alt_pre + '_bb'), getOffset(alt_pre, line));
|
||||
var pt2 = getBBintersect(pt.x, pt.y, elData(line, altPre + '_bb'), getOffset(altPre, line));
|
||||
setPoint(line, conn.is_start ? 'end' : 0, pt2.x, pt2.y, true);
|
||||
|
||||
|
||||
// Update points attribute manually for webkit
|
||||
if (navigator.userAgent.indexOf('AppleWebKit') !== -1) {
|
||||
var pts = line.points;
|
||||
var len = pts.numberOfItems;
|
||||
var pt_arr = [];
|
||||
var ptArr = [];
|
||||
for (j = 0; j < len; j++) {
|
||||
pt = pts.getItem(j);
|
||||
pt_arr[j] = pt.x + ',' + pt.y;
|
||||
ptArr[j] = pt.x + ',' + pt.y;
|
||||
}
|
||||
line.setAttribute('points', pt_arr.join(' '));
|
||||
line.setAttribute('points', ptArr.join(' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do once
|
||||
(function() {
|
||||
(function () {
|
||||
var gse = svgCanvas.groupSelectedElements;
|
||||
|
||||
svgCanvas.groupSelectedElements = function() {
|
||||
svgCanvas.removeFromSelection($(conn_sel).toArray());
|
||||
|
||||
svgCanvas.groupSelectedElements = function () {
|
||||
svgCanvas.removeFromSelection($(connSel).toArray());
|
||||
return gse.apply(this, arguments);
|
||||
};
|
||||
|
||||
|
||||
var mse = svgCanvas.moveSelectedElements;
|
||||
|
||||
svgCanvas.moveSelectedElements = function() {
|
||||
|
||||
svgCanvas.moveSelectedElements = function () {
|
||||
var cmd = mse.apply(this, arguments);
|
||||
updateConnectors();
|
||||
return cmd;
|
||||
};
|
||||
|
||||
se_ns = svgCanvas.getEditorNS();
|
||||
|
||||
seNs = svgCanvas.getEditorNS();
|
||||
}());
|
||||
|
||||
|
||||
// Do on reset
|
||||
function init() {
|
||||
function init () {
|
||||
// Make sure all connectors have data set
|
||||
$(svgcontent).find('*').each(function() {
|
||||
var conn = this.getAttributeNS(se_ns, "connector");
|
||||
if(conn) {
|
||||
this.setAttribute('class', conn_sel.substr(1));
|
||||
var conn_data = conn.split(' ');
|
||||
var sbb = svgCanvas.getStrokedBBox([getElem(conn_data[0])]);
|
||||
var ebb = svgCanvas.getStrokedBBox([getElem(conn_data[1])]);
|
||||
$(this).data('c_start',conn_data[0])
|
||||
.data('c_end',conn_data[1])
|
||||
$(svgcontent).find('*').each(function () {
|
||||
var conn = this.getAttributeNS(seNs, 'connector');
|
||||
if (conn) {
|
||||
this.setAttribute('class', connSel.substr(1));
|
||||
var connData = conn.split(' ');
|
||||
var sbb = svgCanvas.getStrokedBBox([getElem(connData[0])]);
|
||||
var ebb = svgCanvas.getStrokedBBox([getElem(connData[1])]);
|
||||
$(this).data('c_start', connData[0])
|
||||
.data('c_end', connData[1])
|
||||
.data('start_bb', sbb)
|
||||
.data('end_bb', ebb);
|
||||
svgCanvas.getEditorNS(true);
|
||||
}
|
||||
});
|
||||
// updateConnectors();
|
||||
// updateConnectors();
|
||||
}
|
||||
|
||||
// $(svgroot).parent().mousemove(function(e) {
|
||||
// // if(started
|
||||
// // || svgCanvas.getMode() != "connector"
|
||||
// // || e.target.parentNode.parentNode != svgcontent) return;
|
||||
//
|
||||
// console.log('y')
|
||||
// // if(e.target.parentNode.parentNode === svgcontent) {
|
||||
// //
|
||||
// // }
|
||||
// });
|
||||
// $(svgroot).parent().mousemove(function (e) {
|
||||
// // if (started
|
||||
// // || svgCanvas.getMode() !== 'connector'
|
||||
// // || e.target.parentNode.parentNode !== svgcontent) return;
|
||||
//
|
||||
// console.log('y')
|
||||
// // if (e.target.parentNode.parentNode === svgcontent) {
|
||||
// //
|
||||
// // }
|
||||
// });
|
||||
|
||||
return {
|
||||
name: "Connector",
|
||||
svgicons: svgEditor.curConfig.imgPath + "conn.svg",
|
||||
name: 'Connector',
|
||||
svgicons: svgEditor.curConfig.imgPath + 'conn.svg',
|
||||
buttons: [{
|
||||
id: "mode_connect",
|
||||
type: "mode",
|
||||
icon: svgEditor.curConfig.imgPath + "cut.png",
|
||||
title: "Connect two objects",
|
||||
id: 'mode_connect',
|
||||
type: 'mode',
|
||||
icon: svgEditor.curConfig.imgPath + 'cut.png',
|
||||
title: 'Connect two objects',
|
||||
includeWith: {
|
||||
button: '#tool_line',
|
||||
isDefault: false,
|
||||
position: 1
|
||||
},
|
||||
events: {
|
||||
'click': function() {
|
||||
svgCanvas.setMode("connector");
|
||||
'click': function () {
|
||||
svgCanvas.setMode('connector');
|
||||
}
|
||||
}
|
||||
}],
|
||||
addLangData: function(lang) {
|
||||
addLangData: function (lang) {
|
||||
return {
|
||||
data: lang_list[lang]
|
||||
data: langList[lang]
|
||||
};
|
||||
},
|
||||
mouseDown: function(opts) {
|
||||
mouseDown: function (opts) {
|
||||
var e = opts.event;
|
||||
start_x = opts.start_x;
|
||||
start_y = opts.start_y;
|
||||
startX = opts.start_x;
|
||||
startY = opts.start_y;
|
||||
var mode = svgCanvas.getMode();
|
||||
|
||||
if (mode == "connector") {
|
||||
|
||||
if (started) {return;}
|
||||
|
||||
var mouse_target = e.target;
|
||||
|
||||
var parents = $(mouse_target).parents();
|
||||
|
||||
if($.inArray(svgcontent, parents) !== -1) {
|
||||
if (mode === 'connector') {
|
||||
if (started) { return; }
|
||||
|
||||
var mouseTarget = e.target;
|
||||
|
||||
var parents = $(mouseTarget).parents();
|
||||
|
||||
if ($.inArray(svgcontent, parents) !== -1) {
|
||||
// Connectable element
|
||||
|
||||
|
||||
// If child of foreignObject, use parent
|
||||
var fo = $(mouse_target).closest("foreignObject");
|
||||
start_elem = fo.length ? fo[0] : mouse_target;
|
||||
|
||||
var fo = $(mouseTarget).closest('foreignObject');
|
||||
startElem = fo.length ? fo[0] : mouseTarget;
|
||||
|
||||
// Get center of source element
|
||||
var bb = svgCanvas.getStrokedBBox([start_elem]);
|
||||
var x = bb.x + bb.width/2;
|
||||
var y = bb.y + bb.height/2;
|
||||
|
||||
var bb = svgCanvas.getStrokedBBox([startElem]);
|
||||
var x = bb.x + bb.width / 2;
|
||||
var y = bb.y + bb.height / 2;
|
||||
|
||||
started = true;
|
||||
cur_line = addElem({
|
||||
"element": "polyline",
|
||||
"attr": {
|
||||
"id": getNextId(),
|
||||
"points": (x+','+y+' '+x+','+y+' '+start_x+','+start_y),
|
||||
"stroke": '#' + curConfig.initStroke.color,
|
||||
"stroke-width": (!start_elem.stroke_width || start_elem.stroke_width == 0) ? curConfig.initStroke.width : start_elem.stroke_width,
|
||||
"fill": "none",
|
||||
"opacity": curConfig.initStroke.opacity,
|
||||
"style": "pointer-events:none"
|
||||
curLine = addElem({
|
||||
'element': 'polyline',
|
||||
'attr': {
|
||||
'id': getNextId(),
|
||||
'points': (x + ',' + y + ' ' + x + ',' + y + ' ' + startX + ',' + startY),
|
||||
'stroke': '#' + curConfig.initStroke.color,
|
||||
'stroke-width': (!startElem.stroke_width || startElem.stroke_width === 0) ? curConfig.initStroke.width : startElem.stroke_width,
|
||||
'fill': 'none',
|
||||
'opacity': curConfig.initStroke.opacity,
|
||||
'style': 'pointer-events:none'
|
||||
}
|
||||
});
|
||||
elData(cur_line, 'start_bb', bb);
|
||||
elData(curLine, 'start_bb', bb);
|
||||
}
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
if (mode == "select") {
|
||||
if (mode === 'select') {
|
||||
findConnectors();
|
||||
}
|
||||
},
|
||||
mouseMove: function(opts) {
|
||||
mouseMove: function (opts) {
|
||||
var zoom = svgCanvas.getZoom();
|
||||
var e = opts.event;
|
||||
var x = opts.mouse_x/zoom;
|
||||
var y = opts.mouse_y/zoom;
|
||||
|
||||
var diff_x = x - start_x,
|
||||
diff_y = y - start_y;
|
||||
|
||||
// var e = opts.event;
|
||||
var x = opts.mouse_x / zoom;
|
||||
var y = opts.mouse_y / zoom;
|
||||
|
||||
var diffX = x - startX,
|
||||
diffY = y - startY;
|
||||
|
||||
var mode = svgCanvas.getMode();
|
||||
|
||||
if (mode == "connector" && started) {
|
||||
|
||||
var sw = cur_line.getAttribute('stroke-width') * 3;
|
||||
|
||||
if (mode === 'connector' && started) {
|
||||
// var sw = curLine.getAttribute('stroke-width') * 3;
|
||||
// Set start point (adjusts based on bb)
|
||||
var pt = getBBintersect(x, y, elData(cur_line, 'start_bb'), getOffset('start', cur_line));
|
||||
start_x = pt.x;
|
||||
start_y = pt.y;
|
||||
|
||||
setPoint(cur_line, 0, pt.x, pt.y, true);
|
||||
|
||||
var pt = getBBintersect(x, y, elData(curLine, 'start_bb'), getOffset('start', curLine));
|
||||
startX = pt.x;
|
||||
startY = pt.y;
|
||||
|
||||
setPoint(curLine, 0, pt.x, pt.y, true);
|
||||
|
||||
// Set end point
|
||||
setPoint(cur_line, 'end', x, y, true);
|
||||
} else if (mode == "select") {
|
||||
setPoint(curLine, 'end', x, y, true);
|
||||
} else if (mode === 'select') {
|
||||
var slen = selElems.length;
|
||||
|
||||
while(slen--) {
|
||||
|
||||
while (slen--) {
|
||||
var elem = selElems[slen];
|
||||
// Look for selected connector elements
|
||||
if(elem && elData(elem, 'c_start')) {
|
||||
if (elem && elData(elem, 'c_start')) {
|
||||
// Remove the "translate" transform given to move
|
||||
svgCanvas.removeFromSelection([elem]);
|
||||
svgCanvas.getTransformList(elem).clear();
|
||||
|
||||
}
|
||||
}
|
||||
if(connections.length) {
|
||||
updateLine(diff_x, diff_y);
|
||||
|
||||
|
||||
if (connections.length) {
|
||||
updateLine(diffX, diffY);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mouseUp: function(opts) {
|
||||
var zoom = svgCanvas.getZoom();
|
||||
mouseUp: function (opts) {
|
||||
// var zoom = svgCanvas.getZoom();
|
||||
var e = opts.event,
|
||||
x = opts.mouse_x/zoom,
|
||||
y = opts.mouse_y/zoom,
|
||||
mouse_target = e.target;
|
||||
|
||||
if(svgCanvas.getMode() == "connector") {
|
||||
var fo = $(mouse_target).closest("foreignObject");
|
||||
if (fo.length) {mouse_target = fo[0];}
|
||||
|
||||
var parents = $(mouse_target).parents();
|
||||
// x = opts.mouse_x / zoom,
|
||||
// y = opts.mouse_y / zoom,
|
||||
mouseTarget = e.target;
|
||||
|
||||
if (mouse_target == start_elem) {
|
||||
if (svgCanvas.getMode() === 'connector') {
|
||||
var fo = $(mouseTarget).closest('foreignObject');
|
||||
if (fo.length) { mouseTarget = fo[0]; }
|
||||
|
||||
var parents = $(mouseTarget).parents();
|
||||
|
||||
if (mouseTarget === startElem) {
|
||||
// Start line through click
|
||||
started = true;
|
||||
return {
|
||||
@@ -453,7 +446,7 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
}
|
||||
if ($.inArray(svgcontent, parents) === -1) {
|
||||
// Not a valid target element, so remove line
|
||||
$(cur_line).remove();
|
||||
$(curLine).remove();
|
||||
started = false;
|
||||
return {
|
||||
keep: false,
|
||||
@@ -462,66 +455,66 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
};
|
||||
}
|
||||
// Valid end element
|
||||
end_elem = mouse_target;
|
||||
|
||||
var start_id = start_elem.id, end_id = end_elem.id;
|
||||
var conn_str = start_id + " " + end_id;
|
||||
var alt_str = end_id + " " + start_id;
|
||||
endElem = mouseTarget;
|
||||
|
||||
var startId = startElem.id, endId = endElem.id;
|
||||
var connStr = startId + ' ' + endId;
|
||||
var altStr = endId + ' ' + startId;
|
||||
// Don't create connector if one already exists
|
||||
var dupe = $(svgcontent).find(conn_sel).filter(function() {
|
||||
var conn = this.getAttributeNS(se_ns, "connector");
|
||||
if (conn == conn_str || conn == alt_str) {return true;}
|
||||
var dupe = $(svgcontent).find(connSel).filter(function () {
|
||||
var conn = this.getAttributeNS(seNs, 'connector');
|
||||
if (conn === connStr || conn === altStr) { return true; }
|
||||
});
|
||||
if(dupe.length) {
|
||||
$(cur_line).remove();
|
||||
if (dupe.length) {
|
||||
$(curLine).remove();
|
||||
return {
|
||||
keep: false,
|
||||
element: null,
|
||||
started: false
|
||||
};
|
||||
}
|
||||
|
||||
var bb = svgCanvas.getStrokedBBox([end_elem]);
|
||||
|
||||
var pt = getBBintersect(start_x, start_y, bb, getOffset('start', cur_line));
|
||||
setPoint(cur_line, 'end', pt.x, pt.y, true);
|
||||
$(cur_line)
|
||||
.data("c_start", start_id)
|
||||
.data("c_end", end_id)
|
||||
.data("end_bb", bb);
|
||||
se_ns = svgCanvas.getEditorNS(true);
|
||||
cur_line.setAttributeNS(se_ns, "se:connector", conn_str);
|
||||
cur_line.setAttribute('class', conn_sel.substr(1));
|
||||
cur_line.setAttribute('opacity', 1);
|
||||
svgCanvas.addToSelection([cur_line]);
|
||||
|
||||
var bb = svgCanvas.getStrokedBBox([endElem]);
|
||||
|
||||
var pt = getBBintersect(startX, startY, bb, getOffset('start', curLine));
|
||||
setPoint(curLine, 'end', pt.x, pt.y, true);
|
||||
$(curLine)
|
||||
.data('c_start', startId)
|
||||
.data('c_end', endId)
|
||||
.data('end_bb', bb);
|
||||
seNs = svgCanvas.getEditorNS(true);
|
||||
curLine.setAttributeNS(seNs, 'se:connector', connStr);
|
||||
curLine.setAttribute('class', connSel.substr(1));
|
||||
curLine.setAttribute('opacity', 1);
|
||||
svgCanvas.addToSelection([curLine]);
|
||||
svgCanvas.moveToBottomSelectedElement();
|
||||
selManager.requestSelector(cur_line).showGrips(false);
|
||||
selManager.requestSelector(curLine).showGrips(false);
|
||||
started = false;
|
||||
return {
|
||||
keep: true,
|
||||
element: cur_line,
|
||||
element: curLine,
|
||||
started: started
|
||||
};
|
||||
}
|
||||
},
|
||||
selectedChanged: function(opts) {
|
||||
selectedChanged: function (opts) {
|
||||
// TODO: Find better way to skip operations if no connectors are in use
|
||||
if(!$(svgcontent).find(conn_sel).length) {return;}
|
||||
|
||||
if(svgCanvas.getMode() == 'connector') {
|
||||
if (!$(svgcontent).find(connSel).length) { return; }
|
||||
|
||||
if (svgCanvas.getMode() === 'connector') {
|
||||
svgCanvas.setMode('select');
|
||||
}
|
||||
|
||||
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
|
||||
|
||||
var i = selElems.length;
|
||||
|
||||
while(i--) {
|
||||
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if(elem && elData(elem, 'c_start')) {
|
||||
if (elem && elData(elem, 'c_start')) {
|
||||
selManager.requestSelector(elem).showGrips(false);
|
||||
if(opts.selectedElement && !opts.multiselected) {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
// TODO: Set up context tools and hide most regular line tools
|
||||
showPanel(true);
|
||||
} else {
|
||||
@@ -533,48 +526,48 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
}
|
||||
updateConnectors();
|
||||
},
|
||||
elementChanged: function(opts) {
|
||||
elementChanged: function (opts) {
|
||||
var elem = opts.elems[0];
|
||||
if (elem && elem.tagName === 'svg' && elem.id === 'svgcontent') {
|
||||
// Update svgcontent (can change on import)
|
||||
svgcontent = elem;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
// Has marker, so change offset
|
||||
var start;
|
||||
if (elem && (
|
||||
elem.getAttribute("marker-start") ||
|
||||
elem.getAttribute("marker-mid") ||
|
||||
elem.getAttribute("marker-end")
|
||||
elem.getAttribute('marker-start') ||
|
||||
elem.getAttribute('marker-mid') ||
|
||||
elem.getAttribute('marker-end')
|
||||
)) {
|
||||
start = elem.getAttribute("marker-start");
|
||||
var mid = elem.getAttribute("marker-mid");
|
||||
var end = elem.getAttribute("marker-end");
|
||||
cur_line = elem;
|
||||
start = elem.getAttribute('marker-start');
|
||||
var mid = elem.getAttribute('marker-mid');
|
||||
var end = elem.getAttribute('marker-end');
|
||||
curLine = elem;
|
||||
$(elem)
|
||||
.data("start_off", !!start)
|
||||
.data("end_off", !!end);
|
||||
|
||||
.data('start_off', !!start)
|
||||
.data('end_off', !!end);
|
||||
|
||||
if (elem.tagName === 'line' && mid) {
|
||||
// Convert to polyline to accept mid-arrow
|
||||
|
||||
|
||||
var x1 = Number(elem.getAttribute('x1'));
|
||||
var x2 = Number(elem.getAttribute('x2'));
|
||||
var y1 = Number(elem.getAttribute('y1'));
|
||||
var y2 = Number(elem.getAttribute('y2'));
|
||||
var id = elem.id;
|
||||
|
||||
var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' ');
|
||||
|
||||
var midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
|
||||
var pline = addElem({
|
||||
"element": "polyline",
|
||||
"attr": {
|
||||
"points": (x1+','+y1+ mid_pt +x2+','+y2),
|
||||
"stroke": elem.getAttribute('stroke'),
|
||||
"stroke-width": elem.getAttribute('stroke-width'),
|
||||
"marker-mid": mid,
|
||||
"fill": "none",
|
||||
"opacity": elem.getAttribute('opacity') || 1
|
||||
'element': 'polyline',
|
||||
'attr': {
|
||||
'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2),
|
||||
'stroke': elem.getAttribute('stroke'),
|
||||
'stroke-width': elem.getAttribute('stroke-width'),
|
||||
'marker-mid': mid,
|
||||
'fill': 'none',
|
||||
'opacity': elem.getAttribute('opacity') || 1
|
||||
}
|
||||
});
|
||||
$(elem).after(pline).remove();
|
||||
@@ -585,36 +578,37 @@ svgEditor.addExtension("Connector", function(S) {
|
||||
}
|
||||
}
|
||||
// Update line if it's a connector
|
||||
if (elem.getAttribute('class') == conn_sel.substr(1)) {
|
||||
if (elem.getAttribute('class') === connSel.substr(1)) {
|
||||
start = getElem(elData(elem, 'c_start'));
|
||||
updateConnectors([start]);
|
||||
} else {
|
||||
updateConnectors();
|
||||
}
|
||||
},
|
||||
IDsUpdated: function(input) {
|
||||
IDsUpdated: function (input) {
|
||||
var remove = [];
|
||||
input.elems.forEach(function(elem){
|
||||
if('se:connector' in elem.attr) {
|
||||
input.elems.forEach(function (elem) {
|
||||
if ('se:connector' in elem.attr) {
|
||||
elem.attr['se:connector'] = elem.attr['se:connector'].split(' ')
|
||||
.map(function(oldID){ return input.changes[oldID] }).join(' ');
|
||||
.map(function (oldID) { return input.changes[oldID]; }).join(' ');
|
||||
|
||||
// Check validity - the field would be something like 'svg_21 svg_22', but
|
||||
// if one end is missing, it would be 'svg_21' and therefore fail this test
|
||||
if(!/. ./.test(elem.attr['se:connector']))
|
||||
if (!/. ./.test(elem.attr['se:connector'])) {
|
||||
remove.push(elem.attr.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
return {remove: remove};
|
||||
},
|
||||
toolButtonStateUpdate: function(opts) {
|
||||
toolButtonStateUpdate: function (opts) {
|
||||
if (opts.nostroke) {
|
||||
if ($('#mode_connect').hasClass('tool_button_current')) {
|
||||
svgEditor.clickSelect();
|
||||
}
|
||||
}
|
||||
$('#mode_connect')
|
||||
.toggleClass('disabled',opts.nostroke);
|
||||
.toggleClass('disabled', opts.nostroke);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, $*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, $ */
|
||||
/*
|
||||
* ext-eyedropper.js
|
||||
*
|
||||
@@ -15,26 +15,27 @@
|
||||
// 3) svg_editor.js
|
||||
// 4) svgcanvas.js
|
||||
|
||||
svgEditor.addExtension("eyedropper", function(S) {'use strict';
|
||||
svgEditor.addExtension('eyedropper', function (S) {
|
||||
'use strict';
|
||||
var // NS = svgedit.NS,
|
||||
// svgcontent = S.svgcontent,
|
||||
// svgdoc = S.svgroot.parentNode.ownerDocument,
|
||||
svgCanvas = svgEditor.canvas,
|
||||
ChangeElementCommand = svgedit.history.ChangeElementCommand,
|
||||
addToHistory = function(cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); },
|
||||
addToHistory = function (cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); },
|
||||
currentStyle = {
|
||||
fillPaint: "red", fillOpacity: 1.0,
|
||||
strokePaint: "black", strokeOpacity: 1.0,
|
||||
fillPaint: 'red', fillOpacity: 1.0,
|
||||
strokePaint: 'black', strokeOpacity: 1.0,
|
||||
strokeWidth: 5, strokeDashArray: null,
|
||||
opacity: 1.0,
|
||||
strokeLinecap: 'butt',
|
||||
strokeLinejoin: 'miter'
|
||||
};
|
||||
|
||||
function getStyle(opts) {
|
||||
function getStyle (opts) {
|
||||
// if we are in eyedropper mode, we don't want to disable the eye-dropper tool
|
||||
var mode = svgCanvas.getMode();
|
||||
if (mode == "eyedropper") {return;}
|
||||
if (mode === 'eyedropper') { return; }
|
||||
|
||||
var elem = null;
|
||||
var tool = $('#tool_eyedropper');
|
||||
@@ -45,65 +46,63 @@ svgEditor.addExtension("eyedropper", function(S) {'use strict';
|
||||
elem = opts.elems[0];
|
||||
tool.removeClass('disabled');
|
||||
// grab the current style
|
||||
currentStyle.fillPaint = elem.getAttribute("fill") || "black";
|
||||
currentStyle.fillOpacity = elem.getAttribute("fill-opacity") || 1.0;
|
||||
currentStyle.strokePaint = elem.getAttribute("stroke");
|
||||
currentStyle.strokeOpacity = elem.getAttribute("stroke-opacity") || 1.0;
|
||||
currentStyle.strokeWidth = elem.getAttribute("stroke-width");
|
||||
currentStyle.strokeDashArray = elem.getAttribute("stroke-dasharray");
|
||||
currentStyle.strokeLinecap = elem.getAttribute("stroke-linecap");
|
||||
currentStyle.strokeLinejoin = elem.getAttribute("stroke-linejoin");
|
||||
currentStyle.opacity = elem.getAttribute("opacity") || 1.0;
|
||||
}
|
||||
currentStyle.fillPaint = elem.getAttribute('fill') || 'black';
|
||||
currentStyle.fillOpacity = elem.getAttribute('fill-opacity') || 1.0;
|
||||
currentStyle.strokePaint = elem.getAttribute('stroke');
|
||||
currentStyle.strokeOpacity = elem.getAttribute('stroke-opacity') || 1.0;
|
||||
currentStyle.strokeWidth = elem.getAttribute('stroke-width');
|
||||
currentStyle.strokeDashArray = elem.getAttribute('stroke-dasharray');
|
||||
currentStyle.strokeLinecap = elem.getAttribute('stroke-linecap');
|
||||
currentStyle.strokeLinejoin = elem.getAttribute('stroke-linejoin');
|
||||
currentStyle.opacity = elem.getAttribute('opacity') || 1.0;
|
||||
// disable eye-dropper tool
|
||||
else {
|
||||
} else {
|
||||
tool.addClass('disabled');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
name: "eyedropper",
|
||||
svgicons: svgEditor.curConfig.extPath + "eyedropper-icon.xml",
|
||||
name: 'eyedropper',
|
||||
svgicons: svgEditor.curConfig.extPath + 'eyedropper-icon.xml',
|
||||
buttons: [{
|
||||
id: "tool_eyedropper",
|
||||
type: "mode",
|
||||
title: "Eye Dropper Tool",
|
||||
key: "I",
|
||||
id: 'tool_eyedropper',
|
||||
type: 'mode',
|
||||
title: 'Eye Dropper Tool',
|
||||
key: 'I',
|
||||
events: {
|
||||
"click": function() {
|
||||
svgCanvas.setMode("eyedropper");
|
||||
click: function () {
|
||||
svgCanvas.setMode('eyedropper');
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
|
||||
// if we have selected an element, grab its paint and enable the eye dropper button
|
||||
selectedChanged: getStyle,
|
||||
elementChanged: getStyle,
|
||||
|
||||
mouseDown: function(opts) {
|
||||
|
||||
mouseDown: function (opts) {
|
||||
var mode = svgCanvas.getMode();
|
||||
if (mode == "eyedropper") {
|
||||
if (mode === 'eyedropper') {
|
||||
var e = opts.event;
|
||||
var target = e.target;
|
||||
if ($.inArray(target.nodeName, ['svg', 'g', 'use']) === -1) {
|
||||
var changes = {};
|
||||
|
||||
var change = function(elem, attrname, newvalue) {
|
||||
var change = function (elem, attrname, newvalue) {
|
||||
changes[attrname] = elem.getAttribute(attrname);
|
||||
elem.setAttribute(attrname, newvalue);
|
||||
};
|
||||
|
||||
if (currentStyle.fillPaint) {change(target, "fill", currentStyle.fillPaint);}
|
||||
if (currentStyle.fillOpacity) {change(target, "fill-opacity", currentStyle.fillOpacity);}
|
||||
if (currentStyle.strokePaint) {change(target, "stroke", currentStyle.strokePaint);}
|
||||
if (currentStyle.strokeOpacity) {change(target, "stroke-opacity", currentStyle.strokeOpacity);}
|
||||
if (currentStyle.strokeWidth) {change(target, "stroke-width", currentStyle.strokeWidth);}
|
||||
if (currentStyle.strokeDashArray) {change(target, "stroke-dasharray", currentStyle.strokeDashArray);}
|
||||
if (currentStyle.opacity) {change(target, "opacity", currentStyle.opacity);}
|
||||
if (currentStyle.strokeLinecap) {change(target, "stroke-linecap", currentStyle.strokeLinecap);}
|
||||
if (currentStyle.strokeLinejoin) {change(target, "stroke-linejoin", currentStyle.strokeLinejoin);}
|
||||
|
||||
|
||||
if (currentStyle.fillPaint) { change(target, 'fill', currentStyle.fillPaint); }
|
||||
if (currentStyle.fillOpacity) { change(target, 'fill-opacity', currentStyle.fillOpacity); }
|
||||
if (currentStyle.strokePaint) { change(target, 'stroke', currentStyle.strokePaint); }
|
||||
if (currentStyle.strokeOpacity) { change(target, 'stroke-opacity', currentStyle.strokeOpacity); }
|
||||
if (currentStyle.strokeWidth) { change(target, 'stroke-width', currentStyle.strokeWidth); }
|
||||
if (currentStyle.strokeDashArray) { change(target, 'stroke-dasharray', currentStyle.strokeDashArray); }
|
||||
if (currentStyle.opacity) { change(target, 'opacity', currentStyle.opacity); }
|
||||
if (currentStyle.strokeLinecap) { change(target, 'stroke-linecap', currentStyle.strokeLinecap); }
|
||||
if (currentStyle.strokeLinejoin) { change(target, 'stroke-linejoin', currentStyle.strokeLinejoin); }
|
||||
|
||||
addToHistory(new ChangeElementCommand(target, changes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*globals svgEditor, svgedit, svgCanvas, $*/
|
||||
/*jslint vars: true, eqeq: true, todo: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, svgCanvas, $ */
|
||||
/*
|
||||
* ext-foreignobject.js
|
||||
*
|
||||
* Licensed under the Apache License, Version 2
|
||||
*
|
||||
* Copyright(c) 2010 Jacques Distler
|
||||
* Copyright(c) 2010 Alexis Deveria
|
||||
* Copyright(c) 2010 Jacques Distler
|
||||
* Copyright(c) 2010 Alexis Deveria
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("foreignObject", function(S) {
|
||||
svgEditor.addExtension('foreignObject', function (S) {
|
||||
var NS = svgedit.NS,
|
||||
Utils = svgedit.utilities,
|
||||
svgcontent = S.svgcontent,
|
||||
addElem = S.addSvgElementFromJson,
|
||||
// svgcontent = S.svgcontent,
|
||||
// addElem = S.addSvgElementFromJson,
|
||||
selElems,
|
||||
editingforeign = false,
|
||||
svgdoc = S.svgroot.parentNode.ownerDocument,
|
||||
@@ -27,16 +27,16 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
$('#svg_source_textarea').css('height', height);
|
||||
};
|
||||
|
||||
function showPanel(on) {
|
||||
var fc_rules = $('#fc_rules');
|
||||
if(!fc_rules.length) {
|
||||
fc_rules = $('<style id="fc_rules"></style>').appendTo('head');
|
||||
function showPanel (on) {
|
||||
var fcRules = $('#fc_rules');
|
||||
if (!fcRules.length) {
|
||||
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);
|
||||
}
|
||||
|
||||
function toggleSourceButtons(on) {
|
||||
function toggleSourceButtons (on) {
|
||||
$('#tool_source_save, #tool_source_cancel').toggle(!on);
|
||||
$('#foreign_save, #foreign_cancel').toggle(on);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
//
|
||||
// Returns:
|
||||
// This function returns false if the set was unsuccessful, true otherwise.
|
||||
function setForeignString(xmlString) {
|
||||
function setForeignString (xmlString) {
|
||||
var elt = selElems[0];
|
||||
try {
|
||||
// convert string into XML document
|
||||
@@ -58,9 +58,9 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
// run it through our sanitizer to remove anything we do not support
|
||||
S.sanitizeSvg(newDoc.documentElement);
|
||||
elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
|
||||
S.call("changed", [elt]);
|
||||
S.call('changed', [elt]);
|
||||
svgCanvas.clearSelection();
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return false;
|
||||
}
|
||||
@@ -68,9 +68,9 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function showForeignEditor() {
|
||||
function showForeignEditor () {
|
||||
var elt = selElems[0];
|
||||
if (!elt || editingforeign) {return;}
|
||||
if (!elt || editingforeign) { return; }
|
||||
editingforeign = true;
|
||||
toggleSourceButtons(true);
|
||||
elt.removeAttribute('fill');
|
||||
@@ -82,78 +82,78 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
$('#svg_source_textarea').focus();
|
||||
}
|
||||
|
||||
function setAttr(attr, val) {
|
||||
function setAttr (attr, val) {
|
||||
svgCanvas.changeSelectedAttribute(attr, val);
|
||||
S.call("changed", selElems);
|
||||
S.call('changed', selElems);
|
||||
}
|
||||
|
||||
return {
|
||||
name: "foreignObject",
|
||||
svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml",
|
||||
name: 'foreignObject',
|
||||
svgicons: svgEditor.curConfig.extPath + 'foreignobject-icons.xml',
|
||||
buttons: [{
|
||||
id: "tool_foreign",
|
||||
type: "mode",
|
||||
title: "Foreign Object Tool",
|
||||
id: 'tool_foreign',
|
||||
type: 'mode',
|
||||
title: 'Foreign Object Tool',
|
||||
events: {
|
||||
'click': function() {
|
||||
'click': function () {
|
||||
svgCanvas.setMode('foreign');
|
||||
}
|
||||
}
|
||||
},{
|
||||
id: "edit_foreign",
|
||||
type: "context",
|
||||
panel: "foreignObject_panel",
|
||||
title: "Edit ForeignObject Content",
|
||||
}, {
|
||||
id: 'edit_foreign',
|
||||
type: 'context',
|
||||
panel: 'foreignObject_panel',
|
||||
title: 'Edit ForeignObject Content',
|
||||
events: {
|
||||
'click': function() {
|
||||
'click': function () {
|
||||
showForeignEditor();
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
context_tools: [{
|
||||
type: "input",
|
||||
panel: "foreignObject_panel",
|
||||
type: 'input',
|
||||
panel: 'foreignObject_panel',
|
||||
title: "Change foreignObject's width",
|
||||
id: "foreign_width",
|
||||
label: "w",
|
||||
id: 'foreign_width',
|
||||
label: 'w',
|
||||
size: 3,
|
||||
events: {
|
||||
change: function() {
|
||||
change: function () {
|
||||
setAttr('width', this.value);
|
||||
}
|
||||
}
|
||||
},{
|
||||
type: "input",
|
||||
panel: "foreignObject_panel",
|
||||
}, {
|
||||
type: 'input',
|
||||
panel: 'foreignObject_panel',
|
||||
title: "Change foreignObject's height",
|
||||
id: "foreign_height",
|
||||
label: "h",
|
||||
id: 'foreign_height',
|
||||
label: 'h',
|
||||
events: {
|
||||
change: function() {
|
||||
change: function () {
|
||||
setAttr('height', this.value);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
type: "input",
|
||||
panel: "foreignObject_panel",
|
||||
type: 'input',
|
||||
panel: 'foreignObject_panel',
|
||||
title: "Change foreignObject's font size",
|
||||
id: "foreign_font_size",
|
||||
label: "font-size",
|
||||
id: 'foreign_font_size',
|
||||
label: 'font-size',
|
||||
size: 2,
|
||||
defval: 16,
|
||||
events: {
|
||||
change: function() {
|
||||
change: function () {
|
||||
setAttr('font-size', this.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
callback: function() {
|
||||
callback: function () {
|
||||
$('#foreignObject_panel').hide();
|
||||
|
||||
var endChanges = function() {
|
||||
var endChanges = function () {
|
||||
$('#svg_source_editor').hide();
|
||||
editingforeign = false;
|
||||
$('#svg_source_textarea').blur();
|
||||
@@ -161,48 +161,46 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
};
|
||||
|
||||
// TODO: Needs to be done after orig icon loads
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
// Create source save/cancel buttons
|
||||
var save = $('#tool_source_save').clone()
|
||||
/* var save = */ $('#tool_source_save').clone()
|
||||
.hide().attr('id', 'foreign_save').unbind()
|
||||
.appendTo("#tool_source_back").click(function() {
|
||||
|
||||
if (!editingforeign) {return;}
|
||||
.appendTo('#tool_source_back').click(function () {
|
||||
if (!editingforeign) { return; }
|
||||
|
||||
if (!setForeignString($('#svg_source_textarea').val())) {
|
||||
$.confirm("Errors found. Revert to original?", function(ok) {
|
||||
if(!ok) {return false;}
|
||||
$.confirm('Errors found. Revert to original?', function (ok) {
|
||||
if (!ok) { return false; }
|
||||
endChanges();
|
||||
});
|
||||
} else {
|
||||
endChanges();
|
||||
}
|
||||
// setSelectMode();
|
||||
// setSelectMode();
|
||||
});
|
||||
|
||||
var cancel = $('#tool_source_cancel').clone()
|
||||
/* var cancel = */ $('#tool_source_cancel').clone()
|
||||
.hide().attr('id', 'foreign_cancel').unbind()
|
||||
.appendTo("#tool_source_back").click(function() {
|
||||
.appendTo('#tool_source_back').click(function () {
|
||||
endChanges();
|
||||
});
|
||||
}, 3000);
|
||||
},
|
||||
mouseDown: function(opts) {
|
||||
var e = opts.event;
|
||||
|
||||
if(svgCanvas.getMode() == "foreign") {
|
||||
mouseDown: function (opts) {
|
||||
// var e = opts.event;
|
||||
|
||||
if (svgCanvas.getMode() === 'foreign') {
|
||||
started = true;
|
||||
newFO = S.addSvgElementFromJson({
|
||||
"element": "foreignObject",
|
||||
"attr": {
|
||||
"x": opts.start_x,
|
||||
"y": opts.start_y,
|
||||
"id": S.getNextId(),
|
||||
"font-size": 16, //cur_text.font_size,
|
||||
"width": "48",
|
||||
"height": "20",
|
||||
"style": "pointer-events:inherit"
|
||||
'element': 'foreignObject',
|
||||
'attr': {
|
||||
'x': opts.start_x,
|
||||
'y': opts.start_y,
|
||||
'id': S.getNextId(),
|
||||
'font-size': 16, // cur_text.font_size,
|
||||
'width': '48',
|
||||
'height': '20',
|
||||
'style': 'pointer-events:inherit'
|
||||
}
|
||||
});
|
||||
var m = svgdoc.createElementNS(NS.MATH, 'math');
|
||||
@@ -210,11 +208,11 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
m.setAttribute('display', 'inline');
|
||||
var mi = svgdoc.createElementNS(NS.MATH, 'mi');
|
||||
mi.setAttribute('mathvariant', 'normal');
|
||||
mi.textContent = "\u03A6";
|
||||
mi.textContent = '\u03A6';
|
||||
var mo = svgdoc.createElementNS(NS.MATH, 'mo');
|
||||
mo.textContent = "\u222A";
|
||||
mo.textContent = '\u222A';
|
||||
var mi2 = svgdoc.createElementNS(NS.MATH, 'mi');
|
||||
mi2.textContent = "\u2133";
|
||||
mi2.textContent = '\u2133';
|
||||
m.appendChild(mi);
|
||||
m.appendChild(mo);
|
||||
m.appendChild(mi2);
|
||||
@@ -224,34 +222,32 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
};
|
||||
}
|
||||
},
|
||||
mouseUp: function(opts) {
|
||||
var e = opts.event;
|
||||
if(svgCanvas.getMode() == "foreign" && started) {
|
||||
var attrs = $(newFO).attr(["width", "height"]);
|
||||
var keep = (attrs.width != 0 || attrs.height != 0);
|
||||
mouseUp: function (opts) {
|
||||
// var e = opts.event;
|
||||
if (svgCanvas.getMode() === 'foreign' && started) {
|
||||
var attrs = $(newFO).attr(['width', 'height']);
|
||||
var keep = (attrs.width !== '0' || attrs.height !== '0');
|
||||
svgCanvas.addToSelection([newFO], true);
|
||||
|
||||
return {
|
||||
keep: keep,
|
||||
element: newFO
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
selectedChanged: function(opts) {
|
||||
selectedChanged: function (opts) {
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
|
||||
var i = selElems.length;
|
||||
|
||||
while(i--) {
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if(elem && elem.tagName === 'foreignObject') {
|
||||
if(opts.selectedElement && !opts.multiselected) {
|
||||
$('#foreign_font_size').val(elem.getAttribute("font-size"));
|
||||
$('#foreign_width').val(elem.getAttribute("width"));
|
||||
$('#foreign_height').val(elem.getAttribute("height"));
|
||||
if (elem && elem.tagName === 'foreignObject') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
$('#foreign_font_size').val(elem.getAttribute('font-size'));
|
||||
$('#foreign_width').val(elem.getAttribute('width'));
|
||||
$('#foreign_height').val(elem.getAttribute('height'));
|
||||
showPanel(true);
|
||||
} else {
|
||||
showPanel(false);
|
||||
@@ -261,8 +257,8 @@ svgEditor.addExtension("foreignObject", function(S) {
|
||||
}
|
||||
}
|
||||
},
|
||||
elementChanged: function(opts) {
|
||||
var elem = opts.elems[0];
|
||||
elementChanged: function (opts) {
|
||||
// var elem = opts.elems[0];
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, svgCanvas, $*/
|
||||
/*jslint vars: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, svgCanvas, $ */
|
||||
/*
|
||||
* ext-grid.js
|
||||
*
|
||||
@@ -14,7 +14,8 @@
|
||||
// 1) units.js
|
||||
// 2) everything else
|
||||
|
||||
svgEditor.addExtension('view_grid', function() { 'use strict';
|
||||
svgEditor.addExtension('view_grid', function () {
|
||||
'use strict';
|
||||
|
||||
var NS = svgedit.NS,
|
||||
svgdoc = document.getElementById('svgcanvas').ownerDocument,
|
||||
@@ -44,8 +45,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
|
||||
assignAttributes(gridPattern, {
|
||||
'id': 'gridpattern',
|
||||
'patternUnits': 'userSpaceOnUse',
|
||||
'x': 0, //-(value.strokeWidth / 2), // position for strokewidth
|
||||
'y': 0, //-(value.strokeWidth / 2), // position for strokewidth
|
||||
'x': 0, // -(value.strokeWidth / 2), // position for strokewidth
|
||||
'y': 0, // -(value.strokeWidth / 2), // position for strokewidth
|
||||
'width': 100,
|
||||
'height': 100
|
||||
});
|
||||
@@ -74,56 +75,56 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
|
||||
});
|
||||
$('#canvasGrid').append(gridBox);
|
||||
|
||||
function updateGrid(zoom) {
|
||||
function updateGrid (zoom) {
|
||||
var i;
|
||||
// TODO: Try this with <line> elements, then compare performance difference
|
||||
var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px
|
||||
var u_multi = unit * zoom;
|
||||
var uMulti = unit * zoom;
|
||||
// Calculate the main number interval
|
||||
var raw_m = 100 / u_multi;
|
||||
var rawM = 100 / uMulti;
|
||||
var multi = 1;
|
||||
for (i = 0; i < intervals.length; i++) {
|
||||
var num = intervals[i];
|
||||
multi = num;
|
||||
if (raw_m <= num) {
|
||||
if (rawM <= num) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
var big_int = multi * u_multi;
|
||||
var bigInt = multi * uMulti;
|
||||
|
||||
// Set the canvas size to the width of the container
|
||||
hcanvas.width = big_int;
|
||||
hcanvas.height = big_int;
|
||||
hcanvas.width = bigInt;
|
||||
hcanvas.height = bigInt;
|
||||
var ctx = hcanvas.getContext('2d');
|
||||
var cur_d = 0.5;
|
||||
var part = big_int / 10;
|
||||
var curD = 0.5;
|
||||
var part = bigInt / 10;
|
||||
|
||||
ctx.globalAlpha = 0.2;
|
||||
ctx.strokeStyle = svgEditor.curConfig.gridColor;
|
||||
for (i = 1; i < 10; i++) {
|
||||
var sub_d = Math.round(part * i) + 0.5;
|
||||
// var line_num = (i % 2)?12:10;
|
||||
var line_num = 0;
|
||||
ctx.moveTo(sub_d, big_int);
|
||||
ctx.lineTo(sub_d, line_num);
|
||||
ctx.moveTo(big_int, sub_d);
|
||||
ctx.lineTo(line_num ,sub_d);
|
||||
var subD = Math.round(part * i) + 0.5;
|
||||
// var lineNum = (i % 2)?12:10;
|
||||
var lineNum = 0;
|
||||
ctx.moveTo(subD, bigInt);
|
||||
ctx.lineTo(subD, lineNum);
|
||||
ctx.moveTo(bigInt, subD);
|
||||
ctx.lineTo(lineNum, subD);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.globalAlpha = 0.5;
|
||||
ctx.moveTo(cur_d, big_int);
|
||||
ctx.lineTo(cur_d, 0);
|
||||
ctx.moveTo(curD, bigInt);
|
||||
ctx.lineTo(curD, 0);
|
||||
|
||||
ctx.moveTo(big_int, cur_d);
|
||||
ctx.lineTo(0, cur_d);
|
||||
ctx.moveTo(bigInt, curD);
|
||||
ctx.lineTo(0, curD);
|
||||
ctx.stroke();
|
||||
|
||||
var datauri = hcanvas.toDataURL('image/png');
|
||||
gridimg.setAttribute('width', big_int);
|
||||
gridimg.setAttribute('height', big_int);
|
||||
gridimg.parentNode.setAttribute('width', big_int);
|
||||
gridimg.parentNode.setAttribute('height', big_int);
|
||||
gridimg.setAttribute('width', bigInt);
|
||||
gridimg.setAttribute('height', bigInt);
|
||||
gridimg.parentNode.setAttribute('width', bigInt);
|
||||
gridimg.parentNode.setAttribute('height', bigInt);
|
||||
svgCanvas.setHref(gridimg, datauri);
|
||||
}
|
||||
|
||||
@@ -138,8 +139,8 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
|
||||
name: 'view_grid',
|
||||
svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml',
|
||||
|
||||
zoomChanged: function(zoom) {
|
||||
if (showGrid) {updateGrid(zoom);}
|
||||
zoomChanged: function (zoom) {
|
||||
if (showGrid) { updateGrid(zoom); }
|
||||
},
|
||||
callback: function () {
|
||||
if (showGrid) {
|
||||
@@ -152,7 +153,7 @@ svgEditor.addExtension('view_grid', function() { 'use strict';
|
||||
panel: 'editor_panel',
|
||||
title: 'Show/Hide Grid',
|
||||
events: {
|
||||
click: function() {
|
||||
click: function () {
|
||||
svgEditor.curConfig.showGrid = showGrid = !showGrid;
|
||||
gridUpdate();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgCanvas, $*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-helloworld.js
|
||||
*
|
||||
@@ -8,73 +8,72 @@
|
||||
* Copyright(c) 2010 Alexis Deveria
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
This is a very basic SVG-Edit extension. It adds a "Hello World" button in
|
||||
the left panel. Clicking on the button, and then the canvas will show the
|
||||
user the point on the canvas that was clicked on.
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("Hello World", function() {'use strict';
|
||||
|
||||
return {
|
||||
name: "Hello World",
|
||||
// For more notes on how to make an icon file, see the source of
|
||||
// the helloworld-icon.xml
|
||||
svgicons: svgEditor.curConfig.extPath + "helloworld-icon.xml",
|
||||
|
||||
// Multiple buttons can be added in this array
|
||||
buttons: [{
|
||||
// Must match the icon ID in helloworld-icon.xml
|
||||
id: "hello_world",
|
||||
|
||||
// This indicates that the button will be added to the "mode"
|
||||
// button panel on the left side
|
||||
type: "mode",
|
||||
|
||||
// Tooltip text
|
||||
title: "Say 'Hello World'",
|
||||
|
||||
// Events
|
||||
events: {
|
||||
'click': function() {
|
||||
// The action taken when the button is clicked on.
|
||||
// For "mode" buttons, any other button will
|
||||
// automatically be de-pressed.
|
||||
svgCanvas.setMode("hello_world");
|
||||
}
|
||||
}
|
||||
}],
|
||||
// This is triggered when the main mouse button is pressed down
|
||||
// on the editor canvas (not the tool panels)
|
||||
mouseDown: function() {
|
||||
// Check the mode on mousedown
|
||||
if(svgCanvas.getMode() == "hello_world") {
|
||||
|
||||
// The returned object must include "started" with
|
||||
// a value of true in order for mouseUp to be triggered
|
||||
return {started: true};
|
||||
}
|
||||
},
|
||||
|
||||
// This is triggered from anywhere, but "started" must have been set
|
||||
// to true (see above). Note that "opts" is an object with event info
|
||||
mouseUp: function(opts) {
|
||||
// Check the mode on mouseup
|
||||
if(svgCanvas.getMode() == "hello_world") {
|
||||
var zoom = svgCanvas.getZoom();
|
||||
|
||||
// Get the actual coordinate by dividing by the zoom value
|
||||
var x = opts.mouse_x / zoom;
|
||||
var y = opts.mouse_y / zoom;
|
||||
|
||||
var text = "Hello World!\n\nYou clicked here: "
|
||||
+ x + ", " + y;
|
||||
|
||||
// Show the text using the custom alert function
|
||||
$.alert(text);
|
||||
svgEditor.addExtension('Hello World', function () {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
name: 'Hello World',
|
||||
// For more notes on how to make an icon file, see the source of
|
||||
// the helloworld-icon.xml
|
||||
svgicons: svgEditor.curConfig.extPath + 'helloworld-icon.xml',
|
||||
|
||||
// Multiple buttons can be added in this array
|
||||
buttons: [{
|
||||
// Must match the icon ID in helloworld-icon.xml
|
||||
id: 'hello_world',
|
||||
|
||||
// This indicates that the button will be added to the "mode"
|
||||
// button panel on the left side
|
||||
type: 'mode',
|
||||
|
||||
// Tooltip text
|
||||
title: "Say 'Hello World'",
|
||||
|
||||
// Events
|
||||
events: {
|
||||
'click': function () {
|
||||
// The action taken when the button is clicked on.
|
||||
// For "mode" buttons, any other button will
|
||||
// automatically be de-pressed.
|
||||
svgCanvas.setMode('hello_world');
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}],
|
||||
// This is triggered when the main mouse button is pressed down
|
||||
// on the editor canvas (not the tool panels)
|
||||
mouseDown: function () {
|
||||
// Check the mode on mousedown
|
||||
if (svgCanvas.getMode() === 'hello_world') {
|
||||
// The returned object must include "started" with
|
||||
// a value of true in order for mouseUp to be triggered
|
||||
return {started: true};
|
||||
}
|
||||
},
|
||||
|
||||
// This is triggered from anywhere, but "started" must have been set
|
||||
// to true (see above). Note that "opts" is an object with event info
|
||||
mouseUp: function (opts) {
|
||||
// Check the mode on mouseup
|
||||
if (svgCanvas.getMode() === 'hello_world') {
|
||||
var zoom = svgCanvas.getZoom();
|
||||
|
||||
// Get the actual coordinate by dividing by the zoom value
|
||||
var x = opts.mouse_x / zoom;
|
||||
var y = opts.mouse_y / zoom;
|
||||
|
||||
var text = 'Hello World!\n\nYou clicked here: ' +
|
||||
x + ', ' + y;
|
||||
|
||||
// Show the text using the custom alert function
|
||||
$.alert(text);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgEditor, svgedit, svgCanvas, DOMParser*/
|
||||
/*jslint vars: true, eqeq: true, es5: true, todo: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, svgEditor, svgedit, svgCanvas, DOMParser */
|
||||
/*
|
||||
* ext-imagelib.js
|
||||
*
|
||||
@@ -9,7 +9,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
svgEditor.addExtension('imagelib', function () {
|
||||
'use strict';
|
||||
|
||||
var uiStrings = svgEditor.uiStrings;
|
||||
|
||||
@@ -23,7 +24,8 @@ svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
}
|
||||
});
|
||||
|
||||
var img_libs = [{
|
||||
var imgLibs = [
|
||||
{
|
||||
name: 'Demo library (local)',
|
||||
url: svgEditor.curConfig.extPath + 'imagelib/index.html',
|
||||
description: 'Demonstration library for SVG-edit on this server'
|
||||
@@ -40,20 +42,20 @@ svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
}
|
||||
];
|
||||
|
||||
function closeBrowser() {
|
||||
function closeBrowser () {
|
||||
$('#imgbrowse_holder').hide();
|
||||
}
|
||||
|
||||
function importImage(url) {
|
||||
function importImage (url) {
|
||||
var newImage = svgCanvas.addSvgElementFromJson({
|
||||
"element": "image",
|
||||
"attr": {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"id": svgCanvas.getNextId(),
|
||||
"style": "pointer-events:inherit"
|
||||
'element': 'image',
|
||||
'attr': {
|
||||
'x': 0,
|
||||
'y': 0,
|
||||
'width': 0,
|
||||
'height': 0,
|
||||
'id': svgCanvas.getNextId(),
|
||||
'style': 'pointer-events:inherit'
|
||||
}
|
||||
});
|
||||
svgCanvas.clearSelection();
|
||||
@@ -62,16 +64,16 @@ svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
}
|
||||
|
||||
var mode = 's';
|
||||
var multi_arr = [];
|
||||
var tranfer_stopped = false;
|
||||
var multiArr = [];
|
||||
var transferStopped = false;
|
||||
var pending = {};
|
||||
var preview, submit;
|
||||
|
||||
window.addEventListener("message", function(evt) {
|
||||
window.addEventListener('message', function (evt) {
|
||||
// Receive postMessage data
|
||||
var response = evt.data;
|
||||
|
||||
if (!response || typeof response !== "string") { // Todo: Should namespace postMessage API for this extension and filter out here
|
||||
|
||||
if (!response || typeof response !== 'string') { // Todo: Should namespace postMessage API for this extension and filter out here
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
@@ -80,172 +82,168 @@ svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
if (res.namespace) { // Part of embedAPI communications
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
} catch (e) {}
|
||||
|
||||
var char1 = response.charAt(0);
|
||||
var id;
|
||||
var svg_str;
|
||||
var img_str;
|
||||
|
||||
if (char1 != "{" && tranfer_stopped) {
|
||||
tranfer_stopped = false;
|
||||
var svgStr;
|
||||
var imgStr;
|
||||
|
||||
if (char1 !== '{' && transferStopped) {
|
||||
transferStopped = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (char1 == '|') {
|
||||
|
||||
if (char1 === '|') {
|
||||
var secondpos = response.indexOf('|', 1);
|
||||
id = response.substr(1, secondpos-1);
|
||||
response = response.substr(secondpos+1);
|
||||
id = response.substr(1, secondpos - 1);
|
||||
response = response.substr(secondpos + 1);
|
||||
char1 = response.charAt(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Hide possible transfer dialog box
|
||||
$('#dialog_box').hide();
|
||||
var entry, cur_meta;
|
||||
var entry, curMeta;
|
||||
switch (char1) {
|
||||
case '{':
|
||||
// Metadata
|
||||
tranfer_stopped = false;
|
||||
cur_meta = JSON.parse(response);
|
||||
|
||||
pending[cur_meta.id] = cur_meta;
|
||||
|
||||
var name = (cur_meta.name || 'file');
|
||||
|
||||
var message = uiStrings.notification.retrieving.replace('%s', name);
|
||||
|
||||
if (mode != 'm') {
|
||||
$.process_cancel(message, function() {
|
||||
tranfer_stopped = true;
|
||||
// Should a message be sent back to the frame?
|
||||
|
||||
$('#dialog_box').hide();
|
||||
case '{':
|
||||
// Metadata
|
||||
transferStopped = false;
|
||||
curMeta = JSON.parse(response);
|
||||
|
||||
pending[curMeta.id] = curMeta;
|
||||
|
||||
var name = (curMeta.name || 'file');
|
||||
|
||||
var message = uiStrings.notification.retrieving.replace('%s', name);
|
||||
|
||||
if (mode !== 'm') {
|
||||
$.process_cancel(message, function () {
|
||||
transferStopped = true;
|
||||
// Should a message be sent back to the frame?
|
||||
|
||||
$('#dialog_box').hide();
|
||||
});
|
||||
} else {
|
||||
entry = $('<div>' + message + '</div>').data('id', curMeta.id);
|
||||
preview.append(entry);
|
||||
curMeta.entry = entry;
|
||||
}
|
||||
|
||||
return;
|
||||
case '<':
|
||||
svgStr = true;
|
||||
break;
|
||||
case 'd':
|
||||
if (response.indexOf('data:image/svg+xml') === 0) {
|
||||
var pre = 'data:image/svg+xml;base64,';
|
||||
var src = response.substring(pre.length);
|
||||
response = svgedit.utilities.decode64(src);
|
||||
svgStr = true;
|
||||
break;
|
||||
} else if (response.indexOf('data:image/') === 0) {
|
||||
imgStr = true;
|
||||
break;
|
||||
}
|
||||
// Else fall through
|
||||
default:
|
||||
// TODO: See if there's a way to base64 encode the binary data stream
|
||||
// var str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
|
||||
|
||||
// Assume it's raw image data
|
||||
// importImage(str);
|
||||
|
||||
// Don't give warning as postMessage may have been used by something else
|
||||
if (mode !== 'm') {
|
||||
closeBrowser();
|
||||
} else {
|
||||
pending[id].entry.remove();
|
||||
}
|
||||
// $.alert('Unexpected data was returned: ' + response, function() {
|
||||
// if (mode !== 'm') {
|
||||
// closeBrowser();
|
||||
// } else {
|
||||
// pending[id].entry.remove();
|
||||
// }
|
||||
// });
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 's':
|
||||
// Import one
|
||||
if (svgStr) {
|
||||
svgCanvas.importSvgString(response);
|
||||
} else if (imgStr) {
|
||||
importImage(response);
|
||||
}
|
||||
closeBrowser();
|
||||
break;
|
||||
case 'm':
|
||||
// Import multiple
|
||||
multiArr.push([(svgStr ? 'svg' : 'img'), response]);
|
||||
var title;
|
||||
curMeta = pending[id];
|
||||
if (svgStr) {
|
||||
if (curMeta && curMeta.name) {
|
||||
title = curMeta.name;
|
||||
} else {
|
||||
// Try to find a title
|
||||
var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
|
||||
title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
|
||||
}
|
||||
if (curMeta) {
|
||||
preview.children().each(function () {
|
||||
if ($(this).data('id') === id) {
|
||||
if (curMeta.preview_url) {
|
||||
$(this).html('<img src="' + curMeta.preview_url + '">' + title);
|
||||
} else {
|
||||
$(this).text(title);
|
||||
}
|
||||
submit.removeAttr('disabled');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
entry = $('<div>' + message + '</div>').data('id', cur_meta.id);
|
||||
preview.append(entry);
|
||||
cur_meta.entry = entry;
|
||||
preview.append('<div>' + title + '</div>');
|
||||
submit.removeAttr('disabled');
|
||||
}
|
||||
|
||||
return;
|
||||
case '<':
|
||||
svg_str = true;
|
||||
break;
|
||||
case 'd':
|
||||
if (response.indexOf('data:image/svg+xml') === 0) {
|
||||
var pre = 'data:image/svg+xml;base64,';
|
||||
var src = response.substring(pre.length);
|
||||
response = svgedit.utilities.decode64(src);
|
||||
svg_str = true;
|
||||
break;
|
||||
} else if (response.indexOf('data:image/') === 0) {
|
||||
img_str = true;
|
||||
break;
|
||||
} else {
|
||||
if (curMeta && curMeta.preview_url) {
|
||||
title = curMeta.name || '';
|
||||
}
|
||||
// Else fall through
|
||||
default:
|
||||
// TODO: See if there's a way to base64 encode the binary data stream
|
||||
// var str = 'data:;base64,' + svgedit.utilities.encode64(response, true);
|
||||
|
||||
// Assume it's raw image data
|
||||
// importImage(str);
|
||||
|
||||
// Don't give warning as postMessage may have been used by something else
|
||||
if (mode !== 'm') {
|
||||
closeBrowser();
|
||||
if (curMeta && curMeta.preview_url) {
|
||||
entry = '<img src="' + curMeta.preview_url + '">' + title;
|
||||
} else {
|
||||
pending[id].entry.remove();
|
||||
entry = '<img src="' + response + '">';
|
||||
}
|
||||
// $.alert('Unexpected data was returned: ' + response, function() {
|
||||
// if (mode !== 'm') {
|
||||
// closeBrowser();
|
||||
// } else {
|
||||
// pending[id].entry.remove();
|
||||
// }
|
||||
// });
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 's':
|
||||
// Import one
|
||||
if (svg_str) {
|
||||
svgCanvas.importSvgString(response);
|
||||
} else if (img_str) {
|
||||
importImage(response);
|
||||
}
|
||||
closeBrowser();
|
||||
break;
|
||||
case 'm':
|
||||
// Import multiple
|
||||
multi_arr.push([(svg_str ? 'svg' : 'img'), response]);
|
||||
var title;
|
||||
cur_meta = pending[id];
|
||||
if (svg_str) {
|
||||
if (cur_meta && cur_meta.name) {
|
||||
title = cur_meta.name;
|
||||
} else {
|
||||
// Try to find a title
|
||||
var xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
|
||||
title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
|
||||
}
|
||||
if (cur_meta) {
|
||||
preview.children().each(function() {
|
||||
if ($(this).data('id') == id) {
|
||||
if (cur_meta.preview_url) {
|
||||
$(this).html('<img src="' + cur_meta.preview_url + '">' + title);
|
||||
} else {
|
||||
$(this).text(title);
|
||||
}
|
||||
submit.removeAttr('disabled');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
preview.append('<div>'+title+'</div>');
|
||||
submit.removeAttr('disabled');
|
||||
}
|
||||
} else {
|
||||
if (cur_meta && cur_meta.preview_url) {
|
||||
title = cur_meta.name || '';
|
||||
}
|
||||
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');
|
||||
}
|
||||
|
||||
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 (!svg_str) {break;}
|
||||
svgEditor.openPrep(function(ok) {
|
||||
if (!ok) {return;}
|
||||
svgCanvas.clear();
|
||||
svgCanvas.setSvgString(response);
|
||||
// updateCanvas();
|
||||
});
|
||||
closeBrowser();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
// Open
|
||||
if (!svgStr) { break; }
|
||||
svgEditor.openPrep(function (ok) {
|
||||
if (!ok) { return; }
|
||||
svgCanvas.clear();
|
||||
svgCanvas.setSvgString(response);
|
||||
// updateCanvas();
|
||||
});
|
||||
closeBrowser();
|
||||
break;
|
||||
}
|
||||
}, true);
|
||||
|
||||
function toggleMulti(show) {
|
||||
|
||||
function toggleMulti (show) {
|
||||
$('#lib_framewrap, #imglib_opts').css({right: (show ? 200 : 10)});
|
||||
if (!preview) {
|
||||
preview = $('<div id=imglib_preview>').css({
|
||||
@@ -257,208 +255,202 @@ svgEditor.addExtension("imagelib", function() {'use strict';
|
||||
background: '#fff',
|
||||
overflow: 'auto'
|
||||
}).insertAfter('#lib_framewrap');
|
||||
|
||||
|
||||
submit = $('<button disabled>Import selected</button>')
|
||||
.appendTo('#imgbrowse')
|
||||
.on("click touchend", function() {
|
||||
$.each(multi_arr, function(i) {
|
||||
var type = this[0];
|
||||
var data = this[1];
|
||||
if (type == 'svg') {
|
||||
svgCanvas.importSvgString(data);
|
||||
} else {
|
||||
importImage(data);
|
||||
}
|
||||
svgCanvas.moveSelectedElements(i*20, i*20, false);
|
||||
.on('click touchend', function () {
|
||||
$.each(multiArr, function (i) {
|
||||
var type = this[0];
|
||||
var data = this[1];
|
||||
if (type === 'svg') {
|
||||
svgCanvas.importSvgString(data);
|
||||
} else {
|
||||
importImage(data);
|
||||
}
|
||||
svgCanvas.moveSelectedElements(i * 20, i * 20, false);
|
||||
});
|
||||
preview.empty();
|
||||
multiArr = [];
|
||||
$('#imgbrowse_holder').hide();
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
bottom: 10,
|
||||
right: -10
|
||||
});
|
||||
preview.empty();
|
||||
multi_arr = [];
|
||||
$('#imgbrowse_holder').hide();
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
bottom: 10,
|
||||
right: -10
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
preview.toggle(show);
|
||||
submit.toggle(show);
|
||||
}
|
||||
|
||||
function showBrowser() {
|
||||
|
||||
function showBrowser () {
|
||||
var browser = $('#imgbrowse');
|
||||
if (!browser.length) {
|
||||
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>\
|
||||
</div></div>').insertAfter('#svg_docprops');
|
||||
$('<div id=imgbrowse_holder><div id=imgbrowse class=toolbar_button>' +
|
||||
'</div></div>').insertAfter('#svg_docprops');
|
||||
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 header = $('<h1>').prependTo(browser).text(all_libs).css({
|
||||
|
||||
var header = $('<h1>').prependTo(browser).text(allLibs).css({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%'
|
||||
});
|
||||
|
||||
|
||||
var cancel = $('<button>' + uiStrings.common.cancel + '</button>')
|
||||
.appendTo(browser)
|
||||
.on("click touchend", function() {
|
||||
$('#imgbrowse_holder').hide();
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
right: -10
|
||||
});
|
||||
|
||||
var leftBlock = $('<span>').css({position:'absolute',top:5,left:10}).appendTo(browser);
|
||||
|
||||
.on('click touchend', function () {
|
||||
$('#imgbrowse_holder').hide();
|
||||
}).css({
|
||||
position: 'absolute',
|
||||
top: 5,
|
||||
right: -10
|
||||
});
|
||||
|
||||
var leftBlock = $('<span>').css({position: 'absolute', top: 5, left: 10}).appendTo(browser);
|
||||
|
||||
var back = $('<button hidden>' + uiStrings.imagelib.show_list + '</button>')
|
||||
.appendTo(leftBlock)
|
||||
.on("click touchend", function() {
|
||||
frame.attr('src', 'about:blank').hide();
|
||||
lib_opts.show();
|
||||
header.text(all_libs);
|
||||
back.hide();
|
||||
}).css({
|
||||
'margin-right': 5
|
||||
}).hide();
|
||||
|
||||
var type = $('<select><option value=s>' +
|
||||
uiStrings.imagelib.import_single + '</option><option value=m>' +
|
||||
uiStrings.imagelib.import_multi + '</option><option value=o>' +
|
||||
uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function() {
|
||||
.on('click touchend', function () {
|
||||
frame.attr('src', 'about:blank').hide();
|
||||
libOpts.show();
|
||||
header.text(allLibs);
|
||||
back.hide();
|
||||
}).css({
|
||||
'margin-right': 5
|
||||
}).hide();
|
||||
|
||||
/* var type = */ $('<select><option value=s>' +
|
||||
uiStrings.imagelib.import_single + '</option><option value=m>' +
|
||||
uiStrings.imagelib.import_multi + '</option><option value=o>' +
|
||||
uiStrings.imagelib.open + '</option></select>').appendTo(leftBlock).change(function () {
|
||||
mode = $(this).val();
|
||||
switch (mode) {
|
||||
case 's':
|
||||
case 'o':
|
||||
toggleMulti(false);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
// Import multiple
|
||||
toggleMulti(true);
|
||||
break;
|
||||
case 's':
|
||||
case 'o':
|
||||
toggleMulti(false);
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
// Import multiple
|
||||
toggleMulti(true);
|
||||
break;
|
||||
}
|
||||
}).css({
|
||||
'margin-top': 10
|
||||
});
|
||||
|
||||
|
||||
cancel.prepend($.getSvgIcon('cancel', true));
|
||||
back.prepend($.getSvgIcon('tool_imagelib', true));
|
||||
|
||||
$.each(img_libs, function(i, opts) {
|
||||
|
||||
$.each(imgLibs, function (i, opts) {
|
||||
$('<li>')
|
||||
.appendTo(lib_opts)
|
||||
.appendTo(libOpts)
|
||||
.text(opts.name)
|
||||
.on("click touchend", function() {
|
||||
frame.attr('src', opts.url).show();
|
||||
header.text(opts.name);
|
||||
lib_opts.hide();
|
||||
back.show();
|
||||
}).append('<span>' + opts.description + '</span>');
|
||||
.on('click touchend', function () {
|
||||
frame.attr('src', opts.url).show();
|
||||
header.text(opts.name);
|
||||
libOpts.hide();
|
||||
back.show();
|
||||
}).append('<span>' + opts.description + '</span>');
|
||||
});
|
||||
|
||||
} else {
|
||||
$('#imgbrowse_holder').show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
svgicons: svgEditor.curConfig.extPath + "ext-imagelib.xml",
|
||||
svgicons: svgEditor.curConfig.extPath + 'ext-imagelib.xml',
|
||||
buttons: [{
|
||||
id: "tool_imagelib",
|
||||
type: "app_menu", // _flyout
|
||||
id: 'tool_imagelib',
|
||||
type: 'app_menu', // _flyout
|
||||
position: 4,
|
||||
title: "Image library",
|
||||
title: 'Image library',
|
||||
events: {
|
||||
"mouseup": showBrowser
|
||||
'mouseup': showBrowser
|
||||
}
|
||||
}],
|
||||
callback: function() {
|
||||
|
||||
$('<style>').text('\
|
||||
#imgbrowse_holder {\
|
||||
position: absolute;\
|
||||
top: 0;\
|
||||
left: 0;\
|
||||
width: 100%;\
|
||||
height: 100%;\
|
||||
background-color: rgba(0, 0, 0, .5);\
|
||||
z-index: 5;\
|
||||
}\
|
||||
\
|
||||
#imgbrowse {\
|
||||
position: absolute;\
|
||||
top: 25px;\
|
||||
left: 25px;\
|
||||
right: 25px;\
|
||||
bottom: 25px;\
|
||||
min-width: 300px;\
|
||||
min-height: 200px;\
|
||||
background: #B0B0B0;\
|
||||
border: 1px outset #777;\
|
||||
}\
|
||||
#imgbrowse h1 {\
|
||||
font-size: 20px;\
|
||||
margin: .4em;\
|
||||
text-align: center;\
|
||||
}\
|
||||
#lib_framewrap,\
|
||||
#imgbrowse > ul {\
|
||||
position: absolute;\
|
||||
top: 45px;\
|
||||
left: 10px;\
|
||||
right: 10px;\
|
||||
bottom: 10px;\
|
||||
background: white;\
|
||||
margin: 0;\
|
||||
padding: 0;\
|
||||
}\
|
||||
#imgbrowse > ul {\
|
||||
overflow: auto;\
|
||||
}\
|
||||
#imgbrowse > div {\
|
||||
border: 1px solid #666;\
|
||||
}\
|
||||
#imglib_preview > div {\
|
||||
padding: 5px;\
|
||||
font-size: 12px;\
|
||||
}\
|
||||
#imglib_preview img {\
|
||||
display: block;\
|
||||
margin: 0 auto;\
|
||||
max-height: 100px;\
|
||||
}\
|
||||
#imgbrowse li {\
|
||||
list-style: none;\
|
||||
padding: .5em;\
|
||||
background: #E8E8E8;\
|
||||
border-bottom: 1px solid #B0B0B0;\
|
||||
line-height: 1.2em;\
|
||||
font-style: sans-serif;\
|
||||
}\
|
||||
#imgbrowse li > span {\
|
||||
color: #666;\
|
||||
font-size: 15px;\
|
||||
display: block;\
|
||||
}\
|
||||
#imgbrowse li:hover {\
|
||||
background: #FFC;\
|
||||
cursor: pointer;\
|
||||
}\
|
||||
#imgbrowse iframe {\
|
||||
width: 100%;\
|
||||
height: 100%;\
|
||||
border: 0;\
|
||||
}\
|
||||
').appendTo('head');
|
||||
callback: function () {
|
||||
$('<style>').text(
|
||||
'#imgbrowse_holder {' +
|
||||
'position: absolute;' +
|
||||
'top: 0;' +
|
||||
'left: 0;' +
|
||||
'width: 100%;' +
|
||||
'height: 100%;' +
|
||||
'background-color: rgba(0, 0, 0, .5);' +
|
||||
'z-index: 5;' +
|
||||
'}' +
|
||||
'#imgbrowse {' +
|
||||
'position: absolute;' +
|
||||
'top: 25px;' +
|
||||
'left: 25px;' +
|
||||
'right: 25px;' +
|
||||
'bottom: 25px;' +
|
||||
'min-width: 300px;' +
|
||||
'min-height: 200px;' +
|
||||
'background: #B0B0B0;' +
|
||||
'border: 1px outset #777;' +
|
||||
'}' +
|
||||
'#imgbrowse h1 {' +
|
||||
'font-size: 20px;' +
|
||||
'margin: .4em;' +
|
||||
'text-align: center;' +
|
||||
'}' +
|
||||
'#lib_framewrap,' +
|
||||
'#imgbrowse > ul {' +
|
||||
'position: absolute;' +
|
||||
'top: 45px;' +
|
||||
'left: 10px;' +
|
||||
'right: 10px;' +
|
||||
'bottom: 10px;' +
|
||||
'background: white;' +
|
||||
'margin: 0;' +
|
||||
'padding: 0;' +
|
||||
'}' +
|
||||
'#imgbrowse > ul {' +
|
||||
'overflow: auto;' +
|
||||
'}' +
|
||||
'#imgbrowse > div {' +
|
||||
'border: 1px solid #666;' +
|
||||
'}' +
|
||||
'#imglib_preview > div {' +
|
||||
'padding: 5px;' +
|
||||
'font-size: 12px;' +
|
||||
'}' +
|
||||
'#imglib_preview img {' +
|
||||
'display: block;' +
|
||||
'margin: 0 auto;' +
|
||||
'max-height: 100px;' +
|
||||
'}' +
|
||||
'#imgbrowse li {' +
|
||||
'list-style: none;' +
|
||||
'padding: .5em;' +
|
||||
'background: #E8E8E8;' +
|
||||
'border-bottom: 1px solid #B0B0B0;' +
|
||||
'line-height: 1.2em;' +
|
||||
'font-style: sans-serif;' +
|
||||
'}' +
|
||||
'#imgbrowse li > span {' +
|
||||
'color: #666;' +
|
||||
'font-size: 15px;' +
|
||||
'display: block;' +
|
||||
'}' +
|
||||
'#imgbrowse li:hover {' +
|
||||
'background: #FFC;' +
|
||||
'cursor: pointer;' +
|
||||
'}' +
|
||||
'#imgbrowse iframe {' +
|
||||
'width: 100%;' +
|
||||
'height: 100%;' +
|
||||
'border: 0;' +
|
||||
'}'
|
||||
).appendTo('head');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*globals svgEditor, svgCanvas, $*/
|
||||
/*jslint vars: true, eqeq: true, todo: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-markers.js
|
||||
*
|
||||
* Licensed under the Apache License, Version 2
|
||||
*
|
||||
* Copyright(c) 2010 Will Schleter
|
||||
* Copyright(c) 2010 Will Schleter
|
||||
* based on ext-arrows.js by Copyright(c) 2010 Alexis Deveria
|
||||
*
|
||||
* This extension provides for the addition of markers to the either end
|
||||
* or the middle of a line, polyline, path, polygon.
|
||||
*
|
||||
* or the middle of a line, polyline, path, polygon.
|
||||
*
|
||||
* Markers may be either a graphic or arbitary text
|
||||
*
|
||||
*
|
||||
* to simplify the coding and make the implementation as robust as possible,
|
||||
* markers are not shared - every object has its own set of markers.
|
||||
* this relationship is maintained by a naming convention between the
|
||||
* ids of the markers and the ids of the object
|
||||
*
|
||||
*
|
||||
* The following restrictions exist for simplicty of use and programming
|
||||
* objects and their markers to have the same color
|
||||
* marker size is fixed
|
||||
@@ -32,236 +32,235 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("Markers", function(S) {
|
||||
svgEditor.addExtension('Markers', function (S) {
|
||||
var // svgcontent = S.svgcontent,
|
||||
addElem = S.addSvgElementFromJson,
|
||||
selElems;
|
||||
|
||||
var mtypes = ['start','mid','end'];
|
||||
var mtypes = ['start', 'mid', 'end'];
|
||||
|
||||
var markerPrefix = 'se_marker_';
|
||||
var idPrefix = 'mkr_';
|
||||
|
||||
var marker_prefix = 'se_marker_';
|
||||
var id_prefix = 'mkr_';
|
||||
|
||||
// note - to add additional marker types add them below with a unique id
|
||||
// and add the associated icon(s) to marker-icons.svg
|
||||
// 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
|
||||
// remember that the coordinate system has +y downward
|
||||
var marker_types = {
|
||||
nomarker: {},
|
||||
leftarrow:
|
||||
{element:'path', attr:{d:'M0,50 L100,90 L70,50 L100,10 Z'}},
|
||||
var markerTypes = {
|
||||
nomarker: {},
|
||||
leftarrow:
|
||||
{element: 'path', attr: {d: 'M0,50 L100,90 L70,50 L100,10 Z'}},
|
||||
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:
|
||||
{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'}},
|
||||
forwardslash:
|
||||
{element:'path', attr:{d:'M30,100 L70,0'}},
|
||||
{element: 'path', attr: {d: 'M30,100 L70,0'}},
|
||||
reverseslash:
|
||||
{element:'path', attr:{d:'M30,0 L70,100'}},
|
||||
{element: 'path', attr: {d: 'M30,0 L70,100'}},
|
||||
verticalslash:
|
||||
{element:'path', attr:{d:'M50,0 L50,100'}},
|
||||
{element: 'path', attr: {d: 'M50,0 L50,100'}},
|
||||
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:
|
||||
{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:
|
||||
{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:
|
||||
{element:'path', attr:{d:'M10,80 L50,20 L80,80 Z'}},
|
||||
{element: 'path', attr: {d: 'M10,80 L50,20 L80,80 Z'}},
|
||||
mcircle:
|
||||
{element:'circle', attr:{r:30, cx:50, cy:50}}
|
||||
{element: 'circle', attr: {r: 30, cx: 50, cy: 50}}
|
||||
};
|
||||
|
||||
|
||||
var lang_list = {
|
||||
"en":[
|
||||
{id: "start_marker_list", title: "Select start marker type" },
|
||||
{id: "mid_marker_list", title: "Select mid marker type" },
|
||||
{id: "end_marker_list", title: "Select end marker type" },
|
||||
{id: "nomarker", title: "No Marker" },
|
||||
{id: "leftarrow", title: "Left Arrow" },
|
||||
{id: "rightarrow", title: "Right Arrow" },
|
||||
{id: "textmarker", title: "Text Marker" },
|
||||
{id: "forwardslash", title: "Forward Slash" },
|
||||
{id: "reverseslash", title: "Reverse Slash" },
|
||||
{id: "verticalslash", title: "Vertical Slash" },
|
||||
{id: "box", title: "Box" },
|
||||
{id: "star", title: "Star" },
|
||||
{id: "xmark", title: "X" },
|
||||
{id: "triangle", title: "Triangle" },
|
||||
{id: "mcircle", title: "Circle" },
|
||||
{id: "leftarrow_o", title: "Open Left Arrow" },
|
||||
{id: "rightarrow_o", title: "Open Right Arrow" },
|
||||
{id: "box_o", title: "Open Box" },
|
||||
{id: "star_o", title: "Open Star" },
|
||||
{id: "triangle_o", title: "Open Triangle" },
|
||||
{id: "mcircle_o", title: "Open Circle" }
|
||||
|
||||
var langList = {
|
||||
'en': [
|
||||
{id: 'start_marker_list', title: 'Select start marker type'},
|
||||
{id: 'mid_marker_list', title: 'Select mid marker type'},
|
||||
{id: 'end_marker_list', title: 'Select end marker type'},
|
||||
{id: 'nomarker', title: 'No Marker'},
|
||||
{id: 'leftarrow', title: 'Left Arrow'},
|
||||
{id: 'rightarrow', title: 'Right Arrow'},
|
||||
{id: 'textmarker', title: 'Text Marker'},
|
||||
{id: 'forwardslash', title: 'Forward Slash'},
|
||||
{id: 'reverseslash', title: 'Reverse Slash'},
|
||||
{id: 'verticalslash', title: 'Vertical Slash'},
|
||||
{id: 'box', title: 'Box'},
|
||||
{id: 'star', title: 'Star'},
|
||||
{id: 'xmark', title: 'X'},
|
||||
{id: 'triangle', title: 'Triangle'},
|
||||
{id: 'mcircle', title: 'Circle'},
|
||||
{id: 'leftarrow_o', title: 'Open Left Arrow'},
|
||||
{id: 'rightarrow_o', title: 'Open Right Arrow'},
|
||||
{id: 'box_o', title: 'Open Box'},
|
||||
{id: 'star_o', title: 'Open Star'},
|
||||
{id: 'triangle_o', title: 'Open Triangle'},
|
||||
{id: 'mcircle_o', title: 'Open Circle'}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
// duplicate shapes to support unfilled (open) marker types with an _o suffix
|
||||
$.each(['leftarrow','rightarrow','box','star','mcircle','triangle'],function(i,v) {
|
||||
marker_types[v+'_o'] = marker_types[v];
|
||||
$.each(['leftarrow', 'rightarrow', 'box', 'star', 'mcircle', 'triangle'], function (i, v) {
|
||||
markerTypes[v + '_o'] = markerTypes[v];
|
||||
});
|
||||
|
||||
|
||||
// elem = a graphic element will have an attribute like marker-start
|
||||
// attr - marker-start, marker-mid, or marker-end
|
||||
// returns the marker element that is linked to the graphic element
|
||||
function getLinked(elem, attr) {
|
||||
function getLinked (elem, attr) {
|
||||
var str = elem.getAttribute(attr);
|
||||
if(!str) {return null;}
|
||||
var m = str.match(/\(\#(.*)\)/);
|
||||
if(!m || m.length !== 2) {
|
||||
if (!str) { return null; }
|
||||
var m = str.match(/\(#(.*)\)/);
|
||||
if (!m || m.length !== 2) {
|
||||
return null;
|
||||
}
|
||||
return S.getElem(m[1]);
|
||||
}
|
||||
|
||||
function setIcon(pos,id) {
|
||||
if (id.substr(0,1) !== '\\') {id = '\\textmarker';}
|
||||
var ci = '#'+id_prefix+pos+'_'+id.substr(1);
|
||||
svgEditor.setIcon('#cur_' + pos +'_marker_list', $(ci).children());
|
||||
function setIcon (pos, id) {
|
||||
if (id.substr(0, 1) !== '\\') { id = '\\textmarker'; }
|
||||
var ci = '#' + idPrefix + pos + '_' + id.substr(1);
|
||||
svgEditor.setIcon('#cur_' + pos + '_marker_list', $(ci).children());
|
||||
$(ci).addClass('current').siblings().removeClass('current');
|
||||
}
|
||||
|
||||
// toggles context tool panel off/on
|
||||
//sets the controls with the selected element's settings
|
||||
function showPanel(on) {
|
||||
// sets the controls with the selected element's settings
|
||||
function showPanel (on) {
|
||||
$('#marker_panel').toggle(on);
|
||||
|
||||
if(on) {
|
||||
if (on) {
|
||||
var el = selElems[0];
|
||||
var val;
|
||||
var ci;
|
||||
|
||||
$.each(mtypes, function(i, pos) {
|
||||
var m = getLinked(el, "marker-" + pos);
|
||||
$.each(mtypes, function (i, pos) {
|
||||
var m = getLinked(el, 'marker-' + pos);
|
||||
var txtbox = $('#' + pos + '_marker');
|
||||
if (!m) {
|
||||
val = '\\nomarker';
|
||||
ci = val;
|
||||
txtbox.hide(); // hide text box
|
||||
} 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;
|
||||
ci = val;
|
||||
if (val === '\\textmarker') {
|
||||
val = m.lastChild.textContent;
|
||||
//txtbox.show(); // show text box
|
||||
// txtbox.show(); // show text box
|
||||
} else {
|
||||
txtbox.hide(); // hide text box
|
||||
}
|
||||
}
|
||||
txtbox.val(val);
|
||||
setIcon(pos,ci);
|
||||
txtbox.val(val);
|
||||
setIcon(pos, ci);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMarker (id, val) {
|
||||
var txtBoxBg = '#ffffff';
|
||||
var txtBoxBorder = 'none';
|
||||
var txtBoxStrokeWidth = 0;
|
||||
|
||||
function addMarker(id, val) {
|
||||
var txt_box_bg = '#ffffff';
|
||||
var txt_box_border = 'none';
|
||||
var txt_box_stroke_width = 0;
|
||||
|
||||
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');
|
||||
//NOTE: Safari didn't like a negative value in viewBox
|
||||
//so we use a standardized 0 0 100 100
|
||||
//with 50 50 being mapped to the marker position
|
||||
// NOTE: Safari didn't like a negative value in viewBox
|
||||
// so we use a standardized 0 0 100 100
|
||||
// with 50 50 being mapped to the marker position
|
||||
var refX = 50;
|
||||
var refY = 50;
|
||||
var viewBox = "0 0 100 100";
|
||||
var viewBox = '0 0 100 100';
|
||||
var markerWidth = 5;
|
||||
var markerHeight = 5;
|
||||
var strokeWidth = 10;
|
||||
var se_type;
|
||||
if (val.substr(0,1) === '\\') {se_type = val.substr(1);}
|
||||
else {se_type = 'textmarker';}
|
||||
var seType;
|
||||
if (val.substr(0, 1) === '\\') {
|
||||
seType = val.substr(1);
|
||||
} else { seType = 'textmarker'; }
|
||||
|
||||
if (!markerTypes[seType]) { return; } // an unknown type!
|
||||
|
||||
if (!marker_types[se_type]) {return;} // an unknown type!
|
||||
|
||||
// create a generic marker
|
||||
marker = addElem({
|
||||
"element": "marker",
|
||||
"attr": {
|
||||
"id": id,
|
||||
"markerUnits": "strokeWidth",
|
||||
"orient": "auto",
|
||||
"style": "pointer-events:none",
|
||||
"se_type": se_type
|
||||
}
|
||||
'element': 'marker',
|
||||
'attr': {
|
||||
'id': id,
|
||||
'markerUnits': 'strokeWidth',
|
||||
'orient': 'auto',
|
||||
'style': 'pointer-events:none',
|
||||
'se_type': seType
|
||||
}
|
||||
});
|
||||
|
||||
if (se_type != 'textmarker') {
|
||||
var mel = addElem(marker_types[se_type]);
|
||||
if (seType !== 'textmarker') {
|
||||
var mel = addElem(markerTypes[seType]);
|
||||
var fillcolor = color;
|
||||
if (se_type.substr(-2) === '_o') {fillcolor = 'none';}
|
||||
if (seType.substr(-2) === '_o') { fillcolor = 'none'; }
|
||||
mel.setAttribute('fill', fillcolor);
|
||||
mel.setAttribute('stroke', color);
|
||||
mel.setAttribute('stroke-width', strokeWidth);
|
||||
marker.appendChild(mel);
|
||||
} else {
|
||||
var text = addElem(marker_types[se_type]);
|
||||
var text = addElem(markerTypes[seType]);
|
||||
// have to add text to get bounding box
|
||||
text.textContent = val;
|
||||
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 bb = tb;
|
||||
bb.x = 0;
|
||||
bb.y = 0;
|
||||
bb.width += pad*2;
|
||||
bb.height += pad*2;
|
||||
bb.width += pad * 2;
|
||||
bb.height += pad * 2;
|
||||
// shift text according to its size
|
||||
text.setAttribute('x', pad);
|
||||
text.setAttribute('y', bb.height - pad - tb.height/4); // kludge?
|
||||
text.setAttribute('fill',color);
|
||||
refX = bb.width/2 + pad;
|
||||
refY = bb.height/2 + pad;
|
||||
viewBox = bb.x + " " + bb.y + " " + bb.width + " " + bb.height;
|
||||
markerWidth = bb.width/10;
|
||||
markerHeight = bb.height/10;
|
||||
text.setAttribute('y', bb.height - pad - tb.height / 4); // kludge?
|
||||
text.setAttribute('fill', color);
|
||||
refX = bb.width / 2 + pad;
|
||||
refY = bb.height / 2 + pad;
|
||||
viewBox = bb.x + ' ' + bb.y + ' ' + bb.width + ' ' + bb.height;
|
||||
markerWidth = bb.width / 10;
|
||||
markerHeight = bb.height / 10;
|
||||
|
||||
var box = addElem({
|
||||
"element": "rect",
|
||||
"attr": {
|
||||
"x": bb.x,
|
||||
"y": bb.y,
|
||||
"width": bb.width,
|
||||
"height": bb.height,
|
||||
"fill": txt_box_bg,
|
||||
"stroke": txt_box_border,
|
||||
"stroke-width": txt_box_stroke_width
|
||||
'element': 'rect',
|
||||
'attr': {
|
||||
'x': bb.x,
|
||||
'y': bb.y,
|
||||
'width': bb.width,
|
||||
'height': bb.height,
|
||||
'fill': txtBoxBg,
|
||||
'stroke': txtBoxBorder,
|
||||
'stroke-width': txtBoxStrokeWidth
|
||||
}
|
||||
});
|
||||
marker.setAttribute("orient",0);
|
||||
marker.setAttribute('orient', 0);
|
||||
marker.appendChild(box);
|
||||
marker.appendChild(text);
|
||||
}
|
||||
}
|
||||
|
||||
marker.setAttribute("viewBox",viewBox);
|
||||
marker.setAttribute("markerWidth", markerWidth);
|
||||
marker.setAttribute("markerHeight", markerHeight);
|
||||
marker.setAttribute("refX", refX);
|
||||
marker.setAttribute("refY", refY);
|
||||
marker.setAttribute('viewBox', viewBox);
|
||||
marker.setAttribute('markerWidth', markerWidth);
|
||||
marker.setAttribute('markerHeight', markerHeight);
|
||||
marker.setAttribute('refX', refX);
|
||||
marker.setAttribute('refY', refY);
|
||||
S.findDefs().appendChild(marker);
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
function convertline(elem) {
|
||||
function convertline (elem) {
|
||||
// this routine came from the connectors extension
|
||||
// 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
|
||||
|
||||
@@ -271,27 +270,27 @@ svgEditor.addExtension("Markers", function(S) {
|
||||
var y2 = Number(elem.getAttribute('y2'));
|
||||
var id = elem.id;
|
||||
|
||||
var mid_pt = (' '+((x1+x2)/2)+','+((y1+y2)/2) + ' ');
|
||||
var midPt = (' ' + ((x1 + x2) / 2) + ',' + ((y1 + y2) / 2) + ' ');
|
||||
var pline = addElem({
|
||||
"element": "polyline",
|
||||
"attr": {
|
||||
"points": (x1+','+y1+ mid_pt +x2+','+y2),
|
||||
"stroke": elem.getAttribute('stroke'),
|
||||
"stroke-width": elem.getAttribute('stroke-width'),
|
||||
"fill": "none",
|
||||
"opacity": elem.getAttribute('opacity') || 1
|
||||
'element': 'polyline',
|
||||
'attr': {
|
||||
'points': (x1 + ',' + y1 + midPt + x2 + ',' + y2),
|
||||
'stroke': elem.getAttribute('stroke'),
|
||||
'stroke-width': elem.getAttribute('stroke-width'),
|
||||
'fill': 'none',
|
||||
'opacity': elem.getAttribute('opacity') || 1
|
||||
}
|
||||
});
|
||||
$.each(mtypes, function(i, pos) { // get any existing marker definitions
|
||||
var nam = 'marker-'+pos;
|
||||
$.each(mtypes, function (i, pos) { // get any existing marker definitions
|
||||
var nam = 'marker-' + pos;
|
||||
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();
|
||||
batchCmd.addSubCommand(new S.RemoveElementCommand(elem, elem.parentNode));
|
||||
batchCmd.addSubCommand(new S.InsertElementCommand(pline));
|
||||
|
||||
|
||||
$(elem).after(pline).remove();
|
||||
svgCanvas.clearSelection();
|
||||
pline.id = id;
|
||||
@@ -300,85 +299,85 @@ svgEditor.addExtension("Markers", function(S) {
|
||||
return pline;
|
||||
}
|
||||
|
||||
function setMarker() {
|
||||
var poslist={'start_marker':'start','mid_marker':'mid','end_marker':'end'};
|
||||
function setMarker () {
|
||||
var poslist = {'start_marker': 'start', 'mid_marker': 'mid', 'end_marker': 'end'};
|
||||
var pos = poslist[this.id];
|
||||
var marker_name = 'marker-'+pos;
|
||||
var markerName = 'marker-' + pos;
|
||||
var val = this.value;
|
||||
var el = selElems[0];
|
||||
var marker = getLinked(el, marker_name);
|
||||
if (marker) {$(marker).remove();}
|
||||
el.removeAttribute(marker_name);
|
||||
if (val == '') {val = '\\nomarker';}
|
||||
if (val == '\\nomarker') {
|
||||
setIcon(pos,val);
|
||||
S.call("changed", selElems);
|
||||
var marker = getLinked(el, markerName);
|
||||
if (marker) { $(marker).remove(); }
|
||||
el.removeAttribute(markerName);
|
||||
if (val === '') { val = '\\nomarker'; }
|
||||
if (val === '\\nomarker') {
|
||||
setIcon(pos, val);
|
||||
S.call('changed', selElems);
|
||||
return;
|
||||
}
|
||||
// Set marker on element
|
||||
var id = marker_prefix + pos + '_' + el.id;
|
||||
var id = markerPrefix + pos + '_' + el.id;
|
||||
addMarker(id, val);
|
||||
svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")");
|
||||
if (el.tagName === 'line' && pos == 'mid') {el = convertline(el);}
|
||||
S.call("changed", selElems);
|
||||
setIcon(pos,val);
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
|
||||
if (el.tagName === 'line' && pos === 'mid') { el = convertline(el); }
|
||||
S.call('changed', selElems);
|
||||
setIcon(pos, val);
|
||||
}
|
||||
|
||||
// called when the main system modifies an object
|
||||
// this routine changes the associated markers to be the same color
|
||||
function colorChanged(elem) {
|
||||
function colorChanged (elem) {
|
||||
var color = elem.getAttribute('stroke');
|
||||
|
||||
$.each(mtypes, function(i, pos) {
|
||||
var marker = getLinked(elem, 'marker-'+pos);
|
||||
if (!marker) {return;}
|
||||
if (!marker.attributes.se_type) {return;} // not created by this extension
|
||||
$.each(mtypes, function (i, pos) {
|
||||
var marker = getLinked(elem, 'marker-' + pos);
|
||||
if (!marker) { return; }
|
||||
if (!marker.attributes.se_type) { return; } // not created by this extension
|
||||
var ch = marker.lastElementChild;
|
||||
if (!ch) {return;}
|
||||
if (!ch) { return; }
|
||||
var curfill = ch.getAttribute('fill');
|
||||
var curstroke = ch.getAttribute('stroke');
|
||||
if (curfill && curfill != 'none') {ch.setAttribute('fill', color);}
|
||||
if (curstroke && curstroke != 'none') {ch.setAttribute('stroke', color);}
|
||||
if (curfill && curfill !== 'none') { ch.setAttribute('fill', color); }
|
||||
if (curstroke && curstroke !== 'none') { ch.setAttribute('stroke', color); }
|
||||
});
|
||||
}
|
||||
|
||||
// called when the main system creates or modifies an object
|
||||
// primary purpose is create new markers for cloned objects
|
||||
function updateReferences(el) {
|
||||
function updateReferences (el) {
|
||||
$.each(mtypes, function (i, pos) {
|
||||
var id = marker_prefix + pos + '_' + el.id;
|
||||
var marker_name = 'marker-'+pos;
|
||||
var marker = getLinked(el, marker_name);
|
||||
if (!marker || !marker.attributes.se_type) {return;} // not created by this extension
|
||||
var url = el.getAttribute(marker_name);
|
||||
var id = markerPrefix + pos + '_' + el.id;
|
||||
var markerName = 'marker-' + pos;
|
||||
var marker = getLinked(el, markerName);
|
||||
if (!marker || !marker.attributes.se_type) { return; } // not created by this extension
|
||||
var url = el.getAttribute(markerName);
|
||||
if (url) {
|
||||
var len = el.id.length;
|
||||
var linkid = url.substr(-len-1, len);
|
||||
if (el.id != linkid) {
|
||||
var val = $('#'+pos + '_marker').attr('value');
|
||||
var linkid = url.substr(-len - 1, len);
|
||||
if (el.id !== linkid) {
|
||||
var val = $('#' + pos + '_marker').attr('value');
|
||||
addMarker(id, val);
|
||||
svgCanvas.changeSelectedAttribute(marker_name, "url(#" + id + ")");
|
||||
if (el.tagName === 'line' && pos == 'mid') {el = convertline(el);}
|
||||
S.call("changed", selElems);
|
||||
svgCanvas.changeSelectedAttribute(markerName, 'url(#' + id + ')');
|
||||
if (el.tagName === 'line' && pos === 'mid') { el = convertline(el); }
|
||||
S.call('changed', selElems);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// simulate a change event a text box that stores the current element's marker type
|
||||
function triggerTextEntry(pos, val) {
|
||||
$('#'+pos+'_marker').val(val);
|
||||
$('#'+pos+'_marker').change();
|
||||
function triggerTextEntry (pos, val) {
|
||||
$('#' + pos + '_marker').val(val);
|
||||
$('#' + pos + '_marker').change();
|
||||
// var txtbox = $('#'+pos+'_marker');
|
||||
// if (val.substr(0,1)=='\\') {txtbox.hide();}
|
||||
// else {txtbox.show();}
|
||||
}
|
||||
|
||||
function showTextPrompt(pos) {
|
||||
var def = $('#'+pos+'_marker').val();
|
||||
if (def.substr(0,1) === '\\') {def = '';}
|
||||
$.prompt('Enter text for ' + pos + ' marker', def , function(txt) {
|
||||
if (txt) {triggerTextEntry(pos, txt);}
|
||||
function showTextPrompt (pos) {
|
||||
var def = $('#' + pos + '_marker').val();
|
||||
if (def.substr(0, 1) === '\\') { def = ''; }
|
||||
$.prompt('Enter text for ' + pos + ' marker', def, function (txt) {
|
||||
if (txt) { triggerTextEntry(pos, txt); }
|
||||
});
|
||||
}
|
||||
|
||||
@@ -406,66 +405,64 @@ svgEditor.addExtension("Markers", function(S) {
|
||||
}
|
||||
*/
|
||||
// callback function for a toolbar button click
|
||||
function setArrowFromButton(obj) {
|
||||
|
||||
function setArrowFromButton (obj) {
|
||||
var parts = this.id.split('_');
|
||||
var pos = parts[1];
|
||||
var val = parts[2];
|
||||
if (parts[3]) { val += '_' + parts[3];}
|
||||
|
||||
if (val != 'textmarker') {
|
||||
triggerTextEntry(pos, '\\'+val);
|
||||
if (parts[3]) { val += '_' + parts[3]; }
|
||||
|
||||
if (val !== 'textmarker') {
|
||||
triggerTextEntry(pos, '\\' + val);
|
||||
} else {
|
||||
showTextPrompt(pos);
|
||||
}
|
||||
}
|
||||
|
||||
function getTitle(lang, id) {
|
||||
var i, list = lang_list[lang];
|
||||
|
||||
function getTitle (lang, id) {
|
||||
var i, list = langList[lang];
|
||||
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 id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// build the toolbar button array from the marker definitions
|
||||
// TODO: need to incorporate language specific titles
|
||||
function buildButtonList() {
|
||||
var buttons=[];
|
||||
function buildButtonList () {
|
||||
var buttons = [];
|
||||
// var i = 0;
|
||||
/*
|
||||
/*
|
||||
buttons.push({
|
||||
id:id_prefix + 'markers_off',
|
||||
title:'Turn off all markers',
|
||||
type:'context',
|
||||
id: idPrefix + 'markers_off',
|
||||
title: 'Turn off all markers',
|
||||
type: 'context',
|
||||
events: { 'click': setMarkerSet },
|
||||
panel: 'marker_panel'
|
||||
});
|
||||
buttons.push({
|
||||
id:id_prefix + 'markers_dimension',
|
||||
title:'Dimension',
|
||||
type:'context',
|
||||
id: idPrefix + 'markers_dimension',
|
||||
title: 'Dimension',
|
||||
type: 'context',
|
||||
events: { 'click': setMarkerSet },
|
||||
panel: 'marker_panel'
|
||||
});
|
||||
buttons.push({
|
||||
id:id_prefix + 'markers_label',
|
||||
title:'Label',
|
||||
type:'context',
|
||||
id: idPrefix + 'markers_label',
|
||||
title: 'Label',
|
||||
type: 'context',
|
||||
events: { 'click': setMarkerSet },
|
||||
panel: 'marker_panel'
|
||||
});
|
||||
*/
|
||||
$.each(mtypes, function (k, pos) {
|
||||
var listname = pos + "_marker_list";
|
||||
var listname = pos + '_marker_list';
|
||||
var def = true;
|
||||
$.each(marker_types, function (id, v) {
|
||||
var title = getTitle('en', id);
|
||||
$.each(markerTypes, function (id, v) {
|
||||
var title = getTitle('en', String(id));
|
||||
buttons.push({
|
||||
id: id_prefix + pos + '_' + id,
|
||||
id: idPrefix + pos + '_' + id,
|
||||
svgicon: id,
|
||||
title: title,
|
||||
type: 'context',
|
||||
@@ -481,99 +478,98 @@ svgEditor.addExtension("Markers", function(S) {
|
||||
}
|
||||
|
||||
return {
|
||||
name: "Markers",
|
||||
svgicons: svgEditor.curConfig.extPath + "markers-icons.xml",
|
||||
name: 'Markers',
|
||||
svgicons: svgEditor.curConfig.extPath + 'markers-icons.xml',
|
||||
buttons: buildButtonList(),
|
||||
context_tools: [
|
||||
{
|
||||
type: "input",
|
||||
panel: "marker_panel",
|
||||
title: "Start marker",
|
||||
id: "start_marker",
|
||||
label: "s",
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
},{
|
||||
type: "button-select",
|
||||
panel: "marker_panel",
|
||||
title: getTitle('en', 'start_marker_list'),
|
||||
id: "start_marker_list",
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
},{
|
||||
type: "input",
|
||||
panel: "marker_panel",
|
||||
title: "Middle marker",
|
||||
id: "mid_marker",
|
||||
label: "m",
|
||||
defval: "",
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
},{
|
||||
type: "button-select",
|
||||
panel: "marker_panel",
|
||||
title: getTitle('en', 'mid_marker_list'),
|
||||
id: "mid_marker_list",
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
},{
|
||||
type: "input",
|
||||
panel: "marker_panel",
|
||||
title: "End marker",
|
||||
id: "end_marker",
|
||||
label: "e",
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
},{
|
||||
type: "button-select",
|
||||
panel: "marker_panel",
|
||||
title: getTitle('en', 'end_marker_list'),
|
||||
id: "end_marker_list",
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
} ],
|
||||
callback: function() {
|
||||
{
|
||||
type: 'input',
|
||||
panel: 'marker_panel',
|
||||
title: 'Start marker',
|
||||
id: 'start_marker',
|
||||
label: 's',
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
}, {
|
||||
type: 'button-select',
|
||||
panel: 'marker_panel',
|
||||
title: getTitle('en', 'start_marker_list'),
|
||||
id: 'start_marker_list',
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
}, {
|
||||
type: 'input',
|
||||
panel: 'marker_panel',
|
||||
title: 'Middle marker',
|
||||
id: 'mid_marker',
|
||||
label: 'm',
|
||||
defval: '',
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
}, {
|
||||
type: 'button-select',
|
||||
panel: 'marker_panel',
|
||||
title: getTitle('en', 'mid_marker_list'),
|
||||
id: 'mid_marker_list',
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
}, {
|
||||
type: 'input',
|
||||
panel: 'marker_panel',
|
||||
title: 'End marker',
|
||||
id: 'end_marker',
|
||||
label: 'e',
|
||||
size: 3,
|
||||
events: { change: setMarker }
|
||||
}, {
|
||||
type: 'button-select',
|
||||
panel: 'marker_panel',
|
||||
title: getTitle('en', 'end_marker_list'),
|
||||
id: 'end_marker_list',
|
||||
colnum: 3,
|
||||
events: { change: setArrowFromButton }
|
||||
}
|
||||
],
|
||||
callback: function () {
|
||||
$('#marker_panel').addClass('toolset').hide();
|
||||
|
||||
},
|
||||
addLangData: function(lang) {
|
||||
return { data: lang_list[lang] };
|
||||
addLangData: function (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) {
|
||||
// Use this to update the current selected elements
|
||||
//console.log('selectChanged',opts);
|
||||
selElems = opts.elems;
|
||||
var i = selElems.length;
|
||||
var markerElems = ['line', 'path', 'polyline', 'polygon'];
|
||||
|
||||
var i = selElems.length;
|
||||
var marker_elems = ['line','path','polyline','polygon'];
|
||||
|
||||
while(i--) {
|
||||
var elem = selElems[i];
|
||||
if(elem && $.inArray(elem.tagName, marker_elems) !== -1) {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
showPanel(true);
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if (elem && $.inArray(elem.tagName, markerElems) !== -1) {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
showPanel(true);
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
elementChanged: function(opts) {
|
||||
//console.log('elementChanged',opts);
|
||||
var elem = opts.elems[0];
|
||||
if (elem && (
|
||||
elem.getAttribute("marker-start") ||
|
||||
elem.getAttribute("marker-mid") ||
|
||||
elem.getAttribute("marker-end")
|
||||
)) {
|
||||
colorChanged(elem);
|
||||
updateReferences(elem);
|
||||
elementChanged: function (opts) {
|
||||
// console.log('elementChanged',opts);
|
||||
var elem = opts.elems[0];
|
||||
if (elem && (
|
||||
elem.getAttribute('marker-start') ||
|
||||
elem.getAttribute('marker-mid') ||
|
||||
elem.getAttribute('marker-end')
|
||||
)) {
|
||||
colorChanged(elem);
|
||||
updateReferences(elem);
|
||||
}
|
||||
// changing_flag = false; // Not apparently in use
|
||||
}
|
||||
// changing_flag = false; // Not apparently in use
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals MathJax, svgEditor, svgCanvas, $*/
|
||||
/*jslint es5: true, todo: true, vars: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals MathJax, svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-mathjax.js
|
||||
*
|
||||
@@ -9,265 +9,256 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("mathjax", function() {'use strict';
|
||||
// Configuration of the MathJax extention.
|
||||
svgEditor.addExtension('mathjax', function () {
|
||||
'use strict';
|
||||
// Configuration of the MathJax extention.
|
||||
|
||||
// This will be added to the head tag before MathJax is loaded.
|
||||
var /*mathjaxConfiguration = '<script type="text/x-mathjax-config">\
|
||||
MathJax.Hub.Config({\
|
||||
extensions: ["tex2jax.js"],\
|
||||
jax: ["input/TeX","output/SVG"],\
|
||||
showProcessingMessages: true,\
|
||||
showMathMenu: false,\
|
||||
showMathMenuMSIE: false,\
|
||||
errorSettings: {\
|
||||
message: ["[Math Processing Error]"],\
|
||||
style: {color: "#CC0000", "font-style":"italic"}\
|
||||
},\
|
||||
elements: [],\
|
||||
tex2jax: {\
|
||||
ignoreClass: "tex2jax_ignore2", processClass: "tex2jax_process2",\
|
||||
},\
|
||||
TeX: {\
|
||||
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]\
|
||||
},\
|
||||
"SVG": {\
|
||||
}\
|
||||
});\
|
||||
</script>',*/
|
||||
// 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',
|
||||
math,
|
||||
locationX,
|
||||
locationY,
|
||||
mathjaxLoaded = false,
|
||||
uiStrings = svgEditor.uiStrings;
|
||||
// This will be added to the head tag before MathJax is loaded.
|
||||
var /* mathjaxConfiguration = '<script type="text/x-mathjax-config">\
|
||||
MathJax.Hub.Config({\
|
||||
extensions: ["tex2jax.js"],\
|
||||
jax: ["input/TeX","output/SVG"],\
|
||||
showProcessingMessages: true,\
|
||||
showMathMenu: false,\
|
||||
showMathMenuMSIE: false,\
|
||||
errorSettings: {\
|
||||
message: ["[Math Processing Error]"],\
|
||||
style: {color: "#CC0000", "font-style":"italic"}\
|
||||
},\
|
||||
elements: [],\
|
||||
tex2jax: {\
|
||||
ignoreClass: "tex2jax_ignore2", processClass: "tex2jax_process2",\
|
||||
},\
|
||||
TeX: {\
|
||||
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]\
|
||||
},\
|
||||
"SVG": {\
|
||||
}\
|
||||
});\
|
||||
</script>', */
|
||||
// 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',
|
||||
math,
|
||||
locationX,
|
||||
locationY,
|
||||
mathjaxLoaded = false,
|
||||
uiStrings = svgEditor.uiStrings;
|
||||
|
||||
// TODO: Implement language support. Move these uiStrings to the locale files and the code to the langReady callback.
|
||||
$.extend(uiStrings, {
|
||||
mathjax: {
|
||||
embed_svg: 'Save as mathematics',
|
||||
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. ',
|
||||
mathml_save_warning: 'Advised. The math will be saved as a figure.',
|
||||
title: 'Mathematics code editor'
|
||||
}
|
||||
});
|
||||
// TODO: Implement language support. Move these uiStrings to the locale files and the code to the langReady callback.
|
||||
$.extend(uiStrings, {
|
||||
mathjax: {
|
||||
embed_svg: 'Save as mathematics',
|
||||
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. ',
|
||||
mathml_save_warning: 'Advised. The math will be saved as a figure.',
|
||||
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();
|
||||
// displaystyle to force MathJax NOT to use the inline style. Because it is
|
||||
// less fancy!
|
||||
MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']);
|
||||
/*
|
||||
* The MathJax library doesn't want to bloat your webpage so it creates
|
||||
* every symbol (glymph) you need only once. These are saved in a <svg> on
|
||||
* the top of your html document, just under the body tag. Each glymph has
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* The MathJax library doesn't want to bloat your webpage so it creates
|
||||
* every symbol (glymph) you need only once. These are saved in a <svg> on
|
||||
* the top of your html document, just under the body tag. Each glymph has
|
||||
* 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.
|
||||
if ($(this).attr('href')) {
|
||||
id = $(this).attr('href').slice(1); // Works in Chrome.
|
||||
} else {
|
||||
id = $(this).attr('xlink:href').slice(1); // Works in Firefox.
|
||||
}
|
||||
|
||||
// TODO: find a less pragmatic and more elegant solution to this.
|
||||
if ($(this).attr('href')) {
|
||||
id = $(this).attr('href').slice(1); // Works in Chrome.
|
||||
} else {
|
||||
id = $(this).attr('xlink:href').slice(1); // Works in Firefox.
|
||||
}
|
||||
var glymph = $('#' + id).clone().removeAttr('id');
|
||||
x = $(this).attr('x');
|
||||
y = $(this).attr('y');
|
||||
transform = $(this).attr('transform');
|
||||
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');
|
||||
x = $(this).attr('x');
|
||||
y = $(this).attr('y');
|
||||
transform = $(this).attr('transform');
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
return {
|
||||
name: 'MathJax',
|
||||
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">' +
|
||||
'<!-- Here is where MathJax creates the math -->' +
|
||||
'<div id="mathjax_creator" class="tex2jax_process" style="display:none">' +
|
||||
'$${}$$' +
|
||||
'</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();
|
||||
|
||||
return {
|
||||
name: "MathJax",
|
||||
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) {
|
||||
// Make the MathEditor draggable.
|
||||
$('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'});
|
||||
|
||||
$('<div id="mathjax">\
|
||||
<!-- Here is where MathJax creates the math -->\
|
||||
<div id="mathjax_creator" class="tex2jax_process" style="display:none">\
|
||||
$${}$$\
|
||||
</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();
|
||||
// Add functionality and picture to cancel button.
|
||||
$('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true))
|
||||
.on('click touched', function () {
|
||||
$('#mathjax').hide();
|
||||
});
|
||||
|
||||
// Make the MathEditor draggable.
|
||||
$('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'});
|
||||
// Add functionality and picture to the save button.
|
||||
$('#tool_mathjax_save').prepend($.getSvgIcon('ok', true))
|
||||
.on('click touched', function () {
|
||||
saveMath();
|
||||
$('#mathjax').hide();
|
||||
});
|
||||
|
||||
// Add functionality and picture to cancel button.
|
||||
$('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true))
|
||||
.on("click touched", function() {
|
||||
$('#mathjax').hide();
|
||||
});
|
||||
// MathJax preprocessing has to ignore most of the page.
|
||||
$('body').addClass('tex2jax_ignore');
|
||||
|
||||
// Add functionality and picture to the save button.
|
||||
$('#tool_mathjax_save').prepend($.getSvgIcon('ok', true))
|
||||
.on("click touched", function() {
|
||||
saveMath();
|
||||
$('#mathjax').hide();
|
||||
});
|
||||
// Now get (and run) the MathJax Library.
|
||||
$.getScript(mathjaxSrcSecure)
|
||||
.done(function (script, textStatus) {
|
||||
// When MathJax is loaded get the div where the math will be rendered.
|
||||
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.
|
||||
$('body').addClass('tex2jax_ignore');
|
||||
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;
|
||||
|
||||
// Now get (and run) the MathJax Library.
|
||||
$.getScript(mathjaxSrcSecure)
|
||||
.done(function(script, textStatus) {
|
||||
$('#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');
|
||||
|
||||
// When MathJax is loaded get the div where the math will be rendered.
|
||||
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");
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
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');
|
||||
}
|
||||
};
|
||||
// Add the MathJax configuration.
|
||||
// $(mathjaxConfiguration).appendTo('head');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, $ */
|
||||
/*jslint es5: true, vars: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, $ */
|
||||
/*
|
||||
* ext-overview_window.js
|
||||
*
|
||||
@@ -10,11 +10,12 @@
|
||||
*/
|
||||
|
||||
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
|
||||
// https://code.google.com/p/chromium/issues/detail?id=565120.
|
||||
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);
|
||||
if (chromeVersion < 49) {
|
||||
return;
|
||||
@@ -22,130 +23,129 @@ svgEditor.addExtension("overview_window", function() { 'use strict';
|
||||
}
|
||||
|
||||
// Define and insert the base html element.
|
||||
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\" style=\"position:relative; left:12px; top:0px;\">\
|
||||
<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\">\
|
||||
<use x=\"0\" y=\"0\" xlink:href=\"#svgroot\"> </use>\
|
||||
</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>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>";
|
||||
$("#sidepanels").append(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" style="position:relative; left:12px; top:0px;">' +
|
||||
'<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">' +
|
||||
'<use x="0" y="0" xlink:href="#svgroot"> </use>' +
|
||||
'</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>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
$('#sidepanels').append(propsWindowHtml);
|
||||
|
||||
// Define dynamic animation of the view box.
|
||||
var updateViewBox = function(){
|
||||
var portHeight=parseFloat($("#workarea").css("height"));
|
||||
var portWidth=parseFloat($("#workarea").css("width"));
|
||||
var portX=$("#workarea").scrollLeft();
|
||||
var portY=$("#workarea").scrollTop();
|
||||
var windowWidth=parseFloat($("#svgcanvas").css("width"));
|
||||
var windowHeight=parseFloat($("#svgcanvas").css("height"));
|
||||
var overviewWidth=$("#overviewMiniView").attr("width");
|
||||
var overviewHeight=$("#overviewMiniView").attr("height");
|
||||
|
||||
var viewBoxX=portX/windowWidth*overviewWidth;
|
||||
var viewBoxY=portY/windowHeight*overviewHeight;
|
||||
var viewBoxWidth=portWidth/windowWidth*overviewWidth;
|
||||
var viewBoxHeight=portHeight/windowHeight*overviewHeight;
|
||||
|
||||
$("#overview_window_view_box").css("min-width",viewBoxWidth+"px");
|
||||
$("#overview_window_view_box").css("min-height",viewBoxHeight+"px");
|
||||
$("#overview_window_view_box").css("top",viewBoxY+"px");
|
||||
$("#overview_window_view_box").css("left",viewBoxX+"px");
|
||||
var updateViewBox = function () {
|
||||
var portHeight = parseFloat($('#workarea').css('height'));
|
||||
var portWidth = parseFloat($('#workarea').css('width'));
|
||||
var portX = $('#workarea').scrollLeft();
|
||||
var portY = $('#workarea').scrollTop();
|
||||
var windowWidth = parseFloat($('#svgcanvas').css('width'));
|
||||
var windowHeight = parseFloat($('#svgcanvas').css('height'));
|
||||
var overviewWidth = $('#overviewMiniView').attr('width');
|
||||
var overviewHeight = $('#overviewMiniView').attr('height');
|
||||
|
||||
var viewBoxX = portX / windowWidth * overviewWidth;
|
||||
var viewBoxY = portY / windowHeight * overviewHeight;
|
||||
var viewBoxWidth = portWidth / windowWidth * overviewWidth;
|
||||
var viewBoxHeight = portHeight / windowHeight * overviewHeight;
|
||||
|
||||
$('#overview_window_view_box').css('min-width', viewBoxWidth + 'px');
|
||||
$('#overview_window_view_box').css('min-height', viewBoxHeight + 'px');
|
||||
$('#overview_window_view_box').css('top', viewBoxY + 'px');
|
||||
$('#overview_window_view_box').css('left', viewBoxX + 'px');
|
||||
};
|
||||
$("#workarea").scroll(function(){
|
||||
if(!(overviewWindowGlobals.viewBoxDragging)){
|
||||
$('#workarea').scroll(function () {
|
||||
if (!(overviewWindowGlobals.viewBoxDragging)) {
|
||||
updateViewBox();
|
||||
}
|
||||
});
|
||||
$("#workarea").resize(updateViewBox);
|
||||
$('#workarea').resize(updateViewBox);
|
||||
updateViewBox();
|
||||
|
||||
|
||||
// Compensate for changes in zoom and canvas size.
|
||||
var updateViewDimensions= function(){
|
||||
var viewWidth=$("#svgroot").attr("width");
|
||||
var viewHeight=$("#svgroot").attr("height");
|
||||
var viewX=640;
|
||||
var viewY=480;
|
||||
|
||||
if(svgedit.browser.isIE())
|
||||
{
|
||||
var updateViewDimensions = function () {
|
||||
var viewWidth = $('#svgroot').attr('width');
|
||||
var viewHeight = $('#svgroot').attr('height');
|
||||
var viewX = 640;
|
||||
var viewY = 480;
|
||||
|
||||
if (svgedit.browser.isIE()) {
|
||||
// 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.
|
||||
// Either way the one that is noncompliant may become more compliant later.
|
||||
//TAG:HACK
|
||||
//TAG:VERSION_DEPENDENT
|
||||
//TAG:BROWSER_SNIFFING
|
||||
viewX=0;
|
||||
viewY=0;
|
||||
// TAG:HACK
|
||||
// TAG:VERSION_DEPENDENT
|
||||
// TAG:BROWSER_SNIFFING
|
||||
viewX = 0;
|
||||
viewY = 0;
|
||||
}
|
||||
|
||||
var svgWidth_old=$("#overviewMiniView").attr("width");
|
||||
var svgHeight_new=viewHeight/viewWidth*svgWidth_old;
|
||||
$("#overviewMiniView").attr("viewBox",viewX+" "+viewY+" "+viewWidth+" "+viewHeight);
|
||||
$("#overviewMiniView").attr("height",svgHeight_new);
|
||||
|
||||
var svgWidthOld = $('#overviewMiniView').attr('width');
|
||||
var svgHeightNew = viewHeight / viewWidth * svgWidthOld;
|
||||
$('#overviewMiniView').attr('viewBox', viewX + ' ' + viewY + ' ' + viewWidth + ' ' + viewHeight);
|
||||
$('#overviewMiniView').attr('height', svgHeightNew);
|
||||
updateViewBox();
|
||||
};
|
||||
updateViewDimensions();
|
||||
|
||||
// Set up the overview window as a controller for the view port.
|
||||
overviewWindowGlobals.viewBoxDragging=false;
|
||||
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 portX=viewBoxX/overviewWidth *windowWidth;
|
||||
var portY=viewBoxY/overviewHeight*windowHeight;
|
||||
|
||||
$("#workarea").scrollLeft(portX);
|
||||
$("#workarea").scrollTop(portY);
|
||||
// Set up the overview window as a controller for the view port.
|
||||
overviewWindowGlobals.viewBoxDragging = false;
|
||||
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 portX = viewBoxX / overviewWidth * windowWidth;
|
||||
var portY = viewBoxY / overviewHeight * windowHeight;
|
||||
|
||||
$('#workarea').scrollLeft(portX);
|
||||
$('#workarea').scrollTop(portY);
|
||||
};
|
||||
$( "#overview_window_view_box" ).draggable({ containment: "parent"
|
||||
,drag: updateViewPortFromViewBox
|
||||
,start:function(){overviewWindowGlobals.viewBoxDragging=true; }
|
||||
,stop :function(){overviewWindowGlobals.viewBoxDragging=false;}
|
||||
});
|
||||
$("#overviewMiniView").click(function(evt){
|
||||
$('#overview_window_view_box').draggable({
|
||||
containment: 'parent',
|
||||
drag: updateViewPortFromViewBox,
|
||||
start: function () { overviewWindowGlobals.viewBoxDragging = true; },
|
||||
stop: function () { overviewWindowGlobals.viewBoxDragging = false; }
|
||||
});
|
||||
$('#overviewMiniView').click(function (evt) {
|
||||
// Firefox doesn't support evt.offsetX and evt.offsetY.
|
||||
var mouseX=(evt.offsetX || evt.originalEvent.layerX);
|
||||
var mouseY=(evt.offsetY || evt.originalEvent.layerY);
|
||||
var overviewWidth =$("#overviewMiniView").attr("width" );
|
||||
var overviewHeight=$("#overviewMiniView").attr("height");
|
||||
var viewBoxWidth =parseFloat($("#overview_window_view_box").css("min-width" ));
|
||||
var viewBoxHeight=parseFloat($("#overview_window_view_box").css("min-height"));
|
||||
|
||||
var viewBoxX=mouseX - 0.5 * viewBoxWidth;
|
||||
var viewBoxY=mouseY- 0.5 * viewBoxHeight;
|
||||
//deal with constraints
|
||||
if(viewBoxX<0){
|
||||
viewBoxX=0;
|
||||
var mouseX = (evt.offsetX || evt.originalEvent.layerX);
|
||||
var mouseY = (evt.offsetY || evt.originalEvent.layerY);
|
||||
var overviewWidth = $('#overviewMiniView').attr('width');
|
||||
var overviewHeight = $('#overviewMiniView').attr('height');
|
||||
var viewBoxWidth = parseFloat($('#overview_window_view_box').css('min-width'));
|
||||
var viewBoxHeight = parseFloat($('#overview_window_view_box').css('min-height'));
|
||||
|
||||
var viewBoxX = mouseX - 0.5 * viewBoxWidth;
|
||||
var viewBoxY = mouseY - 0.5 * viewBoxHeight;
|
||||
// deal with constraints
|
||||
if (viewBoxX < 0) {
|
||||
viewBoxX = 0;
|
||||
}
|
||||
if(viewBoxY<0){
|
||||
viewBoxY=0;
|
||||
if (viewBoxY < 0) {
|
||||
viewBoxY = 0;
|
||||
}
|
||||
if(viewBoxX+viewBoxWidth>overviewWidth){
|
||||
viewBoxX=overviewWidth-viewBoxWidth;
|
||||
if (viewBoxX + viewBoxWidth > overviewWidth) {
|
||||
viewBoxX = overviewWidth - viewBoxWidth;
|
||||
}
|
||||
if(viewBoxY+viewBoxHeight>overviewHeight){
|
||||
viewBoxY=overviewHeight-viewBoxHeight;
|
||||
if (viewBoxY + viewBoxHeight > overviewHeight) {
|
||||
viewBoxY = overviewHeight - viewBoxHeight;
|
||||
}
|
||||
|
||||
$("#overview_window_view_box").css("top",viewBoxY+"px");
|
||||
$("#overview_window_view_box").css("left",viewBoxX+"px");
|
||||
|
||||
$('#overview_window_view_box').css('top', viewBoxY + 'px');
|
||||
$('#overview_window_view_box').css('left', viewBoxX + 'px');
|
||||
updateViewPortFromViewBox();
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
name: "overview window",
|
||||
name: 'overview window',
|
||||
canvasUpdated: updateViewDimensions,
|
||||
workareaResized: updateViewBox
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/*globals svgEditor, svgCanvas*/
|
||||
/*jslint eqeq: true*/
|
||||
/* globals svgEditor, svgCanvas */
|
||||
/*
|
||||
* ext-panning.js
|
||||
*
|
||||
@@ -8,12 +7,13 @@
|
||||
* Copyright(c) 2013 Luis Aguirre
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
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 {
|
||||
name: 'Extension Panning',
|
||||
svgicons: svgEditor.curConfig.extPath + 'ext-panning.xml',
|
||||
@@ -22,19 +22,19 @@ svgEditor.addExtension('ext-panning', function() {'use strict';
|
||||
type: 'mode',
|
||||
title: 'Panning',
|
||||
events: {
|
||||
click: function() {
|
||||
click: function () {
|
||||
svgCanvas.setMode('ext-panning');
|
||||
}
|
||||
}
|
||||
}],
|
||||
mouseDown: function() {
|
||||
if (svgCanvas.getMode() == 'ext-panning') {
|
||||
mouseDown: function () {
|
||||
if (svgCanvas.getMode() === 'ext-panning') {
|
||||
svgEditor.setPanning(true);
|
||||
return {started: true};
|
||||
}
|
||||
},
|
||||
mouseUp: function() {
|
||||
if (svgCanvas.getMode() == 'ext-panning') {
|
||||
mouseUp: function () {
|
||||
if (svgCanvas.getMode() === 'ext-panning') {
|
||||
svgEditor.setPanning(false);
|
||||
return {
|
||||
keep: false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<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">
|
||||
<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>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 732 B After Width: | Height: | Size: 724 B |
@@ -1,22 +1,22 @@
|
||||
/*globals $, svgCanvas, svgEditor*/
|
||||
/*jslint regexp:true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, svgCanvas, svgEditor */
|
||||
// TODO: Might add support for "exportImage" custom
|
||||
// handler as in "ext-server_opensave.js" (and in savefile.php)
|
||||
|
||||
svgEditor.addExtension("php_savefile", {
|
||||
callback: function() {
|
||||
svgEditor.addExtension('php_savefile', {
|
||||
callback: function () {
|
||||
'use strict';
|
||||
function getFileNameFromTitle () {
|
||||
var title = svgCanvas.getDocumentTitle();
|
||||
return $.trim(title);
|
||||
}
|
||||
var save_svg_action = svgEditor.curConfig.extPath + 'savefile.php';
|
||||
var saveSvgAction = svgEditor.curConfig.extPath + 'savefile.php';
|
||||
svgEditor.setCustomHandlers({
|
||||
save: function(win, data) {
|
||||
save: function (win, data) {
|
||||
var svg = '<?xml version="1.0" encoding="UTF-8"?>\n' + data,
|
||||
filename = getFileNameFromTitle();
|
||||
|
||||
$.post(save_svg_action, {output_svg: svg, filename: filename});
|
||||
$.post(saveSvgAction, {output_svg: svg, filename: filename});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgCanvas, svgedit, $*/
|
||||
/*jslint vars: true, eqeq: true, todo: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* ext-polygon.js
|
||||
*
|
||||
@@ -8,9 +8,10 @@
|
||||
* 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,
|
||||
// addElem = S.addSvgElementFromJson,
|
||||
selElems,
|
||||
@@ -18,53 +19,51 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
|
||||
// svgdoc = S.svgroot.parentNode.ownerDocument,
|
||||
// newFOG, newFOGParent, newDef, newImageName, newMaskID, modeChangeG,
|
||||
// edg = 0,
|
||||
// undoCommand = "Not image";
|
||||
// undoCommand = 'Not image';
|
||||
started, newFO;
|
||||
|
||||
// var ccZoom;
|
||||
// var wEl, hEl;
|
||||
// var wOffset, hOffset;
|
||||
// var ccRBG;
|
||||
var ccRgbEl;
|
||||
// var ccOpacity;
|
||||
// var brushW, brushH;
|
||||
var shape;
|
||||
|
||||
// var ccDebug = document.getElementById('debugpanel');
|
||||
|
||||
/* var properlySourceSizeTextArea = function(){
|
||||
// TODO: remove magic numbers here and get values from CSS
|
||||
var height = $('#svg_source_container').height() - 80;
|
||||
$('#svg_source_textarea').css('height', height);
|
||||
}; */
|
||||
function showPanel(on){
|
||||
var fc_rules = $('#fc_rules');
|
||||
if (!fc_rules.length) {
|
||||
fc_rules = $('<style id="fc_rules"></style>').appendTo('head');
|
||||
}
|
||||
fc_rules.text(!on ? "" : " #tool_topath { display: none !important; }");
|
||||
$('#polygon_panel').toggle(on);
|
||||
}
|
||||
|
||||
|
||||
// var ccZoom;
|
||||
// var wEl, hEl;
|
||||
// var wOffset, hOffset;
|
||||
// var ccRBG;
|
||||
// var ccOpacity;
|
||||
// var brushW, brushH;
|
||||
|
||||
// var ccDebug = document.getElementById('debugpanel');
|
||||
|
||||
/* var properlySourceSizeTextArea = function(){
|
||||
// TODO: remove magic numbers here and get values from CSS
|
||||
var height = $('#svg_source_container').height() - 80;
|
||||
$('#svg_source_textarea').css('height', height);
|
||||
}; */
|
||||
function showPanel (on) {
|
||||
var fcRules = $('#fc_rules');
|
||||
if (!fcRules.length) {
|
||||
fcRules = $('<style id="fc_rules"></style>').appendTo('head');
|
||||
}
|
||||
fcRules.text(!on ? '' : ' #tool_topath { display: none !important; }');
|
||||
$('#polygon_panel').toggle(on);
|
||||
}
|
||||
|
||||
/*
|
||||
function toggleSourceButtons(on){
|
||||
$('#tool_source_save, #tool_source_cancel').toggle(!on);
|
||||
$('#polygon_save, #polygon_cancel').toggle(on);
|
||||
}
|
||||
function toggleSourceButtons(on){
|
||||
$('#tool_source_save, #tool_source_cancel').toggle(!on);
|
||||
$('#polygon_save, #polygon_cancel').toggle(on);
|
||||
}
|
||||
*/
|
||||
|
||||
function setAttr(attr, val){
|
||||
svgCanvas.changeSelectedAttribute(attr, val);
|
||||
S.call("changed", selElems);
|
||||
}
|
||||
|
||||
function cot(n){
|
||||
return 1 / Math.tan(n);
|
||||
}
|
||||
|
||||
function sec(n){
|
||||
return 1 / Math.cos(n);
|
||||
}
|
||||
|
||||
function setAttr (attr, val) {
|
||||
svgCanvas.changeSelectedAttribute(attr, val);
|
||||
S.call('changed', selElems);
|
||||
}
|
||||
|
||||
function cot (n) {
|
||||
return 1 / Math.tan(n);
|
||||
}
|
||||
|
||||
function sec (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
|
||||
@@ -95,13 +94,13 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
|
||||
$.post(ajaxEndpoint, {'tex': tex, 'display': 'inline'}, function(data){
|
||||
var children = data.documentElement.childNodes;
|
||||
while (children.length > 0) {
|
||||
mrow.appendChild(svgdoc.adoptNode(children[0], true));
|
||||
mrow.appendChild(svgdoc.adoptNode(children[0], true));
|
||||
}
|
||||
S.sanitizeSvg(math);
|
||||
S.call("changed", [elt]);
|
||||
S.call('changed', [elt]);
|
||||
});
|
||||
elt.replaceChild(math, elt.firstChild);
|
||||
S.call("changed", [elt]);
|
||||
S.call('changed', [elt]);
|
||||
svgCanvas.clearSelection();
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
@@ -111,184 +110,177 @@ svgEditor.addExtension("polygon", function(S) {'use strict';
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
return {
|
||||
name: "polygon",
|
||||
svgicons: svgEditor.curConfig.extPath + "polygon-icons.svg",
|
||||
buttons: [{
|
||||
id: "tool_polygon",
|
||||
type: "mode",
|
||||
title: "Polygon Tool",
|
||||
position: 11,
|
||||
events: {
|
||||
'click': function(){
|
||||
svgCanvas.setMode('polygon');
|
||||
return {
|
||||
name: 'polygon',
|
||||
svgicons: svgEditor.curConfig.extPath + 'polygon-icons.svg',
|
||||
buttons: [{
|
||||
id: 'tool_polygon',
|
||||
type: 'mode',
|
||||
title: 'Polygon Tool',
|
||||
position: 11,
|
||||
events: {
|
||||
'click': function () {
|
||||
svgCanvas.setMode('polygon');
|
||||
showPanel(true);
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
context_tools: [{
|
||||
type: "input",
|
||||
panel: "polygon_panel",
|
||||
title: "Number of Sides",
|
||||
id: "polySides",
|
||||
label: "sides",
|
||||
size: 3,
|
||||
defval: 5,
|
||||
events: {
|
||||
change: function(){
|
||||
setAttr('sides', this.value);
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
callback: function(){
|
||||
|
||||
$('#polygon_panel').hide();
|
||||
|
||||
var endChanges = function(){
|
||||
};
|
||||
|
||||
// TODO: Needs to be done after orig icon loads
|
||||
setTimeout(function(){
|
||||
// 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) {
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
context_tools: [{
|
||||
type: 'input',
|
||||
panel: 'polygon_panel',
|
||||
title: 'Number of Sides',
|
||||
id: 'polySides',
|
||||
label: 'sides',
|
||||
size: 3,
|
||||
defval: 5,
|
||||
events: {
|
||||
change: function () {
|
||||
setAttr('sides', this.value);
|
||||
}
|
||||
}
|
||||
}],
|
||||
|
||||
callback: function () {
|
||||
$('#polygon_panel').hide();
|
||||
|
||||
var endChanges = function () {
|
||||
};
|
||||
|
||||
// TODO: Needs to be done after orig icon loads
|
||||
setTimeout(function () {
|
||||
// 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;
|
||||
}
|
||||
// Todo: Uncomment the setItexString() function above and handle ajaxEndpoint?
|
||||
if (!setItexString($('#svg_source_textarea').val())) {
|
||||
$.confirm("Errors found. Revert to original?", function(ok){
|
||||
if (!ok) {
|
||||
/*
|
||||
if (!setItexString($('#svg_source_textarea').val())) {
|
||||
$.confirm('Errors found. Revert to original?', function (ok) {
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
endChanges();
|
||||
});
|
||||
}
|
||||
else {
|
||||
endChanges();
|
||||
}
|
||||
// setSelectMode();
|
||||
});
|
||||
|
||||
var cancel = $('#tool_source_cancel').clone().hide().attr('id', 'polygon_cancel').unbind().appendTo("#tool_source_back").click(function(){
|
||||
endChanges();
|
||||
});
|
||||
|
||||
}, 3000);
|
||||
},
|
||||
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") {
|
||||
started = true;
|
||||
|
||||
newFO = S.addSvgElementFromJson({
|
||||
"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
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
},
|
||||
mouseMove: function(opts){
|
||||
if (!started) {
|
||||
return;
|
||||
endChanges();
|
||||
});
|
||||
} else { */
|
||||
endChanges();
|
||||
// }
|
||||
// setSelectMode();
|
||||
});
|
||||
|
||||
/* var cancel = */ $('#tool_source_cancel').clone().hide().attr('id', 'polygon_cancel').unbind().appendTo('#tool_source_back').click(function () {
|
||||
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();
|
||||
|
||||
if (svgCanvas.getMode() === 'polygon') {
|
||||
started = true;
|
||||
|
||||
newFO = S.addSvgElementFromJson({
|
||||
'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
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
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,
|
||||
},
|
||||
mouseMove: function (opts) {
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
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,
|
||||
edg = (Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))) / 1.5;
|
||||
newFO.setAttributeNS(null, "edge", edg);
|
||||
|
||||
var inradius = (edg / 2) * cot(Math.PI / sides);
|
||||
var circumradius = inradius * sec(Math.PI / sides);
|
||||
var points = '';
|
||||
newFO.setAttributeNS(null, 'edge', edg);
|
||||
|
||||
var inradius = (edg / 2) * cot(Math.PI / sides);
|
||||
var circumradius = inradius * sec(Math.PI / sides);
|
||||
var points = '';
|
||||
var s;
|
||||
for (s = 0; sides >= s; s++) {
|
||||
var angle = 2.0 * Math.PI * s / sides;
|
||||
x = (circumradius * Math.cos(angle)) + cx;
|
||||
y = (circumradius * Math.sin(angle)) + cy;
|
||||
|
||||
points += x + ',' + y + ' ';
|
||||
}
|
||||
|
||||
//var poly = newFO.createElementNS(NS.SVG, 'polygon');
|
||||
newFO.setAttributeNS(null, 'points', points);
|
||||
newFO.setAttributeNS(null, 'fill', fill);
|
||||
newFO.setAttributeNS(null, 'stroke', strokecolor);
|
||||
newFO.setAttributeNS(null, 'stroke-width', strokewidth);
|
||||
// newFO.setAttributeNS(null, 'transform', "rotate(-90)");
|
||||
shape = newFO.getAttributeNS(null, 'shape');
|
||||
//newFO.appendChild(poly);
|
||||
//DrawPoly(cx, cy, sides, edg, orient);
|
||||
return {
|
||||
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;
|
||||
|
||||
var i = selElems.length;
|
||||
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if (elem && elem.getAttributeNS(null, 'shape') === 'regularPoly') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
$('#polySides').val(elem.getAttribute("sides"));
|
||||
|
||||
showPanel(true);
|
||||
}
|
||||
else {
|
||||
showPanel(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
showPanel(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
elementChanged: function(opts){
|
||||
// var elem = opts.elems[0];
|
||||
}
|
||||
};
|
||||
for (s = 0; sides >= s; s++) {
|
||||
var angle = 2.0 * Math.PI * s / sides;
|
||||
x = (circumradius * Math.cos(angle)) + cx;
|
||||
y = (circumradius * Math.sin(angle)) + cy;
|
||||
|
||||
points += x + ',' + y + ' ';
|
||||
}
|
||||
|
||||
// var poly = newFO.createElementNS(NS.SVG, 'polygon');
|
||||
newFO.setAttributeNS(null, 'points', points);
|
||||
newFO.setAttributeNS(null, 'fill', fill);
|
||||
newFO.setAttributeNS(null, 'stroke', strokecolor);
|
||||
newFO.setAttributeNS(null, 'stroke-width', strokewidth);
|
||||
// newFO.setAttributeNS(null, 'transform', 'rotate(-90)');
|
||||
// var shape = newFO.getAttributeNS(null, 'shape');
|
||||
// newFO.appendChild(poly);
|
||||
// DrawPoly(cx, cy, sides, edg, orient);
|
||||
return {
|
||||
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;
|
||||
|
||||
var i = selElems.length;
|
||||
|
||||
while (i--) {
|
||||
var elem = selElems[i];
|
||||
if (elem && elem.getAttributeNS(null, 'shape') === 'regularPoly') {
|
||||
if (opts.selectedElement && !opts.multiselected) {
|
||||
$('#polySides').val(elem.getAttribute('sides'));
|
||||
|
||||
showPanel(true);
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
elementChanged: function (opts) {
|
||||
// var elem = opts.elems[0];
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, svgCanvas, canvg, $, top*/
|
||||
/*jslint vars: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, svgCanvas, canvg, $, top */
|
||||
/*
|
||||
* ext-server_moinsave.js
|
||||
*
|
||||
@@ -12,48 +12,47 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("server_opensave", {
|
||||
callback: function() {'use strict';
|
||||
svgEditor.addExtension('server_opensave', {
|
||||
callback: function () {
|
||||
'use strict';
|
||||
var Utils = svgedit.utilities;
|
||||
var save_svg_action = '/+modify';
|
||||
|
||||
var saveSvgAction = '/+modify';
|
||||
|
||||
// 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({
|
||||
save: function(win, data) {
|
||||
var svg = "<?xml version=\"1.0\"?>\n" + data;
|
||||
save: function (win, data) {
|
||||
var svg = '<?xml version="1.0"?>\n' + data;
|
||||
var qstr = $.param.querystring();
|
||||
var name = qstr.substr(9).split('/+get/')[1];
|
||||
var svg_data = Utils.encode64(svg);
|
||||
if(!$('#export_canvas').length) {
|
||||
var svgData = Utils.encode64(svg);
|
||||
if (!$('#export_canvas').length) {
|
||||
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
|
||||
}
|
||||
var c = $('#export_canvas')[0];
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
Utils.buildCanvgCallback(function () {
|
||||
canvg(c, svg, {renderCallback: function() {
|
||||
canvg(c, svg, {renderCallback: function () {
|
||||
var datauri = c.toDataURL('image/png');
|
||||
// var uiStrings = svgEditor.uiStrings;
|
||||
var png_data = Utils.encode64(datauri); // Brett: This encoding seems unnecessary
|
||||
var form = $('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_svg_action + '/' + name,
|
||||
target: 'output_frame'
|
||||
}).append('<input type="hidden" name="png_data" value="' + png_data + '">')
|
||||
.append('<input type="hidden" name="filepath" value="' + svg_data + '">')
|
||||
.append('<input type="hidden" name="filename" value="' + 'drawing.svg">')
|
||||
.append('<input type="hidden" name="contenttype" value="application/x-svgdraw">')
|
||||
.appendTo('body')
|
||||
.submit().remove();
|
||||
var pngData = Utils.encode64(datauri); // Brett: This encoding seems unnecessary
|
||||
/* var form = */ $('<form>').attr({
|
||||
method: 'post',
|
||||
action: saveSvgAction + '/' + name,
|
||||
target: 'output_frame'
|
||||
}).append('<input type="hidden" name="png_data" value="' + pngData + '">')
|
||||
.append('<input type="hidden" name="filepath" value="' + svgData + '">')
|
||||
.append('<input type="hidden" name="filename" value="' + 'drawing.svg">')
|
||||
.append('<input type="hidden" name="contenttype" value="application/x-svgdraw">')
|
||||
.appendTo('body')
|
||||
.submit().remove();
|
||||
}});
|
||||
})();
|
||||
alert("Saved! Return to Item View!");
|
||||
top.window.location = '/'+name;
|
||||
alert('Saved! Return to Item View!');
|
||||
top.window.location = '/' + name;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, svgCanvas, canvg, $*/
|
||||
/*jslint eqeq: true, browser:true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgedit, svgCanvas, canvg, $ */
|
||||
/*
|
||||
* ext-server_opensave.js
|
||||
*
|
||||
@@ -9,15 +9,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension("server_opensave", {
|
||||
callback: function() {
|
||||
svgEditor.addExtension('server_opensave', {
|
||||
callback: function () {
|
||||
'use strict';
|
||||
function getFileNameFromTitle () {
|
||||
var title = svgCanvas.getDocumentTitle();
|
||||
// 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, '&').replace(/"/g, '"').replace(/</g, '<'); // < is actually disallowed above anyways
|
||||
}
|
||||
function clientDownloadSupport (filename, suffix, uri) {
|
||||
@@ -29,17 +29,17 @@ svgEditor.addExtension("server_opensave", {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var open_svg_action, import_svg_action, import_img_action,
|
||||
open_svg_form, import_svg_form, import_img_form,
|
||||
save_svg_action = svgEditor.curConfig.extPath + 'filesave.php',
|
||||
save_img_action = svgEditor.curConfig.extPath + 'filesave.php',
|
||||
var openSvgAction, importSvgAction, importImgAction,
|
||||
openSvgForm, importSvgForm, importImgForm,
|
||||
saveSvgAction = svgEditor.curConfig.extPath + 'filesave.php',
|
||||
saveImgAction = svgEditor.curConfig.extPath + 'filesave.php',
|
||||
// Create upload target (hidden iframe)
|
||||
cancelled = false,
|
||||
Utils = svgedit.utilities;
|
||||
|
||||
|
||||
$('<iframe name="output_frame" src="#"/>').hide().appendTo('body');
|
||||
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
|
||||
filename = getFileNameFromTitle();
|
||||
|
||||
@@ -49,7 +49,7 @@ svgEditor.addExtension("server_opensave", {
|
||||
|
||||
$('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_svg_action,
|
||||
action: saveSvgAction,
|
||||
target: 'output_frame'
|
||||
}).append('<input type="hidden" name="output_svg" value="' + xhtmlEscape(svg) + '">')
|
||||
.append('<input type="hidden" name="filename" value="' + xhtmlEscape(filename) + '">')
|
||||
@@ -64,7 +64,7 @@ svgEditor.addExtension("server_opensave", {
|
||||
}
|
||||
$('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_img_action,
|
||||
action: saveImgAction,
|
||||
target: 'output_frame'
|
||||
}).append('<input type="hidden" name="output_img" value="' + datauri + '">')
|
||||
.append('<input type="hidden" name="mime" value="application/pdf">')
|
||||
@@ -73,46 +73,46 @@ svgEditor.addExtension("server_opensave", {
|
||||
.submit().remove();
|
||||
},
|
||||
// Todo: Integrate this extension with a new built-in exportWindowType, "download"
|
||||
exportImage: function(win, data) {
|
||||
exportImage: function (win, data) {
|
||||
var c,
|
||||
issues = data.issues,
|
||||
mimeType = data.mimeType,
|
||||
quality = data.quality;
|
||||
|
||||
if(!$('#export_canvas').length) {
|
||||
|
||||
if (!$('#export_canvas').length) {
|
||||
$('<canvas>', {id: 'export_canvas'}).hide().appendTo('body');
|
||||
}
|
||||
c = $('#export_canvas')[0];
|
||||
|
||||
|
||||
c.width = svgCanvas.contentW;
|
||||
c.height = svgCanvas.contentH;
|
||||
Utils.buildCanvgCallback(function () {
|
||||
canvg(c, data.svg, {renderCallback: function() {
|
||||
canvg(c, data.svg, {renderCallback: function () {
|
||||
var pre, filename, suffix,
|
||||
datauri = quality ? c.toDataURL(mimeType, quality) : c.toDataURL(mimeType),
|
||||
// uiStrings = svgEditor.uiStrings,
|
||||
note = '';
|
||||
|
||||
|
||||
// Check if there are issues
|
||||
if (issues.length) {
|
||||
pre = "\n \u2022 ";
|
||||
note += ("\n\n" + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
if(note.length) {
|
||||
pre = '\n \u2022 ';
|
||||
note += ('\n\n' + pre + issues.join(pre));
|
||||
}
|
||||
|
||||
if (note.length) {
|
||||
alert(note);
|
||||
}
|
||||
|
||||
|
||||
filename = getFileNameFromTitle();
|
||||
suffix = '.' + data.type.toLowerCase();
|
||||
|
||||
|
||||
if (clientDownloadSupport(filename, suffix, datauri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('<form>').attr({
|
||||
method: 'post',
|
||||
action: save_img_action,
|
||||
action: saveImgAction,
|
||||
target: 'output_frame'
|
||||
}).append('<input type="hidden" name="output_img" value="' + datauri + '">')
|
||||
.append('<input type="hidden" name="mime" value="' + mimeType + '">')
|
||||
@@ -125,81 +125,80 @@ svgEditor.addExtension("server_opensave", {
|
||||
});
|
||||
|
||||
// Do nothing if client support is found
|
||||
if (window.FileReader) {return;}
|
||||
|
||||
if (window.FileReader) { return; }
|
||||
|
||||
// Change these to appropriate script file
|
||||
open_svg_action = svgEditor.curConfig.extPath + 'fileopen.php?type=load_svg';
|
||||
import_svg_action = svgEditor.curConfig.extPath + 'fileopen.php?type=import_svg';
|
||||
import_img_action = svgEditor.curConfig.extPath + 'fileopen.php?type=import_img';
|
||||
|
||||
openSvgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=load_svg';
|
||||
importSvgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=import_svg';
|
||||
importImgAction = svgEditor.curConfig.extPath + 'fileopen.php?type=import_img';
|
||||
|
||||
// Set up function for PHP uploader to use
|
||||
svgEditor.processFile = function(str64, type) {
|
||||
svgEditor.processFile = function (str64, type) {
|
||||
var xmlstr;
|
||||
if (cancelled) {
|
||||
cancelled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$('#dialog_box').hide();
|
||||
|
||||
if (type !== 'import_img') {
|
||||
xmlstr = Utils.decode64(str64);
|
||||
}
|
||||
|
||||
|
||||
switch (type) {
|
||||
case 'load_svg':
|
||||
svgCanvas.clear();
|
||||
svgCanvas.setSvgString(xmlstr);
|
||||
svgEditor.updateCanvas();
|
||||
break;
|
||||
case 'import_svg':
|
||||
svgCanvas.importSvgString(xmlstr);
|
||||
svgEditor.updateCanvas();
|
||||
break;
|
||||
case 'import_img':
|
||||
svgCanvas.setGoodImage(str64);
|
||||
break;
|
||||
case 'load_svg':
|
||||
svgCanvas.clear();
|
||||
svgCanvas.setSvgString(xmlstr);
|
||||
svgEditor.updateCanvas();
|
||||
break;
|
||||
case 'import_svg':
|
||||
svgCanvas.importSvgString(xmlstr);
|
||||
svgEditor.updateCanvas();
|
||||
break;
|
||||
case 'import_img':
|
||||
svgCanvas.setGoodImage(str64);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Create upload form
|
||||
open_svg_form = $('<form>');
|
||||
open_svg_form.attr({
|
||||
openSvgForm = $('<form>');
|
||||
openSvgForm.attr({
|
||||
enctype: 'multipart/form-data',
|
||||
method: 'post',
|
||||
action: open_svg_action,
|
||||
action: openSvgAction,
|
||||
target: 'output_frame'
|
||||
});
|
||||
|
||||
|
||||
// Create import form
|
||||
import_svg_form = open_svg_form.clone().attr('action', import_svg_action);
|
||||
importSvgForm = openSvgForm.clone().attr('action', importSvgAction);
|
||||
|
||||
// Create image form
|
||||
import_img_form = open_svg_form.clone().attr('action', import_img_action);
|
||||
|
||||
// It appears necessary to rebuild this input every time a file is
|
||||
importImgForm = openSvgForm.clone().attr('action', importImgAction);
|
||||
|
||||
// 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.
|
||||
function rebuildInput(form) {
|
||||
function rebuildInput (form) {
|
||||
form.empty();
|
||||
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()
|
||||
form.submit();
|
||||
|
||||
|
||||
rebuildInput(form);
|
||||
$.process_cancel("Uploading...", function() {
|
||||
$.process_cancel('Uploading...', function () {
|
||||
cancelled = true;
|
||||
$('#dialog_box').hide();
|
||||
});
|
||||
}
|
||||
|
||||
if(form[0] == open_svg_form[0]) {
|
||||
inp.change(function() {
|
||||
|
||||
if (form[0] === openSvgForm[0]) {
|
||||
inp.change(function () {
|
||||
// This takes care of the "are you sure" dialog box
|
||||
svgEditor.openPrep(function(ok) {
|
||||
if(!ok) {
|
||||
svgEditor.openPrep(function (ok) {
|
||||
if (!ok) {
|
||||
rebuildInput(form);
|
||||
return;
|
||||
}
|
||||
@@ -207,22 +206,21 @@ svgEditor.addExtension("server_opensave", {
|
||||
});
|
||||
});
|
||||
} else {
|
||||
inp.change(function() {
|
||||
inp.change(function () {
|
||||
// This submits the form, which returns the file data using svgEditor.processFile()
|
||||
submit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Create the input elements
|
||||
rebuildInput(open_svg_form);
|
||||
rebuildInput(import_svg_form);
|
||||
rebuildInput(import_img_form);
|
||||
rebuildInput(openSvgForm);
|
||||
rebuildInput(importSvgForm);
|
||||
rebuildInput(importImgForm);
|
||||
|
||||
// Add forms to buttons
|
||||
$("#tool_open").show().prepend(open_svg_form);
|
||||
$("#tool_import").show().prepend(import_svg_form);
|
||||
$("#tool_image").prepend(import_img_form);
|
||||
$('#tool_open').show().prepend(openSvgForm);
|
||||
$('#tool_import').show().prepend(importSvgForm);
|
||||
$('#tool_image').prepend(importImgForm);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, $, DOMParser*/
|
||||
/*jslint es5: true, vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, $, DOMParser */
|
||||
/*
|
||||
* ext-shapes.js
|
||||
*
|
||||
@@ -10,11 +10,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
svgEditor.addExtension('shapes', function() {'use strict';
|
||||
var current_d, cur_shape_id;
|
||||
svgEditor.addExtension('shapes', function () {
|
||||
'use strict';
|
||||
var currentD, curShapeId;
|
||||
var canv = svgEditor.canvas;
|
||||
var cur_shape;
|
||||
var start_x, start_y;
|
||||
var curShape;
|
||||
var startX, startY;
|
||||
var svgroot = canv.getRootElem();
|
||||
var lastBBox = {};
|
||||
|
||||
@@ -73,67 +74,66 @@ svgEditor.addExtension('shapes', function() {'use strict';
|
||||
}
|
||||
};
|
||||
|
||||
var cur_lib = library.basic;
|
||||
var mode_id = 'shapelib';
|
||||
var curLib = library.basic;
|
||||
var modeId = 'shapelib';
|
||||
var startClientPos = {};
|
||||
|
||||
function loadIcons() {
|
||||
$('#shape_buttons').empty().append(cur_lib.buttons);
|
||||
function loadIcons () {
|
||||
$('#shape_buttons').empty().append(curLib.buttons);
|
||||
}
|
||||
|
||||
function makeButtons(cat, shapes) {
|
||||
var size = cur_lib.size || 300;
|
||||
var fill = cur_lib.fill || false;
|
||||
function makeButtons (cat, shapes) {
|
||||
var size = curLib.size || 300;
|
||||
var fill = curLib.fill || false;
|
||||
var off = size * 0.05;
|
||||
var vb = [-off, -off, size + off*2, size + off*2].join(' ');
|
||||
var stroke = fill ? 0: (size/30);
|
||||
var shape_icon = 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>',
|
||||
var vb = [-off, -off, size + off * 2, size + off * 2].join(' ');
|
||||
var stroke = fill ? 0 : (size / 30);
|
||||
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>',
|
||||
'text/xml');
|
||||
|
||||
var width = 24;
|
||||
var height = 24;
|
||||
shape_icon.documentElement.setAttribute('width', width);
|
||||
shape_icon.documentElement.setAttribute('height', height);
|
||||
var svg_elem = $(document.importNode(shape_icon.documentElement,true));
|
||||
shapeIcon.documentElement.setAttribute('width', width);
|
||||
shapeIcon.documentElement.setAttribute('height', height);
|
||||
var svgElem = $(document.importNode(shapeIcon.documentElement, true));
|
||||
|
||||
var data = shapes.data;
|
||||
|
||||
cur_lib.buttons = [];
|
||||
curLib.buttons = [];
|
||||
var id;
|
||||
for (id in data) {
|
||||
var path_d = data[id];
|
||||
var icon = svg_elem.clone();
|
||||
icon.find('path').attr('d', path_d);
|
||||
var pathD = data[id];
|
||||
var icon = svgElem.clone();
|
||||
icon.find('path').attr('d', pathD);
|
||||
|
||||
var icon_btn = icon.wrap('<div class="tool_button">').parent().attr({
|
||||
id: mode_id + '_' + id,
|
||||
var iconBtn = icon.wrap('<div class="tool_button">').parent().attr({
|
||||
id: modeId + '_' + id,
|
||||
title: id
|
||||
});
|
||||
// Store for later use
|
||||
cur_lib.buttons.push(icon_btn[0]);
|
||||
curLib.buttons.push(iconBtn[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function loadLibrary(cat_id) {
|
||||
|
||||
var lib = library[cat_id];
|
||||
function loadLibrary (catId) {
|
||||
var lib = library[catId];
|
||||
|
||||
if (!lib) {
|
||||
$('#shape_buttons').html('Loading...');
|
||||
$.getJSON(svgEditor.curConfig.extPath + 'shapelib/' + cat_id + '.json', function(result) {
|
||||
cur_lib = library[cat_id] = {
|
||||
$.getJSON(svgEditor.curConfig.extPath + 'shapelib/' + catId + '.json', function (result) {
|
||||
curLib = library[catId] = {
|
||||
data: result.data,
|
||||
size: result.size,
|
||||
fill: result.fill
|
||||
};
|
||||
makeButtons(cat_id, result);
|
||||
makeButtons(catId, result);
|
||||
loadIcons();
|
||||
});
|
||||
return;
|
||||
}
|
||||
cur_lib = lib;
|
||||
if (!lib.buttons.length) {makeButtons(cat_id, lib);}
|
||||
curLib = lib;
|
||||
if (!lib.buttons.length) { makeButtons(catId, lib); }
|
||||
loadIcons();
|
||||
}
|
||||
|
||||
@@ -145,53 +145,52 @@ svgEditor.addExtension('shapes', function() {'use strict';
|
||||
position: 6,
|
||||
title: 'Shape library',
|
||||
events: {
|
||||
click: function() {
|
||||
canv.setMode(mode_id);
|
||||
click: function () {
|
||||
canv.setMode(modeId);
|
||||
}
|
||||
}
|
||||
}],
|
||||
callback: function() {
|
||||
$('<style>').text('\
|
||||
#shape_buttons {\
|
||||
overflow: auto;\
|
||||
width: 180px;\
|
||||
max-height: 300px;\
|
||||
display: table-cell;\
|
||||
vertical-align: middle;\
|
||||
}\
|
||||
\
|
||||
#shape_cats {\
|
||||
min-width: 110px;\
|
||||
display: table-cell;\
|
||||
vertical-align: middle;\
|
||||
height: 300px;\
|
||||
}\
|
||||
#shape_cats > div {\
|
||||
line-height: 1em;\
|
||||
padding: .5em;\
|
||||
border:1px solid #B0B0B0;\
|
||||
background: #E8E8E8;\
|
||||
margin-bottom: -1px;\
|
||||
}\
|
||||
#shape_cats div:hover {\
|
||||
background: #FFFFCC;\
|
||||
}\
|
||||
#shape_cats div.current {\
|
||||
font-weight: bold;\
|
||||
}').appendTo('head');
|
||||
callback: function () {
|
||||
$('<style>').text(
|
||||
'#shape_buttons {' +
|
||||
'overflow: auto;' +
|
||||
'width: 180px;' +
|
||||
'max-height: 300px;' +
|
||||
'display: table-cell;' +
|
||||
'vertical-align: middle;' +
|
||||
'}' +
|
||||
'#shape_cats {' +
|
||||
'min-width: 110px;' +
|
||||
'display: table-cell;' +
|
||||
'vertical-align: middle;' +
|
||||
'height: 300px;' +
|
||||
'}' +
|
||||
'#shape_cats > div {' +
|
||||
'line-height: 1em;' +
|
||||
'padding: .5em;' +
|
||||
'border:1px solid #B0B0B0;' +
|
||||
'background: #E8E8E8;' +
|
||||
'margin-bottom: -1px;' +
|
||||
'}' +
|
||||
'#shape_cats div:hover {' +
|
||||
'background: #FFFFCC;' +
|
||||
'}' +
|
||||
'#shape_cats div.current {' +
|
||||
'font-weight: bold;' +
|
||||
'}').appendTo('head');
|
||||
|
||||
var btn_div = $('<div id="shape_buttons">');
|
||||
$('#tools_shapelib > *').wrapAll(btn_div);
|
||||
var btnDiv = $('<div id="shape_buttons">');
|
||||
$('#tools_shapelib > *').wrapAll(btnDiv);
|
||||
|
||||
var shower = $('#tools_shapelib_show');
|
||||
|
||||
loadLibrary('basic');
|
||||
|
||||
// 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');
|
||||
|
||||
if (!btn.length) {return;}
|
||||
if (!btn.length) { return; }
|
||||
|
||||
var copy = btn.children().clone();
|
||||
shower.children(':not(.flyout_arrow_horiz)').remove();
|
||||
@@ -199,22 +198,22 @@ svgEditor.addExtension('shapes', function() {'use strict';
|
||||
.append(copy)
|
||||
.attr('data-curopt', '#' + btn[0].id) // This sets the current mode
|
||||
.mouseup();
|
||||
canv.setMode(mode_id);
|
||||
canv.setMode(modeId);
|
||||
|
||||
cur_shape_id = btn[0].id.substr((mode_id+'_').length);
|
||||
current_d = cur_lib.data[cur_shape_id];
|
||||
curShapeId = btn[0].id.substr((modeId + '_').length);
|
||||
currentD = curLib.data[curShapeId];
|
||||
|
||||
$('.tools_flyout').fadeOut();
|
||||
});
|
||||
|
||||
var shape_cats = $('<div id="shape_cats">');
|
||||
var cat_str = '';
|
||||
var shapeCats = $('<div id="shape_cats">');
|
||||
var catStr = '';
|
||||
|
||||
$.each(categories, function(id, label) {
|
||||
cat_str += '<div data-cat=' + id + '>' + label + '</div>';
|
||||
$.each(categories, function (id, label) {
|
||||
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);
|
||||
catlink.siblings().removeClass('current');
|
||||
catlink.addClass('current');
|
||||
@@ -224,134 +223,133 @@ svgEditor.addExtension('shapes', function() {'use strict';
|
||||
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() {
|
||||
canv.setMode(current_d ? mode_id : 'select');
|
||||
shower.mouseup(function () {
|
||||
canv.setMode(currentD ? modeId : 'select');
|
||||
});
|
||||
$('#tool_shapelib').remove();
|
||||
|
||||
var h = $('#tools_shapelib').height();
|
||||
$('#tools_shapelib').css({
|
||||
'margin-top': -(h/2 - 15),
|
||||
'margin-top': -(h / 2 - 15),
|
||||
'margin-left': 3
|
||||
});
|
||||
},
|
||||
mouseDown: function(opts) {
|
||||
mouseDown: function (opts) {
|
||||
var mode = canv.getMode();
|
||||
if (mode !== mode_id) {return;}
|
||||
if (mode !== modeId) { return; }
|
||||
|
||||
startX = opts.start_x;
|
||||
var x = startX;
|
||||
startY = opts.start_y;
|
||||
var y = startY;
|
||||
var curStyle = canv.getStyle();
|
||||
|
||||
start_x = opts.start_x;
|
||||
var x = start_x;
|
||||
start_y = opts.start_y;
|
||||
var y = start_y;
|
||||
var cur_style = canv.getStyle();
|
||||
|
||||
startClientPos.x = opts.event.clientX;
|
||||
startClientPos.y = opts.event.clientY;
|
||||
|
||||
cur_shape = canv.addSvgElementFromJson({
|
||||
curShape = canv.addSvgElementFromJson({
|
||||
'element': 'path',
|
||||
'curStyles': true,
|
||||
'attr': {
|
||||
'd': current_d,
|
||||
'd': currentD,
|
||||
'id': canv.getNextId(),
|
||||
'opacity': cur_style.opacity / 2,
|
||||
'opacity': curStyle.opacity / 2,
|
||||
'style': 'pointer-events:none'
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure shape uses absolute values
|
||||
if (/[a-z]/.test(current_d)) {
|
||||
current_d = cur_lib.data[cur_shape_id] = canv.pathActions.convertPath(cur_shape);
|
||||
cur_shape.setAttribute('d', current_d);
|
||||
canv.pathActions.fixEnd(cur_shape);
|
||||
if (/[a-z]/.test(currentD)) {
|
||||
currentD = curLib.data[curShapeId] = canv.pathActions.convertPath(curShape);
|
||||
curShape.setAttribute('d', currentD);
|
||||
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 {
|
||||
started: true
|
||||
};
|
||||
},
|
||||
mouseMove: function(opts) {
|
||||
mouseMove: function (opts) {
|
||||
var mode = canv.getMode();
|
||||
if (mode !== mode_id) {return;}
|
||||
if (mode !== modeId) { return; }
|
||||
|
||||
var zoom = canv.getZoom();
|
||||
var evt = opts.event;
|
||||
|
||||
var x = opts.mouse_x/zoom;
|
||||
var y = opts.mouse_y/zoom;
|
||||
var x = opts.mouse_x / zoom;
|
||||
var y = opts.mouse_y / zoom;
|
||||
|
||||
var tlist = canv.getTransformList(cur_shape),
|
||||
box = cur_shape.getBBox(),
|
||||
var tlist = canv.getTransformList(curShape),
|
||||
box = curShape.getBBox(),
|
||||
left = box.x, top = box.y, width = box.width,
|
||||
height = box.height;
|
||||
var dx = (x-start_x), dy = (y-start_y);
|
||||
var dx = (x - startX), dy = (y - startY);
|
||||
|
||||
var newbox = {
|
||||
'x': Math.min(start_x,x),
|
||||
'y': Math.min(start_y,y),
|
||||
'width': Math.abs(x-start_x),
|
||||
'height': Math.abs(y-start_y)
|
||||
'x': Math.min(startX, x),
|
||||
'y': Math.min(startY, y),
|
||||
'width': Math.abs(x - startX),
|
||||
'height': Math.abs(y - startY)
|
||||
};
|
||||
|
||||
var tx = 0, ty = 0,
|
||||
sy = height ? (height+dy)/height : 1,
|
||||
sx = width ? (width+dx)/width : 1;
|
||||
sy = height ? (height + dy) / height : 1,
|
||||
sx = width ? (width + dx) / width : 1;
|
||||
|
||||
sx = (newbox.width / lastBBox.width) || 1;
|
||||
sy = (newbox.height / lastBBox.height) || 1;
|
||||
|
||||
// Not perfect, but mostly works...
|
||||
if (x < start_x) {
|
||||
if (x < startX) {
|
||||
tx = lastBBox.width;
|
||||
}
|
||||
if (y < start_y) {ty = lastBBox.height;}
|
||||
if (y < startY) { ty = lastBBox.height; }
|
||||
|
||||
// update the transform list with translate,scale,translate
|
||||
var translateOrigin = svgroot.createSVGTransform(),
|
||||
scale = svgroot.createSVGTransform(),
|
||||
translateBack = svgroot.createSVGTransform();
|
||||
|
||||
translateOrigin.setTranslate(-(left+tx), -(top+ty));
|
||||
translateOrigin.setTranslate(-(left + tx), -(top + ty));
|
||||
if (!evt.shiftKey) {
|
||||
var max = Math.min(Math.abs(sx), Math.abs(sy));
|
||||
|
||||
sx = max * (sx < 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(scale);
|
||||
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();
|
||||
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 {
|
||||
keep: keepObject,
|
||||
element: cur_shape,
|
||||
element: curShape,
|
||||
started: false
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgedit, svgCanvas, $*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $ */
|
||||
/*
|
||||
* 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,
|
||||
// svgcontent = S.svgcontent,
|
||||
@@ -17,19 +18,18 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
// editingitex = false,
|
||||
// svgdoc = S.svgroot.parentNode.ownerDocument,
|
||||
started,
|
||||
newFO,
|
||||
newFO;
|
||||
// edg = 0,
|
||||
// newFOG, newFOGParent, newDef, newImageName, newMaskID,
|
||||
// undoCommand = 'Not image',
|
||||
// modeChangeG, ccZoom, wEl, hEl, wOffset, hOffset, ccRgbEl, brushW, brushH,
|
||||
shape;
|
||||
// modeChangeG, ccZoom, wEl, hEl, wOffset, hOffset, ccRgbEl, brushW, brushH;
|
||||
|
||||
function showPanel(on){
|
||||
var fc_rules = $('#fc_rules');
|
||||
if (!fc_rules.length) {
|
||||
fc_rules = $('<style id="fc_rules"></style>').appendTo('head');
|
||||
function showPanel (on) {
|
||||
var fcRules = $('#fc_rules');
|
||||
if (!fcRules.length) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
}
|
||||
*/
|
||||
|
||||
function setAttr(attr, val){
|
||||
function setAttr (attr, val) {
|
||||
svgCanvas.changeSelectedAttribute(attr, val);
|
||||
S.call('changed', selElems);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
title: 'Star Tool',
|
||||
position: 12,
|
||||
events: {
|
||||
click: function(){
|
||||
click: function () {
|
||||
showPanel(true);
|
||||
svgCanvas.setMode('star');
|
||||
}
|
||||
@@ -79,7 +79,7 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
size: 3,
|
||||
defval: 5,
|
||||
events: {
|
||||
change: function(){
|
||||
change: function () {
|
||||
setAttr('point', this.value);
|
||||
}
|
||||
}
|
||||
@@ -100,23 +100,23 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
size: 3,
|
||||
defval: 0,
|
||||
events: {
|
||||
change: function(){
|
||||
change: function () {
|
||||
setAttr('radialshift', this.value);
|
||||
}
|
||||
}
|
||||
}],
|
||||
callback: function(){
|
||||
callback: function () {
|
||||
$('#star_panel').hide();
|
||||
// var endChanges = function(){};
|
||||
},
|
||||
mouseDown: function(opts){
|
||||
mouseDown: function (opts) {
|
||||
var rgb = svgCanvas.getColor('fill');
|
||||
// var ccRgbEl = rgb.substring(1, rgb.length);
|
||||
var sRgb = svgCanvas.getColor('stroke');
|
||||
// var ccSRgbEl = sRgb.substring(1, rgb.length);
|
||||
var sWidth = svgCanvas.getStrokeWidth();
|
||||
|
||||
if (svgCanvas.getMode() == 'star') {
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
started = true;
|
||||
|
||||
newFO = S.addSvgElementFromJson({
|
||||
@@ -141,11 +141,11 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
};
|
||||
}
|
||||
},
|
||||
mouseMove: function(opts){
|
||||
mouseMove: function (opts) {
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
if (svgCanvas.getMode() == 'star') {
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
var x = opts.mouse_x;
|
||||
var y = opts.mouse_y;
|
||||
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;
|
||||
for (s = 0; point >= s; s++) {
|
||||
var angle = 2.0 * Math.PI * (s / point);
|
||||
if ('point' == orient) {
|
||||
if (orient === 'point') {
|
||||
angle -= (Math.PI / 2);
|
||||
} else if ('edge' == orient) {
|
||||
} else if (orient === 'edge') {
|
||||
angle = (angle + (Math.PI / point)) - (Math.PI / 2);
|
||||
}
|
||||
|
||||
@@ -169,11 +169,11 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
|
||||
polyPoints += x + ',' + y + ' ';
|
||||
|
||||
if (null != inradius) {
|
||||
if (inradius != null) {
|
||||
angle = (2.0 * Math.PI * (s / point)) + (Math.PI / point);
|
||||
if ('point' == orient) {
|
||||
if (orient === 'point') {
|
||||
angle -= (Math.PI / 2);
|
||||
} else if ('edge' == orient) {
|
||||
} else if (orient === 'edge') {
|
||||
angle = (angle + (Math.PI / point)) - (Math.PI / 2);
|
||||
}
|
||||
angle += radialShift;
|
||||
@@ -188,25 +188,24 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
newFO.setAttributeNS(null, 'fill', fill);
|
||||
newFO.setAttributeNS(null, 'stroke', strokecolor);
|
||||
newFO.setAttributeNS(null, 'stroke-width', strokewidth);
|
||||
shape = newFO.getAttributeNS(null, 'shape');
|
||||
/* var shape = */ newFO.getAttributeNS(null, 'shape');
|
||||
|
||||
return {
|
||||
started: true
|
||||
};
|
||||
}
|
||||
|
||||
},
|
||||
mouseUp: function(){
|
||||
if (svgCanvas.getMode() == 'star') {
|
||||
mouseUp: function () {
|
||||
if (svgCanvas.getMode() === 'star') {
|
||||
var attrs = $(newFO).attr(['r']);
|
||||
// svgCanvas.addToSelection([newFO], true);
|
||||
return {
|
||||
keep: (attrs.r != 0),
|
||||
keep: (attrs.r !== '0'),
|
||||
element: newFO
|
||||
};
|
||||
}
|
||||
},
|
||||
selectedChanged: function(opts){
|
||||
selectedChanged: function (opts) {
|
||||
// Use this to update the current selected elements
|
||||
selElems = opts.elems;
|
||||
|
||||
@@ -220,8 +219,7 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
$('#starNumPoints').val(elem.getAttribute('point'));
|
||||
$('#radialShift').val(elem.getAttribute('radialshift'));
|
||||
showPanel(true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
showPanel(false);
|
||||
}
|
||||
} else {
|
||||
@@ -229,7 +227,7 @@ svgEditor.addExtension('star', function(S){'use strict';
|
||||
}
|
||||
}
|
||||
},
|
||||
elementChanged: function(opts){
|
||||
elementChanged: function (opts) {
|
||||
// var elem = opts.elems[0];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgEditor, svgCanvas, $, widget*/
|
||||
/*jslint vars: true, eqeq: true, regexp: true, continue: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas, $, widget */
|
||||
/*
|
||||
* ext-storage.js
|
||||
*
|
||||
@@ -26,7 +26,7 @@ TODOS
|
||||
2. We might provide control of storage settings through the UI besides the
|
||||
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,
|
||||
// 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;
|
||||
@@ -53,8 +53,7 @@ svgEditor.addExtension('storage', function() {
|
||||
loc.href = loc.href.replace(/([&?])storagePrompt=[^&]*(&?)/, function (n0, n1, amp) {
|
||||
return (val ? n1 : '') + val + (!val && amp ? n1 : (amp || ''));
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
loc.href += (loc.href.indexOf('?') > -1 ? '&' : '?') + val;
|
||||
}
|
||||
}
|
||||
@@ -63,22 +62,21 @@ svgEditor.addExtension('storage', function() {
|
||||
var name = 'svgedit-' + svgEditor.curConfig.canvasName;
|
||||
if (!val) {
|
||||
storage.removeItem(name);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
storage.setItem(name, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function expireCookie (cookie) {
|
||||
document.cookie = encodeURIComponent(cookie) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
||||
}
|
||||
|
||||
|
||||
function removeStoragePrefCookie () {
|
||||
expireCookie('store');
|
||||
}
|
||||
|
||||
function emptyStorage() {
|
||||
|
||||
function emptyStorage () {
|
||||
setSVGContentStorage('');
|
||||
var name;
|
||||
for (name in svgEditor.curPrefs) {
|
||||
@@ -91,8 +89,8 @@ svgEditor.addExtension('storage', function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// emptyStorage();
|
||||
|
||||
// emptyStorage();
|
||||
|
||||
/**
|
||||
* Listen for unloading: If and only if opted in by the user, set the content
|
||||
@@ -103,14 +101,14 @@ svgEditor.addExtension('storage', function() {
|
||||
* 3. Use localStorage (where available) or cookies to set preferences.
|
||||
*/
|
||||
function setupBeforeUnloadListener () {
|
||||
window.addEventListener('beforeunload', function(e) {
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
// Don't save anything unless the user opted in to storage
|
||||
if (!document.cookie.match(/(?:^|;\s*)store=(?:prefsAndContent|prefsOnly)/)) {
|
||||
return;
|
||||
}
|
||||
var key;
|
||||
if (document.cookie.match(/(?:^|;\s*)store=prefsAndContent/)) {
|
||||
setSVGContentStorage(svgCanvas.getSvgString());
|
||||
setSVGContentStorage(svgCanvas.getSvgString());
|
||||
}
|
||||
|
||||
svgEditor.setConfig({no_save_warning: true}); // No need for explicit saving at all once storage is on
|
||||
@@ -121,18 +119,16 @@ svgEditor.addExtension('storage', function() {
|
||||
for (key in curPrefs) {
|
||||
if (curPrefs.hasOwnProperty(key)) { // It's our own config, so we don't need to iterate up the prototype chain
|
||||
var val = curPrefs[key],
|
||||
store = (val != undefined);
|
||||
store = (val !== undefined);
|
||||
key = 'svg-edit-' + key;
|
||||
if (!store) {
|
||||
continue;
|
||||
}
|
||||
if (storage) {
|
||||
storage.setItem(key, val);
|
||||
}
|
||||
else if (window.widget) {
|
||||
} else if (window.widget) {
|
||||
widget.setPreferenceForKey(val, key);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val = encodeURIComponent(val);
|
||||
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.
|
||||
)) {
|
||||
|
||||
var options = [];
|
||||
if (storage) {
|
||||
options.unshift(
|
||||
@@ -203,8 +198,7 @@ svgEditor.addExtension('storage', function() {
|
||||
{value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefsOnly},
|
||||
{value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefsOrContent}
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
options.unshift(
|
||||
{value: 'prefsOnly', text: uiStrings.confirmSetStorage.storagePrefs},
|
||||
{value: 'noPrefsOrContent', text: uiStrings.confirmSetStorage.storageNoPrefs}
|
||||
@@ -242,8 +236,7 @@ svgEditor.addExtension('storage', function() {
|
||||
replaceStoragePrompt();
|
||||
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();
|
||||
if (pref && // If the user explicitly expresses wish for no storage
|
||||
emptyStorageOnDecline
|
||||
@@ -259,21 +252,21 @@ svgEditor.addExtension('storage', function() {
|
||||
|
||||
// Reset width/height of dialog (e.g., for use by Export)
|
||||
$('#dialog_container')[0].style.width = oldContainerWidth;
|
||||
$('#dialog_container')[0].style.marginLeft = oldContainerMarginLeft;
|
||||
$('#dialog_container')[0].style.marginLeft = oldContainerMarginLeft;
|
||||
$('#dialog_content')[0].style.height = oldContentHeight;
|
||||
$('#dialog_container')[0].style.height = oldContainerHeight;
|
||||
|
||||
|
||||
// It should be enough to (conditionally) add to storage on
|
||||
// beforeunload, but if we wished to update immediately,
|
||||
// we might wish to try setting:
|
||||
// svgEditor.setConfig({noStorageOnLoad: true});
|
||||
// and then call:
|
||||
// svgEditor.loadContentAndPrefs();
|
||||
|
||||
|
||||
// We don't check for noStorageOnLoad here because
|
||||
// the prompt gives the user the option to store data
|
||||
setupBeforeUnloadListener();
|
||||
|
||||
|
||||
svgEditor.storagePromptClosed = true;
|
||||
},
|
||||
null,
|
||||
@@ -284,8 +277,7 @@ svgEditor.addExtension('storage', function() {
|
||||
tooltip: uiStrings.confirmSetStorage.rememberTooltip
|
||||
}
|
||||
);
|
||||
}
|
||||
else if (!noStorageOnLoad || forceStorage) {
|
||||
} else if (!noStorageOnLoad || forceStorage) {
|
||||
setupBeforeUnloadListener();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Todos:
|
||||
1. See WebAppFind Readme for SVG-related todos
|
||||
*/
|
||||
(function () {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var pathID,
|
||||
saveMessage = 'webapp-save',
|
||||
readMessage = 'webapp-read',
|
||||
excludedMessages = [readMessage, saveMessage];
|
||||
saveMessage = 'webapp-save',
|
||||
readMessage = 'webapp-read',
|
||||
excludedMessages = [readMessage, saveMessage];
|
||||
|
||||
window.addEventListener('message', function(e) {
|
||||
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
|
||||
) {
|
||||
return;
|
||||
}
|
||||
var svgString,
|
||||
messageType = e.data[0];
|
||||
switch (messageType) {
|
||||
case 'webapp-view':
|
||||
// Populate the contents
|
||||
pathID = e.data[1];
|
||||
|
||||
svgString = e.data[2];
|
||||
svgEditor.loadFromString(svgString);
|
||||
|
||||
/*if ($('#tool_save_file')) {
|
||||
$('#tool_save_file').disabled = false;
|
||||
}*/
|
||||
break;
|
||||
case 'webapp-save-end':
|
||||
alert('save complete for pathID ' + e.data[1] + '!');
|
||||
break;
|
||||
default:
|
||||
throw 'Unexpected mode';
|
||||
}
|
||||
window.addEventListener('message', function (e) {
|
||||
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
|
||||
) {
|
||||
return;
|
||||
}
|
||||
var svgString,
|
||||
messageType = e.data[0];
|
||||
switch (messageType) {
|
||||
case 'webapp-view':
|
||||
// Populate the contents
|
||||
pathID = e.data[1];
|
||||
|
||||
svgString = e.data[2];
|
||||
svgEditor.loadFromString(svgString);
|
||||
|
||||
/* if ($('#tool_save_file')) {
|
||||
$('#tool_save_file').disabled = false;
|
||||
} */
|
||||
break;
|
||||
case 'webapp-save-end':
|
||||
alert('save complete for pathID ' + e.data[1] + '!');
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected mode');
|
||||
}
|
||||
}, 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)
|
||||
|
||||
svgEditor.addExtension('WebAppFind', function() {
|
||||
|
||||
return {
|
||||
name: 'WebAppFind',
|
||||
svgicons: svgEditor.curConfig.extPath + 'webappfind-icon.svg',
|
||||
buttons: [{
|
||||
id: 'webappfind_save', //
|
||||
type: 'app_menu',
|
||||
title: 'Save Image back to Disk',
|
||||
position: 4, // Before 0-based index position 4 (after the regular "Save Image (S)")
|
||||
events: {
|
||||
click: function () {
|
||||
if (!pathID) { // Not ready yet as haven't received first payload
|
||||
return;
|
||||
}
|
||||
window.postMessage([saveMessage, pathID, svgEditor.canvas.getSvgString()], window.location.origin);
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
svgEditor.addExtension('WebAppFind', function () {
|
||||
return {
|
||||
name: 'WebAppFind',
|
||||
svgicons: svgEditor.curConfig.extPath + 'webappfind-icon.svg',
|
||||
buttons: [{
|
||||
id: 'webappfind_save', //
|
||||
type: 'app_menu',
|
||||
title: 'Save Image back to Disk',
|
||||
position: 4, // Before 0-based index position 4 (after the regular "Save Image (S)")
|
||||
events: {
|
||||
click: function () {
|
||||
if (!pathID) { // Not ready yet as haven't received first payload
|
||||
return;
|
||||
}
|
||||
window.postMessage([saveMessage, pathID, svgEditor.canvas.getSvgString()], window.location.origin);
|
||||
}
|
||||
}
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
}());
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgEditor, svgCanvas */
|
||||
/**
|
||||
* 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
|
||||
* in embedapi.js with a demo at embedapi.html
|
||||
*/
|
||||
/*globals svgEditor, svgCanvas*/
|
||||
svgEditor.addExtension('xdomain-messaging', function() {'use strict';
|
||||
svgEditor.addExtension('xdomain-messaging', function () {
|
||||
'use strict';
|
||||
try {
|
||||
window.addEventListener('message', function(e) {
|
||||
window.addEventListener('message', function (e) {
|
||||
// We accept and post strings for the sake of IE9 support
|
||||
if (typeof e.data !== 'string' || e.data.charAt() === '|') {
|
||||
return;
|
||||
@@ -35,8 +37,7 @@ svgEditor.addExtension('xdomain-messaging', function() {'use strict';
|
||||
}
|
||||
e.source.postMessage(JSON.stringify(message), '*');
|
||||
}, false);
|
||||
}
|
||||
catch (err) {
|
||||
} catch (err) {
|
||||
console.log('Error with xdomain message listener: ' + err);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11,30 +11,30 @@
|
||||
*/
|
||||
// Very minimal PHP file, all we do is Base64 encode the uploaded file and
|
||||
// return it to the editor
|
||||
|
||||
|
||||
if (!isset($_REQUEST['type'])) {
|
||||
echo "No type given";
|
||||
echo 'No type given';
|
||||
exit;
|
||||
}
|
||||
$type = $_REQUEST['type'];
|
||||
if (!in_array($type, array('load_svg', 'import_svg', 'import_img'))) {
|
||||
echo "Not a recognized type";
|
||||
echo 'Not a recognized type';
|
||||
exit;
|
||||
}
|
||||
|
||||
require('allowedMimeTypes.php');
|
||||
|
||||
|
||||
$file = $_FILES['svg_file']['tmp_name'];
|
||||
|
||||
|
||||
$output = file_get_contents($file);
|
||||
|
||||
|
||||
$prefix = '';
|
||||
|
||||
// Make Data URL prefix for import image
|
||||
if ($type == 'import_img') {
|
||||
$info = getimagesize($file);
|
||||
if (!in_array($info['mime'], $allowedMimeTypesBySuffix)) {
|
||||
echo "Disallowed MIME for supplied file";
|
||||
echo 'Disallowed MIME for supplied file';
|
||||
exit;
|
||||
}
|
||||
$prefix = 'data:' . $info['mime'] . ';base64,';
|
||||
@@ -45,7 +45,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<script>
|
||||
|
||||
top.svgEditor.processFile("<?php
|
||||
top.svgEditor.processFile("<?php
|
||||
|
||||
// This should be safe since SVG edit does its own filtering (e.g., if an SVG file contains scripts)
|
||||
echo $prefix . base64_encode($output);
|
||||
|
||||
@@ -44,17 +44,17 @@ if ($suffix == '.svg') {
|
||||
$contents = base64_decode(substr($contents, $pos));
|
||||
}
|
||||
|
||||
header("Cache-Control: public");
|
||||
header("Content-Description: File Transfer");
|
||||
header('Cache-Control: public');
|
||||
header('Content-Description: File Transfer');
|
||||
|
||||
// See http://tools.ietf.org/html/rfc6266#section-4.1
|
||||
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)
|
||||
$file
|
||||
));
|
||||
header("Content-Type: " . $mime);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
header('Content-Type: ' . $mime);
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
echo $contents;
|
||||
|
||||
?>
|
||||
|
||||
?>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>-</title>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -11,59 +12,6 @@
|
||||
<br>
|
||||
<a href="../../images/logo.png">logo.png</a>
|
||||
|
||||
<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>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
51
editor/extensions/imagelib/index.js
Normal file
51
editor/extensions/imagelib/index.js
Normal 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;
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgedit*/
|
||||
/*jslint vars: true, eqeq: true, continue: true, forin: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgedit */
|
||||
/**
|
||||
* Package: svedit.history
|
||||
*
|
||||
@@ -13,7 +13,8 @@
|
||||
// 2) svgtransformlist.js
|
||||
// 3) svgutils.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.history) {
|
||||
svgedit.history = {};
|
||||
@@ -27,7 +28,7 @@ svgedit.history.HistoryEventTypes = {
|
||||
AFTER_UNAPPLY: 'after_unapply'
|
||||
};
|
||||
|
||||
var removedElements = {};
|
||||
// var removedElements = {};
|
||||
|
||||
/**
|
||||
* 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 {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.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.oldParent = oldParent;
|
||||
this.newNextSibling = elem.nextSibling;
|
||||
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.getText = function() {
|
||||
svgedit.history.MoveElementCommand.prototype.getText = function () {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
@@ -80,7 +81,7 @@ svgedit.history.MoveElementCommand.prototype.getText = function() {
|
||||
* Re-positions the element
|
||||
* @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.
|
||||
if (handler) {
|
||||
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
|
||||
* @param {handleHistoryEvent: function}
|
||||
*/
|
||||
svgedit.history.MoveElementCommand.prototype.unapply = function(handler) {
|
||||
svgedit.history.MoveElementCommand.prototype.unapply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||
}
|
||||
@@ -111,11 +112,10 @@ svgedit.history.MoveElementCommand.prototype.unapply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.MoveElementCommand.elements
|
||||
// Returns array with element associated with this command
|
||||
svgedit.history.MoveElementCommand.prototype.elements = function() {
|
||||
svgedit.history.MoveElementCommand.prototype.elements = function () {
|
||||
return [this.elem];
|
||||
};
|
||||
|
||||
|
||||
// Class: svgedit.history.InsertElementCommand
|
||||
// implements svgedit.history.HistoryCommand
|
||||
// History command for an element that was added to the DOM
|
||||
@@ -123,23 +123,23 @@ svgedit.history.MoveElementCommand.prototype.elements = function() {
|
||||
// Parameters:
|
||||
// elem - The newly added DOM element
|
||||
// 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.text = text || ("Create " + elem.tagName);
|
||||
this.text = text || ('Create ' + elem.tagName);
|
||||
this.parent = elem.parentNode;
|
||||
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;
|
||||
|
||||
// Function: svgedit.history.InsertElementCommand.getText
|
||||
svgedit.history.InsertElementCommand.prototype.getText = function() {
|
||||
svgedit.history.InsertElementCommand.prototype.getText = function () {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
// Function: svgedit.history.InsertElementCommand.apply
|
||||
// Re-Inserts the new element
|
||||
svgedit.history.InsertElementCommand.prototype.apply = function(handler) {
|
||||
svgedit.history.InsertElementCommand.prototype.apply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||
}
|
||||
@@ -153,7 +153,7 @@ svgedit.history.InsertElementCommand.prototype.apply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.InsertElementCommand.unapply
|
||||
// Removes the element
|
||||
svgedit.history.InsertElementCommand.prototype.unapply = function(handler) {
|
||||
svgedit.history.InsertElementCommand.prototype.unapply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||
}
|
||||
@@ -168,11 +168,10 @@ svgedit.history.InsertElementCommand.prototype.unapply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.InsertElementCommand.elements
|
||||
// Returns array with element associated with this command
|
||||
svgedit.history.InsertElementCommand.prototype.elements = function() {
|
||||
svgedit.history.InsertElementCommand.prototype.elements = function () {
|
||||
return [this.elem];
|
||||
};
|
||||
|
||||
|
||||
// Class: svgedit.history.RemoveElementCommand
|
||||
// implements svgedit.history.HistoryCommand
|
||||
// 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
|
||||
// oldParent - The DOM element's parent
|
||||
// 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.text = text || ("Delete " + elem.tagName);
|
||||
this.text = text || ('Delete ' + elem.tagName);
|
||||
this.nextSibling = oldNextSibling;
|
||||
this.parent = oldParent;
|
||||
|
||||
// special hack for webkit: remove this element's entry in the svgTransformLists map
|
||||
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;
|
||||
|
||||
// Function: svgedit.history.RemoveElementCommand.getText
|
||||
svgedit.history.RemoveElementCommand.prototype.getText = function() {
|
||||
svgedit.history.RemoveElementCommand.prototype.getText = function () {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
// Function: RemoveElementCommand.apply
|
||||
// Re-removes the new element
|
||||
svgedit.history.RemoveElementCommand.prototype.apply = function(handler) {
|
||||
svgedit.history.RemoveElementCommand.prototype.apply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||
}
|
||||
@@ -217,7 +216,7 @@ svgedit.history.RemoveElementCommand.prototype.apply = function(handler) {
|
||||
|
||||
// Function: RemoveElementCommand.unapply
|
||||
// Re-adds the new element
|
||||
svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) {
|
||||
svgedit.history.RemoveElementCommand.prototype.unapply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||
}
|
||||
@@ -225,12 +224,11 @@ svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) {
|
||||
svgedit.transformlist.removeElementFromListMap(this.elem);
|
||||
if (this.nextSibling == null) {
|
||||
if (window.console) {
|
||||
console.log('Error: reference element was lost');
|
||||
}
|
||||
console.log('Error: reference element was lost');
|
||||
}
|
||||
}
|
||||
this.parent.insertBefore(this.elem, this.nextSibling);
|
||||
|
||||
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||
}
|
||||
@@ -238,11 +236,10 @@ svgedit.history.RemoveElementCommand.prototype.unapply = function(handler) {
|
||||
|
||||
// Function: RemoveElementCommand.elements
|
||||
// Returns array with element associated with this command
|
||||
svgedit.history.RemoveElementCommand.prototype.elements = function() {
|
||||
svgedit.history.RemoveElementCommand.prototype.elements = function () {
|
||||
return [this.elem];
|
||||
};
|
||||
|
||||
|
||||
// Class: svgedit.history.ChangeElementCommand
|
||||
// implements svgedit.history.HistoryCommand
|
||||
// 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
|
||||
// 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
|
||||
svgedit.history.ChangeElementCommand = function(elem, attrs, text) {
|
||||
svgedit.history.ChangeElementCommand = function (elem, attrs, text) {
|
||||
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.oldValues = attrs;
|
||||
var attr;
|
||||
for (attr in attrs) {
|
||||
if (attr == "#text") {this.newValues[attr] = elem.textContent;}
|
||||
else if (attr == "#href") {this.newValues[attr] = svgedit.utilities.getHref(elem);}
|
||||
else {this.newValues[attr] = elem.getAttribute(attr);}
|
||||
if (attr === '#text') {
|
||||
this.newValues[attr] = elem.textContent;
|
||||
} 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;
|
||||
|
||||
// Function: svgedit.history.ChangeElementCommand.getText
|
||||
svgedit.history.ChangeElementCommand.prototype.getText = function() {
|
||||
svgedit.history.ChangeElementCommand.prototype.getText = function () {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
// Function: svgedit.history.ChangeElementCommand.apply
|
||||
// Performs the stored change action
|
||||
svgedit.history.ChangeElementCommand.prototype.apply = function(handler) {
|
||||
svgedit.history.ChangeElementCommand.prototype.apply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||
}
|
||||
|
||||
var bChangedTransform = false;
|
||||
var attr;
|
||||
for (attr in this.newValues ) {
|
||||
for (attr in this.newValues) {
|
||||
if (this.newValues[attr]) {
|
||||
if (attr == "#text") {this.elem.textContent = this.newValues[attr];}
|
||||
else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.newValues[attr]);}
|
||||
else {this.elem.setAttribute(attr, this.newValues[attr]);}
|
||||
}
|
||||
else {
|
||||
if (attr == "#text") {
|
||||
this.elem.textContent = "";
|
||||
if (attr === '#text') {
|
||||
this.elem.textContent = this.newValues[attr];
|
||||
} else if (attr === '#href') {
|
||||
svgedit.utilities.setHref(this.elem, this.newValues[attr]);
|
||||
} else {
|
||||
this.elem.setAttribute(attr, this.newValues[attr]);
|
||||
}
|
||||
else {
|
||||
this.elem.setAttribute(attr, "");
|
||||
} else {
|
||||
if (attr === '#text') {
|
||||
this.elem.textContent = '';
|
||||
} else {
|
||||
this.elem.setAttribute(attr, '');
|
||||
this.elem.removeAttribute(attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (attr == "transform") { bChangedTransform = true; }
|
||||
if (attr === 'transform') { bChangedTransform = true; }
|
||||
}
|
||||
|
||||
// relocate rotational transform, if necessary
|
||||
if (!bChangedTransform) {
|
||||
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
||||
if (angle) {
|
||||
// TODO: These instances of elem either need to be declared as global
|
||||
// (which would not be good for conflicts) or declare/use this.elem
|
||||
var bbox = elem.getBBox();
|
||||
var cx = bbox.x + bbox.width/2,
|
||||
cy = bbox.y + bbox.height/2;
|
||||
var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join('');
|
||||
if (rotate != elem.getAttribute("transform")) {
|
||||
elem.setAttribute("transform", rotate);
|
||||
var bbox = this.elem.getBBox();
|
||||
var cx = bbox.x + bbox.width / 2,
|
||||
cy = bbox.y + bbox.height / 2;
|
||||
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
||||
if (rotate !== this.elem.getAttribute('transform')) {
|
||||
this.elem.setAttribute('transform', rotate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,39 +326,41 @@ svgedit.history.ChangeElementCommand.prototype.apply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.ChangeElementCommand.unapply
|
||||
// Reverses the stored change action
|
||||
svgedit.history.ChangeElementCommand.prototype.unapply = function(handler) {
|
||||
svgedit.history.ChangeElementCommand.prototype.unapply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||
}
|
||||
|
||||
var bChangedTransform = false;
|
||||
var attr;
|
||||
for (attr in this.oldValues ) {
|
||||
for (attr in this.oldValues) {
|
||||
if (this.oldValues[attr]) {
|
||||
if (attr == "#text") {this.elem.textContent = this.oldValues[attr];}
|
||||
else if (attr == "#href") {svgedit.utilities.setHref(this.elem, this.oldValues[attr]);}
|
||||
else {
|
||||
if (attr === '#text') {
|
||||
this.elem.textContent = this.oldValues[attr];
|
||||
} else if (attr === '#href') {
|
||||
svgedit.utilities.setHref(this.elem, this.oldValues[attr]);
|
||||
} else {
|
||||
this.elem.setAttribute(attr, this.oldValues[attr]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (attr == "#text") {
|
||||
this.elem.textContent = "";
|
||||
} else {
|
||||
if (attr === '#text') {
|
||||
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
|
||||
if (!bChangedTransform) {
|
||||
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
||||
if (angle) {
|
||||
var bbox = elem.getBBox();
|
||||
var cx = bbox.x + bbox.width/2,
|
||||
cy = bbox.y + bbox.height/2;
|
||||
var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join('');
|
||||
if (rotate != elem.getAttribute("transform")) {
|
||||
elem.setAttribute("transform", rotate);
|
||||
var bbox = this.elem.getBBox();
|
||||
var cx = bbox.x + bbox.width / 2,
|
||||
cy = bbox.y + bbox.height / 2;
|
||||
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
||||
if (rotate !== this.elem.getAttribute('transform')) {
|
||||
this.elem.setAttribute('transform', rotate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,37 +377,35 @@ svgedit.history.ChangeElementCommand.prototype.unapply = function(handler) {
|
||||
|
||||
// Function: ChangeElementCommand.elements
|
||||
// Returns array with element associated with this command
|
||||
svgedit.history.ChangeElementCommand.prototype.elements = function() {
|
||||
svgedit.history.ChangeElementCommand.prototype.elements = function () {
|
||||
return [this.elem];
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
// and they both affect the same element, then collapse the two commands into one
|
||||
|
||||
|
||||
// Class: svgedit.history.BatchCommand
|
||||
// implements svgedit.history.HistoryCommand
|
||||
// History command that can contain/execute multiple other commands
|
||||
//
|
||||
// Parameters:
|
||||
// text - An optional string visible to user related to this change
|
||||
svgedit.history.BatchCommand = function(text) {
|
||||
this.text = text || "Batch Command";
|
||||
svgedit.history.BatchCommand = function (text) {
|
||||
this.text = text || 'Batch Command';
|
||||
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;
|
||||
|
||||
// Function: svgedit.history.BatchCommand.getText
|
||||
svgedit.history.BatchCommand.prototype.getText = function() {
|
||||
svgedit.history.BatchCommand.prototype.getText = function () {
|
||||
return this.text;
|
||||
};
|
||||
|
||||
// Function: svgedit.history.BatchCommand.apply
|
||||
// Runs "apply" on all subcommands
|
||||
svgedit.history.BatchCommand.prototype.apply = function(handler) {
|
||||
svgedit.history.BatchCommand.prototype.apply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||
}
|
||||
@@ -422,13 +423,13 @@ svgedit.history.BatchCommand.prototype.apply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.BatchCommand.unapply
|
||||
// Runs "unapply" on all subcommands
|
||||
svgedit.history.BatchCommand.prototype.unapply = function(handler) {
|
||||
svgedit.history.BatchCommand.prototype.unapply = function (handler) {
|
||||
if (handler) {
|
||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -439,14 +440,14 @@ svgedit.history.BatchCommand.prototype.unapply = function(handler) {
|
||||
|
||||
// Function: svgedit.history.BatchCommand.elements
|
||||
// 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 cmd = this.stack.length;
|
||||
while (cmd--) {
|
||||
var thisElems = this.stack[cmd].elements();
|
||||
var elem = thisElems.length;
|
||||
while (elem--) {
|
||||
if (elems.indexOf(thisElems[elem]) == -1) {elems.push(thisElems[elem]);}
|
||||
if (elems.indexOf(thisElems[elem]) === -1) { elems.push(thisElems[elem]); }
|
||||
}
|
||||
}
|
||||
return elems;
|
||||
@@ -457,22 +458,21 @@ svgedit.history.BatchCommand.prototype.elements = function() {
|
||||
//
|
||||
// Parameters:
|
||||
// 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);
|
||||
};
|
||||
|
||||
// Function: svgedit.history.BatchCommand.isEmpty
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
// Class: svgedit.history.UndoManager
|
||||
// Parameters:
|
||||
// historyEventHandler - an object that conforms to the HistoryEventHandler interface
|
||||
// (see above)
|
||||
svgedit.history.UndoManager = function(historyEventHandler) {
|
||||
svgedit.history.UndoManager = function (historyEventHandler) {
|
||||
this.handler_ = historyEventHandler || null;
|
||||
this.undoStackPointer = 0;
|
||||
this.undoStack = [];
|
||||
@@ -485,7 +485,7 @@ svgedit.history.UndoManager = function(historyEventHandler) {
|
||||
|
||||
// Function: svgedit.history.UndoManager.resetUndoStack
|
||||
// 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.undoStackPointer = 0;
|
||||
};
|
||||
@@ -493,34 +493,34 @@ svgedit.history.UndoManager.prototype.resetUndoStack = function() {
|
||||
// Function: svgedit.history.UndoManager.getUndoStackSize
|
||||
// Returns:
|
||||
// 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;
|
||||
};
|
||||
|
||||
// Function: svgedit.history.UndoManager.getRedoStackSize
|
||||
// Returns:
|
||||
// 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;
|
||||
};
|
||||
|
||||
// Function: svgedit.history.UndoManager.getNextUndoCommandText
|
||||
// Returns:
|
||||
// String associated with the next undo command
|
||||
svgedit.history.UndoManager.prototype.getNextUndoCommandText = function() {
|
||||
return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer-1].getText() : "";
|
||||
svgedit.history.UndoManager.prototype.getNextUndoCommandText = function () {
|
||||
return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';
|
||||
};
|
||||
|
||||
// Function: svgedit.history.UndoManager.getNextRedoCommandText
|
||||
// Returns:
|
||||
// String associated with the next redo command
|
||||
svgedit.history.UndoManager.prototype.getNextRedoCommandText = function() {
|
||||
return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : "";
|
||||
svgedit.history.UndoManager.prototype.getNextRedoCommandText = function () {
|
||||
return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';
|
||||
};
|
||||
|
||||
// Function: svgedit.history.UndoManager.undo
|
||||
// Performs an undo step
|
||||
svgedit.history.UndoManager.prototype.undo = function() {
|
||||
svgedit.history.UndoManager.prototype.undo = function () {
|
||||
if (this.undoStackPointer > 0) {
|
||||
var cmd = this.undoStack[--this.undoStackPointer];
|
||||
cmd.unapply(this.handler_);
|
||||
@@ -529,7 +529,7 @@ svgedit.history.UndoManager.prototype.undo = function() {
|
||||
|
||||
// Function: svgedit.history.UndoManager.redo
|
||||
// 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) {
|
||||
var cmd = this.undoStack[this.undoStackPointer++];
|
||||
cmd.apply(this.handler_);
|
||||
@@ -541,7 +541,7 @@ svgedit.history.UndoManager.prototype.redo = function() {
|
||||
//
|
||||
// Parameters:
|
||||
// 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
|
||||
// (right now each keystroke is saved as a separate command that includes the
|
||||
// entire text contents of the text element)
|
||||
@@ -556,24 +556,23 @@ svgedit.history.UndoManager.prototype.addCommandToHistory = function(cmd) {
|
||||
this.undoStackPointer = this.undoStack.length;
|
||||
};
|
||||
|
||||
|
||||
// Function: svgedit.history.UndoManager.beginUndoableChange
|
||||
// This function tells the canvas to remember the old values of the
|
||||
// attrName attribute for each element sent in. The elements and values
|
||||
// are stored on a stack, so the next call to finishUndoableChange() will
|
||||
// This function tells the canvas to remember the old values of the
|
||||
// attrName attribute for each element sent in. The elements and values
|
||||
// are stored on a stack, so the next call to finishUndoableChange() will
|
||||
// pop the elements and old values off the stack, gets the current values
|
||||
// from the DOM and uses all of these to construct the undo-able command.
|
||||
//
|
||||
// Parameters:
|
||||
// attrName - The name of the attribute 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 i = elems.length;
|
||||
var oldValues = new Array(i), elements = new Array(i);
|
||||
while (i--) {
|
||||
var elem = elems[i];
|
||||
if (elem == null) {continue;}
|
||||
if (elem == null) { continue; }
|
||||
elements[i] = elem;
|
||||
oldValues[i] = elem.getAttribute(attrName);
|
||||
}
|
||||
@@ -591,23 +590,22 @@ svgedit.history.UndoManager.prototype.beginUndoableChange = function(attrName, e
|
||||
//
|
||||
// Returns:
|
||||
// Batch command object with resulting changes
|
||||
svgedit.history.UndoManager.prototype.finishUndoableChange = function() {
|
||||
svgedit.history.UndoManager.prototype.finishUndoableChange = function () {
|
||||
var p = this.undoChangeStackPointer--;
|
||||
var changeset = this.undoableChangeStack[p];
|
||||
var i = changeset.elements.length;
|
||||
var attrName = changeset.attrName;
|
||||
var batchCmd = new svgedit.history.BatchCommand("Change " + attrName);
|
||||
var batchCmd = new svgedit.history.BatchCommand('Change ' + attrName);
|
||||
while (i--) {
|
||||
var elem = changeset.elements[i];
|
||||
if (elem == null) {continue;}
|
||||
if (elem == null) { continue; }
|
||||
var changes = {};
|
||||
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));
|
||||
}
|
||||
}
|
||||
this.undoableChangeStack[p] = null;
|
||||
return batchCmd;
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgedit*/
|
||||
/*jslint vars: true, eqeq: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals svgedit */
|
||||
/**
|
||||
* Package: svgedit.history
|
||||
*
|
||||
@@ -11,8 +11,8 @@
|
||||
// Dependencies:
|
||||
// 1) history.js
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!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.
|
||||
* See singleton: HistoryRecordingService.NO_HISTORY
|
||||
*/
|
||||
var HistoryRecordingService = history.HistoryRecordingService = function(undoManager) {
|
||||
var HistoryRecordingService = history.HistoryRecordingService = function (undoManager) {
|
||||
this.undoManager_ = undoManager;
|
||||
this.currentBatchCommand_ = null;
|
||||
this.batchCommandStack_ = [];
|
||||
@@ -76,8 +76,8 @@ HistoryRecordingService.NO_HISTORY = new HistoryRecordingService();
|
||||
* @param {string} text - Optional string describing the batch command.
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.startBatchCommand = function(text) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.startBatchCommand = function (text) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
this.currentBatchCommand_ = new history.BatchCommand(text);
|
||||
this.batchCommandStack_.push(this.currentBatchCommand_);
|
||||
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.
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.endBatchCommand = function() {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.endBatchCommand = function () {
|
||||
if (!this.undoManager_) { return this; }
|
||||
if (this.currentBatchCommand_) {
|
||||
var batchCommand = this.currentBatchCommand_;
|
||||
this.batchCommandStack_.pop();
|
||||
var length = this.batchCommandStack_.length;
|
||||
this.currentBatchCommand_ = length ? this.batchCommandStack_[length-1] : null;
|
||||
this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null;
|
||||
this.addCommand_(batchCommand);
|
||||
}
|
||||
return this;
|
||||
@@ -107,8 +107,8 @@ HistoryRecordingService.prototype.endBatchCommand = function() {
|
||||
* @param {string} [text] - An optional string visible to user related to this change
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.moveElement = function(elem, oldNextSibling, oldParent, text) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.moveElement = function (elem, oldNextSibling, oldParent, text) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
this.addCommand_(new history.MoveElementCommand(elem, oldNextSibling, oldParent, text));
|
||||
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
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.insertElement = function(elem, text) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.insertElement = function (elem, text) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
this.addCommand_(new history.InsertElementCommand(elem, text));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a RemoveElementCommand to the history or current batch command
|
||||
* @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
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.removeElement = function(elem, oldNextSibling, oldParent, text) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.removeElement = function (elem, oldNextSibling, oldParent, text) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
this.addCommand_(new history.RemoveElementCommand(elem, oldNextSibling, oldParent, text));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add a ChangeElementCommand to the history or current batch command
|
||||
* @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
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
*/
|
||||
HistoryRecordingService.prototype.changeElement = function(elem, attrs, text) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.changeElement = function (elem, attrs, text) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
this.addCommand_(new history.ChangeElementCommand(elem, attrs, text));
|
||||
return this;
|
||||
};
|
||||
@@ -160,14 +158,12 @@ HistoryRecordingService.prototype.changeElement = function(elem, attrs, text) {
|
||||
* @returns {svgedit.history.HistoryRecordingService}
|
||||
* @private
|
||||
*/
|
||||
HistoryRecordingService.prototype.addCommand_ = function(cmd) {
|
||||
if (!this.undoManager_) {return this;}
|
||||
HistoryRecordingService.prototype.addCommand_ = function (cmd) {
|
||||
if (!this.undoManager_) { return this; }
|
||||
if (this.currentBatchCommand_) {
|
||||
this.currentBatchCommand_.addSubCommand(cmd);
|
||||
} else {
|
||||
this.undoManager_.addCommandToHistory(cmd);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}());
|
||||
|
||||
115
editor/jquery-svg.js
vendored
115
editor/jquery-svg.js
vendored
@@ -1,5 +1,5 @@
|
||||
/*globals $, jQuery */
|
||||
/*jslint vars: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, jQuery */
|
||||
/**
|
||||
* jQuery module to work with SVG.
|
||||
*
|
||||
@@ -10,65 +10,66 @@
|
||||
// Dependencies:
|
||||
// 1) jquery
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// This fixes $(...).attr() to work as expected with SVG elements.
|
||||
// Does not currently use *AttributeNS() since we rarely need that.
|
||||
// This fixes $(...).attr() to work as expected with SVG elements.
|
||||
// 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:
|
||||
// - 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
|
||||
// as an object with values for each given attributes
|
||||
// Additional functionality:
|
||||
// - 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
|
||||
// as an object with values for each given attributes
|
||||
|
||||
var proxied = jQuery.fn.attr,
|
||||
// TODO use NS.SVG instead
|
||||
svgns = "http://www.w3.org/2000/svg";
|
||||
jQuery.fn.attr = function(key, value) {
|
||||
var i, attr;
|
||||
var proxied = jQuery.fn.attr,
|
||||
// TODO use NS.SVG instead
|
||||
svgns = 'http://www.w3.org/2000/svg';
|
||||
jQuery.fn.attr = function (key, value) {
|
||||
var i, attr;
|
||||
var len = this.length;
|
||||
if (!len) {return proxied.apply(this, arguments);}
|
||||
for (i = 0; i < len; ++i) {
|
||||
var elem = this[i];
|
||||
// set/get SVG attribute
|
||||
if (elem.namespaceURI === svgns) {
|
||||
// Setting attribute
|
||||
if (value !== undefined) {
|
||||
elem.setAttribute(key, value);
|
||||
} else if ($.isArray(key)) {
|
||||
// Getting attributes from array
|
||||
var j = key.length, obj = {};
|
||||
if (!len) { return proxied.apply(this, arguments); }
|
||||
for (i = 0; i < len; ++i) {
|
||||
var elem = this[i];
|
||||
// set/get SVG attribute
|
||||
if (elem.namespaceURI === svgns) {
|
||||
// Setting attribute
|
||||
if (value !== undefined) {
|
||||
elem.setAttribute(key, value);
|
||||
} else if ($.isArray(key)) {
|
||||
// Getting attributes from array
|
||||
var j = key.length, obj = {};
|
||||
|
||||
while (j--) {
|
||||
var aname = key[j];
|
||||
attr = elem.getAttribute(aname);
|
||||
// This returns a number when appropriate
|
||||
if (attr || attr === "0") {
|
||||
attr = isNaN(attr) ? attr : (attr - 0);
|
||||
}
|
||||
obj[aname] = attr;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (typeof key === "object") {
|
||||
// Setting attributes form object
|
||||
var v;
|
||||
for (v in key) {
|
||||
elem.setAttribute(v, key[v]);
|
||||
}
|
||||
// Getting attribute
|
||||
} else {
|
||||
attr = elem.getAttribute(key);
|
||||
if (attr || attr === "0") {
|
||||
attr = isNaN(attr) ? attr : (attr - 0);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
} else {
|
||||
return proxied.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
while (j--) {
|
||||
var aname = key[j];
|
||||
attr = elem.getAttribute(aname);
|
||||
// This returns a number when appropriate
|
||||
if (attr || attr === '0') {
|
||||
attr = isNaN(attr) ? attr : (attr - 0);
|
||||
}
|
||||
obj[aname] = attr;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
if (typeof key === 'object') {
|
||||
// Setting attributes form object
|
||||
var v;
|
||||
for (v in key) {
|
||||
elem.setAttribute(v, key[v]);
|
||||
}
|
||||
// Getting attribute
|
||||
} else {
|
||||
attr = elem.getAttribute(key);
|
||||
if (attr || attr === '0') {
|
||||
attr = isNaN(attr) ? attr : (attr - 0);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
} else {
|
||||
return proxied.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals $ svgedit*/
|
||||
/*jslint vars: true, eqeq: true */
|
||||
/* eslint-disable no-var */
|
||||
/* globals $ svgedit */
|
||||
/**
|
||||
* Package: svgedit.history
|
||||
*
|
||||
@@ -13,15 +13,14 @@
|
||||
// 1) svgedit.js
|
||||
// 2) draw.js
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.draw) {
|
||||
svgedit.draw = {};
|
||||
}
|
||||
var NS = svgedit.NS;
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -39,17 +38,17 @@ var NS = svgedit.NS;
|
||||
* @param {SVGGElement=} svgElem - The SVG DOM element. If defined, use this to add
|
||||
* 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.group_ = svgElem ? null : group;
|
||||
|
||||
if (svgElem) {
|
||||
// Create a group element with title and add it to the DOM.
|
||||
var svgdoc = svgElem.ownerDocument;
|
||||
this.group_ = svgdoc.createElementNS(NS.SVG, "g");
|
||||
var layer_title = svgdoc.createElementNS(NS.SVG, "title");
|
||||
layer_title.textContent = name;
|
||||
this.group_.appendChild(layer_title);
|
||||
this.group_ = svgdoc.createElementNS(NS.SVG, 'g');
|
||||
var layerTitle = svgdoc.createElementNS(NS.SVG, 'title');
|
||||
layerTitle.textContent = name;
|
||||
this.group_.appendChild(layerTitle);
|
||||
if (group) {
|
||||
$(group).after(this.group_);
|
||||
} else {
|
||||
@@ -58,9 +57,11 @@ var Layer = svgedit.draw.Layer = function(name, group, svgElem) {
|
||||
}
|
||||
|
||||
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|$)');
|
||||
|
||||
|
||||
/**
|
||||
* Get the layer's name.
|
||||
* @returns {string} The layer name
|
||||
*/
|
||||
Layer.prototype.getName = function() {
|
||||
Layer.prototype.getName = function () {
|
||||
return this.name_;
|
||||
};
|
||||
|
||||
@@ -86,33 +86,33 @@ Layer.prototype.getName = function() {
|
||||
* Get the group element for this layer.
|
||||
* @returns {SVGGElement} The layer SVG group
|
||||
*/
|
||||
Layer.prototype.getGroup = function() {
|
||||
Layer.prototype.getGroup = function () {
|
||||
return this.group_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Active this layer so it takes pointer events.
|
||||
*/
|
||||
Layer.prototype.activate = function() {
|
||||
this.group_.setAttribute("style", "pointer-events:all");
|
||||
Layer.prototype.activate = function () {
|
||||
this.group_.setAttribute('style', 'pointer-events:all');
|
||||
};
|
||||
|
||||
/**
|
||||
* Deactive this layer so it does NOT take pointer events.
|
||||
*/
|
||||
Layer.prototype.deactivate = function() {
|
||||
this.group_.setAttribute("style", "pointer-events:none");
|
||||
Layer.prototype.deactivate = function () {
|
||||
this.group_.setAttribute('style', 'pointer-events:none');
|
||||
};
|
||||
|
||||
/**
|
||||
* Set this layer visible or hidden based on 'visible' parameter.
|
||||
* @param {boolean} visible - If true, make visible; otherwise, hide it.
|
||||
*/
|
||||
Layer.prototype.setVisible = function(visible) {
|
||||
var expected = visible === undefined || visible ? "inline" : "none";
|
||||
var oldDisplay = this.group_.getAttribute("display");
|
||||
Layer.prototype.setVisible = function (visible) {
|
||||
var expected = visible === undefined || visible ? 'inline' : 'none';
|
||||
var oldDisplay = this.group_.getAttribute('display');
|
||||
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?
|
||||
* @returns {boolean} True if visible.
|
||||
*/
|
||||
Layer.prototype.isVisible = function() {
|
||||
Layer.prototype.isVisible = function () {
|
||||
return this.group_.getAttribute('display') !== 'none';
|
||||
};
|
||||
|
||||
@@ -128,7 +128,7 @@ Layer.prototype.isVisible = function() {
|
||||
* Get layer opacity.
|
||||
* @returns {number} Opacity value.
|
||||
*/
|
||||
Layer.prototype.getOpacity = function() {
|
||||
Layer.prototype.getOpacity = function () {
|
||||
var opacity = this.group_.getAttribute('opacity');
|
||||
if (opacity === null || opacity === undefined) {
|
||||
return 1;
|
||||
@@ -141,7 +141,7 @@ Layer.prototype.getOpacity = function() {
|
||||
* nothing happens.
|
||||
* @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) {
|
||||
this.group_.setAttribute('opacity', opacity);
|
||||
}
|
||||
@@ -151,13 +151,13 @@ Layer.prototype.setOpacity = function(opacity) {
|
||||
* Append children 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) {
|
||||
this.group_.appendChild(children[i]);
|
||||
}
|
||||
};
|
||||
|
||||
Layer.prototype.getTitleElement = function() {
|
||||
Layer.prototype.getTitleElement = function () {
|
||||
var len = this.group_.childNodes.length;
|
||||
for (var i = 0; i < len; ++i) {
|
||||
var child = this.group_.childNodes.item(i);
|
||||
@@ -174,7 +174,7 @@ Layer.prototype.getTitleElement = function() {
|
||||
* @param {svgedit.history.HistoryRecordingService} hrService - History recording service
|
||||
* @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_;
|
||||
name = svgedit.utilities.toXml(name);
|
||||
// now change the underlying title element contents
|
||||
@@ -184,7 +184,7 @@ Layer.prototype.setName = function(name, hrService) {
|
||||
title.textContent = name;
|
||||
this.name_ = name;
|
||||
if (hrService) {
|
||||
hrService.changeElement(title, {'#text':previousName});
|
||||
hrService.changeElement(title, {'#text': previousName});
|
||||
}
|
||||
return this.name_;
|
||||
}
|
||||
@@ -196,27 +196,25 @@ Layer.prototype.setName = function(name, hrService) {
|
||||
* @param {SVGGElement} children - The children to append to this layer.
|
||||
* @returns {SVGGElement} The layer SVG group that was just removed.
|
||||
*/
|
||||
Layer.prototype.removeGroup = function() {
|
||||
Layer.prototype.removeGroup = function () {
|
||||
var parent = this.group_.parentNode;
|
||||
var group = parent.removeChild(this.group_);
|
||||
this.group_ = undefined;
|
||||
return group;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Add class Layer.CLASS_NAME to the element (usually class='layer').
|
||||
*
|
||||
* Parameters:
|
||||
* @param {SVGGElement} elem - The SVG element to update
|
||||
*/
|
||||
function addLayerClass(elem) {
|
||||
function addLayerClass (elem) {
|
||||
var classes = elem.getAttribute('class');
|
||||
if (classes === null || classes === undefined || classes.length === 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals svgedit*/
|
||||
/*jslint vars: true, eqeq: true */
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals svgedit */
|
||||
/**
|
||||
* Package: svedit.math
|
||||
*
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
// Dependencies:
|
||||
// None.
|
||||
|
||||
|
||||
/**
|
||||
* @typedef AngleCoord45
|
||||
* @type {object}
|
||||
@@ -20,7 +20,8 @@
|
||||
* @property {number} a - The angle at which to snap
|
||||
*/
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.math) {
|
||||
svgedit.math = {};
|
||||
@@ -41,12 +42,11 @@ var svg = document.createElementNS(svgedit.NS.SVG, 'svg');
|
||||
* @returns {object} An x, y object representing the transformed point
|
||||
*/
|
||||
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)
|
||||
* @param {SVGMatrix} m - The matrix object to check
|
||||
* @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This function tries to return a SVGMatrix that is the multiplication m1*m2.
|
||||
* 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
|
||||
*/
|
||||
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) {
|
||||
var m1 = args[i-1];
|
||||
var m1 = args[i - 1];
|
||||
m = m1.multiply(m);
|
||||
}
|
||||
if (Math.abs(m.a) < NEAR_ZERO) {m.a = 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.d) < NEAR_ZERO) {m.d = 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.a) < NEAR_ZERO) { m.a = 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.d) < NEAR_ZERO) { m.d = 0; }
|
||||
if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }
|
||||
if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }
|
||||
|
||||
return m;
|
||||
};
|
||||
@@ -85,11 +84,11 @@ svgedit.math.matrixMultiply = function (matr) {
|
||||
* @returns {boolean} Whether or not a matrix transform was found
|
||||
*/
|
||||
svgedit.math.hasMatrixTransform = function (tlist) {
|
||||
if (!tlist) {return false;}
|
||||
if (!tlist) { return false; }
|
||||
var num = tlist.numberOfItems;
|
||||
while (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;
|
||||
};
|
||||
@@ -164,15 +163,14 @@ svgedit.math.transformListToTransform = function (tlist, min, max) {
|
||||
var i;
|
||||
for (i = min; i <= max; ++i) {
|
||||
// if our indices are out of range, just use a harmless identity matrix
|
||||
var mtom = (i >= 0 && i < tlist.numberOfItems ?
|
||||
tlist.getItem(i).matrix :
|
||||
svg.createSVGMatrix());
|
||||
var mtom = (i >= 0 && i < tlist.numberOfItems
|
||||
? tlist.getItem(i).matrix
|
||||
: svg.createSVGMatrix());
|
||||
m = svgedit.math.matrixMultiply(m, mtom);
|
||||
}
|
||||
return svg.createSVGTransformFromMatrix(m);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get the matrix object for a given element
|
||||
* @param {Element} elem - The DOM element to check
|
||||
@@ -183,7 +181,6 @@ svgedit.math.getMatrix = function (elem) {
|
||||
return svgedit.math.transformListToTransform(tlist).matrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a 45 degree angle coordinate associated with the two given
|
||||
* coordinates
|
||||
@@ -208,7 +205,6 @@ svgedit.math.snapToAngle = function (x1, y1, x2, y2) {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if two rectangles (BBoxes objects) intersect each other
|
||||
* @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 + r2.height) > r1.y;
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
477
editor/path.js
477
editor/path.js
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit, svgroot*/
|
||||
/*jslint vars: true, eqeq: true, continue: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit, svgroot */
|
||||
/**
|
||||
* Package: svgedit.path
|
||||
*
|
||||
@@ -15,7 +15,8 @@
|
||||
// 3) math.js
|
||||
// 4) svgutils.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.path) {
|
||||
svgedit.path = {};
|
||||
@@ -41,33 +42,33 @@ var segData = {
|
||||
|
||||
var pathFuncs = [];
|
||||
|
||||
var link_control_pts = true;
|
||||
var linkControlPts = true;
|
||||
|
||||
// Stores references to paths via IDs.
|
||||
// TODO: Make this cross-document happy.
|
||||
var pathData = {};
|
||||
|
||||
svgedit.path.setLinkControlPoints = function(lcp) {
|
||||
link_control_pts = lcp;
|
||||
svgedit.path.setLinkControlPoints = function (lcp) {
|
||||
linkControlPts = lcp;
|
||||
};
|
||||
|
||||
svgedit.path.path = null;
|
||||
|
||||
var editorContext_ = null;
|
||||
|
||||
svgedit.path.init = function(editorContext) {
|
||||
svgedit.path.init = function (editorContext) {
|
||||
editorContext_ = editorContext;
|
||||
|
||||
pathFuncs = [0, 'ClosePath'];
|
||||
var pathFuncsStrs = ['Moveto', 'Lineto', 'CurvetoCubic', 'CurvetoQuadratic', 'Arc',
|
||||
'LinetoHorizontal', 'LinetoVertical', 'CurvetoCubicSmooth', 'CurvetoQuadraticSmooth'];
|
||||
$.each(pathFuncsStrs, function(i, s) {
|
||||
pathFuncs.push(s+'Abs');
|
||||
pathFuncs.push(s+'Rel');
|
||||
$.each(pathFuncsStrs, function (i, s) {
|
||||
pathFuncs.push(s + 'Abs');
|
||||
pathFuncs.push(s + 'Rel');
|
||||
});
|
||||
};
|
||||
|
||||
svgedit.path.insertItemBefore = function(elem, newseg, index) {
|
||||
svgedit.path.insertItemBefore = function (elem, newseg, index) {
|
||||
// Support insertItemBefore on paths for FF2
|
||||
var list = elem.pathSegList;
|
||||
|
||||
@@ -78,13 +79,13 @@ svgedit.path.insertItemBefore = function(elem, newseg, index) {
|
||||
var len = list.numberOfItems;
|
||||
var arr = [];
|
||||
var i;
|
||||
for (i=0; i < len; i++) {
|
||||
var cur_seg = list.getItem(i);
|
||||
arr.push(cur_seg);
|
||||
for (i = 0; i < len; i++) {
|
||||
var curSeg = list.getItem(i);
|
||||
arr.push(curSeg);
|
||||
}
|
||||
list.clear();
|
||||
for (i=0; i < len; i++) {
|
||||
if (i == index) { //index+1
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i == index) { // index + 1
|
||||
list.appendItem(newseg);
|
||||
}
|
||||
list.appendItem(arr[i]);
|
||||
@@ -92,20 +93,20 @@ svgedit.path.insertItemBefore = function(elem, newseg, index) {
|
||||
};
|
||||
|
||||
// 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 i, out = [];
|
||||
for (i = 0; i < len; i++) {
|
||||
out[i] = seg_item[arr[i]];
|
||||
out[i] = segItem[arr[i]];
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
svgedit.path.getGripPt = function(seg, alt_pt) {
|
||||
svgedit.path.getGripPt = function (seg, altPt) {
|
||||
var out = {
|
||||
x: alt_pt? alt_pt.x : seg.item.x,
|
||||
y: alt_pt? alt_pt.y : seg.item.y
|
||||
}, path = seg.path;
|
||||
x: altPt ? altPt.x : seg.item.x,
|
||||
y: altPt ? altPt.y : seg.item.y
|
||||
}, path = seg.path;
|
||||
|
||||
if (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;
|
||||
};
|
||||
|
||||
svgedit.path.getPointFromGrip = function(pt, path) {
|
||||
svgedit.path.getPointFromGrip = function (pt, path) {
|
||||
var out = {
|
||||
x: pt.x,
|
||||
y: pt.y
|
||||
@@ -136,11 +137,11 @@ svgedit.path.getPointFromGrip = function(pt, path) {
|
||||
return out;
|
||||
};
|
||||
|
||||
svgedit.path.addPointGrip = function(index, x, y) {
|
||||
svgedit.path.addPointGrip = function (index, x, y) {
|
||||
// create the container of all the point grips
|
||||
var pointGripContainer = svgedit.path.getGripContainer();
|
||||
|
||||
var pointGrip = svgedit.utilities.getElem('pathpointgrip_'+index);
|
||||
var pointGrip = svgedit.utilities.getElem('pathpointgrip_' + index);
|
||||
// create it
|
||||
if (!pointGrip) {
|
||||
pointGrip = document.createElementNS(NS.SVG, 'circle');
|
||||
@@ -157,8 +158,8 @@ svgedit.path.addPointGrip = function(index, x, y) {
|
||||
});
|
||||
pointGrip = pointGripContainer.appendChild(pointGrip);
|
||||
|
||||
var grip = $('#pathpointgrip_'+index);
|
||||
grip.dblclick(function() {
|
||||
var grip = $('#pathpointgrip_' + index);
|
||||
grip.dblclick(function () {
|
||||
if (svgedit.path.path) {
|
||||
svgedit.path.path.setSegType();
|
||||
}
|
||||
@@ -175,7 +176,7 @@ svgedit.path.addPointGrip = function(index, x, y) {
|
||||
return pointGrip;
|
||||
};
|
||||
|
||||
svgedit.path.getGripContainer = function() {
|
||||
svgedit.path.getGripContainer = function () {
|
||||
var c = svgedit.utilities.getElem('pathpointgrip_container');
|
||||
if (!c) {
|
||||
var parent = svgedit.utilities.getElem('selectorParentGroup');
|
||||
@@ -185,9 +186,9 @@ svgedit.path.getGripContainer = function() {
|
||||
return c;
|
||||
};
|
||||
|
||||
svgedit.path.addCtrlGrip = function(id) {
|
||||
var pointGrip = svgedit.utilities.getElem('ctrlpointgrip_'+id);
|
||||
if (pointGrip) {return pointGrip;}
|
||||
svgedit.path.addCtrlGrip = function (id) {
|
||||
var pointGrip = svgedit.utilities.getElem('ctrlpointgrip_' + id);
|
||||
if (pointGrip) { return pointGrip; }
|
||||
|
||||
pointGrip = document.createElementNS(NS.SVG, 'circle');
|
||||
svgedit.utilities.assignAttributes(pointGrip, {
|
||||
@@ -205,13 +206,13 @@ svgedit.path.addCtrlGrip = function(id) {
|
||||
return pointGrip;
|
||||
};
|
||||
|
||||
svgedit.path.getCtrlLine = function(id) {
|
||||
var ctrlLine = svgedit.utilities.getElem('ctrlLine_'+id);
|
||||
if (ctrlLine) {return ctrlLine;}
|
||||
svgedit.path.getCtrlLine = function (id) {
|
||||
var ctrlLine = svgedit.utilities.getElem('ctrlLine_' + id);
|
||||
if (ctrlLine) { return ctrlLine; }
|
||||
|
||||
ctrlLine = document.createElementNS(NS.SVG, 'line');
|
||||
svgedit.utilities.assignAttributes(ctrlLine, {
|
||||
'id': 'ctrlLine_'+id,
|
||||
'id': 'ctrlLine_' + id,
|
||||
'stroke': '#555',
|
||||
'stroke-width': 1,
|
||||
'style': 'pointer-events:none'
|
||||
@@ -220,7 +221,7 @@ svgedit.path.getCtrlLine = function(id) {
|
||||
return ctrlLine;
|
||||
};
|
||||
|
||||
svgedit.path.getPointGrip = function(seg, update) {
|
||||
svgedit.path.getPointGrip = function (seg, update) {
|
||||
var index = seg.index;
|
||||
var pointGrip = svgedit.path.addPointGrip(index);
|
||||
|
||||
@@ -236,17 +237,17 @@ svgedit.path.getPointGrip = function(seg, update) {
|
||||
return pointGrip;
|
||||
};
|
||||
|
||||
svgedit.path.getControlPoints = function(seg) {
|
||||
svgedit.path.getControlPoints = function (seg) {
|
||||
var item = seg.item;
|
||||
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 pointGripContainer = svgedit.path.getGripContainer();
|
||||
/* var pointGripContainer = */ svgedit.path.getGripContainer();
|
||||
|
||||
// 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;
|
||||
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 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 pt = svgedit.path.getGripPt(seg, {x: item['x' + i], y: item['y' + i]});
|
||||
var gpt = svgedit.path.getGripPt(seg, {x: segItems[i - 1].x, y: segItems[i - 1].y});
|
||||
|
||||
svgedit.utilities.assignAttributes(ctrlLine, {
|
||||
'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.
|
||||
svgedit.path.replacePathSeg = function(type, index, pts, elem) {
|
||||
svgedit.path.replacePathSeg = function (type, index, pts, elem) {
|
||||
var path = elem || svgedit.path.path.elem;
|
||||
|
||||
var func = 'createSVGPathSeg' + pathFuncs[type];
|
||||
@@ -295,8 +296,8 @@ svgedit.path.replacePathSeg = function(type, index, pts, elem) {
|
||||
var arr = [];
|
||||
var i;
|
||||
for (i = 0; i < len; i++) {
|
||||
var cur_seg = segList.getItem(i);
|
||||
arr.push(cur_seg);
|
||||
var curSeg = segList.getItem(i);
|
||||
arr.push(curSeg);
|
||||
}
|
||||
segList.clear();
|
||||
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 segLine = svgedit.utilities.getElem('segline_' + index);
|
||||
if (!segLine) {
|
||||
@@ -322,7 +323,7 @@ svgedit.path.getSegSelector = function(seg, update) {
|
||||
'fill': 'none',
|
||||
'stroke': '#0FF',
|
||||
'stroke-width': 2,
|
||||
'style':'pointer-events:none',
|
||||
'style': 'pointer-events:none',
|
||||
'd': 'M0,0 0,0'
|
||||
});
|
||||
pointGripContainer.appendChild(segLine);
|
||||
@@ -342,9 +343,9 @@ svgedit.path.getSegSelector = function(seg, update) {
|
||||
var pts = svgedit.path.ptObjToArr(seg.type, seg.item, true);
|
||||
var i;
|
||||
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+1] = pt.y;
|
||||
pts[i + 1] = pt.y;
|
||||
}
|
||||
|
||||
svgedit.path.replacePathSeg(seg.type, 1, pts, segLine);
|
||||
@@ -354,56 +355,55 @@ svgedit.path.getSegSelector = function(seg, update) {
|
||||
|
||||
// Function: smoothControlPoints
|
||||
// Takes three points and creates a smoother line based on them
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// Parameters:
|
||||
// ct1 - Object with x and y values (first control point)
|
||||
// ct2 - Object with x and y values (second control point)
|
||||
// pt - Object with x and y values (third point)
|
||||
//
|
||||
// Returns:
|
||||
// Returns:
|
||||
// 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
|
||||
var x1 = ct1.x - pt.x,
|
||||
y1 = ct1.y - pt.y,
|
||||
x2 = ct2.x - pt.x,
|
||||
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),
|
||||
angleb = Math.atan2(y2, x2),
|
||||
r1 = Math.sqrt(x1*x1+y1*y1),
|
||||
r2 = Math.sqrt(x2*x2+y2*y2),
|
||||
r1 = Math.sqrt(x1 * x1 + y1 * y1),
|
||||
r2 = Math.sqrt(x2 * x2 + y2 * y2),
|
||||
nct1 = editorContext_.getSVGRoot().createSVGPoint(),
|
||||
nct2 = editorContext_.getSVGRoot().createSVGPoint();
|
||||
if (anglea < 0) { anglea += 2*Math.PI; }
|
||||
if (angleb < 0) { angleb += 2*Math.PI; }
|
||||
if (anglea < 0) { anglea += 2 * Math.PI; }
|
||||
if (angleb < 0) { angleb += 2 * Math.PI; }
|
||||
|
||||
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) {
|
||||
new_anglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff);
|
||||
new_angleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff);
|
||||
}
|
||||
else {
|
||||
new_anglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff);
|
||||
new_angleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);
|
||||
newAnglea = angleBetween < Math.PI ? (anglea + angleDiff) : (anglea - angleDiff);
|
||||
newAngleb = angleBetween < Math.PI ? (angleb - angleDiff) : (angleb + angleDiff);
|
||||
} else {
|
||||
newAnglea = angleBetween < Math.PI ? (anglea - angleDiff) : (anglea + angleDiff);
|
||||
newAngleb = angleBetween < Math.PI ? (angleb + angleDiff) : (angleb - angleDiff);
|
||||
}
|
||||
|
||||
// rotate the points
|
||||
nct1.x = r1 * Math.cos(new_anglea) + pt.x;
|
||||
nct1.y = r1 * Math.sin(new_anglea) + pt.y;
|
||||
nct2.x = r2 * Math.cos(new_angleb) + pt.x;
|
||||
nct2.y = r2 * Math.sin(new_angleb) + pt.y;
|
||||
nct1.x = r1 * Math.cos(newAnglea) + pt.x;
|
||||
nct1.y = r1 * Math.sin(newAnglea) + pt.y;
|
||||
nct2.x = r2 * Math.cos(newAngleb) + pt.x;
|
||||
nct2.y = r2 * Math.sin(newAngleb) + pt.y;
|
||||
|
||||
return [nct1, nct2];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
svgedit.path.Segment = function(index, item) {
|
||||
svgedit.path.Segment = function (index, item) {
|
||||
this.selected = false;
|
||||
this.index = index;
|
||||
this.item = item;
|
||||
@@ -414,7 +414,7 @@ svgedit.path.Segment = function(index, item) {
|
||||
this.segsel = null;
|
||||
};
|
||||
|
||||
svgedit.path.Segment.prototype.showCtrlPts = function(y) {
|
||||
svgedit.path.Segment.prototype.showCtrlPts = function (y) {
|
||||
var i;
|
||||
for (i in this.ctrlpts) {
|
||||
if (this.ctrlpts.hasOwnProperty(i)) {
|
||||
@@ -423,12 +423,12 @@ svgedit.path.Segment.prototype.showCtrlPts = function(y) {
|
||||
}
|
||||
};
|
||||
|
||||
svgedit.path.Segment.prototype.selectCtrls = function(y) {
|
||||
$('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2').
|
||||
attr('fill', y ? '#0FF' : '#EEE');
|
||||
svgedit.path.Segment.prototype.selectCtrls = function (y) {
|
||||
$('#ctrlpointgrip_' + this.index + 'c1, #ctrlpointgrip_' + this.index + 'c2')
|
||||
.attr('fill', y ? '#0FF' : '#EEE');
|
||||
};
|
||||
|
||||
svgedit.path.Segment.prototype.show = function(y) {
|
||||
svgedit.path.Segment.prototype.show = function (y) {
|
||||
if (this.ptgrip) {
|
||||
this.ptgrip.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) {
|
||||
this.ptgrip.setAttribute('stroke', y ? '#0FF' : '#00F');
|
||||
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.ctrlpts = svgedit.path.getControlPoints(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) {
|
||||
var pt = svgedit.path.getGripPt(this);
|
||||
svgedit.utilities.assignAttributes(this.ptgrip, {
|
||||
@@ -475,23 +475,23 @@ svgedit.path.Segment.prototype.update = function(full) {
|
||||
}
|
||||
};
|
||||
|
||||
svgedit.path.Segment.prototype.move = function(dx, dy) {
|
||||
var cur_pts, item = this.item;
|
||||
svgedit.path.Segment.prototype.move = function (dx, dy) {
|
||||
var curPts, item = this.item;
|
||||
|
||||
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];
|
||||
} 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) {
|
||||
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];
|
||||
svgedit.path.replacePathSeg(this.next.type, this.next.index, next_pts);
|
||||
svgedit.path.replacePathSeg(this.next.type, this.next.index, nextPts);
|
||||
}
|
||||
|
||||
if (this.mate) {
|
||||
@@ -504,26 +504,26 @@ svgedit.path.Segment.prototype.move = function(dx, dy) {
|
||||
}
|
||||
|
||||
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;
|
||||
if (num == 2) {
|
||||
anum = 1;
|
||||
seg = this.next;
|
||||
if (!seg) {return;}
|
||||
if (!seg) { return; }
|
||||
pt = this.item;
|
||||
} else {
|
||||
anum = 2;
|
||||
seg = this.prev;
|
||||
if (!seg) {return;}
|
||||
if (!seg) { return; }
|
||||
pt = seg.item;
|
||||
}
|
||||
|
||||
var item = seg.item;
|
||||
item['x' + anum ] = pt.x + (pt.x - this.item['x' + num]);
|
||||
item['y' + anum ] = pt.y + (pt.y - this.item['y' + num]);
|
||||
item['x' + anum] = pt.x + (pt.x - this.item['x' + num]);
|
||||
item['y' + anum] = pt.y + (pt.y - this.item['y' + num]);
|
||||
|
||||
var pts = [item.x, item.y,
|
||||
item.x1, item.y1,
|
||||
@@ -533,30 +533,30 @@ svgedit.path.Segment.prototype.setLinked = function(num) {
|
||||
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;
|
||||
item['x' + num] += dx;
|
||||
item['y' + num] += dy;
|
||||
|
||||
var pts = [item.x,item.y,
|
||||
item.x1,item.y1, item.x2,item.y2];
|
||||
var pts = [item.x, item.y,
|
||||
item.x1, item.y1, item.x2, item.y2];
|
||||
|
||||
svgedit.path.replacePathSeg(this.type, this.index, pts);
|
||||
this.update(true);
|
||||
};
|
||||
|
||||
svgedit.path.Segment.prototype.setType = function(new_type, pts) {
|
||||
svgedit.path.replacePathSeg(new_type, this.index, pts);
|
||||
this.type = new_type;
|
||||
svgedit.path.Segment.prototype.setType = function (newType, pts) {
|
||||
svgedit.path.replacePathSeg(newType, this.index, pts);
|
||||
this.type = newType;
|
||||
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.update(true);
|
||||
};
|
||||
|
||||
svgedit.path.Path = function(elem) {
|
||||
svgedit.path.Path = function (elem) {
|
||||
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;
|
||||
@@ -568,11 +568,13 @@ svgedit.path.Path = function(elem) {
|
||||
};
|
||||
|
||||
// Reset path data
|
||||
svgedit.path.Path.prototype.init = function() {
|
||||
svgedit.path.Path.prototype.init = function () {
|
||||
// Hide all grips, etc
|
||||
|
||||
//fixed, needed to work on all found elements, not just first
|
||||
$(svgedit.path.getGripContainer()).find('*').each( function() { $(this).attr('display', 'none') });
|
||||
// fixed, needed to work on all found elements, not just first
|
||||
$(svgedit.path.getGripContainer()).find('*').each(function () {
|
||||
$(this).attr('display', 'none');
|
||||
});
|
||||
|
||||
var segList = this.elem.pathSegList;
|
||||
var len = segList.numberOfItems;
|
||||
@@ -590,58 +592,58 @@ svgedit.path.Path.prototype.init = function() {
|
||||
}
|
||||
|
||||
var segs = this.segs;
|
||||
var start_i = null;
|
||||
var startI = null;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
var seg = segs[i];
|
||||
var next_seg = (i+1) >= len ? null : segs[i+1];
|
||||
var prev_seg = (i-1) < 0 ? null : segs[i-1];
|
||||
var start_seg;
|
||||
var nextSeg = (i + 1) >= len ? null : segs[i + 1];
|
||||
var prevSeg = (i - 1) < 0 ? null : segs[i - 1];
|
||||
var startSeg;
|
||||
if (seg.type === 2) {
|
||||
if (prev_seg && prev_seg.type !== 1) {
|
||||
if (prevSeg && prevSeg.type !== 1) {
|
||||
// New sub-path, last one is open,
|
||||
// so add a grip to last sub-path's first point
|
||||
start_seg = segs[start_i];
|
||||
start_seg.next = segs[start_i+1];
|
||||
start_seg.next.prev = start_seg;
|
||||
start_seg.addGrip();
|
||||
startSeg = segs[startI];
|
||||
startSeg.next = segs[startI + 1];
|
||||
startSeg.next.prev = startSeg;
|
||||
startSeg.addGrip();
|
||||
}
|
||||
// Remember that this is a starter seg
|
||||
start_i = i;
|
||||
} else if (next_seg && next_seg.type === 1) {
|
||||
startI = i;
|
||||
} else if (nextSeg && nextSeg.type === 1) {
|
||||
// This is the last real segment of a closed sub-path
|
||||
// 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
|
||||
seg.next.prev = seg;
|
||||
seg.mate = segs[start_i];
|
||||
seg.mate = segs[startI];
|
||||
seg.addGrip();
|
||||
if (this.first_seg == null) {
|
||||
this.first_seg = seg;
|
||||
}
|
||||
} else if (!next_seg) {
|
||||
} else if (!nextSeg) {
|
||||
if (seg.type !== 1) {
|
||||
// Last seg, doesn't close so add a grip
|
||||
// to last sub-path's first point
|
||||
start_seg = segs[start_i];
|
||||
start_seg.next = segs[start_i+1];
|
||||
start_seg.next.prev = start_seg;
|
||||
start_seg.addGrip();
|
||||
startSeg = segs[startI];
|
||||
startSeg.next = segs[startI + 1];
|
||||
startSeg.next.prev = startSeg;
|
||||
startSeg.addGrip();
|
||||
seg.addGrip();
|
||||
|
||||
if (!this.first_seg) {
|
||||
// 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"
|
||||
seg.addGrip();
|
||||
|
||||
// Don't set its "next" if it's an "M"
|
||||
if (next_seg && next_seg.type !== 2) {
|
||||
seg.next = next_seg;
|
||||
if (nextSeg && nextSeg.type !== 2) {
|
||||
seg.next = nextSeg;
|
||||
seg.next.prev = seg;
|
||||
}
|
||||
}
|
||||
@@ -649,44 +651,44 @@ svgedit.path.Path.prototype.init = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.eachSeg = function(fn) {
|
||||
svgedit.path.Path.prototype.eachSeg = function (fn) {
|
||||
var i;
|
||||
var len = this.segs.length;
|
||||
for (i = 0; i < len; 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
|
||||
var seg = this.segs[index];
|
||||
if (!seg.prev) {return;}
|
||||
if (!seg.prev) { return; }
|
||||
|
||||
var prev = seg.prev;
|
||||
var newseg, new_x, new_y;
|
||||
switch(seg.item.pathSegType) {
|
||||
var newseg, newX, newY;
|
||||
switch (seg.item.pathSegType) {
|
||||
case 4:
|
||||
new_x = (seg.item.x + prev.item.x) / 2;
|
||||
new_y = (seg.item.y + prev.item.y) / 2;
|
||||
newseg = this.elem.createSVGPathSegLinetoAbs(new_x, new_y);
|
||||
newX = (seg.item.x + prev.item.x) / 2;
|
||||
newY = (seg.item.y + prev.item.y) / 2;
|
||||
newseg = this.elem.createSVGPathSegLinetoAbs(newX, newY);
|
||||
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
|
||||
var p0_x = (prev.item.x + seg.item.x1)/2;
|
||||
var p1_x = (seg.item.x1 + seg.item.x2)/2;
|
||||
var p2_x = (seg.item.x2 + seg.item.x)/2;
|
||||
var p01_x = (p0_x + p1_x)/2;
|
||||
var p12_x = (p1_x + p2_x)/2;
|
||||
new_x = (p01_x + p12_x)/2;
|
||||
var p0_y = (prev.item.y + seg.item.y1)/2;
|
||||
var p1_y = (seg.item.y1 + seg.item.y2)/2;
|
||||
var p2_y = (seg.item.y2 + seg.item.y)/2;
|
||||
var p01_y = (p0_y + p1_y)/2;
|
||||
var p12_y = (p1_y + p2_y)/2;
|
||||
new_y = (p01_y + p12_y)/2;
|
||||
newseg = this.elem.createSVGPathSegCurvetoCubicAbs(new_x, new_y, p0_x, p0_y, p01_x, p01_y);
|
||||
var pts = [seg.item.x, seg.item.y, p12_x, p12_y, p2_x, p2_y];
|
||||
var p0x = (prev.item.x + seg.item.x1) / 2;
|
||||
var p1x = (seg.item.x1 + seg.item.x2) / 2;
|
||||
var p2x = (seg.item.x2 + seg.item.x) / 2;
|
||||
var p01x = (p0x + p1x) / 2;
|
||||
var p12x = (p1x + p2x) / 2;
|
||||
newX = (p01x + p12x) / 2;
|
||||
var p0y = (prev.item.y + seg.item.y1) / 2;
|
||||
var p1y = (seg.item.y1 + seg.item.y2) / 2;
|
||||
var p2y = (seg.item.y2 + seg.item.y) / 2;
|
||||
var p01y = (p0y + p1y) / 2;
|
||||
var p12y = (p1y + p2y) / 2;
|
||||
newY = (p01y + p12y) / 2;
|
||||
newseg = this.elem.createSVGPathSegCurvetoCubicAbs(newX, newY, p0x, p0y, p01x, p01y);
|
||||
var pts = [seg.item.x, seg.item.y, p12x, p12y, p2x, p2y];
|
||||
svgedit.path.replacePathSeg(seg.type, index, pts);
|
||||
break;
|
||||
}
|
||||
@@ -694,7 +696,7 @@ svgedit.path.Path.prototype.addSeg = function(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 list = this.elem.pathSegList;
|
||||
|
||||
@@ -712,7 +714,7 @@ svgedit.path.Path.prototype.deleteSeg = function(index) {
|
||||
list.removeItem(seg.mate.index);
|
||||
} else if (!seg.prev) {
|
||||
// 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];
|
||||
svgedit.path.replacePathSeg(2, seg.next.index, pt);
|
||||
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;
|
||||
// Check if subpath is already open
|
||||
svgedit.path.path.eachSeg(function(i) {
|
||||
if (i <= index) {return true;}
|
||||
svgedit.path.path.eachSeg(function (i) {
|
||||
if (i <= index) { return true; }
|
||||
if (this.type === 2) {
|
||||
// Found M first, so open
|
||||
return false;
|
||||
@@ -740,7 +742,7 @@ svgedit.path.Path.prototype.subpathIsClosed = function(index) {
|
||||
return closed;
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.removePtFromSelection = function(index) {
|
||||
svgedit.path.Path.prototype.removePtFromSelection = function (index) {
|
||||
var pos = this.selected_pts.indexOf(index);
|
||||
if (pos == -1) {
|
||||
return;
|
||||
@@ -749,21 +751,21 @@ svgedit.path.Path.prototype.removePtFromSelection = function(index) {
|
||||
this.selected_pts.splice(pos, 1);
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.clearSelection = function() {
|
||||
this.eachSeg(function() {
|
||||
svgedit.path.Path.prototype.clearSelection = function () {
|
||||
this.eachSeg(function () {
|
||||
// 'this' is the segment here
|
||||
this.select(false);
|
||||
});
|
||||
this.selected_pts = [];
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.storeD = function() {
|
||||
svgedit.path.Path.prototype.storeD = function () {
|
||||
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
|
||||
this.eachSeg(function() {
|
||||
this.eachSeg(function () {
|
||||
// 'this' is the segment here
|
||||
this.show(y);
|
||||
});
|
||||
@@ -774,90 +776,90 @@ svgedit.path.Path.prototype.show = function(y) {
|
||||
};
|
||||
|
||||
// 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;
|
||||
while(i--) {
|
||||
while (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]];
|
||||
seg.moveCtrl(this.dragctrl, d_x, d_y);
|
||||
if (link_control_pts) {
|
||||
seg.moveCtrl(this.dragctrl, dx, dy);
|
||||
if (linkControlPts) {
|
||||
seg.setLinked(this.dragctrl);
|
||||
}
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.setSegType = function(new_type) {
|
||||
svgedit.path.Path.prototype.setSegType = function (newType) {
|
||||
this.storeD();
|
||||
var i = this.selected_pts.length;
|
||||
var text;
|
||||
while(i--) {
|
||||
var sel_pt = this.selected_pts[i];
|
||||
while (i--) {
|
||||
var selPt = this.selected_pts[i];
|
||||
|
||||
// Selected seg
|
||||
var cur = this.segs[sel_pt];
|
||||
var cur = this.segs[selPt];
|
||||
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';
|
||||
|
||||
// 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 cur_y = cur.item.y;
|
||||
var prev_x = prev.item.x;
|
||||
var prev_y = prev.item.y;
|
||||
var curX = cur.item.x;
|
||||
var curY = cur.item.y;
|
||||
var prevX = prev.item.x;
|
||||
var prevY = prev.item.y;
|
||||
var points;
|
||||
switch ( new_type ) {
|
||||
switch (newType) {
|
||||
case 6:
|
||||
if (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 {
|
||||
var diff_x = cur_x - prev_x;
|
||||
var diff_y = cur_y - prev_y;
|
||||
var diffX = curX - prevX;
|
||||
var diffY = curY - prevY;
|
||||
// get control points from straight line segment
|
||||
/*
|
||||
var ct1_x = (prev_x + (diff_y/2));
|
||||
var ct1_y = (prev_y - (diff_x/2));
|
||||
var ct2_x = (cur_x + (diff_y/2));
|
||||
var ct2_y = (cur_y - (diff_x/2));
|
||||
var ct1x = (prevX + (diffY/2));
|
||||
var ct1y = (prevY - (diffX/2));
|
||||
var ct2x = (curX + (diffY/2));
|
||||
var ct2y = (curY - (diffX/2));
|
||||
*/
|
||||
//create control points on the line to preserve the shape (WRS)
|
||||
var ct1_x = (prev_x + (diff_x/3));
|
||||
var ct1_y = (prev_y + (diff_y/3));
|
||||
var ct2_x = (cur_x - (diff_x/3));
|
||||
var ct2_y = (cur_y - (diff_y/3));
|
||||
points = [cur_x, cur_y, ct1_x, ct1_y, ct2_x, ct2_y];
|
||||
// create control points on the line to preserve the shape (WRS)
|
||||
var ct1x = (prevX + (diffX / 3));
|
||||
var ct1y = (prevY + (diffY / 3));
|
||||
var ct2x = (curX - (diffX / 3));
|
||||
var ct2y = (curY - (diffY / 3));
|
||||
points = [curX, curY, ct1x, ct1y, ct2x, ct2y];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
points = [cur_x, cur_y];
|
||||
points = [curX, curY];
|
||||
|
||||
// Store original prevve segment nums
|
||||
cur.olditem = cur.item;
|
||||
break;
|
||||
}
|
||||
|
||||
cur.setType(new_type, points);
|
||||
cur.setType(newType, points);
|
||||
}
|
||||
svgedit.path.path.endChanges(text);
|
||||
};
|
||||
|
||||
svgedit.path.Path.prototype.selectPt = function(pt, ctrl_num) {
|
||||
svgedit.path.Path.prototype.selectPt = function (pt, ctrlNum) {
|
||||
this.clearSelection();
|
||||
if (pt == null) {
|
||||
this.eachSeg(function(i) {
|
||||
this.eachSeg(function (i) {
|
||||
// 'this' is the segment here.
|
||||
if (this.prev) {
|
||||
pt = i;
|
||||
@@ -865,17 +867,17 @@ svgedit.path.Path.prototype.selectPt = function(pt, ctrl_num) {
|
||||
});
|
||||
}
|
||||
this.addPtsToSelection(pt);
|
||||
if (ctrl_num) {
|
||||
this.dragctrl = ctrl_num;
|
||||
if (ctrlNum) {
|
||||
this.dragctrl = ctrlNum;
|
||||
|
||||
if (link_control_pts) {
|
||||
this.segs[pt].setLinked(ctrl_num);
|
||||
if (linkControlPts) {
|
||||
this.segs[pt].setLinked(ctrlNum);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Update position of all points
|
||||
svgedit.path.Path.prototype.update = function() {
|
||||
svgedit.path.Path.prototype.update = function () {
|
||||
var elem = this.elem;
|
||||
if (svgedit.utilities.getRotationAngle(elem)) {
|
||||
this.matrix = svgedit.math.getMatrix(elem);
|
||||
@@ -885,7 +887,7 @@ svgedit.path.Path.prototype.update = function() {
|
||||
this.imatrix = null;
|
||||
}
|
||||
|
||||
this.eachSeg(function(i) {
|
||||
this.eachSeg(function (i) {
|
||||
this.item = elem.pathSegList.getItem(i);
|
||||
this.update();
|
||||
});
|
||||
@@ -893,7 +895,7 @@ svgedit.path.Path.prototype.update = function() {
|
||||
return this;
|
||||
};
|
||||
|
||||
svgedit.path.getPath_ = function(elem) {
|
||||
svgedit.path.getPath_ = function (elem) {
|
||||
var p = pathData[elem.id];
|
||||
if (!p) {
|
||||
p = pathData[elem.id] = new svgedit.path.Path(elem);
|
||||
@@ -901,16 +903,16 @@ svgedit.path.getPath_ = function(elem) {
|
||||
return p;
|
||||
};
|
||||
|
||||
svgedit.path.removePath_ = function(id) {
|
||||
if (id in pathData) {delete pathData[id];}
|
||||
svgedit.path.removePath_ = function (id) {
|
||||
if (id in pathData) { delete pathData[id]; }
|
||||
};
|
||||
var newcx, newcy, oldcx, oldcy, angle;
|
||||
var getRotVals = function(x, y) {
|
||||
var getRotVals = function (x, y) {
|
||||
var dx = x - oldcx;
|
||||
var dy = y - oldcy;
|
||||
|
||||
// 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;
|
||||
dx = r * Math.cos(theta) + oldcx;
|
||||
dy = r * Math.sin(theta) + oldcy;
|
||||
@@ -922,7 +924,7 @@ var getRotVals = function(x, y) {
|
||||
dx -= newcx;
|
||||
dy -= newcy;
|
||||
|
||||
r = Math.sqrt(dx*dx + dy*dy);
|
||||
r = Math.sqrt(dx * dx + dy * dy);
|
||||
theta = Math.atan2(dy, dx) - angle;
|
||||
|
||||
return {'x': r * Math.cos(theta) + newcx,
|
||||
@@ -930,67 +932,66 @@ var getRotVals = function(x, y) {
|
||||
};
|
||||
|
||||
// If the path was rotated, we must now pay the piper:
|
||||
// Every path point must be rotated into the rotated coordinate system of
|
||||
// Every path point must be rotated into the rotated coordinate system of
|
||||
// its old center, then determine the new center, then rotate it back
|
||||
// This is because we want the path to remember its rotation
|
||||
|
||||
// TODO: This is still using ye olde transform methods, can probably
|
||||
// be optimized or even taken care of by recalculateDimensions
|
||||
svgedit.path.recalcRotatedPath = function() {
|
||||
var current_path = svgedit.path.path.elem;
|
||||
angle = svgedit.utilities.getRotationAngle(current_path, true);
|
||||
if (!angle) {return;}
|
||||
// selectedBBoxes[0] = svgedit.path.path.oldbbox;
|
||||
var box = svgedit.utilities.getBBox(current_path),
|
||||
oldbox = svgedit.path.path.oldbbox; //selectedBBoxes[0],
|
||||
oldcx = oldbox.x + oldbox.width/2;
|
||||
oldcy = oldbox.y + oldbox.height/2;
|
||||
newcx = box.x + box.width/2;
|
||||
newcy = box.y + box.height/2;
|
||||
svgedit.path.recalcRotatedPath = function () {
|
||||
var currentPath = svgedit.path.path.elem;
|
||||
angle = svgedit.utilities.getRotationAngle(currentPath, true);
|
||||
if (!angle) { return; }
|
||||
// selectedBBoxes[0] = svgedit.path.path.oldbbox;
|
||||
var box = svgedit.utilities.getBBox(currentPath),
|
||||
oldbox = svgedit.path.path.oldbbox; // selectedBBoxes[0],
|
||||
oldcx = oldbox.x + oldbox.width / 2;
|
||||
oldcy = oldbox.y + oldbox.height / 2;
|
||||
newcx = box.x + box.width / 2;
|
||||
newcy = box.y + box.height / 2;
|
||||
|
||||
// un-rotate the new center to the proper position
|
||||
var dx = newcx - oldcx,
|
||||
dy = newcy - oldcy,
|
||||
r = Math.sqrt(dx*dx + dy*dy),
|
||||
r = Math.sqrt(dx * dx + dy * dy),
|
||||
theta = Math.atan2(dy, dx) + angle;
|
||||
|
||||
newcx = r * Math.cos(theta) + oldcx;
|
||||
newcy = r * Math.sin(theta) + oldcy;
|
||||
|
||||
var list = current_path.pathSegList,
|
||||
var list = currentPath.pathSegList,
|
||||
i = list.numberOfItems;
|
||||
while (i) {
|
||||
i -= 1;
|
||||
var seg = list.getItem(i),
|
||||
type = seg.pathSegType;
|
||||
if (type == 1) {continue;}
|
||||
if (type == 1) { continue; }
|
||||
|
||||
var rvals = getRotVals(seg.x, seg.y),
|
||||
points = [rvals.x, rvals.y];
|
||||
if (seg.x1 != null && seg.x2 != null) {
|
||||
var c_vals1 = getRotVals(seg.x1, seg.y1);
|
||||
var c_vals2 = getRotVals(seg.x2, seg.y2);
|
||||
points.splice(points.length, 0, c_vals1.x , c_vals1.y, c_vals2.x, c_vals2.y);
|
||||
var cVals1 = getRotVals(seg.x1, seg.y1);
|
||||
var cVals2 = getRotVals(seg.x2, seg.y2);
|
||||
points.splice(points.length, 0, cVals1.x, cVals1.y, cVals2.x, cVals2.y);
|
||||
}
|
||||
svgedit.path.replacePathSeg(type, i, points);
|
||||
} // loop for each point
|
||||
|
||||
box = svgedit.utilities.getBBox(current_path);
|
||||
// selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;
|
||||
// selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;
|
||||
box = svgedit.utilities.getBBox(currentPath);
|
||||
// selectedBBoxes[0].x = box.x; selectedBBoxes[0].y = box.y;
|
||||
// selectedBBoxes[0].width = box.width; selectedBBoxes[0].height = box.height;
|
||||
|
||||
// now we must set the new transform to be rotated around the new center
|
||||
var R_nc = svgroot.createSVGTransform(),
|
||||
tlist = svgedit.transformlist.getTransformList(current_path);
|
||||
R_nc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);
|
||||
tlist.replaceItem(R_nc,0);
|
||||
var Rnc = svgroot.createSVGTransform(),
|
||||
tlist = svgedit.transformlist.getTransformList(currentPath);
|
||||
Rnc.setRotate((angle * 180.0 / Math.PI), newcx, newcy);
|
||||
tlist.replaceItem(Rnc, 0);
|
||||
};
|
||||
|
||||
// ====================================
|
||||
// Public API starts here
|
||||
|
||||
svgedit.path.clearData = function() {
|
||||
svgedit.path.clearData = function () {
|
||||
pathData = {};
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
1712
editor/pathseg.js
1712
editor/pathseg.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* Package: svgedit.sanitize
|
||||
*
|
||||
@@ -15,98 +15,99 @@
|
||||
// 3) browser.js
|
||||
// 4) svgutils.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.sanitize) {
|
||||
svgedit.sanitize = {};
|
||||
svgedit.sanitize = {};
|
||||
}
|
||||
|
||||
var NS = svgedit.NS,
|
||||
REVERSE_NS = svgedit.getReverseNS();
|
||||
REVERSE_NS = svgedit.getReverseNS();
|
||||
|
||||
// this defines which elements and attributes that we support
|
||||
var svgWhiteList_ = {
|
||||
// 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"],
|
||||
"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"],
|
||||
"defs": [],
|
||||
"style" : ["type"],
|
||||
"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"],
|
||||
"feGaussianBlur": ["class", "color-interpolation-filters", "id", "requiredFeatures", "stdDeviation"],
|
||||
"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"],
|
||||
"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"],
|
||||
"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"],
|
||||
"marker": ["id", "class", "markerHeight", "markerUnits", "markerWidth", "orient", "preserveAspectRatio", "refX", "refY", "systemLanguage", "viewBox"],
|
||||
"mask": ["class", "height", "id", "maskContentUnits", "maskUnits", "width", "x", "y"],
|
||||
"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"],
|
||||
"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"],
|
||||
"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"],
|
||||
"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"],
|
||||
"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"],
|
||||
"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"],
|
||||
"textPath": ["class", "id", "method", "requiredFeatures", "spacing", "startOffset", "style", "systemLanguage", "transform", "xlink:href"],
|
||||
"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"],
|
||||
"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"],
|
||||
// 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'],
|
||||
'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'],
|
||||
'defs': [],
|
||||
'style': ['type'],
|
||||
'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'],
|
||||
'feGaussianBlur': ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
|
||||
'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'],
|
||||
'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'],
|
||||
'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'],
|
||||
'marker': ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
|
||||
'mask': ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
|
||||
'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'],
|
||||
'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'],
|
||||
'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'],
|
||||
'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'],
|
||||
'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'],
|
||||
'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'],
|
||||
'textPath': ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
|
||||
'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'],
|
||||
'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
|
||||
"annotation": ["encoding"],
|
||||
"annotation-xml": ["encoding"],
|
||||
"maction": ["actiontype", "other", "selection"],
|
||||
"math": ["class", "id", "display", "xmlns"],
|
||||
"menclose": ["notation"],
|
||||
"merror": [],
|
||||
"mfrac": ["linethickness"],
|
||||
"mi": ["mathvariant"],
|
||||
"mmultiscripts": [],
|
||||
"mn": [],
|
||||
"mo": ["fence", "lspace", "maxsize", "minsize", "rspace", "stretchy"],
|
||||
"mover": [],
|
||||
"mpadded": ["lspace", "width", "height", "depth", "voffset"],
|
||||
"mphantom": [],
|
||||
"mprescripts": [],
|
||||
"mroot": [],
|
||||
"mrow": ["xlink:href", "xlink:type", "xmlns:xlink"],
|
||||
"mspace": ["depth", "height", "width"],
|
||||
"msqrt": [],
|
||||
"mstyle": ["displaystyle", "mathbackground", "mathcolor", "mathvariant", "scriptlevel"],
|
||||
"msub": [],
|
||||
"msubsup": [],
|
||||
"msup": [],
|
||||
"mtable": ["align", "columnalign", "columnlines", "columnspacing", "displaystyle", "equalcolumns", "equalrows", "frame", "rowalign", "rowlines", "rowspacing", "width"],
|
||||
"mtd": ["columnalign", "columnspan", "rowalign", "rowspan"],
|
||||
"mtext": [],
|
||||
"mtr": ["columnalign", "rowalign"],
|
||||
"munder": [],
|
||||
"munderover": [],
|
||||
"none": [],
|
||||
"semantics": []
|
||||
// MathML Elements
|
||||
'annotation': ['encoding'],
|
||||
'annotation-xml': ['encoding'],
|
||||
'maction': ['actiontype', 'other', 'selection'],
|
||||
'math': ['class', 'id', 'display', 'xmlns'],
|
||||
'menclose': ['notation'],
|
||||
'merror': [],
|
||||
'mfrac': ['linethickness'],
|
||||
'mi': ['mathvariant'],
|
||||
'mmultiscripts': [],
|
||||
'mn': [],
|
||||
'mo': ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],
|
||||
'mover': [],
|
||||
'mpadded': ['lspace', 'width', 'height', 'depth', 'voffset'],
|
||||
'mphantom': [],
|
||||
'mprescripts': [],
|
||||
'mroot': [],
|
||||
'mrow': ['xlink:href', 'xlink:type', 'xmlns:xlink'],
|
||||
'mspace': ['depth', 'height', 'width'],
|
||||
'msqrt': [],
|
||||
'mstyle': ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],
|
||||
'msub': [],
|
||||
'msubsup': [],
|
||||
'msup': [],
|
||||
'mtable': ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],
|
||||
'mtd': ['columnalign', 'columnspan', 'rowalign', 'rowspan'],
|
||||
'mtext': [],
|
||||
'mtr': ['columnalign', 'rowalign'],
|
||||
'munder': [],
|
||||
'munderover': [],
|
||||
'none': [],
|
||||
'semantics': []
|
||||
};
|
||||
|
||||
// Produce a Namespace-aware version of svgWhitelist
|
||||
var svgWhiteListNS_ = {};
|
||||
$.each(svgWhiteList_, function(elt, atts){
|
||||
var attNS = {};
|
||||
$.each(atts, function(i, att){
|
||||
if (att.indexOf(':') >= 0) {
|
||||
var v = att.split(':');
|
||||
attNS[v[1]] = NS[(v[0]).toUpperCase()];
|
||||
} else {
|
||||
attNS[att] = att == 'xmlns' ? NS.XMLNS : null;
|
||||
}
|
||||
});
|
||||
svgWhiteListNS_[elt] = attNS;
|
||||
$.each(svgWhiteList_, function (elt, atts) {
|
||||
var attNS = {};
|
||||
$.each(atts, function (i, att) {
|
||||
if (att.indexOf(':') >= 0) {
|
||||
var v = att.split(':');
|
||||
attNS[v[1]] = NS[(v[0]).toUpperCase()];
|
||||
} else {
|
||||
attNS[att] = att == 'xmlns' ? NS.XMLNS : null;
|
||||
}
|
||||
});
|
||||
svgWhiteListNS_[elt] = attNS;
|
||||
});
|
||||
|
||||
// Function: svgedit.sanitize.sanitizeSvg
|
||||
@@ -115,145 +116,141 @@ $.each(svgWhiteList_, function(elt, atts){
|
||||
//
|
||||
// Parameters:
|
||||
// node - The DOM element to be checked (we'll also check its children)
|
||||
svgedit.sanitize.sanitizeSvg = function(node) {
|
||||
// Cleanup text nodes
|
||||
if (node.nodeType == 3) { // 3 == TEXT_NODE
|
||||
// Trim whitespace
|
||||
node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
// Remove if empty
|
||||
if (node.nodeValue.length === 0) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
svgedit.sanitize.sanitizeSvg = function (node) {
|
||||
// Cleanup text nodes
|
||||
if (node.nodeType == 3) { // 3 == TEXT_NODE
|
||||
// Trim whitespace
|
||||
node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
// Remove if empty
|
||||
if (node.nodeValue.length === 0) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
// We only care about element nodes.
|
||||
// Automatically return for all non-element nodes, such as comments, etc.
|
||||
if (node.nodeType != 1) { // 1 == ELEMENT_NODE
|
||||
return;
|
||||
}
|
||||
// We only care about element nodes.
|
||||
// Automatically return for all non-element nodes, such as comments, etc.
|
||||
if (node.nodeType != 1) { // 1 == ELEMENT_NODE
|
||||
return;
|
||||
}
|
||||
|
||||
var doc = node.ownerDocument;
|
||||
var parent = node.parentNode;
|
||||
// can parent ever be null here? I think the root node's parent is the document...
|
||||
if (!doc || !parent) {
|
||||
return;
|
||||
}
|
||||
var doc = node.ownerDocument;
|
||||
var parent = node.parentNode;
|
||||
// can parent ever be null here? I think the root node's parent is the document...
|
||||
if (!doc || !parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
var allowedAttrs = svgWhiteList_[node.nodeName];
|
||||
var allowedAttrsNS = svgWhiteListNS_[node.nodeName];
|
||||
var i;
|
||||
// if this element is supported, sanitize it
|
||||
if (typeof allowedAttrs !== 'undefined') {
|
||||
var allowedAttrs = svgWhiteList_[node.nodeName];
|
||||
var allowedAttrsNS = svgWhiteListNS_[node.nodeName];
|
||||
var i;
|
||||
// if this element is supported, sanitize it
|
||||
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 = [];
|
||||
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);
|
||||
}
|
||||
// Add spaces before negative signs where necessary
|
||||
if (svgedit.browser.isGecko()) {
|
||||
switch (attrName) {
|
||||
case 'transform':
|
||||
case 'gradientTransform':
|
||||
case 'patternTransform':
|
||||
var val = attr.value.replace(/(\d)-/g, '$1 -');
|
||||
node.setAttribute(attrName, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add spaces before negative signs where necessary
|
||||
if (svgedit.browser.isGecko()) {
|
||||
switch (attrName) {
|
||||
case 'transform':
|
||||
case 'gradientTransform':
|
||||
case 'patternTransform':
|
||||
var val = attr.value.replace(/(\d)-/g, '$1 -');
|
||||
node.setAttribute(attrName, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// For the style attribute, rewrite it in terms of XML presentational attributes
|
||||
if (attrName == 'style') {
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
// For the style attribute, rewrite it in terms of XML presentational attributes
|
||||
if (attrName == 'style') {
|
||||
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) {
|
||||
node.setAttributeNS(NS.SE, attr[0], attr[1]);
|
||||
});
|
||||
|
||||
$.each(seAttrs, function(i, attr) {
|
||||
node.setAttributeNS(NS.SE, attr[0], attr[1]);
|
||||
});
|
||||
// for some elements that have a xlink:href, ensure the URI refers to a local element
|
||||
// (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
|
||||
// (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');
|
||||
}
|
||||
}
|
||||
// Safari crashes on a <use> without a xlink:href, so we just remove the node here
|
||||
if (node.nodeName == 'use' && !svgedit.utilities.getHref(node)) {
|
||||
parent.removeChild(node);
|
||||
return;
|
||||
}
|
||||
// if the element has attributes pointing to a non-local reference,
|
||||
// need to remove the attribute
|
||||
$.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (i, attr) {
|
||||
var val = node.getAttribute(attr);
|
||||
if (val) {
|
||||
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
|
||||
if (node.nodeName == 'use' && !svgedit.utilities.getHref(node)) {
|
||||
parent.removeChild(node);
|
||||
return;
|
||||
}
|
||||
// if the element has attributes pointing to a non-local reference,
|
||||
// need to remove the attribute
|
||||
$.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function(i, attr) {
|
||||
var val = node.getAttribute(attr);
|
||||
if (val) {
|
||||
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
|
||||
i = node.childNodes.length;
|
||||
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));
|
||||
}
|
||||
|
||||
// recurse to children
|
||||
i = node.childNodes.length;
|
||||
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
|
||||
parent.removeChild(node);
|
||||
|
||||
// remove this node from the document altogether
|
||||
parent.removeChild(node);
|
||||
|
||||
// call sanitizeSvg on each of those children
|
||||
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]); }
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
176
editor/select.js
176
editor/select.js
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true, forin: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* Package: svedit.select
|
||||
*
|
||||
@@ -16,7 +16,8 @@
|
||||
// 4) math.js
|
||||
// 5) svgutils.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.select) {
|
||||
svgedit.select = {};
|
||||
@@ -34,7 +35,7 @@ var gripRadius = svgedit.browser.isTouch() ? 10 : 4;
|
||||
// id - integer to internally indentify the selector
|
||||
// elem - DOM element associated with this selector
|
||||
// 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.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.gripCoords = {
|
||||
'nw': null,
|
||||
'n' : null,
|
||||
'n': null,
|
||||
'ne': null,
|
||||
'e' : null,
|
||||
'e': null,
|
||||
'se': null,
|
||||
's' : null,
|
||||
's': null,
|
||||
'sw': null,
|
||||
'w' : null
|
||||
'w': null
|
||||
};
|
||||
|
||||
this.reset(this.selectedElement, bbox);
|
||||
};
|
||||
|
||||
|
||||
// Function: svgedit.select.Selector.reset
|
||||
// Used to reset the id and element that the selector is attached to
|
||||
//
|
||||
// Parameters:
|
||||
// e - DOM element associated with this selector
|
||||
// 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.selectedElement = e;
|
||||
this.resize(bbox);
|
||||
this.selectorGroup.setAttribute('display', 'inline');
|
||||
};
|
||||
|
||||
|
||||
// Function: svgedit.select.Selector.updateGripCursors
|
||||
// Updates cursors for corner grips on rotation so arrows point the right way
|
||||
//
|
||||
// Parameters:
|
||||
// angle - Float indicating current rotation angle in degrees
|
||||
svgedit.select.Selector.prototype.updateGripCursors = function(angle) {
|
||||
svgedit.select.Selector.prototype.updateGripCursors = function (angle) {
|
||||
var dir,
|
||||
dir_arr = [],
|
||||
dirArr = [],
|
||||
steps = Math.round(angle / 45);
|
||||
if (steps < 0) {steps += 8;}
|
||||
if (steps < 0) { steps += 8; }
|
||||
for (dir in selectorManager_.selectorGrips) {
|
||||
dir_arr.push(dir);
|
||||
dirArr.push(dir);
|
||||
}
|
||||
while (steps > 0) {
|
||||
dir_arr.push(dir_arr.shift());
|
||||
dirArr.push(dirArr.shift());
|
||||
steps--;
|
||||
}
|
||||
var i = 0;
|
||||
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++;
|
||||
}
|
||||
};
|
||||
@@ -125,7 +124,7 @@ svgedit.select.Selector.prototype.updateGripCursors = function(angle) {
|
||||
//
|
||||
// Parameters:
|
||||
// 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';
|
||||
selectorManager_.selectorGripsGroup.setAttribute('display', bShow);
|
||||
var elem = this.selectedElement;
|
||||
@@ -139,21 +138,21 @@ svgedit.select.Selector.prototype.showGrips = function(show) {
|
||||
// Function: svgedit.select.Selector.resize
|
||||
// Updates the selector to match the element's size
|
||||
// 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,
|
||||
mgr = selectorManager_,
|
||||
selectedGrips = mgr.selectorGrips,
|
||||
selected = this.selectedElement,
|
||||
sw = selected.getAttribute('stroke-width'),
|
||||
current_zoom = svgFactory_.currentZoom();
|
||||
var offset = 1/current_zoom;
|
||||
currentZoom = svgFactory_.currentZoom();
|
||||
var offset = 1 / currentZoom;
|
||||
if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {
|
||||
offset += (sw/2);
|
||||
offset += (sw / 2);
|
||||
}
|
||||
|
||||
var tagName = selected.tagName;
|
||||
if (tagName === 'text') {
|
||||
offset += 2/current_zoom;
|
||||
offset += 2 / currentZoom;
|
||||
}
|
||||
|
||||
// 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
|
||||
// it keeps the selection box correctly positioned when zoomed
|
||||
m.e *= current_zoom;
|
||||
m.f *= current_zoom;
|
||||
m.e *= currentZoom;
|
||||
m.f *= currentZoom;
|
||||
|
||||
if (!bbox) {
|
||||
bbox = svgedit.utilities.getBBox(selected);
|
||||
@@ -173,23 +172,23 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
|
||||
if (tagName === 'g' && !$.data(selected, 'gsvg')) {
|
||||
// The bbox for a group does not include stroke vals, so we
|
||||
// get the bbox based on its children.
|
||||
var stroked_bbox = svgFactory_.getStrokedBBox(selected.childNodes);
|
||||
if (stroked_bbox) {
|
||||
bbox = stroked_bbox;
|
||||
var strokedBbox = svgFactory_.getStrokedBBox(selected.childNodes);
|
||||
if (strokedBbox) {
|
||||
bbox = strokedBbox;
|
||||
}
|
||||
}
|
||||
|
||||
// apply the transforms
|
||||
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
|
||||
// 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,
|
||||
nbax = aabox.x - offset,
|
||||
nbay = aabox.y - offset,
|
||||
@@ -197,8 +196,8 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
|
||||
nbah = aabox.height + (offset * 2);
|
||||
|
||||
// now if the shape is rotated, un-rotate it
|
||||
var cx = nbax + nbaw/2,
|
||||
cy = nbay + nbah/2;
|
||||
var cx = nbax + nbaw / 2,
|
||||
cy = nbay + nbah / 2;
|
||||
|
||||
var angle = svgedit.utilities.getRotationAngle(selected);
|
||||
if (angle) {
|
||||
@@ -219,59 +218,58 @@ svgedit.select.Selector.prototype.resize = function(bbox) {
|
||||
|
||||
var min = Math.min, max = Math.max;
|
||||
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
nbax = minx;
|
||||
nbay = miny;
|
||||
nbaw = (maxx-minx);
|
||||
nbah = (maxy-miny);
|
||||
nbaw = (maxx - minx);
|
||||
nbah = (maxy - miny);
|
||||
}
|
||||
|
||||
var dstr = 'M' + nbax + ',' + nbay
|
||||
+ ' L' + (nbax+nbaw) + ',' + nbay
|
||||
+ ' ' + (nbax+nbaw) + ',' + (nbay+nbah)
|
||||
+ ' ' + nbax + ',' + (nbay+nbah) + 'z';
|
||||
var dstr = 'M' + nbax + ',' + nbay +
|
||||
' L' + (nbax + nbaw) + ',' + nbay +
|
||||
' ' + (nbax + nbaw) + ',' + (nbay + nbah) +
|
||||
' ' + nbax + ',' + (nbay + nbah) + 'z';
|
||||
selectedBox.setAttribute('d', dstr);
|
||||
|
||||
var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';
|
||||
this.selectorGroup.setAttribute('transform', xform);
|
||||
|
||||
// TODO(codedread): Is this if needed?
|
||||
// if (selected === selectedElements[0]) {
|
||||
this.gripCoords = {
|
||||
'nw': [nbax, nbay],
|
||||
'ne': [nbax+nbaw, nbay],
|
||||
'sw': [nbax, nbay+nbah],
|
||||
'se': [nbax+nbaw, nbay+nbah],
|
||||
'n': [nbax + (nbaw)/2, nbay],
|
||||
'w': [nbax, nbay + (nbah)/2],
|
||||
'e': [nbax + nbaw, nbay + (nbah)/2],
|
||||
's': [nbax + (nbaw)/2, nbay + nbah]
|
||||
};
|
||||
var dir;
|
||||
for (dir in this.gripCoords) {
|
||||
var coords = this.gripCoords[dir];
|
||||
selectedGrips[dir].setAttribute('cx', coords[0]);
|
||||
selectedGrips[dir].setAttribute('cy', coords[1]);
|
||||
}
|
||||
// if (selected === selectedElements[0]) {
|
||||
this.gripCoords = {
|
||||
'nw': [nbax, nbay],
|
||||
'ne': [nbax + nbaw, nbay],
|
||||
'sw': [nbax, nbay + nbah],
|
||||
'se': [nbax + nbaw, nbay + nbah],
|
||||
'n': [nbax + (nbaw) / 2, nbay],
|
||||
'w': [nbax, nbay + (nbah) / 2],
|
||||
'e': [nbax + nbaw, nbay + (nbah) / 2],
|
||||
's': [nbax + (nbaw) / 2, nbay + nbah]
|
||||
};
|
||||
var dir;
|
||||
for (dir in this.gripCoords) {
|
||||
var coords = this.gripCoords[dir];
|
||||
selectedGrips[dir].setAttribute('cx', coords[0]);
|
||||
selectedGrips[dir].setAttribute('cy', coords[1]);
|
||||
}
|
||||
|
||||
// we want to go 20 pixels in the negative transformed y direction, ignoring scale
|
||||
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw)/2);
|
||||
mgr.rotateGripConnector.setAttribute('y1', nbay);
|
||||
mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw)/2);
|
||||
mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius*5));
|
||||
// we want to go 20 pixels in the negative transformed y direction, ignoring scale
|
||||
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);
|
||||
mgr.rotateGripConnector.setAttribute('y1', nbay);
|
||||
mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);
|
||||
mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));
|
||||
|
||||
mgr.rotateGrip.setAttribute('cx', nbax + (nbaw)/2);
|
||||
mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius*5));
|
||||
// }
|
||||
mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);
|
||||
mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// 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.selectorParentGroup = null;
|
||||
|
||||
@@ -287,13 +285,13 @@ svgedit.select.SelectorManager = function() {
|
||||
// this holds a reference to the grip elements
|
||||
this.selectorGrips = {
|
||||
'nw': null,
|
||||
'n' : null,
|
||||
'n': null,
|
||||
'ne': null,
|
||||
'e' : null,
|
||||
'e': null,
|
||||
'se': null,
|
||||
's' : null,
|
||||
's': null,
|
||||
'sw': null,
|
||||
'w' : null
|
||||
'w': null
|
||||
};
|
||||
|
||||
this.selectorGripsGroup = null;
|
||||
@@ -305,7 +303,7 @@ svgedit.select.SelectorManager = function() {
|
||||
|
||||
// Function: svgedit.select.SelectorManager.initGroup
|
||||
// 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
|
||||
if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {
|
||||
this.selectorParentGroup.parentNode.removeChild(this.selectorParentGroup);
|
||||
@@ -378,7 +376,7 @@ svgedit.select.SelectorManager.prototype.initGroup = function() {
|
||||
);
|
||||
$.data(this.rotateGrip, 'type', 'rotate');
|
||||
|
||||
if ($('#canvasBackground').length) {return;}
|
||||
if ($('#canvasBackground').length) { return; }
|
||||
|
||||
var dims = config_.dimensions;
|
||||
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
|
||||
// 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);
|
||||
svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());
|
||||
};
|
||||
@@ -421,12 +419,12 @@ svgedit.select.SelectorManager.prototype.initGroup = function() {
|
||||
// Parameters:
|
||||
// elem - DOM element to get the selector for
|
||||
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
||||
svgedit.select.SelectorManager.prototype.requestSelector = function(elem, bbox) {
|
||||
if (elem == null) {return null;}
|
||||
svgedit.select.SelectorManager.prototype.requestSelector = function (elem, bbox) {
|
||||
if (elem == null) { return null; }
|
||||
var i,
|
||||
N = this.selectors.length;
|
||||
// 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;
|
||||
return this.selectorMap[elem.id];
|
||||
}
|
||||
@@ -450,8 +448,8 @@ svgedit.select.SelectorManager.prototype.requestSelector = function(elem, bbox)
|
||||
//
|
||||
// Parameters:
|
||||
// elem - DOM element to remove the selector for
|
||||
svgedit.select.SelectorManager.prototype.releaseSelector = function(elem) {
|
||||
if (elem == null) {return;}
|
||||
svgedit.select.SelectorManager.prototype.releaseSelector = function (elem) {
|
||||
if (elem == null) { return; }
|
||||
var i,
|
||||
N = this.selectors.length,
|
||||
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
|
||||
try {
|
||||
sel.selectorGroup.setAttribute('display', 'none');
|
||||
} catch(e) { }
|
||||
} catch (e) {}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -478,7 +476,7 @@ svgedit.select.SelectorManager.prototype.releaseSelector = function(elem) {
|
||||
|
||||
// Function: svgedit.select.SelectorManager.getRubberBandBox
|
||||
// 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) {
|
||||
this.rubberBandBox = this.selectorParentGroup.appendChild(
|
||||
svgFactory_.createSVGElement({
|
||||
@@ -498,7 +496,6 @@ svgedit.select.SelectorManager.prototype.getRubberBandBox = function() {
|
||||
return this.rubberBandBox;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface: svgedit.select.SVGFactory
|
||||
* 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)
|
||||
* svgFactory - an object implementing the SVGFactory interface (see above).
|
||||
*/
|
||||
svgedit.select.init = function(config, svgFactory) {
|
||||
svgedit.select.init = function (config, svgFactory) {
|
||||
config_ = config;
|
||||
svgFactory_ = svgFactory;
|
||||
selectorManager_ = new svgedit.select.SelectorManager();
|
||||
@@ -533,8 +530,7 @@ svgedit.select.init = function(config, svgFactory) {
|
||||
* Returns:
|
||||
* The SelectorManager instance.
|
||||
*/
|
||||
svgedit.select.getSelectorManager = function() {
|
||||
svgedit.select.getSelectorManager = function () {
|
||||
return selectorManager_;
|
||||
};
|
||||
|
||||
}());
|
||||
}());
|
||||
|
||||
9504
editor/svg-editor.js
9504
editor/svg-editor.js
File diff suppressed because it is too large
Load Diff
3053
editor/svgcanvas.js
3053
editor/svgcanvas.js
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, svgedit:true */
|
||||
/**
|
||||
*
|
||||
* Licensed under the MIT License
|
||||
@@ -19,10 +20,11 @@ svgedit = {
|
||||
};
|
||||
|
||||
// return the svgedit.NS with key values switched and lowercase
|
||||
svgedit.getReverseNS = function() {'use strict';
|
||||
svgedit.getReverseNS = function () {
|
||||
'use strict';
|
||||
var reverseNS = {};
|
||||
$.each(this.NS, function(name, URI) {
|
||||
$.each(this.NS, function (name, URI) {
|
||||
reverseNS[URI] = name.toLowerCase();
|
||||
});
|
||||
return reverseNS;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var, eqeqeq */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* SVGTransformList
|
||||
*
|
||||
@@ -12,7 +12,8 @@
|
||||
// Dependencies:
|
||||
// 1) browser.js
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.transformlist) {
|
||||
svgedit.transformlist = {};
|
||||
@@ -21,48 +22,49 @@ if (!svgedit.transformlist) {
|
||||
var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
|
||||
|
||||
// Helper function.
|
||||
function transformToString(xform) {
|
||||
function transformToString (xform) {
|
||||
var m = xform.matrix,
|
||||
text = '';
|
||||
switch(xform.type) {
|
||||
case 1: // MATRIX
|
||||
text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
|
||||
break;
|
||||
case 2: // TRANSLATE
|
||||
text = 'translate(' + m.e + ',' + m.f + ')';
|
||||
break;
|
||||
case 3: // SCALE
|
||||
if (m.a == m.d) {text = 'scale(' + m.a + ')';}
|
||||
else {text = 'scale(' + m.a + ',' + m.d + ')';}
|
||||
break;
|
||||
case 4: // ROTATE
|
||||
var cx = 0, cy = 0;
|
||||
// this prevents divide by zero
|
||||
if (xform.angle != 0) {
|
||||
var K = 1 - m.a;
|
||||
cy = ( K * m.f + m.b*m.e ) / ( K*K + m.b*m.b );
|
||||
cx = ( m.e - m.b * cy ) / K;
|
||||
}
|
||||
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
|
||||
break;
|
||||
switch (xform.type) {
|
||||
case 1: // MATRIX
|
||||
text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
|
||||
break;
|
||||
case 2: // TRANSLATE
|
||||
text = 'translate(' + m.e + ',' + m.f + ')';
|
||||
break;
|
||||
case 3: // SCALE
|
||||
if (m.a == m.d) {
|
||||
text = 'scale(' + m.a + ')';
|
||||
} else {
|
||||
text = 'scale(' + m.a + ',' + m.d + ')';
|
||||
}
|
||||
break;
|
||||
case 4: // ROTATE
|
||||
var cx = 0, cy = 0;
|
||||
// this prevents divide by zero
|
||||
if (xform.angle != 0) {
|
||||
var K = 1 - m.a;
|
||||
cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);
|
||||
cx = (m.e - m.b * cy) / K;
|
||||
}
|
||||
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
|
||||
break;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map of SVGTransformList objects.
|
||||
*/
|
||||
var listMap_ = {};
|
||||
|
||||
|
||||
// **************************************************************************************
|
||||
// SVGTransformList implementation for Webkit
|
||||
// SVGTransformList implementation for Webkit
|
||||
// These methods do not currently raise any exceptions.
|
||||
// These methods also do not check that transforms are being inserted. This is basically
|
||||
// implementing as much of SVGTransformList that we need to get the job done.
|
||||
//
|
||||
// interface SVGEditTransformList {
|
||||
// interface SVGEditTransformList {
|
||||
// attribute unsigned long numberOfItems;
|
||||
// void clear ( )
|
||||
// SVGTransform initialize ( in SVGTransform newItem )
|
||||
@@ -75,13 +77,13 @@ var listMap_ = {};
|
||||
// NOT IMPLEMENTED: SVGTransform consolidate ( );
|
||||
// }
|
||||
// **************************************************************************************
|
||||
svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
svgedit.transformlist.SVGTransformList = function (elem) {
|
||||
this._elem = elem || null;
|
||||
this._xforms = [];
|
||||
// TODO: how do we capture the undo-ability in the changed transform list?
|
||||
this._update = function() {
|
||||
this._update = function () {
|
||||
var tstr = '';
|
||||
var concatMatrix = svgroot.createSVGMatrix();
|
||||
/* var concatMatrix = */ svgroot.createSVGMatrix();
|
||||
var i;
|
||||
for (i = 0; i < this.numberOfItems; ++i) {
|
||||
var xform = this._list.getItem(i);
|
||||
@@ -90,10 +92,10 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
this._elem.setAttribute('transform', tstr);
|
||||
};
|
||||
this._list = this;
|
||||
this._init = function() {
|
||||
this._init = function () {
|
||||
// Transform attribute parser
|
||||
var str = this._elem.getAttribute('transform');
|
||||
if (!str) {return;}
|
||||
if (!str) { return; }
|
||||
|
||||
// TODO: Add skew support in future
|
||||
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
||||
@@ -105,20 +107,20 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
var x = m[1];
|
||||
var bits = x.split(/\s*\(/);
|
||||
var name = bits[0];
|
||||
var val_bits = bits[1].match(/\s*(.*?)\s*\)/);
|
||||
val_bits[1] = val_bits[1].replace(/(\d)-/g, '$1 -');
|
||||
var val_arr = val_bits[1].split(/[, ]+/);
|
||||
var valBits = bits[1].match(/\s*(.*?)\s*\)/);
|
||||
valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
|
||||
var valArr = valBits[1].split(/[, ]+/);
|
||||
var letters = 'abcdef'.split('');
|
||||
var mtx = svgroot.createSVGMatrix();
|
||||
$.each(val_arr, function(i, item) {
|
||||
val_arr[i] = parseFloat(item);
|
||||
$.each(valArr, function (i, item) {
|
||||
valArr[i] = parseFloat(item);
|
||||
if (name == 'matrix') {
|
||||
mtx[letters[i]] = val_arr[i];
|
||||
mtx[letters[i]] = valArr[i];
|
||||
}
|
||||
});
|
||||
var xform = svgroot.createSVGTransform();
|
||||
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) {
|
||||
values.push(values[0]);
|
||||
@@ -132,7 +134,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
}
|
||||
}
|
||||
};
|
||||
this._removeFromOtherLists = function(item) {
|
||||
this._removeFromOtherLists = function (item) {
|
||||
if (item) {
|
||||
// Check if this transform is already in a transformlist, and
|
||||
// remove it if so.
|
||||
@@ -156,25 +158,27 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
};
|
||||
|
||||
this.numberOfItems = 0;
|
||||
this.clear = function() {
|
||||
this.clear = function () {
|
||||
this.numberOfItems = 0;
|
||||
this._xforms = [];
|
||||
};
|
||||
|
||||
this.initialize = function(newItem) {
|
||||
this.initialize = function (newItem) {
|
||||
this.numberOfItems = 1;
|
||||
this._removeFromOtherLists(newItem);
|
||||
this._xforms = [newItem];
|
||||
};
|
||||
|
||||
this.getItem = function(index) {
|
||||
this.getItem = function (index) {
|
||||
if (index < this.numberOfItems && index >= 0) {
|
||||
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;
|
||||
if (index >= 0) {
|
||||
if (index < this.numberOfItems) {
|
||||
@@ -187,22 +191,21 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
}
|
||||
newxforms[i] = newItem;
|
||||
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];
|
||||
}
|
||||
this.numberOfItems++;
|
||||
this._xforms = newxforms;
|
||||
retValue = newItem;
|
||||
this._list._update();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
retValue = this._list.appendItem(newItem);
|
||||
}
|
||||
}
|
||||
return retValue;
|
||||
};
|
||||
|
||||
this.replaceItem = function(newItem, index) {
|
||||
this.replaceItem = function (newItem, index) {
|
||||
var retValue = null;
|
||||
if (index < this.numberOfItems && index >= 0) {
|
||||
this._removeFromOtherLists(newItem);
|
||||
@@ -213,7 +216,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
return retValue;
|
||||
};
|
||||
|
||||
this.removeItem = function(index) {
|
||||
this.removeItem = function (index) {
|
||||
if (index < this.numberOfItems && index >= 0) {
|
||||
var retValue = this._xforms[index];
|
||||
var newxforms = new Array(this.numberOfItems - 1);
|
||||
@@ -221,18 +224,20 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
for (i = 0; i < index; ++i) {
|
||||
newxforms[i] = this._xforms[i];
|
||||
}
|
||||
for (j = i; j < this.numberOfItems-1; ++j, ++i) {
|
||||
newxforms[j] = this._xforms[i+1];
|
||||
for (j = i; j < this.numberOfItems - 1; ++j, ++i) {
|
||||
newxforms[j] = this._xforms[i + 1];
|
||||
}
|
||||
this.numberOfItems--;
|
||||
this._xforms = newxforms;
|
||||
this._list._update();
|
||||
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._xforms.push(newItem);
|
||||
this.numberOfItems++;
|
||||
@@ -241,8 +246,7 @@ svgedit.transformlist.SVGTransformList = function(elem) {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
svgedit.transformlist.resetListMap = function() {
|
||||
svgedit.transformlist.resetListMap = function () {
|
||||
listMap_ = {};
|
||||
};
|
||||
|
||||
@@ -251,7 +255,7 @@ svgedit.transformlist.resetListMap = function() {
|
||||
* Parameters:
|
||||
* elem - a DOM Element
|
||||
*/
|
||||
svgedit.transformlist.removeElementFromListMap = function(elem) {
|
||||
svgedit.transformlist.removeElementFromListMap = function (elem) {
|
||||
if (elem.id && listMap_[elem.id]) {
|
||||
delete listMap_[elem.id];
|
||||
}
|
||||
@@ -262,7 +266,7 @@ svgedit.transformlist.removeElementFromListMap = function(elem) {
|
||||
//
|
||||
// Parameters:
|
||||
// elem - DOM element to get a transformlist from
|
||||
svgedit.transformlist.getTransformList = function(elem) {
|
||||
svgedit.transformlist.getTransformList = function (elem) {
|
||||
if (!svgedit.browser.supportsNativeTransformLists()) {
|
||||
var id = elem.id || 'temp';
|
||||
var t = listMap_[id];
|
||||
@@ -285,5 +289,4 @@ svgedit.transformlist.getTransformList = function(elem) {
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
}());
|
||||
}());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +1,28 @@
|
||||
/* eslint-disable no-var */
|
||||
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
|
||||
function touchHandler(event) {'use strict';
|
||||
function touchHandler (event) {
|
||||
'use strict';
|
||||
|
||||
var simulatedEvent,
|
||||
touches = event.changedTouches,
|
||||
first = touches[0],
|
||||
type = "";
|
||||
type = '';
|
||||
switch (event.type) {
|
||||
case "touchstart": type = "mousedown"; break;
|
||||
case "touchmove": type = "mousemove"; break;
|
||||
case "touchend": type = "mouseup"; break;
|
||||
default: return;
|
||||
case 'touchstart': type = 'mousedown'; break;
|
||||
case 'touchmove': type = 'mousemove'; break;
|
||||
case 'touchend': type = 'mouseup'; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
// initMouseEvent(type, canBubble, cancelable, view, clickCount,
|
||||
// screenX, screenY, clientX, clientY, ctrlKey,
|
||||
// initMouseEvent(type, canBubble, cancelable, view, clickCount,
|
||||
// screenX, screenY, clientX, clientY, ctrlKey,
|
||||
// altKey, shiftKey, metaKey, button, relatedTarget);
|
||||
|
||||
simulatedEvent = document.createEvent("MouseEvent");
|
||||
simulatedEvent = document.createEvent('MouseEvent');
|
||||
simulatedEvent.initMouseEvent(type, true, true, window, 1,
|
||||
first.screenX, first.screenY,
|
||||
first.clientX, first.clientY, false,
|
||||
false, false, false, 0/*left*/, null);
|
||||
first.screenX, first.screenY,
|
||||
first.clientX, first.clientY, false,
|
||||
false, false, false, 0/* left */, null);
|
||||
if (touches.length < 2) {
|
||||
first.target.dispatchEvent(simulatedEvent);
|
||||
event.preventDefault();
|
||||
@@ -30,4 +32,4 @@ function touchHandler(event) {'use strict';
|
||||
document.addEventListener('touchstart', touchHandler, true);
|
||||
document.addEventListener('touchmove', touchHandler, true);
|
||||
document.addEventListener('touchend', touchHandler, true);
|
||||
document.addEventListener('touchcancel', touchHandler, true);
|
||||
document.addEventListener('touchcancel', touchHandler, true);
|
||||
|
||||
121
editor/units.js
121
editor/units.js
@@ -1,5 +1,5 @@
|
||||
/*globals $, svgedit*/
|
||||
/*jslint vars: true, eqeq: true*/
|
||||
/* eslint-disable no-var */
|
||||
/* globals $, svgedit */
|
||||
/**
|
||||
* Package: svgedit.units
|
||||
*
|
||||
@@ -12,7 +12,8 @@
|
||||
// Dependencies:
|
||||
// 1) jQuery
|
||||
|
||||
(function() {'use strict';
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
if (!svgedit.units) {
|
||||
svgedit.units = {};
|
||||
@@ -23,8 +24,9 @@ var wAttrs = ['x', 'x1', 'cx', 'rx', 'width'];
|
||||
var hAttrs = ['y', 'y1', 'cy', 'ry', 'height'];
|
||||
var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs);
|
||||
// unused
|
||||
/*
|
||||
var unitNumMap = {
|
||||
'%': 2,
|
||||
'%': 2,
|
||||
'em': 3,
|
||||
'ex': 4,
|
||||
'px': 5,
|
||||
@@ -34,7 +36,7 @@ var unitNumMap = {
|
||||
'pt': 9,
|
||||
'pc': 10
|
||||
};
|
||||
|
||||
*/
|
||||
// Container of elements.
|
||||
var elementContainer_;
|
||||
|
||||
@@ -60,7 +62,7 @@ var typeMap_ = {};
|
||||
* Parameters:
|
||||
* elementContainer - an object implementing the ElementContainer interface.
|
||||
*/
|
||||
svgedit.units.init = function(elementContainer) {
|
||||
svgedit.units.init = function (elementContainer) {
|
||||
elementContainer_ = elementContainer;
|
||||
|
||||
// Get correct em/ex values by creating a temporary SVG.
|
||||
@@ -92,7 +94,7 @@ svgedit.units.init = function(elementContainer) {
|
||||
|
||||
// Function: svgedit.units.getTypeMap
|
||||
// Returns the unit object with values for each unit
|
||||
svgedit.units.getTypeMap = function() {
|
||||
svgedit.units.getTypeMap = function () {
|
||||
return typeMap_;
|
||||
};
|
||||
|
||||
@@ -105,7 +107,7 @@ svgedit.units.getTypeMap = function() {
|
||||
// Returns:
|
||||
// If a string/number was given, returns a Float. If an array, return a string
|
||||
// with comma-seperated floats
|
||||
svgedit.units.shortFloat = function(val) {
|
||||
svgedit.units.shortFloat = function (val) {
|
||||
var digits = elementContainer_.getRoundDigits();
|
||||
if (!isNaN(val)) {
|
||||
// Note that + converts to Number
|
||||
@@ -119,11 +121,11 @@ svgedit.units.shortFloat = function(val) {
|
||||
|
||||
// Function: svgedit.units.convertUnit
|
||||
// Converts the number to given unit or baseUnit
|
||||
svgedit.units.convertUnit = function(val, unit) {
|
||||
svgedit.units.convertUnit = function (val, unit) {
|
||||
unit = unit || elementContainer_.getBaseUnit();
|
||||
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
|
||||
// var val = baseVal.valueInSpecifiedUnits;
|
||||
// baseVal.convertToSpecifiedUnits(1);
|
||||
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
|
||||
// var val = baseVal.valueInSpecifiedUnits;
|
||||
// baseVal.convertToSpecifiedUnits(1);
|
||||
return svgedit.units.shortFloat(val / typeMap_[unit]);
|
||||
};
|
||||
|
||||
@@ -134,38 +136,38 @@ svgedit.units.convertUnit = function(val, unit) {
|
||||
// elem - DOM element to be changed
|
||||
// attr - String with the name of the attribute associated with the value
|
||||
// val - String with the attribute value to convert
|
||||
svgedit.units.setUnitAttr = function(elem, attr, val) {
|
||||
// if (!isNaN(val)) {
|
||||
// New value is a number, so check currently used unit
|
||||
// var old_val = elem.getAttribute(attr);
|
||||
svgedit.units.setUnitAttr = function (elem, attr, val) {
|
||||
// if (!isNaN(val)) {
|
||||
// New value is a number, so check currently used unit
|
||||
// var old_val = elem.getAttribute(attr);
|
||||
|
||||
// Enable this for alternate mode
|
||||
// if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) {
|
||||
// // Old value was a number, so get unit, then convert
|
||||
// var unit;
|
||||
// if (old_val.substr(-1) === '%') {
|
||||
// var res = getResolution();
|
||||
// unit = '%';
|
||||
// val *= 100;
|
||||
// if (wAttrs.indexOf(attr) >= 0) {
|
||||
// val = val / res.w;
|
||||
// } else if (hAttrs.indexOf(attr) >= 0) {
|
||||
// val = val / res.h;
|
||||
// } else {
|
||||
// return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
|
||||
// }
|
||||
// } else {
|
||||
// if (elementContainer_.getBaseUnit() !== 'px') {
|
||||
// unit = elementContainer_.getBaseUnit();
|
||||
// } else {
|
||||
// unit = old_val.substr(-2);
|
||||
// }
|
||||
// val = val / typeMap_[unit];
|
||||
// }
|
||||
//
|
||||
// val += unit;
|
||||
// }
|
||||
// }
|
||||
// Enable this for alternate mode
|
||||
// if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) {
|
||||
// // Old value was a number, so get unit, then convert
|
||||
// var unit;
|
||||
// if (old_val.substr(-1) === '%') {
|
||||
// var res = getResolution();
|
||||
// unit = '%';
|
||||
// val *= 100;
|
||||
// if (wAttrs.indexOf(attr) >= 0) {
|
||||
// val = val / res.w;
|
||||
// } else if (hAttrs.indexOf(attr) >= 0) {
|
||||
// val = val / res.h;
|
||||
// } else {
|
||||
// return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
|
||||
// }
|
||||
// } else {
|
||||
// if (elementContainer_.getBaseUnit() !== 'px') {
|
||||
// unit = elementContainer_.getBaseUnit();
|
||||
// } else {
|
||||
// unit = old_val.substr(-2);
|
||||
// }
|
||||
// val = val / typeMap_[unit];
|
||||
// }
|
||||
//
|
||||
// val += unit;
|
||||
// }
|
||||
// }
|
||||
elem.setAttribute(attr, val);
|
||||
};
|
||||
|
||||
@@ -185,11 +187,11 @@ var attrsToConvert = {
|
||||
//
|
||||
// Parameters:
|
||||
// element - a DOM element whose attributes should be converted
|
||||
svgedit.units.convertAttrs = function(element) {
|
||||
svgedit.units.convertAttrs = function (element) {
|
||||
var elName = element.tagName;
|
||||
var unit = elementContainer_.getBaseUnit();
|
||||
var attrs = attrsToConvert[elName];
|
||||
if (!attrs) {return;}
|
||||
if (!attrs) { return; }
|
||||
|
||||
var len = attrs.length;
|
||||
var i;
|
||||
@@ -201,26 +203,26 @@ svgedit.units.convertAttrs = function(element) {
|
||||
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
|
||||
}
|
||||
// else {
|
||||
// Convert existing?
|
||||
// Convert existing?
|
||||
// }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Function: svgedit.units.convertToNum
|
||||
// Converts given values to numbers. Attributes must be supplied in
|
||||
// Converts given values to numbers. Attributes must be supplied in
|
||||
// case a percentage is given
|
||||
//
|
||||
// Parameters:
|
||||
// attr - String with the name of the attribute associated with the value
|
||||
// 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
|
||||
if (!isNaN(val)) {return val-0;}
|
||||
if (!isNaN(val)) { return val - 0; }
|
||||
var num;
|
||||
if (val.substr(-1) === '%') {
|
||||
// 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 height = elementContainer_.getHeight();
|
||||
|
||||
@@ -230,10 +232,10 @@ svgedit.units.convertToNum = function(attr, val) {
|
||||
if (hAttrs.indexOf(attr) >= 0) {
|
||||
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);
|
||||
num = val.substr(0, val.length-2);
|
||||
num = val.substr(0, val.length - 2);
|
||||
// Note that this multiplication turns the string into a number
|
||||
return num * typeMap_[unit];
|
||||
};
|
||||
@@ -244,7 +246,7 @@ svgedit.units.convertToNum = function(attr, val) {
|
||||
// Parameters:
|
||||
// attr - String with the name of the attribute associated with the value
|
||||
// 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;
|
||||
if (unitAttrs.indexOf(attr) >= 0) {
|
||||
// True if it's just a number
|
||||
@@ -253,13 +255,13 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
|
||||
} else {
|
||||
// Not a number, check if it has a valid unit
|
||||
val = val.toLowerCase();
|
||||
$.each(typeMap_, function(unit) {
|
||||
if (valid) {return;}
|
||||
$.each(typeMap_, function (unit) {
|
||||
if (valid) { return; }
|
||||
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
|
||||
// and the id value is valid.
|
||||
|
||||
@@ -271,12 +273,11 @@ svgedit.units.isValidUnit = function(attr, val, selectedElement) {
|
||||
try {
|
||||
var elem = elementContainer_.getElement(val);
|
||||
result = (elem == null || elem === selectedElement);
|
||||
} catch(e) {}
|
||||
} catch (e) {}
|
||||
return result;
|
||||
}
|
||||
valid = true;
|
||||
|
||||
return valid;
|
||||
};
|
||||
|
||||
}());
|
||||
}());
|
||||
|
||||
Reference in New Issue
Block a user