Change all tab indentations to 2sp indentation. Addresses issue #37
This commit is contained in:
@@ -16,20 +16,20 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.browser) {
|
if (!svgedit.browser) {
|
||||||
svgedit.browser = {};
|
svgedit.browser = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// alias
|
// alias
|
||||||
var NS = svgedit.NS;
|
var NS = svgedit.NS;
|
||||||
|
|
||||||
var supportsSvg_ = (function () {
|
var supportsSvg_ = (function () {
|
||||||
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
|
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
svgedit.browser.supportsSvg = function () { return supportsSvg_; };
|
svgedit.browser.supportsSvg = function () { return supportsSvg_; };
|
||||||
if (!svgedit.browser.supportsSvg()) {
|
if (!svgedit.browser.supportsSvg()) {
|
||||||
window.location = 'browser-not-supported.html';
|
window.location = 'browser-not-supported.html';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var userAgent = navigator.userAgent;
|
var userAgent = navigator.userAgent;
|
||||||
@@ -46,120 +46,120 @@ var isMac_ = userAgent.indexOf('Macintosh') >= 0;
|
|||||||
var isTouch_ = 'ontouchstart' in window;
|
var isTouch_ = 'ontouchstart' in window;
|
||||||
|
|
||||||
var supportsSelectors_ = (function () {
|
var supportsSelectors_ = (function () {
|
||||||
return !!svg.querySelector;
|
return !!svg.querySelector;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsXpath_ = (function () {
|
var supportsXpath_ = (function () {
|
||||||
return !!document.evaluate;
|
return !!document.evaluate;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// segList functions (for FF1.5 and 2.0)
|
// segList functions (for FF1.5 and 2.0)
|
||||||
var supportsPathReplaceItem_ = (function () {
|
var supportsPathReplaceItem_ = (function () {
|
||||||
var path = document.createElementNS(NS.SVG, 'path');
|
var path = document.createElementNS(NS.SVG, 'path');
|
||||||
path.setAttribute('d', 'M0,0 10,10');
|
path.setAttribute('d', 'M0,0 10,10');
|
||||||
var seglist = path.pathSegList;
|
var seglist = path.pathSegList;
|
||||||
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||||
try {
|
try {
|
||||||
seglist.replaceItem(seg, 1);
|
seglist.replaceItem(seg, 1);
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
return false;
|
return false;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsPathInsertItemBefore_ = (function () {
|
var supportsPathInsertItemBefore_ = (function () {
|
||||||
var path = document.createElementNS(NS.SVG, 'path');
|
var path = document.createElementNS(NS.SVG, 'path');
|
||||||
path.setAttribute('d', 'M0,0 10,10');
|
path.setAttribute('d', 'M0,0 10,10');
|
||||||
var seglist = path.pathSegList;
|
var seglist = path.pathSegList;
|
||||||
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
var seg = path.createSVGPathSegLinetoAbs(5, 5);
|
||||||
try {
|
try {
|
||||||
seglist.insertItemBefore(seg, 1);
|
seglist.insertItemBefore(seg, 1);
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
return false;
|
return false;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// text character positioning (for IE9)
|
// text character positioning (for IE9)
|
||||||
var supportsGoodTextCharPos_ = (function () {
|
var supportsGoodTextCharPos_ = (function () {
|
||||||
var svgroot = document.createElementNS(NS.SVG, 'svg');
|
var svgroot = document.createElementNS(NS.SVG, 'svg');
|
||||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||||
document.documentElement.appendChild(svgroot);
|
document.documentElement.appendChild(svgroot);
|
||||||
svgcontent.setAttribute('x', 5);
|
svgcontent.setAttribute('x', 5);
|
||||||
svgroot.appendChild(svgcontent);
|
svgroot.appendChild(svgcontent);
|
||||||
var text = document.createElementNS(NS.SVG, 'text');
|
var text = document.createElementNS(NS.SVG, 'text');
|
||||||
text.textContent = 'a';
|
text.textContent = 'a';
|
||||||
svgcontent.appendChild(text);
|
svgcontent.appendChild(text);
|
||||||
var pos = text.getStartPositionOfChar(0).x;
|
var pos = text.getStartPositionOfChar(0).x;
|
||||||
document.documentElement.removeChild(svgroot);
|
document.documentElement.removeChild(svgroot);
|
||||||
return (pos === 0);
|
return (pos === 0);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsPathBBox_ = (function () {
|
var supportsPathBBox_ = (function () {
|
||||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||||
document.documentElement.appendChild(svgcontent);
|
document.documentElement.appendChild(svgcontent);
|
||||||
var path = document.createElementNS(NS.SVG, 'path');
|
var path = document.createElementNS(NS.SVG, 'path');
|
||||||
path.setAttribute('d', 'M0,0 C0,0 10,10 10,0');
|
path.setAttribute('d', 'M0,0 C0,0 10,10 10,0');
|
||||||
svgcontent.appendChild(path);
|
svgcontent.appendChild(path);
|
||||||
var bbox = path.getBBox();
|
var bbox = path.getBBox();
|
||||||
document.documentElement.removeChild(svgcontent);
|
document.documentElement.removeChild(svgcontent);
|
||||||
return (bbox.height > 4 && bbox.height < 5);
|
return (bbox.height > 4 && bbox.height < 5);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// Support for correct bbox sizing on groups with horizontal/vertical lines
|
// Support for correct bbox sizing on groups with horizontal/vertical lines
|
||||||
var supportsHVLineContainerBBox_ = (function () {
|
var supportsHVLineContainerBBox_ = (function () {
|
||||||
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
var svgcontent = document.createElementNS(NS.SVG, 'svg');
|
||||||
document.documentElement.appendChild(svgcontent);
|
document.documentElement.appendChild(svgcontent);
|
||||||
var path = document.createElementNS(NS.SVG, 'path');
|
var path = document.createElementNS(NS.SVG, 'path');
|
||||||
path.setAttribute('d', 'M0,0 10,0');
|
path.setAttribute('d', 'M0,0 10,0');
|
||||||
var path2 = document.createElementNS(NS.SVG, 'path');
|
var path2 = document.createElementNS(NS.SVG, 'path');
|
||||||
path2.setAttribute('d', 'M5,0 15,0');
|
path2.setAttribute('d', 'M5,0 15,0');
|
||||||
var g = document.createElementNS(NS.SVG, 'g');
|
var g = document.createElementNS(NS.SVG, 'g');
|
||||||
g.appendChild(path);
|
g.appendChild(path);
|
||||||
g.appendChild(path2);
|
g.appendChild(path2);
|
||||||
svgcontent.appendChild(g);
|
svgcontent.appendChild(g);
|
||||||
var bbox = g.getBBox();
|
var bbox = g.getBBox();
|
||||||
document.documentElement.removeChild(svgcontent);
|
document.documentElement.removeChild(svgcontent);
|
||||||
// Webkit gives 0, FF gives 10, Opera (correctly) gives 15
|
// Webkit gives 0, FF gives 10, Opera (correctly) gives 15
|
||||||
return (bbox.width === 15);
|
return (bbox.width === 15);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsEditableText_ = (function () {
|
var supportsEditableText_ = (function () {
|
||||||
// TODO: Find better way to check support for this
|
// TODO: Find better way to check support for this
|
||||||
return isOpera_;
|
return isOpera_;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsGoodDecimals_ = (function () {
|
var supportsGoodDecimals_ = (function () {
|
||||||
// Correct decimals on clone attributes (Opera < 10.5/win/non-en)
|
// Correct decimals on clone attributes (Opera < 10.5/win/non-en)
|
||||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||||
rect.setAttribute('x', 0.1);
|
rect.setAttribute('x', 0.1);
|
||||||
var crect = rect.cloneNode(false);
|
var crect = rect.cloneNode(false);
|
||||||
var retValue = (crect.getAttribute('x').indexOf(',') === -1);
|
var retValue = (crect.getAttribute('x').indexOf(',') === -1);
|
||||||
if (!retValue) {
|
if (!retValue) {
|
||||||
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' +
|
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n' +
|
||||||
'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.');
|
'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.');
|
||||||
}
|
}
|
||||||
return retValue;
|
return retValue;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsNonScalingStroke_ = (function () {
|
var supportsNonScalingStroke_ = (function () {
|
||||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||||
rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
|
rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
|
||||||
return rect.style.vectorEffect === 'non-scaling-stroke';
|
return rect.style.vectorEffect === 'non-scaling-stroke';
|
||||||
}());
|
}());
|
||||||
|
|
||||||
var supportsNativeSVGTransformLists_ = (function () {
|
var supportsNativeSVGTransformLists_ = (function () {
|
||||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||||
var rxform = rect.transform.baseVal;
|
var rxform = rect.transform.baseVal;
|
||||||
var t1 = svg.createSVGTransform();
|
var t1 = svg.createSVGTransform();
|
||||||
rxform.appendItem(t1);
|
rxform.appendItem(t1);
|
||||||
var r1 = rxform.getItem(0);
|
var r1 = rxform.getItem(0);
|
||||||
return r1 instanceof SVGTransform && t1 instanceof SVGTransform &&
|
return r1 instanceof SVGTransform && t1 instanceof SVGTransform &&
|
||||||
r1.type === t1.type && r1.angle === t1.angle &&
|
r1.type === t1.type && r1.angle === t1.angle &&
|
||||||
r1.matrix.a === t1.matrix.a &&
|
r1.matrix.a === t1.matrix.a &&
|
||||||
r1.matrix.b === t1.matrix.b &&
|
r1.matrix.b === t1.matrix.b &&
|
||||||
r1.matrix.c === t1.matrix.c &&
|
r1.matrix.c === t1.matrix.c &&
|
||||||
r1.matrix.d === t1.matrix.d &&
|
r1.matrix.d === t1.matrix.d &&
|
||||||
r1.matrix.e === t1.matrix.e &&
|
r1.matrix.e === t1.matrix.e &&
|
||||||
r1.matrix.f === t1.matrix.f;
|
r1.matrix.f === t1.matrix.f;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
|
|||||||
@@ -21,86 +21,86 @@ See svg-editor.js for documentation on using setConfig().
|
|||||||
|
|
||||||
// URL OVERRIDE CONFIG
|
// URL OVERRIDE CONFIG
|
||||||
svgEditor.setConfig({
|
svgEditor.setConfig({
|
||||||
/**
|
/**
|
||||||
To override the ability for URLs to set URL-based SVG content,
|
To override the ability for URLs to set URL-based SVG content,
|
||||||
uncomment the following:
|
uncomment the following:
|
||||||
*/
|
*/
|
||||||
// preventURLContentLoading: true,
|
// preventURLContentLoading: true,
|
||||||
/**
|
/**
|
||||||
To override the ability for URLs to set other configuration (including
|
To override the ability for URLs to set other configuration (including
|
||||||
extension config), uncomment the following:
|
extension config), uncomment the following:
|
||||||
*/
|
*/
|
||||||
// preventAllURLConfig: true,
|
// preventAllURLConfig: true,
|
||||||
/**
|
/**
|
||||||
To override the ability for URLs to set their own extensions,
|
To override the ability for URLs to set their own extensions,
|
||||||
uncomment the following (note that if setConfig() is used in
|
uncomment the following (note that if setConfig() is used in
|
||||||
extension code, it will still be additive to extensions,
|
extension code, it will still be additive to extensions,
|
||||||
however):
|
however):
|
||||||
*/
|
*/
|
||||||
// lockExtensions: true,
|
// lockExtensions: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
svgEditor.setConfig({
|
svgEditor.setConfig({
|
||||||
/*
|
/*
|
||||||
Provide default values here which differ from that of the editor but
|
Provide default values here which differ from that of the editor but
|
||||||
which the URL can override
|
which the URL can override
|
||||||
*/
|
*/
|
||||||
}, {allowInitialUserOverride: true});
|
}, {allowInitialUserOverride: true});
|
||||||
|
|
||||||
// EXTENSION CONFIG
|
// EXTENSION CONFIG
|
||||||
svgEditor.setConfig({
|
svgEditor.setConfig({
|
||||||
extensions: [
|
extensions: [
|
||||||
// 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js'
|
// 'ext-overview_window.js', 'ext-markers.js', 'ext-connector.js', 'ext-eyedropper.js', 'ext-shapes.js', 'ext-imagelib.js', 'ext-grid.js', 'ext-polygon.js', 'ext-star.js', 'ext-panning.js', 'ext-storage.js'
|
||||||
]
|
]
|
||||||
// , noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL
|
// , noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL
|
||||||
});
|
});
|
||||||
|
|
||||||
// OTHER CONFIG
|
// OTHER CONFIG
|
||||||
svgEditor.setConfig({
|
svgEditor.setConfig({
|
||||||
// canvasName: 'default',
|
// canvasName: 'default',
|
||||||
// canvas_expansion: 3,
|
// canvas_expansion: 3,
|
||||||
// initFill: {
|
// initFill: {
|
||||||
// color: 'FF0000', // solid red
|
// color: 'FF0000', // solid red
|
||||||
// opacity: 1
|
// opacity: 1
|
||||||
// },
|
// },
|
||||||
// initStroke: {
|
// initStroke: {
|
||||||
// width: 5,
|
// width: 5,
|
||||||
// color: '000000', // solid black
|
// color: '000000', // solid black
|
||||||
// opacity: 1
|
// opacity: 1
|
||||||
// },
|
// },
|
||||||
// initOpacity: 1,
|
// initOpacity: 1,
|
||||||
// colorPickerCSS: null,
|
// colorPickerCSS: null,
|
||||||
// initTool: 'select',
|
// initTool: 'select',
|
||||||
// exportWindowType: 'new', // 'same'
|
// exportWindowType: 'new', // 'same'
|
||||||
// wireframe: false,
|
// wireframe: false,
|
||||||
// showlayers: false,
|
// showlayers: false,
|
||||||
// no_save_warning: false,
|
// no_save_warning: false,
|
||||||
// PATH CONFIGURATION
|
// PATH CONFIGURATION
|
||||||
// imgPath: 'images/',
|
// imgPath: 'images/',
|
||||||
// langPath: 'locale/',
|
// langPath: 'locale/',
|
||||||
// extPath: 'extensions/',
|
// extPath: 'extensions/',
|
||||||
// jGraduatePath: 'jgraduate/images/',
|
// jGraduatePath: 'jgraduate/images/',
|
||||||
/*
|
/*
|
||||||
Uncomment the following to allow at least same domain (embedded) access,
|
Uncomment the following to allow at least same domain (embedded) access,
|
||||||
including file:// access.
|
including file:// access.
|
||||||
Setting as `['*']` would allow any domain to access but would be unsafe to
|
Setting as `['*']` would allow any domain to access but would be unsafe to
|
||||||
data privacy and integrity.
|
data privacy and integrity.
|
||||||
*/
|
*/
|
||||||
// allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL
|
// allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL
|
||||||
// DOCUMENT PROPERTIES
|
// DOCUMENT PROPERTIES
|
||||||
// dimensions: [640, 480],
|
// dimensions: [640, 480],
|
||||||
// EDITOR OPTIONS
|
// EDITOR OPTIONS
|
||||||
// gridSnapping: false,
|
// gridSnapping: false,
|
||||||
// gridColor: '#000',
|
// gridColor: '#000',
|
||||||
// baseUnit: 'px',
|
// baseUnit: 'px',
|
||||||
// snappingStep: 10,
|
// snappingStep: 10,
|
||||||
// showRulers: true,
|
// showRulers: true,
|
||||||
// EXTENSION-RELATED (GRID)
|
// EXTENSION-RELATED (GRID)
|
||||||
// showGrid: false, // Set by ext-grid.js
|
// showGrid: false, // Set by ext-grid.js
|
||||||
// EXTENSION-RELATED (STORAGE)
|
// EXTENSION-RELATED (STORAGE)
|
||||||
// noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage
|
// noStorageOnLoad: false, // Some interaction with ext-storage.js; prevent even the loading of previously saved local storage
|
||||||
// forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not
|
// forceStorage: false, // Some interaction with ext-storage.js; strongly discouraged from modification as it bypasses user privacy by preventing them from choosing whether to keep local storage or not
|
||||||
// emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store
|
// emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store
|
||||||
});
|
});
|
||||||
|
|
||||||
// PREF CHANGES
|
// PREF CHANGES
|
||||||
@@ -118,29 +118,29 @@ As with configuration, one may use allowInitialUserOverride, but
|
|||||||
are hard-coded here regardless of URL or prior user storage setting.
|
are hard-coded here regardless of URL or prior user storage setting.
|
||||||
*/
|
*/
|
||||||
svgEditor.setConfig(
|
svgEditor.setConfig(
|
||||||
{
|
{
|
||||||
// lang: '', // Set dynamically within locale.js if not previously set
|
// lang: '', // Set dynamically within locale.js if not previously set
|
||||||
// iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise
|
// iconsize: '', // Will default to 's' if the window height is smaller than the minimum height and 'm' otherwise
|
||||||
/**
|
/**
|
||||||
* When showing the preferences dialog, svg-editor.js currently relies
|
* When showing the preferences dialog, svg-editor.js currently relies
|
||||||
* on curPrefs instead of $.pref, so allowing an override for bkgd_color
|
* on curPrefs instead of $.pref, so allowing an override for bkgd_color
|
||||||
* means that this value won't have priority over block auto-detection as
|
* means that this value won't have priority over block auto-detection as
|
||||||
* far as determining which color shows initially in the preferences
|
* far as determining which color shows initially in the preferences
|
||||||
* dialog (though it can be changed and saved).
|
* dialog (though it can be changed and saved).
|
||||||
*/
|
*/
|
||||||
// bkgd_color: '#FFF',
|
// bkgd_color: '#FFF',
|
||||||
// bkgd_url: '',
|
// bkgd_url: '',
|
||||||
// img_save: 'embed',
|
// img_save: 'embed',
|
||||||
// Only shows in UI as far as alert notices
|
// Only shows in UI as far as alert notices
|
||||||
// save_notice_done: false,
|
// save_notice_done: false,
|
||||||
// export_notice_done: false
|
// export_notice_done: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
svgEditor.setConfig(
|
svgEditor.setConfig(
|
||||||
{
|
{
|
||||||
// Indicate pref settings here if you wish to allow user storage or URL settings
|
// Indicate pref settings here if you wish to allow user storage or URL settings
|
||||||
// to be able to override your default preferences (unless other config options
|
// to be able to override your default preferences (unless other config options
|
||||||
// have already explicitly prevented one or the other)
|
// have already explicitly prevented one or the other)
|
||||||
},
|
},
|
||||||
{allowInitialUserOverride: true}
|
{allowInitialUserOverride: true}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,51 +13,51 @@ var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define
|
|||||||
(function () {
|
(function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!svgedit.contextmenu) {
|
if (!svgedit.contextmenu) {
|
||||||
svgedit.contextmenu = {};
|
svgedit.contextmenu = {};
|
||||||
}
|
}
|
||||||
self.contextMenuExtensions = {};
|
self.contextMenuExtensions = {};
|
||||||
var menuItemIsValid = function (menuItem) {
|
var menuItemIsValid = function (menuItem) {
|
||||||
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action === 'function';
|
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action === 'function';
|
||||||
};
|
};
|
||||||
var addContextMenuItem = function (menuItem) {
|
var addContextMenuItem = function (menuItem) {
|
||||||
// menuItem: {id, label, shortcut, action}
|
// menuItem: {id, label, shortcut, action}
|
||||||
if (!menuItemIsValid(menuItem)) {
|
if (!menuItemIsValid(menuItem)) {
|
||||||
console.error('Menu items must be defined and have at least properties: id, label, action, where action must be a function');
|
console.error('Menu items must be defined and have at least properties: id, label, action, where action must be a function');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (menuItem.id in self.contextMenuExtensions) {
|
if (menuItem.id in self.contextMenuExtensions) {
|
||||||
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
|
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Register menuItem action, see below for deferred menu dom injection
|
// Register menuItem action, see below for deferred menu dom injection
|
||||||
console.log('Registed contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}');
|
console.log('Registed contextmenu item: {id:' + menuItem.id + ', label:' + menuItem.label + '}');
|
||||||
self.contextMenuExtensions[menuItem.id] = menuItem;
|
self.contextMenuExtensions[menuItem.id] = menuItem;
|
||||||
// TODO: Need to consider how to handle custom enable/disable behavior
|
// TODO: Need to consider how to handle custom enable/disable behavior
|
||||||
};
|
};
|
||||||
var hasCustomHandler = function (handlerKey) {
|
var hasCustomHandler = function (handlerKey) {
|
||||||
return self.contextMenuExtensions[handlerKey] && true;
|
return self.contextMenuExtensions[handlerKey] && true;
|
||||||
};
|
};
|
||||||
var getCustomHandler = function (handlerKey) {
|
var getCustomHandler = function (handlerKey) {
|
||||||
return self.contextMenuExtensions[handlerKey].action;
|
return self.contextMenuExtensions[handlerKey].action;
|
||||||
};
|
};
|
||||||
var injectExtendedContextMenuItemIntoDom = function (menuItem) {
|
var injectExtendedContextMenuItemIntoDom = function (menuItem) {
|
||||||
if (Object.keys(self.contextMenuExtensions).length === 0) {
|
if (Object.keys(self.contextMenuExtensions).length === 0) {
|
||||||
// all menuItems appear at the bottom of the menu in their own container.
|
// 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.
|
// if this is the first extension menu we need to add the separator.
|
||||||
$('#cmenu_canvas').append("<li class='separator'>");
|
$('#cmenu_canvas').append("<li class='separator'>");
|
||||||
}
|
}
|
||||||
var shortcut = menuItem.shortcut || '';
|
var shortcut = menuItem.shortcut || '';
|
||||||
$('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" +
|
$('#cmenu_canvas').append("<li class='disabled'><a href='#" + menuItem.id + "'>" +
|
||||||
menuItem.label + "<span class='shortcut'>" +
|
menuItem.label + "<span class='shortcut'>" +
|
||||||
shortcut + '</span></a></li>');
|
shortcut + '</span></a></li>');
|
||||||
};
|
};
|
||||||
// Defer injection to wait out initial menu processing. This probably goes away once all context
|
// Defer injection to wait out initial menu processing. This probably goes away once all context
|
||||||
// menu behavior is brought here.
|
// menu behavior is brought here.
|
||||||
svgEditor.ready(function () {
|
svgEditor.ready(function () {
|
||||||
var menuItem;
|
var menuItem;
|
||||||
for (menuItem in self.contextMenuExtensions) {
|
for (menuItem in self.contextMenuExtensions) {
|
||||||
injectExtendedContextMenuItemIntoDom(self.contextMenuExtensions[menuItem]);
|
injectExtendedContextMenuItemIntoDom(self.contextMenuExtensions[menuItem]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
svgedit.contextmenu.resetCustomMenus = function () { self.contextMenuExtensions = {}; };
|
svgedit.contextmenu.resetCustomMenus = function () { self.contextMenuExtensions = {}; };
|
||||||
svgedit.contextmenu.add = addContextMenuItem;
|
svgedit.contextmenu.add = addContextMenuItem;
|
||||||
|
|||||||
510
editor/coords.js
510
editor/coords.js
@@ -22,12 +22,12 @@ var svgedit = svgedit || {}; // eslint-disable-line no-use-before-define
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.coords) {
|
if (!svgedit.coords) {
|
||||||
svgedit.coords = {};
|
svgedit.coords = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is how we map paths to our preferred relative segment types
|
// this is how we map paths to our preferred relative segment types
|
||||||
var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
var pathMap = [0, 'z', 'M', 'm', 'L', 'l', 'C', 'c', 'Q', 'q', 'A', 'a',
|
||||||
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
'H', 'h', 'V', 'v', 'S', 's', 'T', 't'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef editorContext
|
* @typedef editorContext
|
||||||
@@ -41,7 +41,7 @@ var editorContext_ = null;
|
|||||||
* @param {editorContext} editorContext
|
* @param {editorContext} editorContext
|
||||||
*/
|
*/
|
||||||
svgedit.coords.init = function (editorContext) {
|
svgedit.coords.init = function (editorContext) {
|
||||||
editorContext_ = editorContext;
|
editorContext_ = editorContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,266 +51,266 @@ svgedit.coords.init = function (editorContext) {
|
|||||||
* @param {SVGMatrix} m - Matrix object to use for remapping coordinates
|
* @param {SVGMatrix} m - Matrix object to use for remapping coordinates
|
||||||
*/
|
*/
|
||||||
svgedit.coords.remapElement = function (selected, changes, m) {
|
svgedit.coords.remapElement = function (selected, changes, m) {
|
||||||
var i, type,
|
var i, type,
|
||||||
remap = function (x, y) { return svgedit.math.transformPoint(x, y, m); },
|
remap = function (x, y) { return svgedit.math.transformPoint(x, y, m); },
|
||||||
scalew = function (w) { return m.a * w; },
|
scalew = function (w) { return m.a * w; },
|
||||||
scaleh = function (h) { return m.d * h; },
|
scaleh = function (h) { return m.d * h; },
|
||||||
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
|
doSnapping = editorContext_.getGridSnapping() && selected.parentNode.parentNode.localName === 'svg',
|
||||||
finishUp = function () {
|
finishUp = function () {
|
||||||
var o;
|
var o;
|
||||||
if (doSnapping) {
|
if (doSnapping) {
|
||||||
for (o in changes) {
|
for (o in changes) {
|
||||||
changes[o] = svgedit.utilities.snapToGrid(changes[o]);
|
changes[o] = svgedit.utilities.snapToGrid(changes[o]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svgedit.utilities.assignAttributes(selected, changes, 1000, true);
|
svgedit.utilities.assignAttributes(selected, changes, 1000, true);
|
||||||
},
|
},
|
||||||
box = svgedit.utilities.getBBox(selected);
|
box = svgedit.utilities.getBBox(selected);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
type = i === 0 ? 'fill' : 'stroke';
|
type = i === 0 ? 'fill' : 'stroke';
|
||||||
var attrVal = selected.getAttribute(type);
|
var attrVal = selected.getAttribute(type);
|
||||||
if (attrVal && attrVal.indexOf('url(') === 0) {
|
if (attrVal && attrVal.indexOf('url(') === 0) {
|
||||||
if (m.a < 0 || m.d < 0) {
|
if (m.a < 0 || m.d < 0) {
|
||||||
var grad = svgedit.utilities.getRefElem(attrVal);
|
var grad = svgedit.utilities.getRefElem(attrVal);
|
||||||
var newgrad = grad.cloneNode(true);
|
var newgrad = grad.cloneNode(true);
|
||||||
if (m.a < 0) {
|
if (m.a < 0) {
|
||||||
// flip x
|
// flip x
|
||||||
var x1 = newgrad.getAttribute('x1');
|
var x1 = newgrad.getAttribute('x1');
|
||||||
var x2 = newgrad.getAttribute('x2');
|
var x2 = newgrad.getAttribute('x2');
|
||||||
newgrad.setAttribute('x1', -(x1 - 1));
|
newgrad.setAttribute('x1', -(x1 - 1));
|
||||||
newgrad.setAttribute('x2', -(x2 - 1));
|
newgrad.setAttribute('x2', -(x2 - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.d < 0) {
|
if (m.d < 0) {
|
||||||
// flip y
|
// flip y
|
||||||
var y1 = newgrad.getAttribute('y1');
|
var y1 = newgrad.getAttribute('y1');
|
||||||
var y2 = newgrad.getAttribute('y2');
|
var y2 = newgrad.getAttribute('y2');
|
||||||
newgrad.setAttribute('y1', -(y1 - 1));
|
newgrad.setAttribute('y1', -(y1 - 1));
|
||||||
newgrad.setAttribute('y2', -(y2 - 1));
|
newgrad.setAttribute('y2', -(y2 - 1));
|
||||||
}
|
}
|
||||||
newgrad.id = editorContext_.getDrawing().getNextId();
|
newgrad.id = editorContext_.getDrawing().getNextId();
|
||||||
svgedit.utilities.findDefs().appendChild(newgrad);
|
svgedit.utilities.findDefs().appendChild(newgrad);
|
||||||
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
selected.setAttribute(type, 'url(#' + newgrad.id + ')');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not really working :(
|
// Not really working :(
|
||||||
// if (selected.tagName === 'path') {
|
// if (selected.tagName === 'path') {
|
||||||
// reorientGrads(selected, m);
|
// reorientGrads(selected, m);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var elName = selected.tagName;
|
var elName = selected.tagName;
|
||||||
var chlist, mt;
|
var chlist, mt;
|
||||||
if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {
|
if (elName === 'g' || elName === 'text' || elName === 'tspan' || elName === 'use') {
|
||||||
// if it was a translate, then just update x,y
|
// if it was a translate, then just update x,y
|
||||||
if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) {
|
if (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && (m.e !== 0 || m.f !== 0)) {
|
||||||
// [T][M] = [M][T']
|
// [T][M] = [M][T']
|
||||||
// therefore [T'] = [M_inv][T][M]
|
// therefore [T'] = [M_inv][T][M]
|
||||||
var existing = svgedit.math.transformListToTransform(selected).matrix,
|
var existing = svgedit.math.transformListToTransform(selected).matrix,
|
||||||
tNew = svgedit.math.matrixMultiply(existing.inverse(), m, existing);
|
tNew = svgedit.math.matrixMultiply(existing.inverse(), m, existing);
|
||||||
changes.x = parseFloat(changes.x) + tNew.e;
|
changes.x = parseFloat(changes.x) + tNew.e;
|
||||||
changes.y = parseFloat(changes.y) + tNew.f;
|
changes.y = parseFloat(changes.y) + tNew.f;
|
||||||
} else {
|
} else {
|
||||||
// we just absorb all matrices into the element and don't do any remapping
|
// we just absorb all matrices into the element and don't do any remapping
|
||||||
chlist = svgedit.transformlist.getTransformList(selected);
|
chlist = svgedit.transformlist.getTransformList(selected);
|
||||||
mt = svgroot.createSVGTransform();
|
mt = svgroot.createSVGTransform();
|
||||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||||
chlist.clear();
|
chlist.clear();
|
||||||
chlist.appendItem(mt);
|
chlist.appendItem(mt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var c, pt, pt1, pt2, len;
|
var c, pt, pt1, pt2, len;
|
||||||
// now we have a set of changes and an applied reduced transform list
|
// now we have a set of changes and an applied reduced transform list
|
||||||
// we apply the changes directly to the DOM
|
// we apply the changes directly to the DOM
|
||||||
switch (elName) {
|
switch (elName) {
|
||||||
case 'foreignObject':
|
case 'foreignObject':
|
||||||
case 'rect':
|
case 'rect':
|
||||||
case 'image':
|
case 'image':
|
||||||
// Allow images to be inverted (give them matrix when flipped)
|
// Allow images to be inverted (give them matrix when flipped)
|
||||||
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
if (elName === 'image' && (m.a < 0 || m.d < 0)) {
|
||||||
// Convert to matrix
|
// Convert to matrix
|
||||||
chlist = svgedit.transformlist.getTransformList(selected);
|
chlist = svgedit.transformlist.getTransformList(selected);
|
||||||
mt = svgroot.createSVGTransform();
|
mt = svgroot.createSVGTransform();
|
||||||
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
mt.setMatrix(svgedit.math.matrixMultiply(svgedit.math.transformListToTransform(chlist).matrix, m));
|
||||||
chlist.clear();
|
chlist.clear();
|
||||||
chlist.appendItem(mt);
|
chlist.appendItem(mt);
|
||||||
} else {
|
} else {
|
||||||
pt1 = remap(changes.x, changes.y);
|
pt1 = remap(changes.x, changes.y);
|
||||||
changes.width = scalew(changes.width);
|
changes.width = scalew(changes.width);
|
||||||
changes.height = scaleh(changes.height);
|
changes.height = scaleh(changes.height);
|
||||||
changes.x = pt1.x + Math.min(0, changes.width);
|
changes.x = pt1.x + Math.min(0, changes.width);
|
||||||
changes.y = pt1.y + Math.min(0, changes.height);
|
changes.y = pt1.y + Math.min(0, changes.height);
|
||||||
changes.width = Math.abs(changes.width);
|
changes.width = Math.abs(changes.width);
|
||||||
changes.height = Math.abs(changes.height);
|
changes.height = Math.abs(changes.height);
|
||||||
}
|
}
|
||||||
finishUp();
|
finishUp();
|
||||||
break;
|
break;
|
||||||
case 'ellipse':
|
case 'ellipse':
|
||||||
c = remap(changes.cx, changes.cy);
|
c = remap(changes.cx, changes.cy);
|
||||||
changes.cx = c.x;
|
changes.cx = c.x;
|
||||||
changes.cy = c.y;
|
changes.cy = c.y;
|
||||||
changes.rx = scalew(changes.rx);
|
changes.rx = scalew(changes.rx);
|
||||||
changes.ry = scaleh(changes.ry);
|
changes.ry = scaleh(changes.ry);
|
||||||
changes.rx = Math.abs(changes.rx);
|
changes.rx = Math.abs(changes.rx);
|
||||||
changes.ry = Math.abs(changes.ry);
|
changes.ry = Math.abs(changes.ry);
|
||||||
finishUp();
|
finishUp();
|
||||||
break;
|
break;
|
||||||
case 'circle':
|
case 'circle':
|
||||||
c = remap(changes.cx, changes.cy);
|
c = remap(changes.cx, changes.cy);
|
||||||
changes.cx = c.x;
|
changes.cx = c.x;
|
||||||
changes.cy = c.y;
|
changes.cy = c.y;
|
||||||
// take the minimum of the new selected box's dimensions for the new circle radius
|
// take the minimum of the new selected box's dimensions for the new circle radius
|
||||||
var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m);
|
var tbox = svgedit.math.transformBox(box.x, box.y, box.width, box.height, m);
|
||||||
var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
var w = tbox.tr.x - tbox.tl.x, h = tbox.bl.y - tbox.tl.y;
|
||||||
changes.r = Math.min(w / 2, h / 2);
|
changes.r = Math.min(w / 2, h / 2);
|
||||||
|
|
||||||
if (changes.r) { changes.r = Math.abs(changes.r); }
|
if (changes.r) { changes.r = Math.abs(changes.r); }
|
||||||
finishUp();
|
finishUp();
|
||||||
break;
|
break;
|
||||||
case 'line':
|
case 'line':
|
||||||
pt1 = remap(changes.x1, changes.y1);
|
pt1 = remap(changes.x1, changes.y1);
|
||||||
pt2 = remap(changes.x2, changes.y2);
|
pt2 = remap(changes.x2, changes.y2);
|
||||||
changes.x1 = pt1.x;
|
changes.x1 = pt1.x;
|
||||||
changes.y1 = pt1.y;
|
changes.y1 = pt1.y;
|
||||||
changes.x2 = pt2.x;
|
changes.x2 = pt2.x;
|
||||||
changes.y2 = pt2.y;
|
changes.y2 = pt2.y;
|
||||||
// deliberately fall through here
|
// deliberately fall through here
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'tspan':
|
case 'tspan':
|
||||||
case 'use':
|
case 'use':
|
||||||
finishUp();
|
finishUp();
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
var gsvg = $(selected).data('gsvg');
|
var gsvg = $(selected).data('gsvg');
|
||||||
if (gsvg) {
|
if (gsvg) {
|
||||||
svgedit.utilities.assignAttributes(gsvg, changes, 1000, true);
|
svgedit.utilities.assignAttributes(gsvg, changes, 1000, true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'polyline':
|
case 'polyline':
|
||||||
case 'polygon':
|
case 'polygon':
|
||||||
len = changes.points.length;
|
len = changes.points.length;
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
pt = changes.points[i];
|
pt = changes.points[i];
|
||||||
pt = remap(pt.x, pt.y);
|
pt = remap(pt.x, pt.y);
|
||||||
changes.points[i].x = pt.x;
|
changes.points[i].x = pt.x;
|
||||||
changes.points[i].y = pt.y;
|
changes.points[i].y = pt.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = changes.points.length;
|
len = changes.points.length;
|
||||||
var pstr = '';
|
var pstr = '';
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
pt = changes.points[i];
|
pt = changes.points[i];
|
||||||
pstr += pt.x + ',' + pt.y + ' ';
|
pstr += pt.x + ',' + pt.y + ' ';
|
||||||
}
|
}
|
||||||
selected.setAttribute('points', pstr);
|
selected.setAttribute('points', pstr);
|
||||||
break;
|
break;
|
||||||
case 'path':
|
case 'path':
|
||||||
var seg;
|
var seg;
|
||||||
var segList = selected.pathSegList;
|
var segList = selected.pathSegList;
|
||||||
len = segList.numberOfItems;
|
len = segList.numberOfItems;
|
||||||
changes.d = [];
|
changes.d = [];
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
seg = segList.getItem(i);
|
seg = segList.getItem(i);
|
||||||
changes.d[i] = {
|
changes.d[i] = {
|
||||||
type: seg.pathSegType,
|
type: seg.pathSegType,
|
||||||
x: seg.x,
|
x: seg.x,
|
||||||
y: seg.y,
|
y: seg.y,
|
||||||
x1: seg.x1,
|
x1: seg.x1,
|
||||||
y1: seg.y1,
|
y1: seg.y1,
|
||||||
x2: seg.x2,
|
x2: seg.x2,
|
||||||
y2: seg.y2,
|
y2: seg.y2,
|
||||||
r1: seg.r1,
|
r1: seg.r1,
|
||||||
r2: seg.r2,
|
r2: seg.r2,
|
||||||
angle: seg.angle,
|
angle: seg.angle,
|
||||||
largeArcFlag: seg.largeArcFlag,
|
largeArcFlag: seg.largeArcFlag,
|
||||||
sweepFlag: seg.sweepFlag
|
sweepFlag: seg.sweepFlag
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
len = changes.d.length;
|
len = changes.d.length;
|
||||||
var firstseg = changes.d[0],
|
var firstseg = changes.d[0],
|
||||||
currentpt = remap(firstseg.x, firstseg.y);
|
currentpt = remap(firstseg.x, firstseg.y);
|
||||||
changes.d[0].x = currentpt.x;
|
changes.d[0].x = currentpt.x;
|
||||||
changes.d[0].y = currentpt.y;
|
changes.d[0].y = currentpt.y;
|
||||||
for (i = 1; i < len; ++i) {
|
for (i = 1; i < len; ++i) {
|
||||||
seg = changes.d[i];
|
seg = changes.d[i];
|
||||||
type = seg.type;
|
type = seg.type;
|
||||||
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
// if absolute or first segment, we want to remap x, y, x1, y1, x2, y2
|
||||||
// if relative, we want to scalew, scaleh
|
// if relative, we want to scalew, scaleh
|
||||||
if (type % 2 === 0) { // absolute
|
if (type % 2 === 0) { // absolute
|
||||||
var thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands
|
var thisx = (seg.x !== undefined) ? seg.x : currentpt.x, // for V commands
|
||||||
thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands
|
thisy = (seg.y !== undefined) ? seg.y : currentpt.y; // for H commands
|
||||||
pt = remap(thisx, thisy);
|
pt = remap(thisx, thisy);
|
||||||
pt1 = remap(seg.x1, seg.y1);
|
pt1 = remap(seg.x1, seg.y1);
|
||||||
pt2 = remap(seg.x2, seg.y2);
|
pt2 = remap(seg.x2, seg.y2);
|
||||||
seg.x = pt.x;
|
seg.x = pt.x;
|
||||||
seg.y = pt.y;
|
seg.y = pt.y;
|
||||||
seg.x1 = pt1.x;
|
seg.x1 = pt1.x;
|
||||||
seg.y1 = pt1.y;
|
seg.y1 = pt1.y;
|
||||||
seg.x2 = pt2.x;
|
seg.x2 = pt2.x;
|
||||||
seg.y2 = pt2.y;
|
seg.y2 = pt2.y;
|
||||||
seg.r1 = scalew(seg.r1);
|
seg.r1 = scalew(seg.r1);
|
||||||
seg.r2 = scaleh(seg.r2);
|
seg.r2 = scaleh(seg.r2);
|
||||||
} else { // relative
|
} else { // relative
|
||||||
seg.x = scalew(seg.x);
|
seg.x = scalew(seg.x);
|
||||||
seg.y = scaleh(seg.y);
|
seg.y = scaleh(seg.y);
|
||||||
seg.x1 = scalew(seg.x1);
|
seg.x1 = scalew(seg.x1);
|
||||||
seg.y1 = scaleh(seg.y1);
|
seg.y1 = scaleh(seg.y1);
|
||||||
seg.x2 = scalew(seg.x2);
|
seg.x2 = scalew(seg.x2);
|
||||||
seg.y2 = scaleh(seg.y2);
|
seg.y2 = scaleh(seg.y2);
|
||||||
seg.r1 = scalew(seg.r1);
|
seg.r1 = scalew(seg.r1);
|
||||||
seg.r2 = scaleh(seg.r2);
|
seg.r2 = scaleh(seg.r2);
|
||||||
}
|
}
|
||||||
} // for each segment
|
} // for each segment
|
||||||
|
|
||||||
var dstr = '';
|
var dstr = '';
|
||||||
len = changes.d.length;
|
len = changes.d.length;
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
seg = changes.d[i];
|
seg = changes.d[i];
|
||||||
type = seg.type;
|
type = seg.type;
|
||||||
dstr += pathMap[type];
|
dstr += pathMap[type];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 13: // relative horizontal line (h)
|
case 13: // relative horizontal line (h)
|
||||||
case 12: // absolute horizontal line (H)
|
case 12: // absolute horizontal line (H)
|
||||||
dstr += seg.x + ' ';
|
dstr += seg.x + ' ';
|
||||||
break;
|
break;
|
||||||
case 15: // relative vertical line (v)
|
case 15: // relative vertical line (v)
|
||||||
case 14: // absolute vertical line (V)
|
case 14: // absolute vertical line (V)
|
||||||
dstr += seg.y + ' ';
|
dstr += seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
case 3: // relative move (m)
|
case 3: // relative move (m)
|
||||||
case 5: // relative line (l)
|
case 5: // relative line (l)
|
||||||
case 19: // relative smooth quad (t)
|
case 19: // relative smooth quad (t)
|
||||||
case 2: // absolute move (M)
|
case 2: // absolute move (M)
|
||||||
case 4: // absolute line (L)
|
case 4: // absolute line (L)
|
||||||
case 18: // absolute smooth quad (T)
|
case 18: // absolute smooth quad (T)
|
||||||
dstr += seg.x + ',' + seg.y + ' ';
|
dstr += seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
case 7: // relative cubic (c)
|
case 7: // relative cubic (c)
|
||||||
case 6: // absolute cubic (C)
|
case 6: // absolute cubic (C)
|
||||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x2 + ',' + seg.y2 + ' ' +
|
||||||
seg.x + ',' + seg.y + ' ';
|
seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
case 9: // relative quad (q)
|
case 9: // relative quad (q)
|
||||||
case 8: // absolute quad (Q)
|
case 8: // absolute quad (Q)
|
||||||
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
dstr += seg.x1 + ',' + seg.y1 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
case 11: // relative elliptical arc (a)
|
case 11: // relative elliptical arc (a)
|
||||||
case 10: // absolute elliptical arc (A)
|
case 10: // absolute elliptical arc (A)
|
||||||
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
|
dstr += seg.r1 + ',' + seg.r2 + ' ' + seg.angle + ' ' + (+seg.largeArcFlag) +
|
||||||
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
' ' + (+seg.sweepFlag) + ' ' + seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
case 17: // relative smooth cubic (s)
|
case 17: // relative smooth cubic (s)
|
||||||
case 16: // absolute smooth cubic (S)
|
case 16: // absolute smooth cubic (S)
|
||||||
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
dstr += seg.x2 + ',' + seg.y2 + ' ' + seg.x + ',' + seg.y + ' ';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selected.setAttribute('d', dstr);
|
selected.setAttribute('d', dstr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
704
editor/draw.js
704
editor/draw.js
@@ -17,7 +17,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.draw) {
|
if (!svgedit.draw) {
|
||||||
svgedit.draw = {};
|
svgedit.draw = {};
|
||||||
}
|
}
|
||||||
// alias
|
// alias
|
||||||
var NS = svgedit.NS;
|
var NS = svgedit.NS;
|
||||||
@@ -25,9 +25,9 @@ var NS = svgedit.NS;
|
|||||||
var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(',');
|
var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(',');
|
||||||
|
|
||||||
var RandomizeModes = {
|
var RandomizeModes = {
|
||||||
LET_DOCUMENT_DECIDE: 0,
|
LET_DOCUMENT_DECIDE: 0,
|
||||||
ALWAYS_RANDOMIZE: 1,
|
ALWAYS_RANDOMIZE: 1,
|
||||||
NEVER_RANDOMIZE: 2
|
NEVER_RANDOMIZE: 2
|
||||||
};
|
};
|
||||||
var randomizeIds = RandomizeModes.LET_DOCUMENT_DECIDE;
|
var randomizeIds = RandomizeModes.LET_DOCUMENT_DECIDE;
|
||||||
|
|
||||||
@@ -38,15 +38,15 @@ var randomizeIds = RandomizeModes.LET_DOCUMENT_DECIDE;
|
|||||||
* @param {svgedit.draw.Drawing} currentDrawing
|
* @param {svgedit.draw.Drawing} currentDrawing
|
||||||
*/
|
*/
|
||||||
svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) {
|
svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) {
|
||||||
randomizeIds = enableRandomization === false
|
randomizeIds = enableRandomization === false
|
||||||
? RandomizeModes.NEVER_RANDOMIZE
|
? RandomizeModes.NEVER_RANDOMIZE
|
||||||
: RandomizeModes.ALWAYS_RANDOMIZE;
|
: RandomizeModes.ALWAYS_RANDOMIZE;
|
||||||
|
|
||||||
if (randomizeIds === RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {
|
if (randomizeIds === RandomizeModes.ALWAYS_RANDOMIZE && !currentDrawing.getNonce()) {
|
||||||
currentDrawing.setNonce(Math.floor(Math.random() * 100001));
|
currentDrawing.setNonce(Math.floor(Math.random() * 100001));
|
||||||
} else if (randomizeIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {
|
} else if (randomizeIds === RandomizeModes.NEVER_RANDOMIZE && currentDrawing.getNonce()) {
|
||||||
currentDrawing.clearNonce();
|
currentDrawing.clearNonce();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,72 +57,72 @@ svgedit.draw.randomizeIds = function (enableRandomization, currentDrawing) {
|
|||||||
* @param {String=svg_} [optIdPrefix] - The ID prefix to use.
|
* @param {String=svg_} [optIdPrefix] - The ID prefix to use.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing = function (svgElem, optIdPrefix) {
|
svgedit.draw.Drawing = function (svgElem, optIdPrefix) {
|
||||||
if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||
|
if (!svgElem || !svgElem.tagName || !svgElem.namespaceURI ||
|
||||||
svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) {
|
svgElem.tagName !== 'svg' || svgElem.namespaceURI !== NS.SVG) {
|
||||||
throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');
|
throw new Error('Error: svgedit.draw.Drawing instance initialized without a <svg> element');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SVG DOM Element that represents this drawing.
|
* The SVG DOM Element that represents this drawing.
|
||||||
* @type {SVGSVGElement}
|
* @type {SVGSVGElement}
|
||||||
*/
|
*/
|
||||||
this.svgElem_ = svgElem;
|
this.svgElem_ = svgElem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The latest object number used in this drawing.
|
* The latest object number used in this drawing.
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
this.obj_num = 0;
|
this.obj_num = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix to prepend to each element id in the drawing.
|
* The prefix to prepend to each element id in the drawing.
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
this.idPrefix = optIdPrefix || 'svg_';
|
this.idPrefix = optIdPrefix || 'svg_';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of released element ids to immediately reuse.
|
* An array of released element ids to immediately reuse.
|
||||||
* @type {Array.<number>}
|
* @type {Array.<number>}
|
||||||
*/
|
*/
|
||||||
this.releasedNums = [];
|
this.releasedNums = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The z-ordered array of Layer objects. Each layer has a name
|
* The z-ordered array of Layer objects. Each layer has a name
|
||||||
* and group element.
|
* and group element.
|
||||||
* The first layer is the one at the bottom of the rendering.
|
* The first layer is the one at the bottom of the rendering.
|
||||||
* @type {Array.<Layer>}
|
* @type {Array.<Layer>}
|
||||||
*/
|
*/
|
||||||
this.all_layers = [];
|
this.all_layers = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of all_layers by name.
|
* Map of all_layers by name.
|
||||||
*
|
*
|
||||||
* Note: Layers are ordered, but referenced externally by name; so, we need both container
|
* Note: Layers are ordered, but referenced externally by name; so, we need both container
|
||||||
* types depending on which function is called (i.e. all_layers and layer_map).
|
* types depending on which function is called (i.e. all_layers and layer_map).
|
||||||
*
|
*
|
||||||
* @type {Object.<string, Layer>}
|
* @type {Object.<string, Layer>}
|
||||||
*/
|
*/
|
||||||
this.layer_map = {};
|
this.layer_map = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current layer being used.
|
* The current layer being used.
|
||||||
* @type {Layer}
|
* @type {Layer}
|
||||||
*/
|
*/
|
||||||
this.current_layer = null;
|
this.current_layer = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The nonce to use to uniquely identify elements across drawings.
|
* The nonce to use to uniquely identify elements across drawings.
|
||||||
* @type {!String}
|
* @type {!String}
|
||||||
*/
|
*/
|
||||||
this.nonce_ = '';
|
this.nonce_ = '';
|
||||||
var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');
|
var n = this.svgElem_.getAttributeNS(NS.SE, 'nonce');
|
||||||
// If already set in the DOM, use the nonce throughout the document
|
// If already set in the DOM, use the nonce throughout the document
|
||||||
// else, if randomizeIds(true) has been called, create and set the nonce.
|
// else, if randomizeIds(true) has been called, create and set the nonce.
|
||||||
if (!!n && randomizeIds !== RandomizeModes.NEVER_RANDOMIZE) {
|
if (!!n && randomizeIds !== RandomizeModes.NEVER_RANDOMIZE) {
|
||||||
this.nonce_ = n;
|
this.nonce_ = n;
|
||||||
} else if (randomizeIds === RandomizeModes.ALWAYS_RANDOMIZE) {
|
} else if (randomizeIds === RandomizeModes.ALWAYS_RANDOMIZE) {
|
||||||
this.setNonce(Math.floor(Math.random() * 100001));
|
this.setNonce(Math.floor(Math.random() * 100001));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,44 +130,44 @@ svgedit.draw.Drawing = function (svgElem, optIdPrefix) {
|
|||||||
* @returns {Element} SVG element within the root SVGSVGElement
|
* @returns {Element} SVG element within the root SVGSVGElement
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getElem_ = function (id) {
|
svgedit.draw.Drawing.prototype.getElem_ = function (id) {
|
||||||
if (this.svgElem_.querySelector) {
|
if (this.svgElem_.querySelector) {
|
||||||
// querySelector lookup
|
// querySelector lookup
|
||||||
return this.svgElem_.querySelector('#' + id);
|
return this.svgElem_.querySelector('#' + id);
|
||||||
}
|
}
|
||||||
// jQuery lookup: twice as slow as xpath in FF
|
// jQuery lookup: twice as slow as xpath in FF
|
||||||
return $(this.svgElem_).find('[id=' + id + ']')[0];
|
return $(this.svgElem_).find('[id=' + id + ']')[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {SVGSVGElement}
|
* @returns {SVGSVGElement}
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getSvgElem = function () {
|
svgedit.draw.Drawing.prototype.getSvgElem = function () {
|
||||||
return this.svgElem_;
|
return this.svgElem_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {!string|number} The previously set nonce
|
* @returns {!string|number} The previously set nonce
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getNonce = function () {
|
svgedit.draw.Drawing.prototype.getNonce = function () {
|
||||||
return this.nonce_;
|
return this.nonce_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!string|number} n The nonce to set
|
* @param {!string|number} n The nonce to set
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setNonce = function (n) {
|
svgedit.draw.Drawing.prototype.setNonce = function (n) {
|
||||||
this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE);
|
this.svgElem_.setAttributeNS(NS.XMLNS, 'xmlns:se', NS.SE);
|
||||||
this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);
|
this.svgElem_.setAttributeNS(NS.SE, 'se:nonce', n);
|
||||||
this.nonce_ = n;
|
this.nonce_ = n;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears any previously set nonce
|
* Clears any previously set nonce
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.clearNonce = function () {
|
svgedit.draw.Drawing.prototype.clearNonce = function () {
|
||||||
// We deliberately leave any se:nonce attributes alone,
|
// We deliberately leave any se:nonce attributes alone,
|
||||||
// we just don't use it to randomize ids.
|
// we just don't use it to randomize ids.
|
||||||
this.nonce_ = '';
|
this.nonce_ = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,9 +175,9 @@ svgedit.draw.Drawing.prototype.clearNonce = function () {
|
|||||||
* @return {String} The latest object Id.
|
* @return {String} The latest object Id.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getId = function () {
|
svgedit.draw.Drawing.prototype.getId = function () {
|
||||||
return this.nonce_
|
return this.nonce_
|
||||||
? this.idPrefix + this.nonce_ + '_' + this.obj_num
|
? this.idPrefix + this.nonce_ + '_' + this.obj_num
|
||||||
: this.idPrefix + this.obj_num;
|
: this.idPrefix + this.obj_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,35 +185,35 @@ svgedit.draw.Drawing.prototype.getId = function () {
|
|||||||
* @return {String} The next object Id to use.
|
* @return {String} The next object Id to use.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getNextId = function () {
|
svgedit.draw.Drawing.prototype.getNextId = function () {
|
||||||
var oldObjNum = this.obj_num;
|
var oldObjNum = this.obj_num;
|
||||||
var restoreOldObjNum = false;
|
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.
|
// use the last one instead of the next obj_num.
|
||||||
// We need to temporarily use obj_num as that is what getId() depends on.
|
// We need to temporarily use obj_num as that is what getId() depends on.
|
||||||
if (this.releasedNums.length > 0) {
|
if (this.releasedNums.length > 0) {
|
||||||
this.obj_num = this.releasedNums.pop();
|
this.obj_num = this.releasedNums.pop();
|
||||||
restoreOldObjNum = true;
|
restoreOldObjNum = true;
|
||||||
} else {
|
} else {
|
||||||
// If we are not using a released id, then increment the obj_num.
|
// If we are not using a released id, then increment the obj_num.
|
||||||
this.obj_num++;
|
this.obj_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the ID does not exist.
|
// Ensure the ID does not exist.
|
||||||
var id = this.getId();
|
var id = this.getId();
|
||||||
while (this.getElem_(id)) {
|
while (this.getElem_(id)) {
|
||||||
if (restoreOldObjNum) {
|
if (restoreOldObjNum) {
|
||||||
this.obj_num = oldObjNum;
|
this.obj_num = oldObjNum;
|
||||||
restoreOldObjNum = false;
|
restoreOldObjNum = false;
|
||||||
}
|
}
|
||||||
this.obj_num++;
|
this.obj_num++;
|
||||||
id = this.getId();
|
id = this.getId();
|
||||||
}
|
}
|
||||||
// Restore the old object number if required.
|
// Restore the old object number if required.
|
||||||
if (restoreOldObjNum) {
|
if (restoreOldObjNum) {
|
||||||
this.obj_num = oldObjNum;
|
this.obj_num = oldObjNum;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,24 +224,24 @@ svgedit.draw.Drawing.prototype.getNextId = function () {
|
|||||||
* @returns {boolean} True if the id was valid to be released, false otherwise.
|
* @returns {boolean} True if the id was valid to be released, false otherwise.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.releaseId = function (id) {
|
svgedit.draw.Drawing.prototype.releaseId = function (id) {
|
||||||
// confirm if this is a valid id for this Document, else return false
|
// confirm if this is a valid id for this Document, else return false
|
||||||
var front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : '');
|
var front = this.idPrefix + (this.nonce_ ? this.nonce_ + '_' : '');
|
||||||
if (typeof id !== 'string' || id.indexOf(front) !== 0) {
|
if (typeof id !== 'string' || id.indexOf(front) !== 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// extract the obj_num of this id
|
// extract the obj_num of this id
|
||||||
var num = parseInt(id.substr(front.length), 10);
|
var num = parseInt(id.substr(front.length), 10);
|
||||||
|
|
||||||
// if we didn't get a positive number or we already released this number
|
// if we didn't get a positive number or we already released this number
|
||||||
// then return false.
|
// then return false.
|
||||||
if (typeof num !== 'number' || num <= 0 || this.releasedNums.indexOf(num) !== -1) {
|
if (typeof num !== 'number' || num <= 0 || this.releasedNums.indexOf(num) !== -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// push the released number into the released queue
|
// push the released number into the released queue
|
||||||
this.releasedNums.push(num);
|
this.releasedNums.push(num);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -249,7 +249,7 @@ svgedit.draw.Drawing.prototype.releaseId = function (id) {
|
|||||||
* @returns {integer} The number of layers in the current drawing.
|
* @returns {integer} The number of layers in the current drawing.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getNumLayers = function () {
|
svgedit.draw.Drawing.prototype.getNumLayers = function () {
|
||||||
return this.all_layers.length;
|
return this.all_layers.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,7 +257,7 @@ svgedit.draw.Drawing.prototype.getNumLayers = function () {
|
|||||||
* @param {string} name - The layer name to check
|
* @param {string} name - The layer name to check
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.hasLayer = function (name) {
|
svgedit.draw.Drawing.prototype.hasLayer = function (name) {
|
||||||
return this.layer_map[name] !== undefined;
|
return this.layer_map[name] !== undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,14 +266,14 @@ svgedit.draw.Drawing.prototype.hasLayer = function (name) {
|
|||||||
* @returns {string} The name of the ith layer (or the empty string if none found)
|
* @returns {string} The name of the ith layer (or the empty string if none found)
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getLayerName = function (i) {
|
svgedit.draw.Drawing.prototype.getLayerName = function (i) {
|
||||||
return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : '';
|
return i >= 0 && i < this.getNumLayers() ? this.all_layers[i].getName() : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {SVGGElement} The SVGGElement representing the current layer.
|
* @returns {SVGGElement} The SVGGElement representing the current layer.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getCurrentLayer = function () {
|
svgedit.draw.Drawing.prototype.getCurrentLayer = function () {
|
||||||
return this.current_layer ? this.current_layer.getGroup() : null;
|
return this.current_layer ? this.current_layer.getGroup() : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,8 +281,8 @@ svgedit.draw.Drawing.prototype.getCurrentLayer = function () {
|
|||||||
* @returns {SVGGElement} The SVGGElement representing the named layer or null.
|
* @returns {SVGGElement} The SVGGElement representing the named layer or null.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getLayerByName = function (name) {
|
svgedit.draw.Drawing.prototype.getLayerByName = function (name) {
|
||||||
var layer = this.layer_map[name];
|
var layer = this.layer_map[name];
|
||||||
return layer ? layer.getGroup() : null;
|
return layer ? layer.getGroup() : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,7 +291,7 @@ svgedit.draw.Drawing.prototype.getLayerByName = function (name) {
|
|||||||
* @returns {string} The name of the currently active layer (or the empty string if none found).
|
* @returns {string} The name of the currently active layer (or the empty string if none found).
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getCurrentLayerName = function () {
|
svgedit.draw.Drawing.prototype.getCurrentLayerName = function () {
|
||||||
return this.current_layer ? this.current_layer.getName() : '';
|
return this.current_layer ? this.current_layer.getName() : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,16 +301,16 @@ svgedit.draw.Drawing.prototype.getCurrentLayerName = function () {
|
|||||||
* @returns {string|null} The new name if changed; otherwise, null.
|
* @returns {string|null} The new name if changed; otherwise, null.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setCurrentLayerName = function (name, hrService) {
|
svgedit.draw.Drawing.prototype.setCurrentLayerName = function (name, hrService) {
|
||||||
var finalName = null;
|
var finalName = null;
|
||||||
if (this.current_layer) {
|
if (this.current_layer) {
|
||||||
var oldName = this.current_layer.getName();
|
var oldName = this.current_layer.getName();
|
||||||
finalName = this.current_layer.setName(name, hrService);
|
finalName = this.current_layer.setName(name, hrService);
|
||||||
if (finalName) {
|
if (finalName) {
|
||||||
delete this.layer_map[oldName];
|
delete this.layer_map[oldName];
|
||||||
this.layer_map[finalName] = this.current_layer;
|
this.layer_map[finalName] = this.current_layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return finalName;
|
return finalName;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -319,89 +319,89 @@ svgedit.draw.Drawing.prototype.setCurrentLayerName = function (name, hrService)
|
|||||||
* @returns {Object} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.
|
* @returns {Object} If the name was changed, returns {title:SVGGElement, previousName:string}; otherwise null.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
|
svgedit.draw.Drawing.prototype.setCurrentLayerPosition = function (newpos) {
|
||||||
var layerCount = this.getNumLayers();
|
var layerCount = this.getNumLayers();
|
||||||
if (!this.current_layer || newpos < 0 || newpos >= layerCount) {
|
if (!this.current_layer || newpos < 0 || newpos >= layerCount) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldpos;
|
var oldpos;
|
||||||
for (oldpos = 0; oldpos < layerCount; ++oldpos) {
|
for (oldpos = 0; oldpos < layerCount; ++oldpos) {
|
||||||
if (this.all_layers[oldpos] === this.current_layer) { break; }
|
if (this.all_layers[oldpos] === this.current_layer) { break; }
|
||||||
}
|
}
|
||||||
// some unknown error condition (current_layer not in all_layers)
|
// some unknown error condition (current_layer not in all_layers)
|
||||||
if (oldpos === layerCount) { return null; }
|
if (oldpos === layerCount) { return null; }
|
||||||
|
|
||||||
if (oldpos !== newpos) {
|
if (oldpos !== newpos) {
|
||||||
// if our new position is below us, we need to insert before the node after newpos
|
// if our new position is below us, we need to insert before the node after newpos
|
||||||
var refGroup = null;
|
var refGroup = null;
|
||||||
var currentGroup = this.current_layer.getGroup();
|
var currentGroup = this.current_layer.getGroup();
|
||||||
var oldNextSibling = currentGroup.nextSibling;
|
var oldNextSibling = currentGroup.nextSibling;
|
||||||
if (newpos > oldpos) {
|
if (newpos > oldpos) {
|
||||||
if (newpos < layerCount - 1) {
|
if (newpos < layerCount - 1) {
|
||||||
refGroup = this.all_layers[newpos + 1].getGroup();
|
refGroup = this.all_layers[newpos + 1].getGroup();
|
||||||
}
|
}
|
||||||
// if our new position is above us, we need to insert before the node at newpos
|
// if our new position is above us, we need to insert before the node at newpos
|
||||||
} else {
|
} else {
|
||||||
refGroup = this.all_layers[newpos].getGroup();
|
refGroup = this.all_layers[newpos].getGroup();
|
||||||
}
|
}
|
||||||
this.svgElem_.insertBefore(currentGroup, refGroup);
|
this.svgElem_.insertBefore(currentGroup, refGroup);
|
||||||
|
|
||||||
this.identifyLayers();
|
this.identifyLayers();
|
||||||
this.setCurrentLayer(this.getLayerName(newpos));
|
this.setCurrentLayer(this.getLayerName(newpos));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentGroup: currentGroup,
|
currentGroup: currentGroup,
|
||||||
oldNextSibling: oldNextSibling
|
oldNextSibling: oldNextSibling
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
|
svgedit.draw.Drawing.prototype.mergeLayer = function (hrService) {
|
||||||
var currentGroup = this.current_layer.getGroup();
|
var currentGroup = this.current_layer.getGroup();
|
||||||
var prevGroup = $(currentGroup).prev()[0];
|
var prevGroup = $(currentGroup).prev()[0];
|
||||||
if (!prevGroup) { return; }
|
if (!prevGroup) { return; }
|
||||||
|
|
||||||
hrService.startBatchCommand('Merge Layer');
|
hrService.startBatchCommand('Merge Layer');
|
||||||
|
|
||||||
var layerNextSibling = currentGroup.nextSibling;
|
var layerNextSibling = currentGroup.nextSibling;
|
||||||
hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);
|
hrService.removeElement(currentGroup, layerNextSibling, this.svgElem_);
|
||||||
|
|
||||||
while (currentGroup.firstChild) {
|
while (currentGroup.firstChild) {
|
||||||
var child = currentGroup.firstChild;
|
var child = currentGroup.firstChild;
|
||||||
if (child.localName === 'title') {
|
if (child.localName === 'title') {
|
||||||
hrService.removeElement(child, child.nextSibling, currentGroup);
|
hrService.removeElement(child, child.nextSibling, currentGroup);
|
||||||
currentGroup.removeChild(child);
|
currentGroup.removeChild(child);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var oldNextSibling = child.nextSibling;
|
var oldNextSibling = child.nextSibling;
|
||||||
prevGroup.appendChild(child);
|
prevGroup.appendChild(child);
|
||||||
hrService.moveElement(child, oldNextSibling, currentGroup);
|
hrService.moveElement(child, oldNextSibling, currentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove current layer's group
|
// Remove current layer's group
|
||||||
this.current_layer.removeGroup();
|
this.current_layer.removeGroup();
|
||||||
// Remove the current layer and set the previous layer as the new current layer
|
// Remove the current layer and set the previous layer as the new current layer
|
||||||
var index = this.all_layers.indexOf(this.current_layer);
|
var index = this.all_layers.indexOf(this.current_layer);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
var name = this.current_layer.getName();
|
var name = this.current_layer.getName();
|
||||||
this.current_layer = this.all_layers[index - 1];
|
this.current_layer = this.all_layers[index - 1];
|
||||||
this.all_layers.splice(index, 1);
|
this.all_layers.splice(index, 1);
|
||||||
delete this.layer_map[name];
|
delete this.layer_map[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
hrService.endBatchCommand();
|
hrService.endBatchCommand();
|
||||||
};
|
};
|
||||||
|
|
||||||
svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
|
svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
|
||||||
// Set the current layer to the last layer.
|
// Set the current layer to the last layer.
|
||||||
this.current_layer = this.all_layers[this.all_layers.length - 1];
|
this.current_layer = this.all_layers[this.all_layers.length - 1];
|
||||||
|
|
||||||
hrService.startBatchCommand('Merge all Layers');
|
hrService.startBatchCommand('Merge all Layers');
|
||||||
while (this.all_layers.length > 1) {
|
while (this.all_layers.length > 1) {
|
||||||
this.mergeLayer(hrService);
|
this.mergeLayer(hrService);
|
||||||
}
|
}
|
||||||
hrService.endBatchCommand();
|
hrService.endBatchCommand();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -412,16 +412,16 @@ svgedit.draw.Drawing.prototype.mergeAllLayers = function (hrService) {
|
|||||||
* @returns {boolean} true if the current layer was switched, otherwise false
|
* @returns {boolean} true if the current layer was switched, otherwise false
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setCurrentLayer = function (name) {
|
svgedit.draw.Drawing.prototype.setCurrentLayer = function (name) {
|
||||||
var layer = this.layer_map[name];
|
var layer = this.layer_map[name];
|
||||||
if (layer) {
|
if (layer) {
|
||||||
if (this.current_layer) {
|
if (this.current_layer) {
|
||||||
this.current_layer.deactivate();
|
this.current_layer.deactivate();
|
||||||
}
|
}
|
||||||
this.current_layer = layer;
|
this.current_layer = layer;
|
||||||
this.current_layer.activate();
|
this.current_layer.activate();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -430,12 +430,12 @@ svgedit.draw.Drawing.prototype.setCurrentLayer = function (name) {
|
|||||||
* @returns {SVGGElement} The SVGGElement of the layer removed or null.
|
* @returns {SVGGElement} The SVGGElement of the layer removed or null.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.deleteCurrentLayer = function () {
|
svgedit.draw.Drawing.prototype.deleteCurrentLayer = function () {
|
||||||
if (this.current_layer && this.getNumLayers() > 1) {
|
if (this.current_layer && this.getNumLayers() > 1) {
|
||||||
var oldLayerGroup = this.current_layer.removeGroup();
|
var oldLayerGroup = this.current_layer.removeGroup();
|
||||||
this.identifyLayers();
|
this.identifyLayers();
|
||||||
return oldLayerGroup;
|
return oldLayerGroup;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -444,13 +444,13 @@ svgedit.draw.Drawing.prototype.deleteCurrentLayer = function () {
|
|||||||
* @returns {string} The layer name or empty string.
|
* @returns {string} The layer name or empty string.
|
||||||
*/
|
*/
|
||||||
function findLayerNameInGroup (group) {
|
function findLayerNameInGroup (group) {
|
||||||
var name = $('title', group).text();
|
var name = $('title', group).text();
|
||||||
|
|
||||||
// Hack for Opera 10.60
|
// Hack for Opera 10.60
|
||||||
if (!name && svgedit.browser.isOpera() && group.querySelectorAll) {
|
if (!name && svgedit.browser.isOpera() && group.querySelectorAll) {
|
||||||
name = $(group.querySelectorAll('title')).text();
|
name = $(group.querySelectorAll('title')).text();
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -459,10 +459,10 @@ function findLayerNameInGroup (group) {
|
|||||||
* @returns {string} - The new name.
|
* @returns {string} - The new name.
|
||||||
*/
|
*/
|
||||||
function getNewLayerName (existingLayerNames) {
|
function getNewLayerName (existingLayerNames) {
|
||||||
var i = 1;
|
var i = 1;
|
||||||
// TODO(codedread): What about internationalization of "Layer"?
|
// TODO(codedread): What about internationalization of "Layer"?
|
||||||
while (existingLayerNames.indexOf(('Layer ' + i)) >= 0) { i++; }
|
while (existingLayerNames.indexOf(('Layer ' + i)) >= 0) { i++; }
|
||||||
return 'Layer ' + i;
|
return 'Layer ' + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -470,46 +470,46 @@ function getNewLayerName (existingLayerNames) {
|
|||||||
* top-most layer (last <g> child of this drawing).
|
* top-most layer (last <g> child of this drawing).
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.identifyLayers = function () {
|
svgedit.draw.Drawing.prototype.identifyLayers = function () {
|
||||||
this.all_layers = [];
|
this.all_layers = [];
|
||||||
this.layer_map = {};
|
this.layer_map = {};
|
||||||
var numchildren = this.svgElem_.childNodes.length;
|
var numchildren = this.svgElem_.childNodes.length;
|
||||||
// loop through all children of SVG element
|
// loop through all children of SVG element
|
||||||
var orphans = [], layernames = [];
|
var orphans = [], layernames = [];
|
||||||
var layer = null;
|
var layer = null;
|
||||||
var childgroups = false;
|
var childgroups = false;
|
||||||
for (var i = 0; i < numchildren; ++i) {
|
for (var i = 0; i < numchildren; ++i) {
|
||||||
var child = this.svgElem_.childNodes.item(i);
|
var child = this.svgElem_.childNodes.item(i);
|
||||||
// for each g, find its layer name
|
// for each g, find its layer name
|
||||||
if (child && child.nodeType === 1) {
|
if (child && child.nodeType === 1) {
|
||||||
if (child.tagName === 'g') {
|
if (child.tagName === 'g') {
|
||||||
childgroups = true;
|
childgroups = true;
|
||||||
var name = findLayerNameInGroup(child);
|
var name = findLayerNameInGroup(child);
|
||||||
if (name) {
|
if (name) {
|
||||||
layernames.push(name);
|
layernames.push(name);
|
||||||
layer = new svgedit.draw.Layer(name, child);
|
layer = new svgedit.draw.Layer(name, child);
|
||||||
this.all_layers.push(layer);
|
this.all_layers.push(layer);
|
||||||
this.layer_map[name] = layer;
|
this.layer_map[name] = layer;
|
||||||
} else {
|
} else {
|
||||||
// if group did not have a name, it is an orphan
|
// if group did not have a name, it is an orphan
|
||||||
orphans.push(child);
|
orphans.push(child);
|
||||||
}
|
}
|
||||||
} else if (~visElems.indexOf(child.nodeName)) {
|
} else if (~visElems.indexOf(child.nodeName)) {
|
||||||
// Child is "visible" (i.e. not a <title> or <defs> element), so it is an orphan
|
// Child is "visible" (i.e. not a <title> or <defs> element), so it is an orphan
|
||||||
orphans.push(child);
|
orphans.push(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If orphans or no layers found, create a new layer and add all the orphans to it
|
// If orphans or no layers found, create a new layer and add all the orphans to it
|
||||||
if (orphans.length > 0 || !childgroups) {
|
if (orphans.length > 0 || !childgroups) {
|
||||||
layer = new svgedit.draw.Layer(getNewLayerName(layernames), null, this.svgElem_);
|
layer = new svgedit.draw.Layer(getNewLayerName(layernames), null, this.svgElem_);
|
||||||
layer.appendChildren(orphans);
|
layer.appendChildren(orphans);
|
||||||
this.all_layers.push(layer);
|
this.all_layers.push(layer);
|
||||||
this.layer_map[name] = layer;
|
this.layer_map[name] = layer;
|
||||||
} else {
|
} else {
|
||||||
layer.activate();
|
layer.activate();
|
||||||
}
|
}
|
||||||
this.current_layer = layer;
|
this.current_layer = layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -521,27 +521,27 @@ svgedit.draw.Drawing.prototype.identifyLayers = function () {
|
|||||||
* also the current layer of this drawing.
|
* also the current layer of this drawing.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.createLayer = function (name, hrService) {
|
svgedit.draw.Drawing.prototype.createLayer = function (name, hrService) {
|
||||||
if (this.current_layer) {
|
if (this.current_layer) {
|
||||||
this.current_layer.deactivate();
|
this.current_layer.deactivate();
|
||||||
}
|
}
|
||||||
// Check for duplicate name.
|
// Check for duplicate name.
|
||||||
if (name === undefined || name === null || name === '' || this.layer_map[name]) {
|
if (name === undefined || name === null || name === '' || this.layer_map[name]) {
|
||||||
name = getNewLayerName(Object.keys(this.layer_map));
|
name = getNewLayerName(Object.keys(this.layer_map));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crate new layer and add to DOM as last layer
|
// Crate new layer and add to DOM as last layer
|
||||||
var layer = new svgedit.draw.Layer(name, null, this.svgElem_);
|
var layer = new svgedit.draw.Layer(name, null, this.svgElem_);
|
||||||
// Like to assume hrService exists, but this is backwards compatible with old version of createLayer.
|
// Like to assume hrService exists, but this is backwards compatible with old version of createLayer.
|
||||||
if (hrService) {
|
if (hrService) {
|
||||||
hrService.startBatchCommand('Create Layer');
|
hrService.startBatchCommand('Create Layer');
|
||||||
hrService.insertElement(layer.getGroup());
|
hrService.insertElement(layer.getGroup());
|
||||||
hrService.endBatchCommand();
|
hrService.endBatchCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.all_layers.push(layer);
|
this.all_layers.push(layer);
|
||||||
this.layer_map[name] = layer;
|
this.layer_map[name] = layer;
|
||||||
this.current_layer = layer;
|
this.current_layer = layer;
|
||||||
return layer.getGroup();
|
return layer.getGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -552,43 +552,43 @@ svgedit.draw.Drawing.prototype.createLayer = function (name, hrService) {
|
|||||||
* also the current layer of this drawing.
|
* also the current layer of this drawing.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) {
|
svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) {
|
||||||
if (!this.current_layer) { return null; }
|
if (!this.current_layer) { return null; }
|
||||||
this.current_layer.deactivate();
|
this.current_layer.deactivate();
|
||||||
// Check for duplicate name.
|
// Check for duplicate name.
|
||||||
if (name === undefined || name === null || name === '' || this.layer_map[name]) {
|
if (name === undefined || name === null || name === '' || this.layer_map[name]) {
|
||||||
name = getNewLayerName(Object.keys(this.layer_map));
|
name = getNewLayerName(Object.keys(this.layer_map));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new group and add to DOM just after current_layer
|
// Create new group and add to DOM just after current_layer
|
||||||
var currentGroup = this.current_layer.getGroup();
|
var currentGroup = this.current_layer.getGroup();
|
||||||
var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_);
|
var layer = new svgedit.draw.Layer(name, currentGroup, this.svgElem_);
|
||||||
var group = layer.getGroup();
|
var group = layer.getGroup();
|
||||||
|
|
||||||
// Clone children
|
// Clone children
|
||||||
var children = currentGroup.childNodes;
|
var children = currentGroup.childNodes;
|
||||||
var index;
|
var index;
|
||||||
for (index = 0; index < children.length; index++) {
|
for (index = 0; index < children.length; index++) {
|
||||||
var ch = children[index];
|
var ch = children[index];
|
||||||
if (ch.localName === 'title') { continue; }
|
if (ch.localName === 'title') { continue; }
|
||||||
group.appendChild(this.copyElem(ch));
|
group.appendChild(this.copyElem(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hrService) {
|
if (hrService) {
|
||||||
hrService.startBatchCommand('Duplicate Layer');
|
hrService.startBatchCommand('Duplicate Layer');
|
||||||
hrService.insertElement(group);
|
hrService.insertElement(group);
|
||||||
hrService.endBatchCommand();
|
hrService.endBatchCommand();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update layer containers and current_layer.
|
// Update layer containers and current_layer.
|
||||||
index = this.all_layers.indexOf(this.current_layer);
|
index = this.all_layers.indexOf(this.current_layer);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
this.all_layers.splice(index + 1, 0, layer);
|
this.all_layers.splice(index + 1, 0, layer);
|
||||||
} else {
|
} else {
|
||||||
this.all_layers.push(layer);
|
this.all_layers.push(layer);
|
||||||
}
|
}
|
||||||
this.layer_map[name] = layer;
|
this.layer_map[name] = layer;
|
||||||
this.current_layer = layer;
|
this.current_layer = layer;
|
||||||
return group;
|
return group;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -598,8 +598,8 @@ svgedit.draw.Drawing.prototype.cloneLayer = function (name, hrService) {
|
|||||||
* @returns {boolean} The visibility state of the layer, or false if the layer name was invalid.
|
* @returns {boolean} The visibility state of the layer, or false if the layer name was invalid.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getLayerVisibility = function (layername) {
|
svgedit.draw.Drawing.prototype.getLayerVisibility = function (layername) {
|
||||||
var layer = this.layer_map[layername];
|
var layer = this.layer_map[layername];
|
||||||
return layer ? layer.isVisible() : false;
|
return layer ? layer.isVisible() : false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -612,13 +612,13 @@ svgedit.draw.Drawing.prototype.getLayerVisibility = function (layername) {
|
|||||||
* layername was valid, otherwise null.
|
* layername was valid, otherwise null.
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setLayerVisibility = function (layername, bVisible) {
|
svgedit.draw.Drawing.prototype.setLayerVisibility = function (layername, bVisible) {
|
||||||
if (typeof bVisible !== 'boolean') {
|
if (typeof bVisible !== 'boolean') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var layer = this.layer_map[layername];
|
var layer = this.layer_map[layername];
|
||||||
if (!layer) { return null; }
|
if (!layer) { return null; }
|
||||||
layer.setVisible(bVisible);
|
layer.setVisible(bVisible);
|
||||||
return layer.getGroup();
|
return layer.getGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -628,9 +628,9 @@ svgedit.draw.Drawing.prototype.setLayerVisibility = function (layername, bVisibl
|
|||||||
* if layername is not a valid layer
|
* if layername is not a valid layer
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.getLayerOpacity = function (layername) {
|
svgedit.draw.Drawing.prototype.getLayerOpacity = function (layername) {
|
||||||
var layer = this.layer_map[layername];
|
var layer = this.layer_map[layername];
|
||||||
if (!layer) { return null; }
|
if (!layer) { return null; }
|
||||||
return layer.getOpacity();
|
return layer.getOpacity();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -641,13 +641,13 @@ svgedit.draw.Drawing.prototype.getLayerOpacity = function (layername) {
|
|||||||
* @param {number} opacity - A float value in the range 0.0-1.0
|
* @param {number} opacity - A float value in the range 0.0-1.0
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.setLayerOpacity = function (layername, opacity) {
|
svgedit.draw.Drawing.prototype.setLayerOpacity = function (layername, opacity) {
|
||||||
if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {
|
if (typeof opacity !== 'number' || opacity < 0.0 || opacity > 1.0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var layer = this.layer_map[layername];
|
var layer = this.layer_map[layername];
|
||||||
if (layer) {
|
if (layer) {
|
||||||
layer.setOpacity(opacity);
|
layer.setOpacity(opacity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -656,8 +656,8 @@ svgedit.draw.Drawing.prototype.setLayerOpacity = function (layername, opacity) {
|
|||||||
* @returns {Element}
|
* @returns {Element}
|
||||||
*/
|
*/
|
||||||
svgedit.draw.Drawing.prototype.copyElem = function (el) {
|
svgedit.draw.Drawing.prototype.copyElem = function (el) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var getNextIdClosure = function () { return self.getNextId(); };
|
var getNextIdClosure = function () { return self.getNextId(); };
|
||||||
return svgedit.utilities.copyElem(el, getNextIdClosure);
|
return svgedit.utilities.copyElem(el, getNextIdClosure);
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -5,76 +5,76 @@ var initEmbed; // eslint-disable-line no-unused-vars
|
|||||||
// Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
|
// Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var svgCanvas = null;
|
var svgCanvas = null;
|
||||||
var frame;
|
var frame;
|
||||||
|
|
||||||
initEmbed = function () {
|
initEmbed = function () {
|
||||||
var doc, mainButton;
|
var doc, mainButton;
|
||||||
svgCanvas = new EmbeddedSVGEdit(frame);
|
svgCanvas = new EmbeddedSVGEdit(frame);
|
||||||
// Hide main button, as we will be controlling new, load, save, etc. from the host document
|
// Hide main button, as we will be controlling new, load, save, etc. from the host document
|
||||||
doc = frame.contentDocument || frame.contentWindow.document;
|
doc = frame.contentDocument || frame.contentWindow.document;
|
||||||
mainButton = doc.getElementById('main_button');
|
mainButton = doc.getElementById('main_button');
|
||||||
mainButton.style.display = 'none';
|
mainButton.style.display = 'none';
|
||||||
};
|
};
|
||||||
|
|
||||||
function handleSvgData (data, error) {
|
function handleSvgData (data, error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
alert('error ' + error);
|
alert('error ' + error);
|
||||||
} else {
|
} else {
|
||||||
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
|
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSvg () {
|
function loadSvg () {
|
||||||
var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>';
|
var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>';
|
||||||
svgCanvas.setSvgString(svgexample);
|
svgCanvas.setSvgString(svgexample);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveSvg () {
|
function saveSvg () {
|
||||||
svgCanvas.getSvgString()(handleSvgData);
|
svgCanvas.getSvgString()(handleSvgData);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportPNG () {
|
function exportPNG () {
|
||||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||||
|
|
||||||
var exportWindow = window.open(
|
var exportWindow = window.open(
|
||||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||||
'svg-edit-exportWindow'
|
'svg-edit-exportWindow'
|
||||||
);
|
);
|
||||||
svgCanvas.rasterExport('PNG', null, exportWindow.name);
|
svgCanvas.rasterExport('PNG', null, exportWindow.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
function exportPDF () {
|
function exportPDF () {
|
||||||
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
// If you want to handle the PDF blob yourself, do as follows
|
// If you want to handle the PDF blob yourself, do as follows
|
||||||
svgCanvas.bind('exportedPDF', function (win, data) {
|
svgCanvas.bind('exportedPDF', function (win, data) {
|
||||||
alert(data.dataurlstring);
|
alert(data.dataurlstring);
|
||||||
});
|
});
|
||||||
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
|
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
|
||||||
return;
|
return;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var exportWindow = window.open(
|
var exportWindow = window.open(
|
||||||
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
|
||||||
'svg-edit-exportWindow'
|
'svg-edit-exportWindow'
|
||||||
);
|
);
|
||||||
svgCanvas.exportPDF(exportWindow.name);
|
svgCanvas.exportPDF(exportWindow.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add event handlers
|
// Add event handlers
|
||||||
$('#load').click(loadSvg);
|
$('#load').click(loadSvg);
|
||||||
$('#save').click(saveSvg);
|
$('#save').click(saveSvg);
|
||||||
$('#exportPNG').click(exportPNG);
|
$('#exportPNG').click(exportPNG);
|
||||||
$('#exportPDF').click(exportPDF);
|
$('#exportPDF').click(exportPDF);
|
||||||
$('body').append(
|
$('body').append(
|
||||||
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
|
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
|
||||||
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
|
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
|
||||||
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
|
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
frame = document.getElementById('svgedit');
|
frame = document.getElementById('svgedit');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>Embed API</title>
|
<title>Embed API</title>
|
||||||
<script src="jquery.js"></script>
|
<script src="jquery.js"></script>
|
||||||
<script src="embedapi.js"></script>
|
<script src="embedapi.js"></script>
|
||||||
<script src="embedapi-dom.js"></script>
|
<script src="embedapi-dom.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<button id="load">Load example</button>
|
<button id="load">Load example</button>
|
||||||
<button id="save">Save data</button>
|
<button id="save">Save data</button>
|
||||||
<button id="exportPNG">Export data to PNG</button>
|
<button id="exportPNG">Export data to PNG</button>
|
||||||
<button id="exportPDF">Export data to PDF</button>
|
<button id="exportPDF">Export data to PDF</button>
|
||||||
<br/>
|
<br/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit);
|
|||||||
svgCanvas.setSvgString('string')
|
svgCanvas.setSvgString('string')
|
||||||
- Or if a callback is needed:
|
- Or if a callback is needed:
|
||||||
svgCanvas.setSvgString('string')(function(data, error){
|
svgCanvas.setSvgString('string')(function(data, error){
|
||||||
if (error){
|
if (error){
|
||||||
// There was an error
|
// There was an error
|
||||||
} else{
|
} else{
|
||||||
// Handle data
|
// Handle data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Everything is done with the same API as the real svg-edit,
|
Everything is done with the same API as the real svg-edit,
|
||||||
@@ -42,15 +42,15 @@ blah.clearSelection('woot', 'blah', 1337, [1, 2, 3, 4, 5, 'moo'], -42, {a: 'tree
|
|||||||
var cbid = 0;
|
var cbid = 0;
|
||||||
|
|
||||||
function getCallbackSetter (d) {
|
function getCallbackSetter (d) {
|
||||||
return function () {
|
return function () {
|
||||||
var t = this, // New callback
|
var t = this, // New callback
|
||||||
args = [].slice.call(arguments),
|
args = [].slice.call(arguments),
|
||||||
cbid = t.send(d, args, function () {}); // The callback (currently it's nothing, but will be set later)
|
cbid = t.send(d, args, function () {}); // The callback (currently it's nothing, but will be set later)
|
||||||
|
|
||||||
return function (newcallback) {
|
return function (newcallback) {
|
||||||
t.callbacks[cbid] = newcallback; // Set callback
|
t.callbacks[cbid] = newcallback; // Set callback
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -59,38 +59,38 @@ function getCallbackSetter (d) {
|
|||||||
* of same domain control
|
* of same domain control
|
||||||
*/
|
*/
|
||||||
function addCallback (t, data) {
|
function addCallback (t, data) {
|
||||||
var result = data.result || data.error,
|
var result = data.result || data.error,
|
||||||
cbid = data.id;
|
cbid = data.id;
|
||||||
if (t.callbacks[cbid]) {
|
if (t.callbacks[cbid]) {
|
||||||
if (data.result) {
|
if (data.result) {
|
||||||
t.callbacks[cbid](result);
|
t.callbacks[cbid](result);
|
||||||
} else {
|
} else {
|
||||||
t.callbacks[cbid](result, 'error');
|
t.callbacks[cbid](result, 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function messageListener (e) {
|
function messageListener (e) {
|
||||||
// We accept and post strings as opposed to objects for the sake of IE9 support; this
|
// We accept and post strings as opposed to objects for the sake of IE9 support; this
|
||||||
// will most likely be changed in the future
|
// will most likely be changed in the future
|
||||||
if (typeof e.data !== 'string') {
|
if (typeof e.data !== 'string') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var allowedOrigins = this.allowedOrigins,
|
var allowedOrigins = this.allowedOrigins,
|
||||||
data = e.data && JSON.parse(e.data);
|
data = e.data && JSON.parse(e.data);
|
||||||
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
|
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
|
||||||
e.source !== this.frame.contentWindow ||
|
e.source !== this.frame.contentWindow ||
|
||||||
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
|
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addCallback(this, data);
|
addCallback(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMessageListener (t) {
|
function getMessageListener (t) {
|
||||||
return function (e) {
|
return function (e) {
|
||||||
messageListener.call(t, e);
|
messageListener.call(t, e);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,77 +100,77 @@ function getMessageListener (t) {
|
|||||||
* If supplied, it should probably be the same as svgEditor's allowedOrigins
|
* If supplied, it should probably be the same as svgEditor's allowedOrigins
|
||||||
*/
|
*/
|
||||||
function EmbeddedSVGEdit (frame, allowedOrigins) {
|
function EmbeddedSVGEdit (frame, allowedOrigins) {
|
||||||
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
|
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
|
||||||
return new EmbeddedSVGEdit(frame);
|
return new EmbeddedSVGEdit(frame);
|
||||||
}
|
}
|
||||||
this.allowedOrigins = allowedOrigins || [];
|
this.allowedOrigins = allowedOrigins || [];
|
||||||
// Initialize communication
|
// Initialize communication
|
||||||
this.frame = frame;
|
this.frame = frame;
|
||||||
this.callbacks = {};
|
this.callbacks = {};
|
||||||
// List of functions extracted with this:
|
// List of functions extracted with this:
|
||||||
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
|
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
|
||||||
|
|
||||||
// for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q
|
// for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q
|
||||||
// var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
|
// var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
|
||||||
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
|
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
|
||||||
// 'moveSelectedToLayer', 'clear'];
|
// 'moveSelectedToLayer', 'clear'];
|
||||||
|
|
||||||
// Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
|
// Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
|
||||||
// var svgCanvas = frame.contentWindow.svgCanvas;
|
// var svgCanvas = frame.contentWindow.svgCanvas;
|
||||||
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
|
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
|
||||||
// alert("['" + l.join("', '") + "']");
|
// alert("['" + l.join("', '") + "']");
|
||||||
// Run in svgedit itself
|
// Run in svgedit itself
|
||||||
var i,
|
var i,
|
||||||
functions = [
|
functions = [
|
||||||
'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready'
|
'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready'
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: rewrite the following, it's pretty scary.
|
// TODO: rewrite the following, it's pretty scary.
|
||||||
for (i = 0; i < functions.length; i++) {
|
for (i = 0; i < functions.length; i++) {
|
||||||
this[functions[i]] = getCallbackSetter(functions[i]);
|
this[functions[i]] = getCallbackSetter(functions[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Older IE may need a polyfill for addEventListener, but so it would for SVG
|
// Older IE may need a polyfill for addEventListener, but so it would for SVG
|
||||||
window.addEventListener('message', getMessageListener(this), false);
|
window.addEventListener('message', getMessageListener(this), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EmbeddedSVGEdit.prototype.send = function (name, args, callback) {
|
EmbeddedSVGEdit.prototype.send = function (name, args, callback) {
|
||||||
var t = this;
|
var t = this;
|
||||||
cbid++;
|
cbid++;
|
||||||
|
|
||||||
this.callbacks[cbid] = callback;
|
this.callbacks[cbid] = callback;
|
||||||
setTimeout((function (cbid) {
|
setTimeout((function (cbid) {
|
||||||
return function () { // Delay for the callback to be set in case its synchronous
|
return function () { // Delay for the callback to be set in case its synchronous
|
||||||
/*
|
/*
|
||||||
* Todo: Handle non-JSON arguments and return values (undefined,
|
* Todo: Handle non-JSON arguments and return values (undefined,
|
||||||
* nonfinite numbers, functions, and built-in objects like Date,
|
* nonfinite numbers, functions, and built-in objects like Date,
|
||||||
* RegExp), etc.? Allow promises instead of callbacks? Review
|
* RegExp), etc.? Allow promises instead of callbacks? Review
|
||||||
* SVG-Edit functions for whether JSON-able parameters can be
|
* SVG-Edit functions for whether JSON-able parameters can be
|
||||||
* made compatile with all API functionality
|
* made compatile with all API functionality
|
||||||
*/
|
*/
|
||||||
// We accept and post strings for the sake of IE9 support
|
// We accept and post strings for the sake of IE9 support
|
||||||
if (window.location.origin === t.frame.contentWindow.location.origin) {
|
if (window.location.origin === t.frame.contentWindow.location.origin) {
|
||||||
// Although we do not really need this API if we are working same
|
// Although we do not really need this API if we are working same
|
||||||
// domain, it could allow us to write in a way that would work
|
// domain, it could allow us to write in a way that would work
|
||||||
// cross-domain as well, assuming we stick to the argument limitations
|
// cross-domain as well, assuming we stick to the argument limitations
|
||||||
// of the current JSON-based communication API (e.g., not passing
|
// of the current JSON-based communication API (e.g., not passing
|
||||||
// callbacks). We might be able to address these shortcomings; see
|
// callbacks). We might be able to address these shortcomings; see
|
||||||
// the todo elsewhere in this file.
|
// the todo elsewhere in this file.
|
||||||
var message = {id: cbid},
|
var message = {id: cbid},
|
||||||
svgCanvas = t.frame.contentWindow.svgCanvas;
|
svgCanvas = t.frame.contentWindow.svgCanvas;
|
||||||
try {
|
try {
|
||||||
message.result = svgCanvas[name].apply(svgCanvas, args);
|
message.result = svgCanvas[name].apply(svgCanvas, args);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
message.error = err.message;
|
message.error = err.message;
|
||||||
}
|
}
|
||||||
addCallback(t, message);
|
addCallback(t, message);
|
||||||
} else { // Requires the ext-xdomain-messaging.js extension
|
} else { // Requires the ext-xdomain-messaging.js extension
|
||||||
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*');
|
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}(cbid)), 0);
|
}(cbid)), 0);
|
||||||
|
|
||||||
return cbid;
|
return cbid;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API
|
window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API
|
||||||
|
|||||||
@@ -17,15 +17,15 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.history) {
|
if (!svgedit.history) {
|
||||||
svgedit.history = {};
|
svgedit.history = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group: Undo/Redo history management
|
// Group: Undo/Redo history management
|
||||||
svgedit.history.HistoryEventTypes = {
|
svgedit.history.HistoryEventTypes = {
|
||||||
BEFORE_APPLY: 'before_apply',
|
BEFORE_APPLY: 'before_apply',
|
||||||
AFTER_APPLY: 'after_apply',
|
AFTER_APPLY: 'after_apply',
|
||||||
BEFORE_UNAPPLY: 'before_unapply',
|
BEFORE_UNAPPLY: 'before_unapply',
|
||||||
AFTER_UNAPPLY: 'after_unapply'
|
AFTER_UNAPPLY: 'after_unapply'
|
||||||
};
|
};
|
||||||
|
|
||||||
// var removedElements = {};
|
// var removedElements = {};
|
||||||
@@ -63,18 +63,18 @@ svgedit.history.HistoryEventTypes = {
|
|||||||
* @param {string} [text] - An optional string visible to user related to this change
|
* @param {string} [text] - An optional string visible to user related to this change
|
||||||
*/
|
*/
|
||||||
svgedit.history.MoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
|
svgedit.history.MoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
this.text = text ? ('Move ' + elem.tagName + ' to ' + text) : ('Move ' + elem.tagName);
|
this.text = text ? ('Move ' + elem.tagName + ' to ' + text) : ('Move ' + elem.tagName);
|
||||||
this.oldNextSibling = oldNextSibling;
|
this.oldNextSibling = oldNextSibling;
|
||||||
this.oldParent = oldParent;
|
this.oldParent = oldParent;
|
||||||
this.newNextSibling = elem.nextSibling;
|
this.newNextSibling = elem.nextSibling;
|
||||||
this.newParent = elem.parentNode;
|
this.newParent = elem.parentNode;
|
||||||
};
|
};
|
||||||
svgedit.history.MoveElementCommand.type = function () { return 'svgedit.history.MoveElementCommand'; };
|
svgedit.history.MoveElementCommand.type = function () { return 'svgedit.history.MoveElementCommand'; };
|
||||||
svgedit.history.MoveElementCommand.prototype.type = svgedit.history.MoveElementCommand.type;
|
svgedit.history.MoveElementCommand.prototype.type = svgedit.history.MoveElementCommand.type;
|
||||||
|
|
||||||
svgedit.history.MoveElementCommand.prototype.getText = function () {
|
svgedit.history.MoveElementCommand.prototype.getText = function () {
|
||||||
return this.text;
|
return this.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,16 +82,16 @@ svgedit.history.MoveElementCommand.prototype.getText = function () {
|
|||||||
* @param {handleHistoryEvent: function}
|
* @param {handleHistoryEvent: function}
|
||||||
*/
|
*/
|
||||||
svgedit.history.MoveElementCommand.prototype.apply = function (handler) {
|
svgedit.history.MoveElementCommand.prototype.apply = function (handler) {
|
||||||
// TODO(codedread): Refactor this common event code into a base HistoryCommand class.
|
// TODO(codedread): Refactor this common event code into a base HistoryCommand class.
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling);
|
this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,21 +99,21 @@ svgedit.history.MoveElementCommand.prototype.apply = function (handler) {
|
|||||||
* @param {handleHistoryEvent: function}
|
* @param {handleHistoryEvent: function}
|
||||||
*/
|
*/
|
||||||
svgedit.history.MoveElementCommand.prototype.unapply = function (handler) {
|
svgedit.history.MoveElementCommand.prototype.unapply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);
|
this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.MoveElementCommand.elements
|
// Function: svgedit.history.MoveElementCommand.elements
|
||||||
// Returns array with element associated with this command
|
// Returns array with element associated with this command
|
||||||
svgedit.history.MoveElementCommand.prototype.elements = function () {
|
svgedit.history.MoveElementCommand.prototype.elements = function () {
|
||||||
return [this.elem];
|
return [this.elem];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class: svgedit.history.InsertElementCommand
|
// Class: svgedit.history.InsertElementCommand
|
||||||
@@ -124,52 +124,52 @@ svgedit.history.MoveElementCommand.prototype.elements = function () {
|
|||||||
// elem - The newly added DOM element
|
// elem - The newly added DOM element
|
||||||
// text - An optional string visible to user related to this change
|
// text - An optional string visible to user related to this change
|
||||||
svgedit.history.InsertElementCommand = function (elem, text) {
|
svgedit.history.InsertElementCommand = function (elem, text) {
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
this.text = text || ('Create ' + elem.tagName);
|
this.text = text || ('Create ' + elem.tagName);
|
||||||
this.parent = elem.parentNode;
|
this.parent = elem.parentNode;
|
||||||
this.nextSibling = this.elem.nextSibling;
|
this.nextSibling = this.elem.nextSibling;
|
||||||
};
|
};
|
||||||
svgedit.history.InsertElementCommand.type = function () { return 'svgedit.history.InsertElementCommand'; };
|
svgedit.history.InsertElementCommand.type = function () { return 'svgedit.history.InsertElementCommand'; };
|
||||||
svgedit.history.InsertElementCommand.prototype.type = svgedit.history.InsertElementCommand.type;
|
svgedit.history.InsertElementCommand.prototype.type = svgedit.history.InsertElementCommand.type;
|
||||||
|
|
||||||
// Function: svgedit.history.InsertElementCommand.getText
|
// Function: svgedit.history.InsertElementCommand.getText
|
||||||
svgedit.history.InsertElementCommand.prototype.getText = function () {
|
svgedit.history.InsertElementCommand.prototype.getText = function () {
|
||||||
return this.text;
|
return this.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.InsertElementCommand.apply
|
// Function: svgedit.history.InsertElementCommand.apply
|
||||||
// Re-Inserts the new element
|
// Re-Inserts the new element
|
||||||
svgedit.history.InsertElementCommand.prototype.apply = function (handler) {
|
svgedit.history.InsertElementCommand.prototype.apply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.elem = this.parent.insertBefore(this.elem, this.nextSibling);
|
this.elem = this.parent.insertBefore(this.elem, this.nextSibling);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.InsertElementCommand.unapply
|
// Function: svgedit.history.InsertElementCommand.unapply
|
||||||
// Removes the element
|
// Removes the element
|
||||||
svgedit.history.InsertElementCommand.prototype.unapply = function (handler) {
|
svgedit.history.InsertElementCommand.prototype.unapply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.parent = this.elem.parentNode;
|
this.parent = this.elem.parentNode;
|
||||||
this.elem = this.elem.parentNode.removeChild(this.elem);
|
this.elem = this.elem.parentNode.removeChild(this.elem);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.InsertElementCommand.elements
|
// Function: svgedit.history.InsertElementCommand.elements
|
||||||
// Returns array with element associated with this command
|
// Returns array with element associated with this command
|
||||||
svgedit.history.InsertElementCommand.prototype.elements = function () {
|
svgedit.history.InsertElementCommand.prototype.elements = function () {
|
||||||
return [this.elem];
|
return [this.elem];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class: svgedit.history.RemoveElementCommand
|
// Class: svgedit.history.RemoveElementCommand
|
||||||
@@ -182,62 +182,62 @@ svgedit.history.InsertElementCommand.prototype.elements = function () {
|
|||||||
// oldParent - The DOM element's parent
|
// oldParent - The DOM element's parent
|
||||||
// text - An optional string visible to user related to this change
|
// text - An optional string visible to user related to this change
|
||||||
svgedit.history.RemoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
|
svgedit.history.RemoveElementCommand = function (elem, oldNextSibling, oldParent, text) {
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
this.text = text || ('Delete ' + elem.tagName);
|
this.text = text || ('Delete ' + elem.tagName);
|
||||||
this.nextSibling = oldNextSibling;
|
this.nextSibling = oldNextSibling;
|
||||||
this.parent = oldParent;
|
this.parent = oldParent;
|
||||||
|
|
||||||
// special hack for webkit: remove this element's entry in the svgTransformLists map
|
// special hack for webkit: remove this element's entry in the svgTransformLists map
|
||||||
svgedit.transformlist.removeElementFromListMap(elem);
|
svgedit.transformlist.removeElementFromListMap(elem);
|
||||||
};
|
};
|
||||||
svgedit.history.RemoveElementCommand.type = function () { return 'svgedit.history.RemoveElementCommand'; };
|
svgedit.history.RemoveElementCommand.type = function () { return 'svgedit.history.RemoveElementCommand'; };
|
||||||
svgedit.history.RemoveElementCommand.prototype.type = svgedit.history.RemoveElementCommand.type;
|
svgedit.history.RemoveElementCommand.prototype.type = svgedit.history.RemoveElementCommand.type;
|
||||||
|
|
||||||
// Function: svgedit.history.RemoveElementCommand.getText
|
// Function: svgedit.history.RemoveElementCommand.getText
|
||||||
svgedit.history.RemoveElementCommand.prototype.getText = function () {
|
svgedit.history.RemoveElementCommand.prototype.getText = function () {
|
||||||
return this.text;
|
return this.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: RemoveElementCommand.apply
|
// Function: RemoveElementCommand.apply
|
||||||
// Re-removes the new element
|
// Re-removes the new element
|
||||||
svgedit.history.RemoveElementCommand.prototype.apply = function (handler) {
|
svgedit.history.RemoveElementCommand.prototype.apply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
svgedit.transformlist.removeElementFromListMap(this.elem);
|
svgedit.transformlist.removeElementFromListMap(this.elem);
|
||||||
this.parent = this.elem.parentNode;
|
this.parent = this.elem.parentNode;
|
||||||
this.elem = this.parent.removeChild(this.elem);
|
this.elem = this.parent.removeChild(this.elem);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: RemoveElementCommand.unapply
|
// Function: RemoveElementCommand.unapply
|
||||||
// Re-adds the new element
|
// Re-adds the new element
|
||||||
svgedit.history.RemoveElementCommand.prototype.unapply = function (handler) {
|
svgedit.history.RemoveElementCommand.prototype.unapply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
svgedit.transformlist.removeElementFromListMap(this.elem);
|
svgedit.transformlist.removeElementFromListMap(this.elem);
|
||||||
if (this.nextSibling == null) {
|
if (this.nextSibling == null) {
|
||||||
if (window.console) {
|
if (window.console) {
|
||||||
console.log('Error: reference element was lost');
|
console.log('Error: reference element was lost');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.parent.insertBefore(this.elem, this.nextSibling);
|
this.parent.insertBefore(this.elem, this.nextSibling);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: RemoveElementCommand.elements
|
// Function: RemoveElementCommand.elements
|
||||||
// Returns array with element associated with this command
|
// Returns array with element associated with this command
|
||||||
svgedit.history.RemoveElementCommand.prototype.elements = function () {
|
svgedit.history.RemoveElementCommand.prototype.elements = function () {
|
||||||
return [this.elem];
|
return [this.elem];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class: svgedit.history.ChangeElementCommand
|
// Class: svgedit.history.ChangeElementCommand
|
||||||
@@ -250,135 +250,135 @@ svgedit.history.RemoveElementCommand.prototype.elements = function () {
|
|||||||
// attrs - An object with the attributes to be changed and the values they had *before* the change
|
// attrs - An object with the attributes to be changed and the values they had *before* the change
|
||||||
// text - An optional string visible to user related to this change
|
// text - An optional string visible to user related to this change
|
||||||
svgedit.history.ChangeElementCommand = function (elem, attrs, text) {
|
svgedit.history.ChangeElementCommand = function (elem, attrs, text) {
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
this.text = text ? ('Change ' + elem.tagName + ' ' + text) : ('Change ' + elem.tagName);
|
this.text = text ? ('Change ' + elem.tagName + ' ' + text) : ('Change ' + elem.tagName);
|
||||||
this.newValues = {};
|
this.newValues = {};
|
||||||
this.oldValues = attrs;
|
this.oldValues = attrs;
|
||||||
var attr;
|
var attr;
|
||||||
for (attr in attrs) {
|
for (attr in attrs) {
|
||||||
if (attr === '#text') {
|
if (attr === '#text') {
|
||||||
this.newValues[attr] = elem.textContent;
|
this.newValues[attr] = elem.textContent;
|
||||||
} else if (attr === '#href') {
|
} else if (attr === '#href') {
|
||||||
this.newValues[attr] = svgedit.utilities.getHref(elem);
|
this.newValues[attr] = svgedit.utilities.getHref(elem);
|
||||||
} else {
|
} else {
|
||||||
this.newValues[attr] = elem.getAttribute(attr);
|
this.newValues[attr] = elem.getAttribute(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
svgedit.history.ChangeElementCommand.type = function () { return 'svgedit.history.ChangeElementCommand'; };
|
svgedit.history.ChangeElementCommand.type = function () { return 'svgedit.history.ChangeElementCommand'; };
|
||||||
svgedit.history.ChangeElementCommand.prototype.type = svgedit.history.ChangeElementCommand.type;
|
svgedit.history.ChangeElementCommand.prototype.type = svgedit.history.ChangeElementCommand.type;
|
||||||
|
|
||||||
// Function: svgedit.history.ChangeElementCommand.getText
|
// Function: svgedit.history.ChangeElementCommand.getText
|
||||||
svgedit.history.ChangeElementCommand.prototype.getText = function () {
|
svgedit.history.ChangeElementCommand.prototype.getText = function () {
|
||||||
return this.text;
|
return this.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.ChangeElementCommand.apply
|
// Function: svgedit.history.ChangeElementCommand.apply
|
||||||
// Performs the stored change action
|
// Performs the stored change action
|
||||||
svgedit.history.ChangeElementCommand.prototype.apply = function (handler) {
|
svgedit.history.ChangeElementCommand.prototype.apply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bChangedTransform = false;
|
var bChangedTransform = false;
|
||||||
var attr;
|
var attr;
|
||||||
for (attr in this.newValues) {
|
for (attr in this.newValues) {
|
||||||
if (this.newValues[attr]) {
|
if (this.newValues[attr]) {
|
||||||
if (attr === '#text') {
|
if (attr === '#text') {
|
||||||
this.elem.textContent = this.newValues[attr];
|
this.elem.textContent = this.newValues[attr];
|
||||||
} else if (attr === '#href') {
|
} else if (attr === '#href') {
|
||||||
svgedit.utilities.setHref(this.elem, this.newValues[attr]);
|
svgedit.utilities.setHref(this.elem, this.newValues[attr]);
|
||||||
} else {
|
} else {
|
||||||
this.elem.setAttribute(attr, this.newValues[attr]);
|
this.elem.setAttribute(attr, this.newValues[attr]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (attr === '#text') {
|
if (attr === '#text') {
|
||||||
this.elem.textContent = '';
|
this.elem.textContent = '';
|
||||||
} else {
|
} else {
|
||||||
this.elem.setAttribute(attr, '');
|
this.elem.setAttribute(attr, '');
|
||||||
this.elem.removeAttribute(attr);
|
this.elem.removeAttribute(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr === 'transform') { bChangedTransform = true; }
|
if (attr === 'transform') { bChangedTransform = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// relocate rotational transform, if necessary
|
// relocate rotational transform, if necessary
|
||||||
if (!bChangedTransform) {
|
if (!bChangedTransform) {
|
||||||
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
||||||
if (angle) {
|
if (angle) {
|
||||||
var bbox = this.elem.getBBox();
|
var bbox = this.elem.getBBox();
|
||||||
var cx = bbox.x + bbox.width / 2,
|
var cx = bbox.x + bbox.width / 2,
|
||||||
cy = bbox.y + bbox.height / 2;
|
cy = bbox.y + bbox.height / 2;
|
||||||
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
||||||
if (rotate !== this.elem.getAttribute('transform')) {
|
if (rotate !== this.elem.getAttribute('transform')) {
|
||||||
this.elem.setAttribute('transform', rotate);
|
this.elem.setAttribute('transform', rotate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.ChangeElementCommand.unapply
|
// Function: svgedit.history.ChangeElementCommand.unapply
|
||||||
// Reverses the stored change action
|
// Reverses the stored change action
|
||||||
svgedit.history.ChangeElementCommand.prototype.unapply = function (handler) {
|
svgedit.history.ChangeElementCommand.prototype.unapply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bChangedTransform = false;
|
var bChangedTransform = false;
|
||||||
var attr;
|
var attr;
|
||||||
for (attr in this.oldValues) {
|
for (attr in this.oldValues) {
|
||||||
if (this.oldValues[attr]) {
|
if (this.oldValues[attr]) {
|
||||||
if (attr === '#text') {
|
if (attr === '#text') {
|
||||||
this.elem.textContent = this.oldValues[attr];
|
this.elem.textContent = this.oldValues[attr];
|
||||||
} else if (attr === '#href') {
|
} else if (attr === '#href') {
|
||||||
svgedit.utilities.setHref(this.elem, this.oldValues[attr]);
|
svgedit.utilities.setHref(this.elem, this.oldValues[attr]);
|
||||||
} else {
|
} else {
|
||||||
this.elem.setAttribute(attr, this.oldValues[attr]);
|
this.elem.setAttribute(attr, this.oldValues[attr]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (attr === '#text') {
|
if (attr === '#text') {
|
||||||
this.elem.textContent = '';
|
this.elem.textContent = '';
|
||||||
} else {
|
} else {
|
||||||
this.elem.removeAttribute(attr);
|
this.elem.removeAttribute(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (attr === 'transform') { bChangedTransform = true; }
|
if (attr === 'transform') { bChangedTransform = true; }
|
||||||
}
|
}
|
||||||
// relocate rotational transform, if necessary
|
// relocate rotational transform, if necessary
|
||||||
if (!bChangedTransform) {
|
if (!bChangedTransform) {
|
||||||
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
var angle = svgedit.utilities.getRotationAngle(this.elem);
|
||||||
if (angle) {
|
if (angle) {
|
||||||
var bbox = this.elem.getBBox();
|
var bbox = this.elem.getBBox();
|
||||||
var cx = bbox.x + bbox.width / 2,
|
var cx = bbox.x + bbox.width / 2,
|
||||||
cy = bbox.y + bbox.height / 2;
|
cy = bbox.y + bbox.height / 2;
|
||||||
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
var rotate = ['rotate(', angle, ' ', cx, ',', cy, ')'].join('');
|
||||||
if (rotate !== this.elem.getAttribute('transform')) {
|
if (rotate !== this.elem.getAttribute('transform')) {
|
||||||
this.elem.setAttribute('transform', rotate);
|
this.elem.setAttribute('transform', rotate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove transformlist to prevent confusion that causes bugs like 575.
|
// Remove transformlist to prevent confusion that causes bugs like 575.
|
||||||
svgedit.transformlist.removeElementFromListMap(this.elem);
|
svgedit.transformlist.removeElementFromListMap(this.elem);
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: ChangeElementCommand.elements
|
// Function: ChangeElementCommand.elements
|
||||||
// Returns array with element associated with this command
|
// Returns array with element associated with this command
|
||||||
svgedit.history.ChangeElementCommand.prototype.elements = function () {
|
svgedit.history.ChangeElementCommand.prototype.elements = function () {
|
||||||
return [this.elem];
|
return [this.elem];
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: create a 'typing' command object that tracks changes in text
|
// TODO: create a 'typing' command object that tracks changes in text
|
||||||
@@ -392,65 +392,65 @@ svgedit.history.ChangeElementCommand.prototype.elements = function () {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// text - An optional string visible to user related to this change
|
// text - An optional string visible to user related to this change
|
||||||
svgedit.history.BatchCommand = function (text) {
|
svgedit.history.BatchCommand = function (text) {
|
||||||
this.text = text || 'Batch Command';
|
this.text = text || 'Batch Command';
|
||||||
this.stack = [];
|
this.stack = [];
|
||||||
};
|
};
|
||||||
svgedit.history.BatchCommand.type = function () { return 'svgedit.history.BatchCommand'; };
|
svgedit.history.BatchCommand.type = function () { return 'svgedit.history.BatchCommand'; };
|
||||||
svgedit.history.BatchCommand.prototype.type = svgedit.history.BatchCommand.type;
|
svgedit.history.BatchCommand.prototype.type = svgedit.history.BatchCommand.type;
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.getText
|
// Function: svgedit.history.BatchCommand.getText
|
||||||
svgedit.history.BatchCommand.prototype.getText = function () {
|
svgedit.history.BatchCommand.prototype.getText = function () {
|
||||||
return this.text;
|
return this.text;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.apply
|
// Function: svgedit.history.BatchCommand.apply
|
||||||
// Runs "apply" on all subcommands
|
// Runs "apply" on all subcommands
|
||||||
svgedit.history.BatchCommand.prototype.apply = function (handler) {
|
svgedit.history.BatchCommand.prototype.apply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_APPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var i,
|
var i,
|
||||||
len = this.stack.length;
|
len = this.stack.length;
|
||||||
for (i = 0; i < len; ++i) {
|
for (i = 0; i < len; ++i) {
|
||||||
this.stack[i].apply(handler);
|
this.stack[i].apply(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_APPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.unapply
|
// Function: svgedit.history.BatchCommand.unapply
|
||||||
// Runs "unapply" on all subcommands
|
// Runs "unapply" on all subcommands
|
||||||
svgedit.history.BatchCommand.prototype.unapply = function (handler) {
|
svgedit.history.BatchCommand.prototype.unapply = function (handler) {
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.BEFORE_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
var i;
|
var i;
|
||||||
for (i = this.stack.length - 1; i >= 0; i--) {
|
for (i = this.stack.length - 1; i >= 0; i--) {
|
||||||
this.stack[i].unapply(handler);
|
this.stack[i].unapply(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
handler.handleHistoryEvent(svgedit.history.HistoryEventTypes.AFTER_UNAPPLY, this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.elements
|
// Function: svgedit.history.BatchCommand.elements
|
||||||
// Iterate through all our subcommands and returns all the elements we are changing
|
// Iterate through all our subcommands and returns all the elements we are changing
|
||||||
svgedit.history.BatchCommand.prototype.elements = function () {
|
svgedit.history.BatchCommand.prototype.elements = function () {
|
||||||
var elems = [];
|
var elems = [];
|
||||||
var cmd = this.stack.length;
|
var cmd = this.stack.length;
|
||||||
while (cmd--) {
|
while (cmd--) {
|
||||||
var thisElems = this.stack[cmd].elements();
|
var thisElems = this.stack[cmd].elements();
|
||||||
var elem = thisElems.length;
|
var elem = thisElems.length;
|
||||||
while (elem--) {
|
while (elem--) {
|
||||||
if (elems.indexOf(thisElems[elem]) === -1) { elems.push(thisElems[elem]); }
|
if (elems.indexOf(thisElems[elem]) === -1) { elems.push(thisElems[elem]); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return elems;
|
return elems;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.addSubCommand
|
// Function: svgedit.history.BatchCommand.addSubCommand
|
||||||
@@ -459,13 +459,13 @@ svgedit.history.BatchCommand.prototype.elements = function () {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// cmd - The undo command object to add
|
// cmd - The undo command object to add
|
||||||
svgedit.history.BatchCommand.prototype.addSubCommand = function (cmd) {
|
svgedit.history.BatchCommand.prototype.addSubCommand = function (cmd) {
|
||||||
this.stack.push(cmd);
|
this.stack.push(cmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.BatchCommand.isEmpty
|
// Function: svgedit.history.BatchCommand.isEmpty
|
||||||
// Returns a boolean indicating whether or not the batch command is empty
|
// Returns a boolean indicating whether or not the batch command is empty
|
||||||
svgedit.history.BatchCommand.prototype.isEmpty = function () {
|
svgedit.history.BatchCommand.prototype.isEmpty = function () {
|
||||||
return this.stack.length === 0;
|
return this.stack.length === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class: svgedit.history.UndoManager
|
// Class: svgedit.history.UndoManager
|
||||||
@@ -473,67 +473,67 @@ svgedit.history.BatchCommand.prototype.isEmpty = function () {
|
|||||||
// historyEventHandler - an object that conforms to the HistoryEventHandler interface
|
// historyEventHandler - an object that conforms to the HistoryEventHandler interface
|
||||||
// (see above)
|
// (see above)
|
||||||
svgedit.history.UndoManager = function (historyEventHandler) {
|
svgedit.history.UndoManager = function (historyEventHandler) {
|
||||||
this.handler_ = historyEventHandler || null;
|
this.handler_ = historyEventHandler || null;
|
||||||
this.undoStackPointer = 0;
|
this.undoStackPointer = 0;
|
||||||
this.undoStack = [];
|
this.undoStack = [];
|
||||||
|
|
||||||
// this is the stack that stores the original values, the elements and
|
// this is the stack that stores the original values, the elements and
|
||||||
// the attribute name for begin/finish
|
// the attribute name for begin/finish
|
||||||
this.undoChangeStackPointer = -1;
|
this.undoChangeStackPointer = -1;
|
||||||
this.undoableChangeStack = [];
|
this.undoableChangeStack = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.resetUndoStack
|
// Function: svgedit.history.UndoManager.resetUndoStack
|
||||||
// Resets the undo stack, effectively clearing the undo/redo history
|
// Resets the undo stack, effectively clearing the undo/redo history
|
||||||
svgedit.history.UndoManager.prototype.resetUndoStack = function () {
|
svgedit.history.UndoManager.prototype.resetUndoStack = function () {
|
||||||
this.undoStack = [];
|
this.undoStack = [];
|
||||||
this.undoStackPointer = 0;
|
this.undoStackPointer = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.getUndoStackSize
|
// Function: svgedit.history.UndoManager.getUndoStackSize
|
||||||
// Returns:
|
// Returns:
|
||||||
// Integer with the current size of the undo history stack
|
// Integer with the current size of the undo history stack
|
||||||
svgedit.history.UndoManager.prototype.getUndoStackSize = function () {
|
svgedit.history.UndoManager.prototype.getUndoStackSize = function () {
|
||||||
return this.undoStackPointer;
|
return this.undoStackPointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.getRedoStackSize
|
// Function: svgedit.history.UndoManager.getRedoStackSize
|
||||||
// Returns:
|
// Returns:
|
||||||
// Integer with the current size of the redo history stack
|
// Integer with the current size of the redo history stack
|
||||||
svgedit.history.UndoManager.prototype.getRedoStackSize = function () {
|
svgedit.history.UndoManager.prototype.getRedoStackSize = function () {
|
||||||
return this.undoStack.length - this.undoStackPointer;
|
return this.undoStack.length - this.undoStackPointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.getNextUndoCommandText
|
// Function: svgedit.history.UndoManager.getNextUndoCommandText
|
||||||
// Returns:
|
// Returns:
|
||||||
// String associated with the next undo command
|
// String associated with the next undo command
|
||||||
svgedit.history.UndoManager.prototype.getNextUndoCommandText = function () {
|
svgedit.history.UndoManager.prototype.getNextUndoCommandText = function () {
|
||||||
return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';
|
return this.undoStackPointer > 0 ? this.undoStack[this.undoStackPointer - 1].getText() : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.getNextRedoCommandText
|
// Function: svgedit.history.UndoManager.getNextRedoCommandText
|
||||||
// Returns:
|
// Returns:
|
||||||
// String associated with the next redo command
|
// String associated with the next redo command
|
||||||
svgedit.history.UndoManager.prototype.getNextRedoCommandText = function () {
|
svgedit.history.UndoManager.prototype.getNextRedoCommandText = function () {
|
||||||
return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';
|
return this.undoStackPointer < this.undoStack.length ? this.undoStack[this.undoStackPointer].getText() : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.undo
|
// Function: svgedit.history.UndoManager.undo
|
||||||
// Performs an undo step
|
// Performs an undo step
|
||||||
svgedit.history.UndoManager.prototype.undo = function () {
|
svgedit.history.UndoManager.prototype.undo = function () {
|
||||||
if (this.undoStackPointer > 0) {
|
if (this.undoStackPointer > 0) {
|
||||||
var cmd = this.undoStack[--this.undoStackPointer];
|
var cmd = this.undoStack[--this.undoStackPointer];
|
||||||
cmd.unapply(this.handler_);
|
cmd.unapply(this.handler_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.redo
|
// Function: svgedit.history.UndoManager.redo
|
||||||
// Performs a redo step
|
// Performs a redo step
|
||||||
svgedit.history.UndoManager.prototype.redo = function () {
|
svgedit.history.UndoManager.prototype.redo = function () {
|
||||||
if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {
|
if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {
|
||||||
var cmd = this.undoStack[this.undoStackPointer++];
|
var cmd = this.undoStack[this.undoStackPointer++];
|
||||||
cmd.apply(this.handler_);
|
cmd.apply(this.handler_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.addCommandToHistory
|
// Function: svgedit.history.UndoManager.addCommandToHistory
|
||||||
@@ -542,18 +542,18 @@ svgedit.history.UndoManager.prototype.redo = function () {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// cmd - The command object to add
|
// cmd - The command object to add
|
||||||
svgedit.history.UndoManager.prototype.addCommandToHistory = function (cmd) {
|
svgedit.history.UndoManager.prototype.addCommandToHistory = function (cmd) {
|
||||||
// FIXME: we MUST compress consecutive text changes to the same element
|
// FIXME: we MUST compress consecutive text changes to the same element
|
||||||
// (right now each keystroke is saved as a separate command that includes the
|
// (right now each keystroke is saved as a separate command that includes the
|
||||||
// entire text contents of the text element)
|
// entire text contents of the text element)
|
||||||
// TODO: consider limiting the history that we store here (need to do some slicing)
|
// TODO: consider limiting the history that we store here (need to do some slicing)
|
||||||
|
|
||||||
// if our stack pointer is not at the end, then we have to remove
|
// if our stack pointer is not at the end, then we have to remove
|
||||||
// all commands after the pointer and insert the new command
|
// all commands after the pointer and insert the new command
|
||||||
if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {
|
if (this.undoStackPointer < this.undoStack.length && this.undoStack.length > 0) {
|
||||||
this.undoStack = this.undoStack.splice(0, this.undoStackPointer);
|
this.undoStack = this.undoStack.splice(0, this.undoStackPointer);
|
||||||
}
|
}
|
||||||
this.undoStack.push(cmd);
|
this.undoStack.push(cmd);
|
||||||
this.undoStackPointer = this.undoStack.length;
|
this.undoStackPointer = this.undoStack.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.beginUndoableChange
|
// Function: svgedit.history.UndoManager.beginUndoableChange
|
||||||
@@ -567,20 +567,20 @@ svgedit.history.UndoManager.prototype.addCommandToHistory = function (cmd) {
|
|||||||
// attrName - The name of the attribute being changed
|
// attrName - The name of the attribute being changed
|
||||||
// elems - Array of DOM elements being changed
|
// elems - Array of DOM elements being changed
|
||||||
svgedit.history.UndoManager.prototype.beginUndoableChange = function (attrName, elems) {
|
svgedit.history.UndoManager.prototype.beginUndoableChange = function (attrName, elems) {
|
||||||
var p = ++this.undoChangeStackPointer;
|
var p = ++this.undoChangeStackPointer;
|
||||||
var i = elems.length;
|
var i = elems.length;
|
||||||
var oldValues = new Array(i), elements = new Array(i);
|
var oldValues = new Array(i), elements = new Array(i);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
var elem = elems[i];
|
var elem = elems[i];
|
||||||
if (elem == null) { continue; }
|
if (elem == null) { continue; }
|
||||||
elements[i] = elem;
|
elements[i] = elem;
|
||||||
oldValues[i] = elem.getAttribute(attrName);
|
oldValues[i] = elem.getAttribute(attrName);
|
||||||
}
|
}
|
||||||
this.undoableChangeStack[p] = {
|
this.undoableChangeStack[p] = {
|
||||||
'attrName': attrName,
|
'attrName': attrName,
|
||||||
'oldValues': oldValues,
|
'oldValues': oldValues,
|
||||||
'elements': elements
|
'elements': elements
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.history.UndoManager.finishUndoableChange
|
// Function: svgedit.history.UndoManager.finishUndoableChange
|
||||||
@@ -591,21 +591,21 @@ svgedit.history.UndoManager.prototype.beginUndoableChange = function (attrName,
|
|||||||
// Returns:
|
// Returns:
|
||||||
// Batch command object with resulting changes
|
// Batch command object with resulting changes
|
||||||
svgedit.history.UndoManager.prototype.finishUndoableChange = function () {
|
svgedit.history.UndoManager.prototype.finishUndoableChange = function () {
|
||||||
var p = this.undoChangeStackPointer--;
|
var p = this.undoChangeStackPointer--;
|
||||||
var changeset = this.undoableChangeStack[p];
|
var changeset = this.undoableChangeStack[p];
|
||||||
var i = changeset.elements.length;
|
var i = changeset.elements.length;
|
||||||
var attrName = changeset.attrName;
|
var attrName = changeset.attrName;
|
||||||
var batchCmd = new svgedit.history.BatchCommand('Change ' + attrName);
|
var batchCmd = new svgedit.history.BatchCommand('Change ' + attrName);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
var elem = changeset.elements[i];
|
var elem = changeset.elements[i];
|
||||||
if (elem == null) { continue; }
|
if (elem == null) { continue; }
|
||||||
var changes = {};
|
var changes = {};
|
||||||
changes[attrName] = changeset.oldValues[i];
|
changes[attrName] = changeset.oldValues[i];
|
||||||
if (changes[attrName] !== elem.getAttribute(attrName)) {
|
if (changes[attrName] !== elem.getAttribute(attrName)) {
|
||||||
batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(elem, changes, attrName));
|
batchCmd.addSubCommand(new svgedit.history.ChangeElementCommand(elem, changes, attrName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.undoableChangeStack[p] = null;
|
this.undoableChangeStack[p] = null;
|
||||||
return batchCmd;
|
return batchCmd;
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.history) {
|
if (!svgedit.history) {
|
||||||
svgedit.history = {};
|
svgedit.history = {};
|
||||||
}
|
}
|
||||||
var history = svgedit.history;
|
var history = svgedit.history;
|
||||||
|
|
||||||
@@ -58,9 +58,9 @@ var history = svgedit.history;
|
|||||||
* See singleton: HistoryRecordingService.NO_HISTORY
|
* See singleton: HistoryRecordingService.NO_HISTORY
|
||||||
*/
|
*/
|
||||||
var HistoryRecordingService = history.HistoryRecordingService = function (undoManager) {
|
var HistoryRecordingService = history.HistoryRecordingService = function (undoManager) {
|
||||||
this.undoManager_ = undoManager;
|
this.undoManager_ = undoManager;
|
||||||
this.currentBatchCommand_ = null;
|
this.currentBatchCommand_ = null;
|
||||||
this.batchCommandStack_ = [];
|
this.batchCommandStack_ = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,10 +77,10 @@ HistoryRecordingService.NO_HISTORY = new HistoryRecordingService();
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.startBatchCommand = function (text) {
|
HistoryRecordingService.prototype.startBatchCommand = function (text) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
this.currentBatchCommand_ = new history.BatchCommand(text);
|
this.currentBatchCommand_ = new history.BatchCommand(text);
|
||||||
this.batchCommandStack_.push(this.currentBatchCommand_);
|
this.batchCommandStack_.push(this.currentBatchCommand_);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -88,15 +88,15 @@ HistoryRecordingService.prototype.startBatchCommand = function (text) {
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.endBatchCommand = function () {
|
HistoryRecordingService.prototype.endBatchCommand = function () {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
if (this.currentBatchCommand_) {
|
if (this.currentBatchCommand_) {
|
||||||
var batchCommand = this.currentBatchCommand_;
|
var batchCommand = this.currentBatchCommand_;
|
||||||
this.batchCommandStack_.pop();
|
this.batchCommandStack_.pop();
|
||||||
var length = this.batchCommandStack_.length;
|
var length = this.batchCommandStack_.length;
|
||||||
this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null;
|
this.currentBatchCommand_ = length ? this.batchCommandStack_[length - 1] : null;
|
||||||
this.addCommand_(batchCommand);
|
this.addCommand_(batchCommand);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,9 +108,9 @@ HistoryRecordingService.prototype.endBatchCommand = function () {
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.moveElement = function (elem, oldNextSibling, oldParent, text) {
|
HistoryRecordingService.prototype.moveElement = function (elem, oldNextSibling, oldParent, text) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
this.addCommand_(new history.MoveElementCommand(elem, oldNextSibling, oldParent, text));
|
this.addCommand_(new history.MoveElementCommand(elem, oldNextSibling, oldParent, text));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,9 +120,9 @@ HistoryRecordingService.prototype.moveElement = function (elem, oldNextSibling,
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.insertElement = function (elem, text) {
|
HistoryRecordingService.prototype.insertElement = function (elem, text) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
this.addCommand_(new history.InsertElementCommand(elem, text));
|
this.addCommand_(new history.InsertElementCommand(elem, text));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,9 +134,9 @@ HistoryRecordingService.prototype.insertElement = function (elem, text) {
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.removeElement = function (elem, oldNextSibling, oldParent, text) {
|
HistoryRecordingService.prototype.removeElement = function (elem, oldNextSibling, oldParent, text) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
this.addCommand_(new history.RemoveElementCommand(elem, oldNextSibling, oldParent, text));
|
this.addCommand_(new history.RemoveElementCommand(elem, oldNextSibling, oldParent, text));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,9 +147,9 @@ HistoryRecordingService.prototype.removeElement = function (elem, oldNextSibling
|
|||||||
* @returns {svgedit.history.HistoryRecordingService}
|
* @returns {svgedit.history.HistoryRecordingService}
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.changeElement = function (elem, attrs, text) {
|
HistoryRecordingService.prototype.changeElement = function (elem, attrs, text) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
this.addCommand_(new history.ChangeElementCommand(elem, attrs, text));
|
this.addCommand_(new history.ChangeElementCommand(elem, attrs, text));
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,11 +159,11 @@ HistoryRecordingService.prototype.changeElement = function (elem, attrs, text) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
HistoryRecordingService.prototype.addCommand_ = function (cmd) {
|
HistoryRecordingService.prototype.addCommand_ = function (cmd) {
|
||||||
if (!this.undoManager_) { return this; }
|
if (!this.undoManager_) { return this; }
|
||||||
if (this.currentBatchCommand_) {
|
if (this.currentBatchCommand_) {
|
||||||
this.currentBatchCommand_.addSubCommand(cmd);
|
this.currentBatchCommand_.addSubCommand(cmd);
|
||||||
} else {
|
} else {
|
||||||
this.undoManager_.addCommandToHistory(cmd);
|
this.undoManager_.addCommandToHistory(cmd);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
148
editor/layer.js
148
editor/layer.js
@@ -17,7 +17,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.draw) {
|
if (!svgedit.draw) {
|
||||||
svgedit.draw = {};
|
svgedit.draw = {};
|
||||||
}
|
}
|
||||||
var NS = svgedit.NS;
|
var NS = svgedit.NS;
|
||||||
|
|
||||||
@@ -39,29 +39,29 @@ var NS = svgedit.NS;
|
|||||||
* a new layer to the document.
|
* a new layer to the document.
|
||||||
*/
|
*/
|
||||||
var Layer = svgedit.draw.Layer = function (name, group, svgElem) {
|
var Layer = svgedit.draw.Layer = function (name, group, svgElem) {
|
||||||
this.name_ = name;
|
this.name_ = name;
|
||||||
this.group_ = svgElem ? null : group;
|
this.group_ = svgElem ? null : group;
|
||||||
|
|
||||||
if (svgElem) {
|
if (svgElem) {
|
||||||
// Create a group element with title and add it to the DOM.
|
// Create a group element with title and add it to the DOM.
|
||||||
var svgdoc = svgElem.ownerDocument;
|
var svgdoc = svgElem.ownerDocument;
|
||||||
this.group_ = svgdoc.createElementNS(NS.SVG, 'g');
|
this.group_ = svgdoc.createElementNS(NS.SVG, 'g');
|
||||||
var layerTitle = svgdoc.createElementNS(NS.SVG, 'title');
|
var layerTitle = svgdoc.createElementNS(NS.SVG, 'title');
|
||||||
layerTitle.textContent = name;
|
layerTitle.textContent = name;
|
||||||
this.group_.appendChild(layerTitle);
|
this.group_.appendChild(layerTitle);
|
||||||
if (group) {
|
if (group) {
|
||||||
$(group).after(this.group_);
|
$(group).after(this.group_);
|
||||||
} else {
|
} else {
|
||||||
svgElem.appendChild(this.group_);
|
svgElem.appendChild(this.group_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addLayerClass(this.group_);
|
addLayerClass(this.group_);
|
||||||
svgedit.utilities.walkTree(this.group_, function (e) {
|
svgedit.utilities.walkTree(this.group_, function (e) {
|
||||||
e.setAttribute('style', 'pointer-events:inherit');
|
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');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +79,7 @@ Layer.CLASS_REGEX = new RegExp('(\\s|^)' + Layer.CLASS_NAME + '(\\s|$)');
|
|||||||
* @returns {string} The layer name
|
* @returns {string} The layer name
|
||||||
*/
|
*/
|
||||||
Layer.prototype.getName = function () {
|
Layer.prototype.getName = function () {
|
||||||
return this.name_;
|
return this.name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,21 +87,21 @@ Layer.prototype.getName = function () {
|
|||||||
* @returns {SVGGElement} The layer SVG group
|
* @returns {SVGGElement} The layer SVG group
|
||||||
*/
|
*/
|
||||||
Layer.prototype.getGroup = function () {
|
Layer.prototype.getGroup = function () {
|
||||||
return this.group_;
|
return this.group_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Active this layer so it takes pointer events.
|
* Active this layer so it takes pointer events.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.activate = function () {
|
Layer.prototype.activate = function () {
|
||||||
this.group_.setAttribute('style', 'pointer-events:all');
|
this.group_.setAttribute('style', 'pointer-events:all');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactive this layer so it does NOT take pointer events.
|
* Deactive this layer so it does NOT take pointer events.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.deactivate = function () {
|
Layer.prototype.deactivate = function () {
|
||||||
this.group_.setAttribute('style', 'pointer-events:none');
|
this.group_.setAttribute('style', 'pointer-events:none');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,11 +109,11 @@ Layer.prototype.deactivate = function () {
|
|||||||
* @param {boolean} visible - If true, make visible; otherwise, hide it.
|
* @param {boolean} visible - If true, make visible; otherwise, hide it.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.setVisible = function (visible) {
|
Layer.prototype.setVisible = function (visible) {
|
||||||
var expected = visible === undefined || visible ? 'inline' : 'none';
|
var expected = visible === undefined || visible ? 'inline' : 'none';
|
||||||
var oldDisplay = this.group_.getAttribute('display');
|
var oldDisplay = this.group_.getAttribute('display');
|
||||||
if (oldDisplay !== expected) {
|
if (oldDisplay !== expected) {
|
||||||
this.group_.setAttribute('display', expected);
|
this.group_.setAttribute('display', expected);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,7 +121,7 @@ Layer.prototype.setVisible = function (visible) {
|
|||||||
* @returns {boolean} True if visible.
|
* @returns {boolean} True if visible.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.isVisible = function () {
|
Layer.prototype.isVisible = function () {
|
||||||
return this.group_.getAttribute('display') !== 'none';
|
return this.group_.getAttribute('display') !== 'none';
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,11 +129,11 @@ Layer.prototype.isVisible = function () {
|
|||||||
* @returns {number} Opacity value.
|
* @returns {number} Opacity value.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.getOpacity = function () {
|
Layer.prototype.getOpacity = function () {
|
||||||
var opacity = this.group_.getAttribute('opacity');
|
var opacity = this.group_.getAttribute('opacity');
|
||||||
if (opacity === null || opacity === undefined) {
|
if (opacity === null || opacity === undefined) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return parseFloat(opacity);
|
return parseFloat(opacity);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,9 +142,9 @@ Layer.prototype.getOpacity = function () {
|
|||||||
* @param {number} opacity - A float value in the range 0.0-1.0
|
* @param {number} opacity - A float value in the range 0.0-1.0
|
||||||
*/
|
*/
|
||||||
Layer.prototype.setOpacity = function (opacity) {
|
Layer.prototype.setOpacity = function (opacity) {
|
||||||
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {
|
if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {
|
||||||
this.group_.setAttribute('opacity', opacity);
|
this.group_.setAttribute('opacity', opacity);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,20 +152,20 @@ Layer.prototype.setOpacity = function (opacity) {
|
|||||||
* @param {SVGGElement} children - The children to append to this layer.
|
* @param {SVGGElement} children - The children to append to this layer.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.appendChildren = function (children) {
|
Layer.prototype.appendChildren = function (children) {
|
||||||
for (var i = 0; i < children.length; ++i) {
|
for (var i = 0; i < children.length; ++i) {
|
||||||
this.group_.appendChild(children[i]);
|
this.group_.appendChild(children[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Layer.prototype.getTitleElement = function () {
|
Layer.prototype.getTitleElement = function () {
|
||||||
var len = this.group_.childNodes.length;
|
var len = this.group_.childNodes.length;
|
||||||
for (var i = 0; i < len; ++i) {
|
for (var i = 0; i < len; ++i) {
|
||||||
var child = this.group_.childNodes.item(i);
|
var child = this.group_.childNodes.item(i);
|
||||||
if (child && child.tagName === 'title') {
|
if (child && child.tagName === 'title') {
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -175,20 +175,20 @@ Layer.prototype.getTitleElement = function () {
|
|||||||
* @returns {string|null} The new name if changed; otherwise, null.
|
* @returns {string|null} The new name if changed; otherwise, null.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.setName = function (name, hrService) {
|
Layer.prototype.setName = function (name, hrService) {
|
||||||
var previousName = this.name_;
|
var previousName = this.name_;
|
||||||
name = svgedit.utilities.toXml(name);
|
name = svgedit.utilities.toXml(name);
|
||||||
// now change the underlying title element contents
|
// now change the underlying title element contents
|
||||||
var title = this.getTitleElement();
|
var title = this.getTitleElement();
|
||||||
if (title) {
|
if (title) {
|
||||||
$(title).empty();
|
$(title).empty();
|
||||||
title.textContent = name;
|
title.textContent = name;
|
||||||
this.name_ = name;
|
this.name_ = name;
|
||||||
if (hrService) {
|
if (hrService) {
|
||||||
hrService.changeElement(title, {'#text': previousName});
|
hrService.changeElement(title, {'#text': previousName});
|
||||||
}
|
}
|
||||||
return this.name_;
|
return this.name_;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,10 +197,10 @@ Layer.prototype.setName = function (name, hrService) {
|
|||||||
* @returns {SVGGElement} The layer SVG group that was just removed.
|
* @returns {SVGGElement} The layer SVG group that was just removed.
|
||||||
*/
|
*/
|
||||||
Layer.prototype.removeGroup = function () {
|
Layer.prototype.removeGroup = function () {
|
||||||
var parent = this.group_.parentNode;
|
var parent = this.group_.parentNode;
|
||||||
var group = parent.removeChild(this.group_);
|
var group = parent.removeChild(this.group_);
|
||||||
this.group_ = undefined;
|
this.group_ = undefined;
|
||||||
return group;
|
return group;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,11 +210,11 @@ Layer.prototype.removeGroup = function () {
|
|||||||
* @param {SVGGElement} elem - The SVG element to update
|
* @param {SVGGElement} elem - The SVG element to update
|
||||||
*/
|
*/
|
||||||
function addLayerClass (elem) {
|
function addLayerClass (elem) {
|
||||||
var classes = elem.getAttribute('class');
|
var classes = elem.getAttribute('class');
|
||||||
if (classes === null || classes === undefined || classes.length === 0) {
|
if (classes === null || classes === undefined || classes.length === 0) {
|
||||||
elem.setAttribute('class', Layer.CLASS_NAME);
|
elem.setAttribute('class', Layer.CLASS_NAME);
|
||||||
} else if (!Layer.CLASS_REGEX.test(classes)) {
|
} else if (!Layer.CLASS_REGEX.test(classes)) {
|
||||||
elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);
|
elem.setAttribute('class', classes + ' ' + Layer.CLASS_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
158
editor/math.js
158
editor/math.js
@@ -24,7 +24,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.math) {
|
if (!svgedit.math) {
|
||||||
svgedit.math = {};
|
svgedit.math = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
@@ -42,7 +42,7 @@ var svg = document.createElementNS(svgedit.NS.SVG, 'svg');
|
|||||||
* @returns {Object} An x, y object representing the transformed point
|
* @returns {Object} An x, y object representing the transformed point
|
||||||
*/
|
*/
|
||||||
svgedit.math.transformPoint = function (x, y, m) {
|
svgedit.math.transformPoint = function (x, y, m) {
|
||||||
return {x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};
|
return {x: m.a * x + m.c * y + m.e, y: m.b * x + m.d * y + m.f};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +52,7 @@ svgedit.math.transformPoint = function (x, y, m) {
|
|||||||
* @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0
|
* @returns {boolean} Indicates whether or not the matrix is 1,0,0,1,0,0
|
||||||
*/
|
*/
|
||||||
svgedit.math.isIdentity = function (m) {
|
svgedit.math.isIdentity = function (m) {
|
||||||
return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
|
return (m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,20 +62,20 @@ svgedit.math.isIdentity = function (m) {
|
|||||||
* @returns {SVGMatrix} The matrix object resulting from the calculation
|
* @returns {SVGMatrix} The matrix object resulting from the calculation
|
||||||
*/
|
*/
|
||||||
svgedit.math.matrixMultiply = function (matr) {
|
svgedit.math.matrixMultiply = function (matr) {
|
||||||
var args = arguments, i = args.length, m = args[i - 1];
|
var args = arguments, i = args.length, m = args[i - 1];
|
||||||
|
|
||||||
while (i-- > 1) {
|
while (i-- > 1) {
|
||||||
var m1 = args[i - 1];
|
var m1 = args[i - 1];
|
||||||
m = m1.multiply(m);
|
m = m1.multiply(m);
|
||||||
}
|
}
|
||||||
if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; }
|
if (Math.abs(m.a) < NEAR_ZERO) { m.a = 0; }
|
||||||
if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; }
|
if (Math.abs(m.b) < NEAR_ZERO) { m.b = 0; }
|
||||||
if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; }
|
if (Math.abs(m.c) < NEAR_ZERO) { m.c = 0; }
|
||||||
if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; }
|
if (Math.abs(m.d) < NEAR_ZERO) { m.d = 0; }
|
||||||
if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }
|
if (Math.abs(m.e) < NEAR_ZERO) { m.e = 0; }
|
||||||
if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }
|
if (Math.abs(m.f) < NEAR_ZERO) { m.f = 0; }
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,13 +84,13 @@ svgedit.math.matrixMultiply = function (matr) {
|
|||||||
* @returns {boolean} Whether or not a matrix transform was found
|
* @returns {boolean} Whether or not a matrix transform was found
|
||||||
*/
|
*/
|
||||||
svgedit.math.hasMatrixTransform = function (tlist) {
|
svgedit.math.hasMatrixTransform = function (tlist) {
|
||||||
if (!tlist) { return false; }
|
if (!tlist) { return false; }
|
||||||
var num = tlist.numberOfItems;
|
var num = tlist.numberOfItems;
|
||||||
while (num--) {
|
while (num--) {
|
||||||
var xform = tlist.getItem(num);
|
var xform = tlist.getItem(num);
|
||||||
if (xform.type === 1 && !svgedit.math.isIdentity(xform.matrix)) { return true; }
|
if (xform.type === 1 && !svgedit.math.isIdentity(xform.matrix)) { return true; }
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,30 +112,30 @@ svgedit.math.hasMatrixTransform = function (tlist) {
|
|||||||
* height - Float with the axis-aligned height coordinate
|
* height - Float with the axis-aligned height coordinate
|
||||||
*/
|
*/
|
||||||
svgedit.math.transformBox = function (l, t, w, h, m) {
|
svgedit.math.transformBox = function (l, t, w, h, m) {
|
||||||
var transformPoint = svgedit.math.transformPoint,
|
var transformPoint = svgedit.math.transformPoint,
|
||||||
|
|
||||||
tl = transformPoint(l, t, m),
|
tl = transformPoint(l, t, m),
|
||||||
tr = transformPoint((l + w), t, m),
|
tr = transformPoint((l + w), t, m),
|
||||||
bl = transformPoint(l, (t + h), m),
|
bl = transformPoint(l, (t + h), m),
|
||||||
br = transformPoint((l + w), (t + h), m),
|
br = transformPoint((l + w), (t + h), m),
|
||||||
|
|
||||||
minx = Math.min(tl.x, tr.x, bl.x, br.x),
|
minx = Math.min(tl.x, tr.x, bl.x, br.x),
|
||||||
maxx = Math.max(tl.x, tr.x, bl.x, br.x),
|
maxx = Math.max(tl.x, tr.x, bl.x, br.x),
|
||||||
miny = Math.min(tl.y, tr.y, bl.y, br.y),
|
miny = Math.min(tl.y, tr.y, bl.y, br.y),
|
||||||
maxy = Math.max(tl.y, tr.y, bl.y, br.y);
|
maxy = Math.max(tl.y, tr.y, bl.y, br.y);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tl: tl,
|
tl: tl,
|
||||||
tr: tr,
|
tr: tr,
|
||||||
bl: bl,
|
bl: bl,
|
||||||
br: br,
|
br: br,
|
||||||
aabox: {
|
aabox: {
|
||||||
x: minx,
|
x: minx,
|
||||||
y: miny,
|
y: miny,
|
||||||
width: (maxx - minx),
|
width: (maxx - minx),
|
||||||
height: (maxy - miny)
|
height: (maxy - miny)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,25 +150,25 @@ svgedit.math.transformBox = function (l, t, w, h, m) {
|
|||||||
* @returns {Object} A single matrix transform object
|
* @returns {Object} A single matrix transform object
|
||||||
*/
|
*/
|
||||||
svgedit.math.transformListToTransform = function (tlist, min, max) {
|
svgedit.math.transformListToTransform = function (tlist, min, max) {
|
||||||
if (tlist == null) {
|
if (tlist == null) {
|
||||||
// Or should tlist = null have been prevented before this?
|
// Or should tlist = null have been prevented before this?
|
||||||
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());
|
return svg.createSVGTransformFromMatrix(svg.createSVGMatrix());
|
||||||
}
|
}
|
||||||
min = min || 0;
|
min = min || 0;
|
||||||
max = max || (tlist.numberOfItems - 1);
|
max = max || (tlist.numberOfItems - 1);
|
||||||
min = parseInt(min, 10);
|
min = parseInt(min, 10);
|
||||||
max = parseInt(max, 10);
|
max = parseInt(max, 10);
|
||||||
if (min > max) { var temp = max; max = min; min = temp; }
|
if (min > max) { var temp = max; max = min; min = temp; }
|
||||||
var m = svg.createSVGMatrix();
|
var m = svg.createSVGMatrix();
|
||||||
var i;
|
var i;
|
||||||
for (i = min; i <= max; ++i) {
|
for (i = min; i <= max; ++i) {
|
||||||
// if our indices are out of range, just use a harmless identity matrix
|
// if our indices are out of range, just use a harmless identity matrix
|
||||||
var mtom = (i >= 0 && i < tlist.numberOfItems
|
var mtom = (i >= 0 && i < tlist.numberOfItems
|
||||||
? tlist.getItem(i).matrix
|
? tlist.getItem(i).matrix
|
||||||
: svg.createSVGMatrix());
|
: svg.createSVGMatrix());
|
||||||
m = svgedit.math.matrixMultiply(m, mtom);
|
m = svgedit.math.matrixMultiply(m, mtom);
|
||||||
}
|
}
|
||||||
return svg.createSVGTransformFromMatrix(m);
|
return svg.createSVGTransformFromMatrix(m);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,8 +177,8 @@ svgedit.math.transformListToTransform = function (tlist, min, max) {
|
|||||||
* @returns {SVGMatrix} The matrix object associated with the element's transformlist
|
* @returns {SVGMatrix} The matrix object associated with the element's transformlist
|
||||||
*/
|
*/
|
||||||
svgedit.math.getMatrix = function (elem) {
|
svgedit.math.getMatrix = function (elem) {
|
||||||
var tlist = svgedit.transformlist.getTransformList(elem);
|
var tlist = svgedit.transformlist.getTransformList(elem);
|
||||||
return svgedit.math.transformListToTransform(tlist).matrix;
|
return svgedit.math.transformListToTransform(tlist).matrix;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,18 +191,18 @@ svgedit.math.getMatrix = function (elem) {
|
|||||||
* @returns {AngleCoord45}
|
* @returns {AngleCoord45}
|
||||||
*/
|
*/
|
||||||
svgedit.math.snapToAngle = function (x1, y1, x2, y2) {
|
svgedit.math.snapToAngle = function (x1, y1, x2, y2) {
|
||||||
var snap = Math.PI / 4; // 45 degrees
|
var snap = Math.PI / 4; // 45 degrees
|
||||||
var dx = x2 - x1;
|
var dx = x2 - x1;
|
||||||
var dy = y2 - y1;
|
var dy = y2 - y1;
|
||||||
var angle = Math.atan2(dy, dx);
|
var angle = Math.atan2(dy, dx);
|
||||||
var dist = Math.sqrt(dx * dx + dy * dy);
|
var dist = Math.sqrt(dx * dx + dy * dy);
|
||||||
var snapangle = Math.round(angle / snap) * snap;
|
var snapangle = Math.round(angle / snap) * snap;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: x1 + dist * Math.cos(snapangle),
|
x: x1 + dist * Math.cos(snapangle),
|
||||||
y: y1 + dist * Math.sin(snapangle),
|
y: y1 + dist * Math.sin(snapangle),
|
||||||
a: snapangle
|
a: snapangle
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -212,9 +212,9 @@ svgedit.math.snapToAngle = function (x1, y1, x2, y2) {
|
|||||||
* @returns {boolean} True if rectangles intersect
|
* @returns {boolean} True if rectangles intersect
|
||||||
*/
|
*/
|
||||||
svgedit.math.rectsIntersect = function (r1, r2) {
|
svgedit.math.rectsIntersect = function (r1, r2) {
|
||||||
return r2.x < (r1.x + r1.width) &&
|
return r2.x < (r1.x + r1.width) &&
|
||||||
(r2.x + r2.width) > r1.x &&
|
(r2.x + r2.width) > r1.x &&
|
||||||
r2.y < (r1.y + r1.height) &&
|
r2.y < (r1.y + r1.height) &&
|
||||||
(r2.y + r2.height) > r1.y;
|
(r2.y + r2.height) > r1.y;
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
1414
editor/path.js
1414
editor/path.js
File diff suppressed because it is too large
Load Diff
1534
editor/pathseg.js
1534
editor/pathseg.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -19,95 +19,95 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.sanitize) {
|
if (!svgedit.sanitize) {
|
||||||
svgedit.sanitize = {};
|
svgedit.sanitize = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var NS = svgedit.NS,
|
var NS = svgedit.NS,
|
||||||
REVERSE_NS = svgedit.getReverseNS();
|
REVERSE_NS = svgedit.getReverseNS();
|
||||||
|
|
||||||
// this defines which elements and attributes that we support
|
// this defines which elements and attributes that we support
|
||||||
var svgWhiteList_ = {
|
var svgWhiteList_ = {
|
||||||
// SVG Elements
|
// SVG Elements
|
||||||
'a': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],
|
'a': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'xlink:href', 'xlink:title'],
|
||||||
'circle': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
'circle': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||||
'clipPath': ['class', 'clipPathUnits', 'id'],
|
'clipPath': ['class', 'clipPathUnits', 'id'],
|
||||||
'defs': [],
|
'defs': [],
|
||||||
'style': ['type'],
|
'style': ['type'],
|
||||||
'desc': [],
|
'desc': [],
|
||||||
'ellipse': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
'ellipse': ['class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||||
'feGaussianBlur': ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
|
'feGaussianBlur': ['class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation'],
|
||||||
'filter': ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
|
'filter': ['class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y'],
|
||||||
'foreignObject': ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],
|
'foreignObject': ['class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y'],
|
||||||
'g': ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
|
'g': ['class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor'],
|
||||||
'image': ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],
|
'image': ['class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y'],
|
||||||
'line': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],
|
'line': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2'],
|
||||||
'linearGradient': ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],
|
'linearGradient': ['class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2'],
|
||||||
'marker': ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
|
'marker': ['id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox'],
|
||||||
'mask': ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
|
'mask': ['class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y'],
|
||||||
'metadata': ['class', 'id'],
|
'metadata': ['class', 'id'],
|
||||||
'path': ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
'path': ['class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||||
'pattern': ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],
|
'pattern': ['class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y'],
|
||||||
'polygon': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
'polygon': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||||
'polyline': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
'polyline': ['class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform'],
|
||||||
'radialGradient': ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],
|
'radialGradient': ['class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href'],
|
||||||
'rect': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],
|
'rect': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y'],
|
||||||
'stop': ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],
|
'stop': ['class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage'],
|
||||||
'svg': ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],
|
'svg': ['class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y'],
|
||||||
'switch': ['class', 'id', 'requiredFeatures', 'systemLanguage'],
|
'switch': ['class', 'id', 'requiredFeatures', 'systemLanguage'],
|
||||||
'symbol': ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],
|
'symbol': ['class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox'],
|
||||||
'text': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],
|
'text': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y'],
|
||||||
'textPath': ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
|
'textPath': ['class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href'],
|
||||||
'title': [],
|
'title': [],
|
||||||
'tspan': ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],
|
'tspan': ['class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y'],
|
||||||
'use': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],
|
'use': ['class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y'],
|
||||||
|
|
||||||
// MathML Elements
|
// MathML Elements
|
||||||
'annotation': ['encoding'],
|
'annotation': ['encoding'],
|
||||||
'annotation-xml': ['encoding'],
|
'annotation-xml': ['encoding'],
|
||||||
'maction': ['actiontype', 'other', 'selection'],
|
'maction': ['actiontype', 'other', 'selection'],
|
||||||
'math': ['class', 'id', 'display', 'xmlns'],
|
'math': ['class', 'id', 'display', 'xmlns'],
|
||||||
'menclose': ['notation'],
|
'menclose': ['notation'],
|
||||||
'merror': [],
|
'merror': [],
|
||||||
'mfrac': ['linethickness'],
|
'mfrac': ['linethickness'],
|
||||||
'mi': ['mathvariant'],
|
'mi': ['mathvariant'],
|
||||||
'mmultiscripts': [],
|
'mmultiscripts': [],
|
||||||
'mn': [],
|
'mn': [],
|
||||||
'mo': ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],
|
'mo': ['fence', 'lspace', 'maxsize', 'minsize', 'rspace', 'stretchy'],
|
||||||
'mover': [],
|
'mover': [],
|
||||||
'mpadded': ['lspace', 'width', 'height', 'depth', 'voffset'],
|
'mpadded': ['lspace', 'width', 'height', 'depth', 'voffset'],
|
||||||
'mphantom': [],
|
'mphantom': [],
|
||||||
'mprescripts': [],
|
'mprescripts': [],
|
||||||
'mroot': [],
|
'mroot': [],
|
||||||
'mrow': ['xlink:href', 'xlink:type', 'xmlns:xlink'],
|
'mrow': ['xlink:href', 'xlink:type', 'xmlns:xlink'],
|
||||||
'mspace': ['depth', 'height', 'width'],
|
'mspace': ['depth', 'height', 'width'],
|
||||||
'msqrt': [],
|
'msqrt': [],
|
||||||
'mstyle': ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],
|
'mstyle': ['displaystyle', 'mathbackground', 'mathcolor', 'mathvariant', 'scriptlevel'],
|
||||||
'msub': [],
|
'msub': [],
|
||||||
'msubsup': [],
|
'msubsup': [],
|
||||||
'msup': [],
|
'msup': [],
|
||||||
'mtable': ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],
|
'mtable': ['align', 'columnalign', 'columnlines', 'columnspacing', 'displaystyle', 'equalcolumns', 'equalrows', 'frame', 'rowalign', 'rowlines', 'rowspacing', 'width'],
|
||||||
'mtd': ['columnalign', 'columnspan', 'rowalign', 'rowspan'],
|
'mtd': ['columnalign', 'columnspan', 'rowalign', 'rowspan'],
|
||||||
'mtext': [],
|
'mtext': [],
|
||||||
'mtr': ['columnalign', 'rowalign'],
|
'mtr': ['columnalign', 'rowalign'],
|
||||||
'munder': [],
|
'munder': [],
|
||||||
'munderover': [],
|
'munderover': [],
|
||||||
'none': [],
|
'none': [],
|
||||||
'semantics': []
|
'semantics': []
|
||||||
};
|
};
|
||||||
|
|
||||||
// Produce a Namespace-aware version of svgWhitelist
|
// Produce a Namespace-aware version of svgWhitelist
|
||||||
var svgWhiteListNS_ = {};
|
var svgWhiteListNS_ = {};
|
||||||
$.each(svgWhiteList_, function (elt, atts) {
|
$.each(svgWhiteList_, function (elt, atts) {
|
||||||
var attNS = {};
|
var attNS = {};
|
||||||
$.each(atts, function (i, att) {
|
$.each(atts, function (i, att) {
|
||||||
if (att.indexOf(':') >= 0) {
|
if (att.indexOf(':') >= 0) {
|
||||||
var v = att.split(':');
|
var v = att.split(':');
|
||||||
attNS[v[1]] = NS[(v[0]).toUpperCase()];
|
attNS[v[1]] = NS[(v[0]).toUpperCase()];
|
||||||
} else {
|
} else {
|
||||||
attNS[att] = att === 'xmlns' ? NS.XMLNS : null;
|
attNS[att] = att === 'xmlns' ? NS.XMLNS : null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
svgWhiteListNS_[elt] = attNS;
|
svgWhiteListNS_[elt] = attNS;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function: svgedit.sanitize.sanitizeSvg
|
// Function: svgedit.sanitize.sanitizeSvg
|
||||||
@@ -117,140 +117,140 @@ $.each(svgWhiteList_, function (elt, atts) {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// node - The DOM element to be checked (we'll also check its children)
|
// node - The DOM element to be checked (we'll also check its children)
|
||||||
svgedit.sanitize.sanitizeSvg = function (node) {
|
svgedit.sanitize.sanitizeSvg = function (node) {
|
||||||
// Cleanup text nodes
|
// Cleanup text nodes
|
||||||
if (node.nodeType === 3) { // 3 == TEXT_NODE
|
if (node.nodeType === 3) { // 3 == TEXT_NODE
|
||||||
// Trim whitespace
|
// Trim whitespace
|
||||||
node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, '');
|
node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||||
// Remove if empty
|
// Remove if empty
|
||||||
if (node.nodeValue.length === 0) {
|
if (node.nodeValue.length === 0) {
|
||||||
node.parentNode.removeChild(node);
|
node.parentNode.removeChild(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only care about element nodes.
|
// We only care about element nodes.
|
||||||
// Automatically return for all non-element nodes, such as comments, etc.
|
// Automatically return for all non-element nodes, such as comments, etc.
|
||||||
if (node.nodeType !== 1) { // 1 == ELEMENT_NODE
|
if (node.nodeType !== 1) { // 1 == ELEMENT_NODE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var doc = node.ownerDocument;
|
var doc = node.ownerDocument;
|
||||||
var parent = node.parentNode;
|
var parent = node.parentNode;
|
||||||
// can parent ever be null here? I think the root node's parent is the document...
|
// can parent ever be null here? I think the root node's parent is the document...
|
||||||
if (!doc || !parent) {
|
if (!doc || !parent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allowedAttrs = svgWhiteList_[node.nodeName];
|
var allowedAttrs = svgWhiteList_[node.nodeName];
|
||||||
var allowedAttrsNS = svgWhiteListNS_[node.nodeName];
|
var allowedAttrsNS = svgWhiteListNS_[node.nodeName];
|
||||||
var i;
|
var i;
|
||||||
// if this element is supported, sanitize it
|
// if this element is supported, sanitize it
|
||||||
if (typeof allowedAttrs !== 'undefined') {
|
if (typeof allowedAttrs !== 'undefined') {
|
||||||
var seAttrs = [];
|
var seAttrs = [];
|
||||||
i = node.attributes.length;
|
i = node.attributes.length;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
// if the attribute is not in our whitelist, then remove it
|
// 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
|
// could use jQuery's inArray(), but I don't know if that's any better
|
||||||
var attr = node.attributes.item(i);
|
var attr = node.attributes.item(i);
|
||||||
var attrName = attr.nodeName;
|
var attrName = attr.nodeName;
|
||||||
var attrLocalName = attr.localName;
|
var attrLocalName = attr.localName;
|
||||||
var attrNsURI = attr.namespaceURI;
|
var attrNsURI = attr.namespaceURI;
|
||||||
// Check that an attribute with the correct localName in the correct namespace is on
|
// 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
|
// our whitelist or is a namespace declaration for one of our allowed namespaces
|
||||||
if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&
|
if (!(allowedAttrsNS.hasOwnProperty(attrLocalName) && attrNsURI === allowedAttrsNS[attrLocalName] && attrNsURI !== NS.XMLNS) &&
|
||||||
!(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) {
|
!(attrNsURI === NS.XMLNS && REVERSE_NS[attr.value])) {
|
||||||
// TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.
|
// TODO(codedread): Programmatically add the se: attributes to the NS-aware whitelist.
|
||||||
// Bypassing the whitelist to allow se: prefixes.
|
// Bypassing the whitelist to allow se: prefixes.
|
||||||
// Is there a more appropriate way to do this?
|
// Is there a more appropriate way to do this?
|
||||||
if (attrName.indexOf('se:') === 0 || attrName.indexOf('data-') === 0) {
|
if (attrName.indexOf('se:') === 0 || attrName.indexOf('data-') === 0) {
|
||||||
seAttrs.push([attrName, attr.value]);
|
seAttrs.push([attrName, attr.value]);
|
||||||
}
|
}
|
||||||
node.removeAttributeNS(attrNsURI, attrLocalName);
|
node.removeAttributeNS(attrNsURI, attrLocalName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add spaces before negative signs where necessary
|
// Add spaces before negative signs where necessary
|
||||||
if (svgedit.browser.isGecko()) {
|
if (svgedit.browser.isGecko()) {
|
||||||
switch (attrName) {
|
switch (attrName) {
|
||||||
case 'transform':
|
case 'transform':
|
||||||
case 'gradientTransform':
|
case 'gradientTransform':
|
||||||
case 'patternTransform':
|
case 'patternTransform':
|
||||||
var val = attr.value.replace(/(\d)-/g, '$1 -');
|
var val = attr.value.replace(/(\d)-/g, '$1 -');
|
||||||
node.setAttribute(attrName, val);
|
node.setAttribute(attrName, val);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the style attribute, rewrite it in terms of XML presentational attributes
|
// For the style attribute, rewrite it in terms of XML presentational attributes
|
||||||
if (attrName === 'style') {
|
if (attrName === 'style') {
|
||||||
var props = attr.value.split(';'),
|
var props = attr.value.split(';'),
|
||||||
p = props.length;
|
p = props.length;
|
||||||
while (p--) {
|
while (p--) {
|
||||||
var nv = props[p].split(':');
|
var nv = props[p].split(':');
|
||||||
var styleAttrName = $.trim(nv[0]);
|
var styleAttrName = $.trim(nv[0]);
|
||||||
var styleAttrVal = $.trim(nv[1]);
|
var styleAttrVal = $.trim(nv[1]);
|
||||||
// Now check that this attribute is supported
|
// Now check that this attribute is supported
|
||||||
if (allowedAttrs.indexOf(styleAttrName) >= 0) {
|
if (allowedAttrs.indexOf(styleAttrName) >= 0) {
|
||||||
node.setAttribute(styleAttrName, styleAttrVal);
|
node.setAttribute(styleAttrName, styleAttrVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.removeAttribute('style');
|
node.removeAttribute('style');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$.each(seAttrs, function (i, attr) {
|
$.each(seAttrs, function (i, attr) {
|
||||||
node.setAttributeNS(NS.SE, attr[0], attr[1]);
|
node.setAttributeNS(NS.SE, attr[0], attr[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
// for some elements that have a xlink:href, ensure the URI refers to a local element
|
// for some elements that have a xlink:href, ensure the URI refers to a local element
|
||||||
// (but not for links)
|
// (but not for links)
|
||||||
var href = svgedit.utilities.getHref(node);
|
var href = svgedit.utilities.getHref(node);
|
||||||
if (href &&
|
if (href &&
|
||||||
['filter', 'linearGradient', 'pattern',
|
['filter', 'linearGradient', 'pattern',
|
||||||
'radialGradient', 'textPath', 'use'].indexOf(node.nodeName) >= 0) {
|
'radialGradient', 'textPath', 'use'].indexOf(node.nodeName) >= 0) {
|
||||||
// TODO: we simply check if the first character is a #, is this bullet-proof?
|
// TODO: we simply check if the first character is a #, is this bullet-proof?
|
||||||
if (href[0] !== '#') {
|
if (href[0] !== '#') {
|
||||||
// remove the attribute (but keep the element)
|
// remove the attribute (but keep the element)
|
||||||
svgedit.utilities.setHref(node, '');
|
svgedit.utilities.setHref(node, '');
|
||||||
node.removeAttributeNS(NS.XLINK, 'href');
|
node.removeAttributeNS(NS.XLINK, 'href');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safari crashes on a <use> without a xlink:href, so we just remove the node here
|
// Safari crashes on a <use> without a xlink:href, so we just remove the node here
|
||||||
if (node.nodeName === 'use' && !svgedit.utilities.getHref(node)) {
|
if (node.nodeName === 'use' && !svgedit.utilities.getHref(node)) {
|
||||||
parent.removeChild(node);
|
parent.removeChild(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if the element has attributes pointing to a non-local reference,
|
// if the element has attributes pointing to a non-local reference,
|
||||||
// need to remove the attribute
|
// need to remove the attribute
|
||||||
$.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (i, attr) {
|
$.each(['clip-path', 'fill', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke'], function (i, attr) {
|
||||||
var val = node.getAttribute(attr);
|
var val = node.getAttribute(attr);
|
||||||
if (val) {
|
if (val) {
|
||||||
val = svgedit.utilities.getUrlFromAttr(val);
|
val = svgedit.utilities.getUrlFromAttr(val);
|
||||||
// simply check for first character being a '#'
|
// simply check for first character being a '#'
|
||||||
if (val && val[0] !== '#') {
|
if (val && val[0] !== '#') {
|
||||||
node.setAttribute(attr, '');
|
node.setAttribute(attr, '');
|
||||||
node.removeAttribute(attr);
|
node.removeAttribute(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// recurse to children
|
// recurse to children
|
||||||
i = node.childNodes.length;
|
i = node.childNodes.length;
|
||||||
while (i--) { svgedit.sanitize.sanitizeSvg(node.childNodes.item(i)); }
|
while (i--) { svgedit.sanitize.sanitizeSvg(node.childNodes.item(i)); }
|
||||||
// else (element not supported), remove it
|
// else (element not supported), remove it
|
||||||
} else {
|
} else {
|
||||||
// remove all children from this node and insert them before this node
|
// 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
|
// FIXME: in the case of animation elements this will hardly ever be correct
|
||||||
var children = [];
|
var children = [];
|
||||||
while (node.hasChildNodes()) {
|
while (node.hasChildNodes()) {
|
||||||
children.push(parent.insertBefore(node.firstChild, node));
|
children.push(parent.insertBefore(node.firstChild, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove this node from the document altogether
|
// remove this node from the document altogether
|
||||||
parent.removeChild(node);
|
parent.removeChild(node);
|
||||||
|
|
||||||
// call sanitizeSvg on each of those children
|
// call sanitizeSvg on each of those children
|
||||||
i = children.length;
|
i = children.length;
|
||||||
while (i--) { svgedit.sanitize.sanitizeSvg(children[i]); }
|
while (i--) { svgedit.sanitize.sanitizeSvg(children[i]); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
716
editor/select.js
716
editor/select.js
@@ -20,7 +20,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.select) {
|
if (!svgedit.select) {
|
||||||
svgedit.select = {};
|
svgedit.select = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var svgFactory_;
|
var svgFactory_;
|
||||||
@@ -36,50 +36,50 @@ var gripRadius = svgedit.browser.isTouch() ? 10 : 4;
|
|||||||
// elem - DOM element associated with this selector
|
// elem - DOM element associated with this selector
|
||||||
// bbox - Optional bbox to use for initialization (prevents duplicate getBBox call).
|
// bbox - Optional bbox to use for initialization (prevents duplicate getBBox call).
|
||||||
svgedit.select.Selector = function (id, elem, bbox) {
|
svgedit.select.Selector = function (id, elem, bbox) {
|
||||||
// this is the selector's unique number
|
// this is the selector's unique number
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
// this holds a reference to the element for which this selector is being used
|
// this holds a reference to the element for which this selector is being used
|
||||||
this.selectedElement = elem;
|
this.selectedElement = elem;
|
||||||
|
|
||||||
// this is a flag used internally to track whether the selector is being used or not
|
// this is a flag used internally to track whether the selector is being used or not
|
||||||
this.locked = true;
|
this.locked = true;
|
||||||
|
|
||||||
// this holds a reference to the <g> element that holds all visual elements of the selector
|
// this holds a reference to the <g> element that holds all visual elements of the selector
|
||||||
this.selectorGroup = svgFactory_.createSVGElement({
|
this.selectorGroup = svgFactory_.createSVGElement({
|
||||||
'element': 'g',
|
'element': 'g',
|
||||||
'attr': {'id': ('selectorGroup' + this.id)}
|
'attr': {'id': ('selectorGroup' + this.id)}
|
||||||
});
|
});
|
||||||
|
|
||||||
// this holds a reference to the path rect
|
// this holds a reference to the path rect
|
||||||
this.selectorRect = this.selectorGroup.appendChild(
|
this.selectorRect = this.selectorGroup.appendChild(
|
||||||
svgFactory_.createSVGElement({
|
svgFactory_.createSVGElement({
|
||||||
'element': 'path',
|
'element': 'path',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': ('selectedBox' + this.id),
|
'id': ('selectedBox' + this.id),
|
||||||
'fill': 'none',
|
'fill': 'none',
|
||||||
'stroke': '#22C',
|
'stroke': '#22C',
|
||||||
'stroke-width': '1',
|
'stroke-width': '1',
|
||||||
'stroke-dasharray': '5,5',
|
'stroke-dasharray': '5,5',
|
||||||
// need to specify this so that the rect is not selectable
|
// need to specify this so that the rect is not selectable
|
||||||
'style': 'pointer-events:none'
|
'style': 'pointer-events:none'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// this holds a reference to the grip coordinates for this selector
|
// this holds a reference to the grip coordinates for this selector
|
||||||
this.gripCoords = {
|
this.gripCoords = {
|
||||||
'nw': null,
|
'nw': null,
|
||||||
'n': null,
|
'n': null,
|
||||||
'ne': null,
|
'ne': null,
|
||||||
'e': null,
|
'e': null,
|
||||||
'se': null,
|
'se': null,
|
||||||
's': null,
|
's': null,
|
||||||
'sw': null,
|
'sw': null,
|
||||||
'w': null
|
'w': null
|
||||||
};
|
};
|
||||||
|
|
||||||
this.reset(this.selectedElement, bbox);
|
this.reset(this.selectedElement, bbox);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.Selector.reset
|
// Function: svgedit.select.Selector.reset
|
||||||
@@ -89,10 +89,10 @@ svgedit.select.Selector = function (id, elem, bbox) {
|
|||||||
// e - DOM element associated with this selector
|
// e - DOM element associated with this selector
|
||||||
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
||||||
svgedit.select.Selector.prototype.reset = function (e, bbox) {
|
svgedit.select.Selector.prototype.reset = function (e, bbox) {
|
||||||
this.locked = true;
|
this.locked = true;
|
||||||
this.selectedElement = e;
|
this.selectedElement = e;
|
||||||
this.resize(bbox);
|
this.resize(bbox);
|
||||||
this.selectorGroup.setAttribute('display', 'inline');
|
this.selectorGroup.setAttribute('display', 'inline');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.Selector.updateGripCursors
|
// Function: svgedit.select.Selector.updateGripCursors
|
||||||
@@ -101,22 +101,22 @@ svgedit.select.Selector.prototype.reset = function (e, bbox) {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// angle - Float indicating current rotation angle in degrees
|
// angle - Float indicating current rotation angle in degrees
|
||||||
svgedit.select.Selector.prototype.updateGripCursors = function (angle) {
|
svgedit.select.Selector.prototype.updateGripCursors = function (angle) {
|
||||||
var dir,
|
var dir,
|
||||||
dirArr = [],
|
dirArr = [],
|
||||||
steps = Math.round(angle / 45);
|
steps = Math.round(angle / 45);
|
||||||
if (steps < 0) { steps += 8; }
|
if (steps < 0) { steps += 8; }
|
||||||
for (dir in selectorManager_.selectorGrips) {
|
for (dir in selectorManager_.selectorGrips) {
|
||||||
dirArr.push(dir);
|
dirArr.push(dir);
|
||||||
}
|
}
|
||||||
while (steps > 0) {
|
while (steps > 0) {
|
||||||
dirArr.push(dirArr.shift());
|
dirArr.push(dirArr.shift());
|
||||||
steps--;
|
steps--;
|
||||||
}
|
}
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (dir in selectorManager_.selectorGrips) {
|
for (dir in selectorManager_.selectorGrips) {
|
||||||
selectorManager_.selectorGrips[dir].setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));
|
selectorManager_.selectorGrips[dir].setAttribute('style', ('cursor:' + dirArr[i] + '-resize'));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.Selector.showGrips
|
// Function: svgedit.select.Selector.showGrips
|
||||||
@@ -125,292 +125,292 @@ svgedit.select.Selector.prototype.updateGripCursors = function (angle) {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// show - boolean indicating whether grips should be shown or not
|
// show - boolean indicating whether grips should be shown or not
|
||||||
svgedit.select.Selector.prototype.showGrips = function (show) {
|
svgedit.select.Selector.prototype.showGrips = function (show) {
|
||||||
var bShow = show ? 'inline' : 'none';
|
var bShow = show ? 'inline' : 'none';
|
||||||
selectorManager_.selectorGripsGroup.setAttribute('display', bShow);
|
selectorManager_.selectorGripsGroup.setAttribute('display', bShow);
|
||||||
var elem = this.selectedElement;
|
var elem = this.selectedElement;
|
||||||
this.hasGrips = show;
|
this.hasGrips = show;
|
||||||
if (elem && show) {
|
if (elem && show) {
|
||||||
this.selectorGroup.appendChild(selectorManager_.selectorGripsGroup);
|
this.selectorGroup.appendChild(selectorManager_.selectorGripsGroup);
|
||||||
this.updateGripCursors(svgedit.utilities.getRotationAngle(elem));
|
this.updateGripCursors(svgedit.utilities.getRotationAngle(elem));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.Selector.resize
|
// Function: svgedit.select.Selector.resize
|
||||||
// Updates the selector to match the element's size
|
// Updates the selector to match the element's size
|
||||||
// bbox - Optional bbox to use for resize (prevents duplicate getBBox call).
|
// bbox - Optional bbox to use for resize (prevents duplicate getBBox call).
|
||||||
svgedit.select.Selector.prototype.resize = function (bbox) {
|
svgedit.select.Selector.prototype.resize = function (bbox) {
|
||||||
var selectedBox = this.selectorRect,
|
var selectedBox = this.selectorRect,
|
||||||
mgr = selectorManager_,
|
mgr = selectorManager_,
|
||||||
selectedGrips = mgr.selectorGrips,
|
selectedGrips = mgr.selectorGrips,
|
||||||
selected = this.selectedElement,
|
selected = this.selectedElement,
|
||||||
sw = selected.getAttribute('stroke-width'),
|
sw = selected.getAttribute('stroke-width'),
|
||||||
currentZoom = svgFactory_.currentZoom();
|
currentZoom = svgFactory_.currentZoom();
|
||||||
var offset = 1 / currentZoom;
|
var offset = 1 / currentZoom;
|
||||||
if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {
|
if (selected.getAttribute('stroke') !== 'none' && !isNaN(sw)) {
|
||||||
offset += (sw / 2);
|
offset += (sw / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagName = selected.tagName;
|
var tagName = selected.tagName;
|
||||||
if (tagName === 'text') {
|
if (tagName === 'text') {
|
||||||
offset += 2 / currentZoom;
|
offset += 2 / currentZoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop and transform our bounding box until we reach our first rotation
|
// loop and transform our bounding box until we reach our first rotation
|
||||||
var tlist = svgedit.transformlist.getTransformList(selected);
|
var tlist = svgedit.transformlist.getTransformList(selected);
|
||||||
var m = svgedit.math.transformListToTransform(tlist).matrix;
|
var m = svgedit.math.transformListToTransform(tlist).matrix;
|
||||||
|
|
||||||
// This should probably be handled somewhere else, but for now
|
// This should probably be handled somewhere else, but for now
|
||||||
// it keeps the selection box correctly positioned when zoomed
|
// it keeps the selection box correctly positioned when zoomed
|
||||||
m.e *= currentZoom;
|
m.e *= currentZoom;
|
||||||
m.f *= currentZoom;
|
m.f *= currentZoom;
|
||||||
|
|
||||||
if (!bbox) {
|
if (!bbox) {
|
||||||
bbox = svgedit.utilities.getBBox(selected);
|
bbox = svgedit.utilities.getBBox(selected);
|
||||||
}
|
}
|
||||||
// TODO: svgedit.utilities.getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this?
|
// TODO: svgedit.utilities.getBBox (previous line) already knows to call getStrokedBBox when tagName === 'g'. Remove this?
|
||||||
// TODO: svgedit.utilities.getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated?
|
// TODO: svgedit.utilities.getBBox doesn't exclude 'gsvg' and calls getStrokedBBox for any 'g'. Should getBBox be updated?
|
||||||
if (tagName === 'g' && !$.data(selected, 'gsvg')) {
|
if (tagName === 'g' && !$.data(selected, 'gsvg')) {
|
||||||
// The bbox for a group does not include stroke vals, so we
|
// The bbox for a group does not include stroke vals, so we
|
||||||
// get the bbox based on its children.
|
// get the bbox based on its children.
|
||||||
var strokedBbox = svgFactory_.getStrokedBBox(selected.childNodes);
|
var strokedBbox = svgFactory_.getStrokedBBox(selected.childNodes);
|
||||||
if (strokedBbox) {
|
if (strokedBbox) {
|
||||||
bbox = strokedBbox;
|
bbox = strokedBbox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply the transforms
|
// apply the transforms
|
||||||
var l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height;
|
var l = bbox.x, t = bbox.y, w = bbox.width, h = bbox.height;
|
||||||
bbox = {x: l, y: t, width: w, height: h};
|
bbox = {x: l, y: t, width: w, height: h};
|
||||||
|
|
||||||
// we need to handle temporary transforms too
|
// we need to handle temporary transforms too
|
||||||
// if skewed, get its transformed box, then find its axis-aligned bbox
|
// if skewed, get its transformed box, then find its axis-aligned bbox
|
||||||
|
|
||||||
// *
|
// *
|
||||||
offset *= currentZoom;
|
offset *= currentZoom;
|
||||||
|
|
||||||
var nbox = svgedit.math.transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),
|
var nbox = svgedit.math.transformBox(l * currentZoom, t * currentZoom, w * currentZoom, h * currentZoom, m),
|
||||||
aabox = nbox.aabox,
|
aabox = nbox.aabox,
|
||||||
nbax = aabox.x - offset,
|
nbax = aabox.x - offset,
|
||||||
nbay = aabox.y - offset,
|
nbay = aabox.y - offset,
|
||||||
nbaw = aabox.width + (offset * 2),
|
nbaw = aabox.width + (offset * 2),
|
||||||
nbah = aabox.height + (offset * 2);
|
nbah = aabox.height + (offset * 2);
|
||||||
|
|
||||||
// now if the shape is rotated, un-rotate it
|
// now if the shape is rotated, un-rotate it
|
||||||
var cx = nbax + nbaw / 2,
|
var cx = nbax + nbaw / 2,
|
||||||
cy = nbay + nbah / 2;
|
cy = nbay + nbah / 2;
|
||||||
|
|
||||||
var angle = svgedit.utilities.getRotationAngle(selected);
|
var angle = svgedit.utilities.getRotationAngle(selected);
|
||||||
if (angle) {
|
if (angle) {
|
||||||
var rot = svgFactory_.svgRoot().createSVGTransform();
|
var rot = svgFactory_.svgRoot().createSVGTransform();
|
||||||
rot.setRotate(-angle, cx, cy);
|
rot.setRotate(-angle, cx, cy);
|
||||||
var rotm = rot.matrix;
|
var rotm = rot.matrix;
|
||||||
nbox.tl = svgedit.math.transformPoint(nbox.tl.x, nbox.tl.y, rotm);
|
nbox.tl = svgedit.math.transformPoint(nbox.tl.x, nbox.tl.y, rotm);
|
||||||
nbox.tr = svgedit.math.transformPoint(nbox.tr.x, nbox.tr.y, rotm);
|
nbox.tr = svgedit.math.transformPoint(nbox.tr.x, nbox.tr.y, rotm);
|
||||||
nbox.bl = svgedit.math.transformPoint(nbox.bl.x, nbox.bl.y, rotm);
|
nbox.bl = svgedit.math.transformPoint(nbox.bl.x, nbox.bl.y, rotm);
|
||||||
nbox.br = svgedit.math.transformPoint(nbox.br.x, nbox.br.y, rotm);
|
nbox.br = svgedit.math.transformPoint(nbox.br.x, nbox.br.y, rotm);
|
||||||
|
|
||||||
// calculate the axis-aligned bbox
|
// calculate the axis-aligned bbox
|
||||||
var tl = nbox.tl;
|
var tl = nbox.tl;
|
||||||
var minx = tl.x,
|
var minx = tl.x,
|
||||||
miny = tl.y,
|
miny = tl.y,
|
||||||
maxx = tl.x,
|
maxx = tl.x,
|
||||||
maxy = tl.y;
|
maxy = tl.y;
|
||||||
|
|
||||||
var min = Math.min, max = Math.max;
|
var min = Math.min, max = Math.max;
|
||||||
|
|
||||||
minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;
|
minx = min(minx, min(nbox.tr.x, min(nbox.bl.x, nbox.br.x))) - offset;
|
||||||
miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;
|
miny = min(miny, min(nbox.tr.y, min(nbox.bl.y, nbox.br.y))) - offset;
|
||||||
maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset;
|
maxx = max(maxx, max(nbox.tr.x, max(nbox.bl.x, nbox.br.x))) + offset;
|
||||||
maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset;
|
maxy = max(maxy, max(nbox.tr.y, max(nbox.bl.y, nbox.br.y))) + offset;
|
||||||
|
|
||||||
nbax = minx;
|
nbax = minx;
|
||||||
nbay = miny;
|
nbay = miny;
|
||||||
nbaw = (maxx - minx);
|
nbaw = (maxx - minx);
|
||||||
nbah = (maxy - miny);
|
nbah = (maxy - miny);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dstr = 'M' + nbax + ',' + nbay +
|
var dstr = 'M' + nbax + ',' + nbay +
|
||||||
' L' + (nbax + nbaw) + ',' + nbay +
|
' L' + (nbax + nbaw) + ',' + nbay +
|
||||||
' ' + (nbax + nbaw) + ',' + (nbay + nbah) +
|
' ' + (nbax + nbaw) + ',' + (nbay + nbah) +
|
||||||
' ' + nbax + ',' + (nbay + nbah) + 'z';
|
' ' + nbax + ',' + (nbay + nbah) + 'z';
|
||||||
selectedBox.setAttribute('d', dstr);
|
selectedBox.setAttribute('d', dstr);
|
||||||
|
|
||||||
var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';
|
var xform = angle ? 'rotate(' + [angle, cx, cy].join(',') + ')' : '';
|
||||||
this.selectorGroup.setAttribute('transform', xform);
|
this.selectorGroup.setAttribute('transform', xform);
|
||||||
|
|
||||||
// TODO(codedread): Is this if needed?
|
// TODO(codedread): Is this if needed?
|
||||||
// if (selected === selectedElements[0]) {
|
// if (selected === selectedElements[0]) {
|
||||||
this.gripCoords = {
|
this.gripCoords = {
|
||||||
'nw': [nbax, nbay],
|
'nw': [nbax, nbay],
|
||||||
'ne': [nbax + nbaw, nbay],
|
'ne': [nbax + nbaw, nbay],
|
||||||
'sw': [nbax, nbay + nbah],
|
'sw': [nbax, nbay + nbah],
|
||||||
'se': [nbax + nbaw, nbay + nbah],
|
'se': [nbax + nbaw, nbay + nbah],
|
||||||
'n': [nbax + (nbaw) / 2, nbay],
|
'n': [nbax + (nbaw) / 2, nbay],
|
||||||
'w': [nbax, nbay + (nbah) / 2],
|
'w': [nbax, nbay + (nbah) / 2],
|
||||||
'e': [nbax + nbaw, nbay + (nbah) / 2],
|
'e': [nbax + nbaw, nbay + (nbah) / 2],
|
||||||
's': [nbax + (nbaw) / 2, nbay + nbah]
|
's': [nbax + (nbaw) / 2, nbay + nbah]
|
||||||
};
|
};
|
||||||
var dir;
|
var dir;
|
||||||
for (dir in this.gripCoords) {
|
for (dir in this.gripCoords) {
|
||||||
var coords = this.gripCoords[dir];
|
var coords = this.gripCoords[dir];
|
||||||
selectedGrips[dir].setAttribute('cx', coords[0]);
|
selectedGrips[dir].setAttribute('cx', coords[0]);
|
||||||
selectedGrips[dir].setAttribute('cy', coords[1]);
|
selectedGrips[dir].setAttribute('cy', coords[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to go 20 pixels in the negative transformed y direction, ignoring scale
|
// we want to go 20 pixels in the negative transformed y direction, ignoring scale
|
||||||
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);
|
mgr.rotateGripConnector.setAttribute('x1', nbax + (nbaw) / 2);
|
||||||
mgr.rotateGripConnector.setAttribute('y1', nbay);
|
mgr.rotateGripConnector.setAttribute('y1', nbay);
|
||||||
mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);
|
mgr.rotateGripConnector.setAttribute('x2', nbax + (nbaw) / 2);
|
||||||
mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));
|
mgr.rotateGripConnector.setAttribute('y2', nbay - (gripRadius * 5));
|
||||||
|
|
||||||
mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);
|
mgr.rotateGrip.setAttribute('cx', nbax + (nbaw) / 2);
|
||||||
mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));
|
mgr.rotateGrip.setAttribute('cy', nbay - (gripRadius * 5));
|
||||||
// }
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class: svgedit.select.SelectorManager
|
// Class: svgedit.select.SelectorManager
|
||||||
svgedit.select.SelectorManager = function () {
|
svgedit.select.SelectorManager = function () {
|
||||||
// this will hold the <g> element that contains all selector rects/grips
|
// this will hold the <g> element that contains all selector rects/grips
|
||||||
this.selectorParentGroup = null;
|
this.selectorParentGroup = null;
|
||||||
|
|
||||||
// this is a special rect that is used for multi-select
|
// this is a special rect that is used for multi-select
|
||||||
this.rubberBandBox = null;
|
this.rubberBandBox = null;
|
||||||
|
|
||||||
// this will hold objects of type svgedit.select.Selector (see above)
|
// this will hold objects of type svgedit.select.Selector (see above)
|
||||||
this.selectors = [];
|
this.selectors = [];
|
||||||
|
|
||||||
// this holds a map of SVG elements to their Selector object
|
// this holds a map of SVG elements to their Selector object
|
||||||
this.selectorMap = {};
|
this.selectorMap = {};
|
||||||
|
|
||||||
// this holds a reference to the grip elements
|
// this holds a reference to the grip elements
|
||||||
this.selectorGrips = {
|
this.selectorGrips = {
|
||||||
'nw': null,
|
'nw': null,
|
||||||
'n': null,
|
'n': null,
|
||||||
'ne': null,
|
'ne': null,
|
||||||
'e': null,
|
'e': null,
|
||||||
'se': null,
|
'se': null,
|
||||||
's': null,
|
's': null,
|
||||||
'sw': null,
|
'sw': null,
|
||||||
'w': null
|
'w': null
|
||||||
};
|
};
|
||||||
|
|
||||||
this.selectorGripsGroup = null;
|
this.selectorGripsGroup = null;
|
||||||
this.rotateGripConnector = null;
|
this.rotateGripConnector = null;
|
||||||
this.rotateGrip = null;
|
this.rotateGrip = null;
|
||||||
|
|
||||||
this.initGroup();
|
this.initGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.SelectorManager.initGroup
|
// Function: svgedit.select.SelectorManager.initGroup
|
||||||
// Resets the parent selector group element
|
// Resets the parent selector group element
|
||||||
svgedit.select.SelectorManager.prototype.initGroup = function () {
|
svgedit.select.SelectorManager.prototype.initGroup = function () {
|
||||||
// remove old selector parent group if it existed
|
// remove old selector parent group if it existed
|
||||||
if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {
|
if (this.selectorParentGroup && this.selectorParentGroup.parentNode) {
|
||||||
this.selectorParentGroup.parentNode.removeChild(this.selectorParentGroup);
|
this.selectorParentGroup.parentNode.removeChild(this.selectorParentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create parent selector group and add it to svgroot
|
// create parent selector group and add it to svgroot
|
||||||
this.selectorParentGroup = svgFactory_.createSVGElement({
|
this.selectorParentGroup = svgFactory_.createSVGElement({
|
||||||
'element': 'g',
|
'element': 'g',
|
||||||
'attr': {'id': 'selectorParentGroup'}
|
'attr': {'id': 'selectorParentGroup'}
|
||||||
});
|
});
|
||||||
this.selectorGripsGroup = svgFactory_.createSVGElement({
|
this.selectorGripsGroup = svgFactory_.createSVGElement({
|
||||||
'element': 'g',
|
'element': 'g',
|
||||||
'attr': {'display': 'none'}
|
'attr': {'display': 'none'}
|
||||||
});
|
});
|
||||||
this.selectorParentGroup.appendChild(this.selectorGripsGroup);
|
this.selectorParentGroup.appendChild(this.selectorGripsGroup);
|
||||||
svgFactory_.svgRoot().appendChild(this.selectorParentGroup);
|
svgFactory_.svgRoot().appendChild(this.selectorParentGroup);
|
||||||
|
|
||||||
this.selectorMap = {};
|
this.selectorMap = {};
|
||||||
this.selectors = [];
|
this.selectors = [];
|
||||||
this.rubberBandBox = null;
|
this.rubberBandBox = null;
|
||||||
|
|
||||||
// add the corner grips
|
// add the corner grips
|
||||||
var dir;
|
var dir;
|
||||||
for (dir in this.selectorGrips) {
|
for (dir in this.selectorGrips) {
|
||||||
var grip = svgFactory_.createSVGElement({
|
var grip = svgFactory_.createSVGElement({
|
||||||
'element': 'circle',
|
'element': 'circle',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': ('selectorGrip_resize_' + dir),
|
'id': ('selectorGrip_resize_' + dir),
|
||||||
'fill': '#22C',
|
'fill': '#22C',
|
||||||
'r': gripRadius,
|
'r': gripRadius,
|
||||||
'style': ('cursor:' + dir + '-resize'),
|
'style': ('cursor:' + dir + '-resize'),
|
||||||
// This expands the mouse-able area of the grips making them
|
// This expands the mouse-able area of the grips making them
|
||||||
// easier to grab with the mouse.
|
// easier to grab with the mouse.
|
||||||
// This works in Opera and WebKit, but does not work in Firefox
|
// This works in Opera and WebKit, but does not work in Firefox
|
||||||
// see https://bugzilla.mozilla.org/show_bug.cgi?id=500174
|
// see https://bugzilla.mozilla.org/show_bug.cgi?id=500174
|
||||||
'stroke-width': 2,
|
'stroke-width': 2,
|
||||||
'pointer-events': 'all'
|
'pointer-events': 'all'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$.data(grip, 'dir', dir);
|
$.data(grip, 'dir', dir);
|
||||||
$.data(grip, 'type', 'resize');
|
$.data(grip, 'type', 'resize');
|
||||||
this.selectorGrips[dir] = this.selectorGripsGroup.appendChild(grip);
|
this.selectorGrips[dir] = this.selectorGripsGroup.appendChild(grip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add rotator elems
|
// add rotator elems
|
||||||
this.rotateGripConnector = this.selectorGripsGroup.appendChild(
|
this.rotateGripConnector = this.selectorGripsGroup.appendChild(
|
||||||
svgFactory_.createSVGElement({
|
svgFactory_.createSVGElement({
|
||||||
'element': 'line',
|
'element': 'line',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': ('selectorGrip_rotateconnector'),
|
'id': ('selectorGrip_rotateconnector'),
|
||||||
'stroke': '#22C',
|
'stroke': '#22C',
|
||||||
'stroke-width': '1'
|
'stroke-width': '1'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.rotateGrip = this.selectorGripsGroup.appendChild(
|
this.rotateGrip = this.selectorGripsGroup.appendChild(
|
||||||
svgFactory_.createSVGElement({
|
svgFactory_.createSVGElement({
|
||||||
'element': 'circle',
|
'element': 'circle',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': 'selectorGrip_rotate',
|
'id': 'selectorGrip_rotate',
|
||||||
'fill': 'lime',
|
'fill': 'lime',
|
||||||
'r': gripRadius,
|
'r': gripRadius,
|
||||||
'stroke': '#22C',
|
'stroke': '#22C',
|
||||||
'stroke-width': 2,
|
'stroke-width': 2,
|
||||||
'style': 'cursor:url(' + config_.imgPath + 'rotate.png) 12 12, auto;'
|
'style': 'cursor:url(' + config_.imgPath + 'rotate.png) 12 12, auto;'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
$.data(this.rotateGrip, 'type', 'rotate');
|
$.data(this.rotateGrip, 'type', 'rotate');
|
||||||
|
|
||||||
if ($('#canvasBackground').length) { return; }
|
if ($('#canvasBackground').length) { return; }
|
||||||
|
|
||||||
var dims = config_.dimensions;
|
var dims = config_.dimensions;
|
||||||
var canvasbg = svgFactory_.createSVGElement({
|
var canvasbg = svgFactory_.createSVGElement({
|
||||||
'element': 'svg',
|
'element': 'svg',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': 'canvasBackground',
|
'id': 'canvasBackground',
|
||||||
'width': dims[0],
|
'width': dims[0],
|
||||||
'height': dims[1],
|
'height': dims[1],
|
||||||
'x': 0,
|
'x': 0,
|
||||||
'y': 0,
|
'y': 0,
|
||||||
'overflow': (svgedit.browser.isWebkit() ? 'none' : 'visible'), // Chrome 7 has a problem with this when zooming out
|
'overflow': (svgedit.browser.isWebkit() ? 'none' : 'visible'), // Chrome 7 has a problem with this when zooming out
|
||||||
'style': 'pointer-events:none'
|
'style': 'pointer-events:none'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var rect = svgFactory_.createSVGElement({
|
var rect = svgFactory_.createSVGElement({
|
||||||
'element': 'rect',
|
'element': 'rect',
|
||||||
'attr': {
|
'attr': {
|
||||||
'width': '100%',
|
'width': '100%',
|
||||||
'height': '100%',
|
'height': '100%',
|
||||||
'x': 0,
|
'x': 0,
|
||||||
'y': 0,
|
'y': 0,
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'stroke': '#000',
|
'stroke': '#000',
|
||||||
'fill': '#FFF',
|
'fill': '#FFF',
|
||||||
'style': 'pointer-events:none'
|
'style': 'pointer-events:none'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Both Firefox and WebKit are too slow with this filter region (especially at higher
|
// Both Firefox and WebKit are too slow with this filter region (especially at higher
|
||||||
// zoom levels) and Opera has at least one bug
|
// zoom levels) and Opera has at least one bug
|
||||||
// if (!svgedit.browser.isOpera()) rect.setAttribute('filter', 'url(#canvashadow)');
|
// if (!svgedit.browser.isOpera()) rect.setAttribute('filter', 'url(#canvashadow)');
|
||||||
canvasbg.appendChild(rect);
|
canvasbg.appendChild(rect);
|
||||||
svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());
|
svgFactory_.svgRoot().insertBefore(canvasbg, svgFactory_.svgContent());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.SelectorManager.requestSelector
|
// Function: svgedit.select.SelectorManager.requestSelector
|
||||||
@@ -420,27 +420,27 @@ svgedit.select.SelectorManager.prototype.initGroup = function () {
|
|||||||
// elem - DOM element to get the selector for
|
// elem - DOM element to get the selector for
|
||||||
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
// bbox - Optional bbox to use for reset (prevents duplicate getBBox call).
|
||||||
svgedit.select.SelectorManager.prototype.requestSelector = function (elem, bbox) {
|
svgedit.select.SelectorManager.prototype.requestSelector = function (elem, bbox) {
|
||||||
if (elem == null) { return null; }
|
if (elem == null) { return null; }
|
||||||
var i,
|
var i,
|
||||||
N = this.selectors.length;
|
N = this.selectors.length;
|
||||||
// If we've already acquired one for this element, return it.
|
// If we've already acquired one for this element, return it.
|
||||||
if (typeof this.selectorMap[elem.id] === 'object') {
|
if (typeof this.selectorMap[elem.id] === 'object') {
|
||||||
this.selectorMap[elem.id].locked = true;
|
this.selectorMap[elem.id].locked = true;
|
||||||
return this.selectorMap[elem.id];
|
return this.selectorMap[elem.id];
|
||||||
}
|
}
|
||||||
for (i = 0; i < N; ++i) {
|
for (i = 0; i < N; ++i) {
|
||||||
if (this.selectors[i] && !this.selectors[i].locked) {
|
if (this.selectors[i] && !this.selectors[i].locked) {
|
||||||
this.selectors[i].locked = true;
|
this.selectors[i].locked = true;
|
||||||
this.selectors[i].reset(elem, bbox);
|
this.selectors[i].reset(elem, bbox);
|
||||||
this.selectorMap[elem.id] = this.selectors[i];
|
this.selectorMap[elem.id] = this.selectors[i];
|
||||||
return this.selectors[i];
|
return this.selectors[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we reached here, no available selectors were found, we create one
|
// if we reached here, no available selectors were found, we create one
|
||||||
this.selectors[N] = new svgedit.select.Selector(N, elem, bbox);
|
this.selectors[N] = new svgedit.select.Selector(N, elem, bbox);
|
||||||
this.selectorParentGroup.appendChild(this.selectors[N].selectorGroup);
|
this.selectorParentGroup.appendChild(this.selectors[N].selectorGroup);
|
||||||
this.selectorMap[elem.id] = this.selectors[N];
|
this.selectorMap[elem.id] = this.selectors[N];
|
||||||
return this.selectors[N];
|
return this.selectors[N];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.SelectorManager.releaseSelector
|
// Function: svgedit.select.SelectorManager.releaseSelector
|
||||||
@@ -449,51 +449,51 @@ svgedit.select.SelectorManager.prototype.requestSelector = function (elem, bbox)
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// elem - DOM element to remove the selector for
|
// elem - DOM element to remove the selector for
|
||||||
svgedit.select.SelectorManager.prototype.releaseSelector = function (elem) {
|
svgedit.select.SelectorManager.prototype.releaseSelector = function (elem) {
|
||||||
if (elem == null) { return; }
|
if (elem == null) { return; }
|
||||||
var i,
|
var i,
|
||||||
N = this.selectors.length,
|
N = this.selectors.length,
|
||||||
sel = this.selectorMap[elem.id];
|
sel = this.selectorMap[elem.id];
|
||||||
if (!sel.locked) {
|
if (!sel.locked) {
|
||||||
// TODO(codedread): Ensure this exists in this module.
|
// TODO(codedread): Ensure this exists in this module.
|
||||||
console.log('WARNING! selector was released but was already unlocked');
|
console.log('WARNING! selector was released but was already unlocked');
|
||||||
}
|
}
|
||||||
for (i = 0; i < N; ++i) {
|
for (i = 0; i < N; ++i) {
|
||||||
if (this.selectors[i] && this.selectors[i] === sel) {
|
if (this.selectors[i] && this.selectors[i] === sel) {
|
||||||
delete this.selectorMap[elem.id];
|
delete this.selectorMap[elem.id];
|
||||||
sel.locked = false;
|
sel.locked = false;
|
||||||
sel.selectedElement = null;
|
sel.selectedElement = null;
|
||||||
sel.showGrips(false);
|
sel.showGrips(false);
|
||||||
|
|
||||||
// remove from DOM and store reference in JS but only if it exists in the DOM
|
// remove from DOM and store reference in JS but only if it exists in the DOM
|
||||||
try {
|
try {
|
||||||
sel.selectorGroup.setAttribute('display', 'none');
|
sel.selectorGroup.setAttribute('display', 'none');
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.select.SelectorManager.getRubberBandBox
|
// Function: svgedit.select.SelectorManager.getRubberBandBox
|
||||||
// Returns the rubberBandBox DOM element. This is the rectangle drawn by the user for selecting/zooming
|
// Returns the rubberBandBox DOM element. This is the rectangle drawn by the user for selecting/zooming
|
||||||
svgedit.select.SelectorManager.prototype.getRubberBandBox = function () {
|
svgedit.select.SelectorManager.prototype.getRubberBandBox = function () {
|
||||||
if (!this.rubberBandBox) {
|
if (!this.rubberBandBox) {
|
||||||
this.rubberBandBox = this.selectorParentGroup.appendChild(
|
this.rubberBandBox = this.selectorParentGroup.appendChild(
|
||||||
svgFactory_.createSVGElement({
|
svgFactory_.createSVGElement({
|
||||||
'element': 'rect',
|
'element': 'rect',
|
||||||
'attr': {
|
'attr': {
|
||||||
'id': 'selectorRubberBand',
|
'id': 'selectorRubberBand',
|
||||||
'fill': '#22C',
|
'fill': '#22C',
|
||||||
'fill-opacity': 0.15,
|
'fill-opacity': 0.15,
|
||||||
'stroke': '#22C',
|
'stroke': '#22C',
|
||||||
'stroke-width': 0.5,
|
'stroke-width': 0.5,
|
||||||
'display': 'none',
|
'display': 'none',
|
||||||
'style': 'pointer-events:none'
|
'style': 'pointer-events:none'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return this.rubberBandBox;
|
return this.rubberBandBox;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -519,9 +519,9 @@ svgedit.select.SelectorManager.prototype.getRubberBandBox = function () {
|
|||||||
* svgFactory - an object implementing the SVGFactory interface (see above).
|
* svgFactory - an object implementing the SVGFactory interface (see above).
|
||||||
*/
|
*/
|
||||||
svgedit.select.init = function (config, svgFactory) {
|
svgedit.select.init = function (config, svgFactory) {
|
||||||
config_ = config;
|
config_ = config;
|
||||||
svgFactory_ = svgFactory;
|
svgFactory_ = svgFactory;
|
||||||
selectorManager_ = new svgedit.select.SelectorManager();
|
selectorManager_ = new svgedit.select.SelectorManager();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -531,6 +531,6 @@ svgedit.select.init = function (config, svgFactory) {
|
|||||||
* The SelectorManager instance.
|
* The SelectorManager instance.
|
||||||
*/
|
*/
|
||||||
svgedit.select.getSelectorManager = function () {
|
svgedit.select.getSelectorManager = function () {
|
||||||
return selectorManager_;
|
return selectorManager_;
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
10282
editor/svg-editor.js
10282
editor/svg-editor.js
File diff suppressed because it is too large
Load Diff
10420
editor/svgcanvas.js
10420
editor/svgcanvas.js
File diff suppressed because it is too large
Load Diff
@@ -7,24 +7,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
svgedit = {
|
svgedit = {
|
||||||
// common namepaces constants in alpha order
|
// common namepaces constants in alpha order
|
||||||
NS: {
|
NS: {
|
||||||
HTML: 'http://www.w3.org/1999/xhtml',
|
HTML: 'http://www.w3.org/1999/xhtml',
|
||||||
MATH: 'http://www.w3.org/1998/Math/MathML',
|
MATH: 'http://www.w3.org/1998/Math/MathML',
|
||||||
SE: 'http://svg-edit.googlecode.com',
|
SE: 'http://svg-edit.googlecode.com',
|
||||||
SVG: 'http://www.w3.org/2000/svg',
|
SVG: 'http://www.w3.org/2000/svg',
|
||||||
XLINK: 'http://www.w3.org/1999/xlink',
|
XLINK: 'http://www.w3.org/1999/xlink',
|
||||||
XML: 'http://www.w3.org/XML/1998/namespace',
|
XML: 'http://www.w3.org/XML/1998/namespace',
|
||||||
XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved
|
XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// return the svgedit.NS with key values switched and lowercase
|
// return the svgedit.NS with key values switched and lowercase
|
||||||
svgedit.getReverseNS = function () {
|
svgedit.getReverseNS = function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
var reverseNS = {};
|
var reverseNS = {};
|
||||||
$.each(this.NS, function (name, URI) {
|
$.each(this.NS, function (name, URI) {
|
||||||
reverseNS[URI] = name.toLowerCase();
|
reverseNS[URI] = name.toLowerCase();
|
||||||
});
|
});
|
||||||
return reverseNS;
|
return reverseNS;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,41 +16,41 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.transformlist) {
|
if (!svgedit.transformlist) {
|
||||||
svgedit.transformlist = {};
|
svgedit.transformlist = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
|
var svgroot = document.createElementNS(svgedit.NS.SVG, 'svg');
|
||||||
|
|
||||||
// Helper function.
|
// Helper function.
|
||||||
function transformToString (xform) {
|
function transformToString (xform) {
|
||||||
var m = xform.matrix,
|
var m = xform.matrix,
|
||||||
text = '';
|
text = '';
|
||||||
switch (xform.type) {
|
switch (xform.type) {
|
||||||
case 1: // MATRIX
|
case 1: // MATRIX
|
||||||
text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
|
text = 'matrix(' + [m.a, m.b, m.c, m.d, m.e, m.f].join(',') + ')';
|
||||||
break;
|
break;
|
||||||
case 2: // TRANSLATE
|
case 2: // TRANSLATE
|
||||||
text = 'translate(' + m.e + ',' + m.f + ')';
|
text = 'translate(' + m.e + ',' + m.f + ')';
|
||||||
break;
|
break;
|
||||||
case 3: // SCALE
|
case 3: // SCALE
|
||||||
if (m.a === m.d) {
|
if (m.a === m.d) {
|
||||||
text = 'scale(' + m.a + ')';
|
text = 'scale(' + m.a + ')';
|
||||||
} else {
|
} else {
|
||||||
text = 'scale(' + m.a + ',' + m.d + ')';
|
text = 'scale(' + m.a + ',' + m.d + ')';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: // ROTATE
|
case 4: // ROTATE
|
||||||
var cx = 0, cy = 0;
|
var cx = 0, cy = 0;
|
||||||
// this prevents divide by zero
|
// this prevents divide by zero
|
||||||
if (xform.angle !== 0) {
|
if (xform.angle !== 0) {
|
||||||
var K = 1 - m.a;
|
var K = 1 - m.a;
|
||||||
cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);
|
cy = (K * m.f + m.b * m.e) / (K * K + m.b * m.b);
|
||||||
cx = (m.e - m.b * cy) / K;
|
cx = (m.e - m.b * cy) / K;
|
||||||
}
|
}
|
||||||
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
|
text = 'rotate(' + xform.angle + ' ' + cx + ',' + cy + ')';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,176 +78,176 @@ var listMap_ = {};
|
|||||||
// }
|
// }
|
||||||
// **************************************************************************************
|
// **************************************************************************************
|
||||||
svgedit.transformlist.SVGTransformList = function (elem) {
|
svgedit.transformlist.SVGTransformList = function (elem) {
|
||||||
this._elem = elem || null;
|
this._elem = elem || null;
|
||||||
this._xforms = [];
|
this._xforms = [];
|
||||||
// TODO: how do we capture the undo-ability in the changed transform list?
|
// TODO: how do we capture the undo-ability in the changed transform list?
|
||||||
this._update = function () {
|
this._update = function () {
|
||||||
var tstr = '';
|
var tstr = '';
|
||||||
/* var concatMatrix = */ svgroot.createSVGMatrix();
|
/* var concatMatrix = */ svgroot.createSVGMatrix();
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < this.numberOfItems; ++i) {
|
for (i = 0; i < this.numberOfItems; ++i) {
|
||||||
var xform = this._list.getItem(i);
|
var xform = this._list.getItem(i);
|
||||||
tstr += transformToString(xform) + ' ';
|
tstr += transformToString(xform) + ' ';
|
||||||
}
|
}
|
||||||
this._elem.setAttribute('transform', tstr);
|
this._elem.setAttribute('transform', tstr);
|
||||||
};
|
};
|
||||||
this._list = this;
|
this._list = this;
|
||||||
this._init = function () {
|
this._init = function () {
|
||||||
// Transform attribute parser
|
// Transform attribute parser
|
||||||
var str = this._elem.getAttribute('transform');
|
var str = this._elem.getAttribute('transform');
|
||||||
if (!str) { return; }
|
if (!str) { return; }
|
||||||
|
|
||||||
// TODO: Add skew support in future
|
// TODO: Add skew support in future
|
||||||
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
var re = /\s*((scale|matrix|rotate|translate)\s*\(.*?\))\s*,?\s*/;
|
||||||
var m = true;
|
var m = true;
|
||||||
while (m) {
|
while (m) {
|
||||||
m = str.match(re);
|
m = str.match(re);
|
||||||
str = str.replace(re, '');
|
str = str.replace(re, '');
|
||||||
if (m && m[1]) {
|
if (m && m[1]) {
|
||||||
var x = m[1];
|
var x = m[1];
|
||||||
var bits = x.split(/\s*\(/);
|
var bits = x.split(/\s*\(/);
|
||||||
var name = bits[0];
|
var name = bits[0];
|
||||||
var valBits = bits[1].match(/\s*(.*?)\s*\)/);
|
var valBits = bits[1].match(/\s*(.*?)\s*\)/);
|
||||||
valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
|
valBits[1] = valBits[1].replace(/(\d)-/g, '$1 -');
|
||||||
var valArr = valBits[1].split(/[, ]+/);
|
var valArr = valBits[1].split(/[, ]+/);
|
||||||
var letters = 'abcdef'.split('');
|
var letters = 'abcdef'.split('');
|
||||||
var mtx = svgroot.createSVGMatrix();
|
var mtx = svgroot.createSVGMatrix();
|
||||||
$.each(valArr, function (i, item) {
|
$.each(valArr, function (i, item) {
|
||||||
valArr[i] = parseFloat(item);
|
valArr[i] = parseFloat(item);
|
||||||
if (name === 'matrix') {
|
if (name === 'matrix') {
|
||||||
mtx[letters[i]] = valArr[i];
|
mtx[letters[i]] = valArr[i];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var xform = svgroot.createSVGTransform();
|
var xform = svgroot.createSVGTransform();
|
||||||
var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
|
var fname = 'set' + name.charAt(0).toUpperCase() + name.slice(1);
|
||||||
var values = name === 'matrix' ? [mtx] : valArr;
|
var values = name === 'matrix' ? [mtx] : valArr;
|
||||||
|
|
||||||
if (name === 'scale' && values.length === 1) {
|
if (name === 'scale' && values.length === 1) {
|
||||||
values.push(values[0]);
|
values.push(values[0]);
|
||||||
} else if (name === 'translate' && values.length === 1) {
|
} else if (name === 'translate' && values.length === 1) {
|
||||||
values.push(0);
|
values.push(0);
|
||||||
} else if (name === 'rotate' && values.length === 1) {
|
} else if (name === 'rotate' && values.length === 1) {
|
||||||
values.push(0, 0);
|
values.push(0, 0);
|
||||||
}
|
}
|
||||||
xform[fname].apply(xform, values);
|
xform[fname].apply(xform, values);
|
||||||
this._list.appendItem(xform);
|
this._list.appendItem(xform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this._removeFromOtherLists = function (item) {
|
this._removeFromOtherLists = function (item) {
|
||||||
if (item) {
|
if (item) {
|
||||||
// Check if this transform is already in a transformlist, and
|
// Check if this transform is already in a transformlist, and
|
||||||
// remove it if so.
|
// remove it if so.
|
||||||
var found = false;
|
var found = false;
|
||||||
var id;
|
var id;
|
||||||
for (id in listMap_) {
|
for (id in listMap_) {
|
||||||
var tl = listMap_[id];
|
var tl = listMap_[id];
|
||||||
var i, len;
|
var i, len;
|
||||||
for (i = 0, len = tl._xforms.length; i < len; ++i) {
|
for (i = 0, len = tl._xforms.length; i < len; ++i) {
|
||||||
if (tl._xforms[i] === item) {
|
if (tl._xforms[i] === item) {
|
||||||
found = true;
|
found = true;
|
||||||
tl.removeItem(i);
|
tl.removeItem(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.numberOfItems = 0;
|
this.numberOfItems = 0;
|
||||||
this.clear = function () {
|
this.clear = function () {
|
||||||
this.numberOfItems = 0;
|
this.numberOfItems = 0;
|
||||||
this._xforms = [];
|
this._xforms = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initialize = function (newItem) {
|
this.initialize = function (newItem) {
|
||||||
this.numberOfItems = 1;
|
this.numberOfItems = 1;
|
||||||
this._removeFromOtherLists(newItem);
|
this._removeFromOtherLists(newItem);
|
||||||
this._xforms = [newItem];
|
this._xforms = [newItem];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getItem = function (index) {
|
this.getItem = function (index) {
|
||||||
if (index < this.numberOfItems && index >= 0) {
|
if (index < this.numberOfItems && index >= 0) {
|
||||||
return this._xforms[index];
|
return this._xforms[index];
|
||||||
}
|
}
|
||||||
var err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
var err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
||||||
err.code = 1;
|
err.code = 1;
|
||||||
throw err;
|
throw err;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.insertItemBefore = function (newItem, index) {
|
this.insertItemBefore = function (newItem, index) {
|
||||||
var retValue = null;
|
var retValue = null;
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
if (index < this.numberOfItems) {
|
if (index < this.numberOfItems) {
|
||||||
this._removeFromOtherLists(newItem);
|
this._removeFromOtherLists(newItem);
|
||||||
var newxforms = new Array(this.numberOfItems + 1);
|
var newxforms = new Array(this.numberOfItems + 1);
|
||||||
// TODO: use array copying and slicing
|
// TODO: use array copying and slicing
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < index; ++i) {
|
for (i = 0; i < index; ++i) {
|
||||||
newxforms[i] = this._xforms[i];
|
newxforms[i] = this._xforms[i];
|
||||||
}
|
}
|
||||||
newxforms[i] = newItem;
|
newxforms[i] = newItem;
|
||||||
var j;
|
var j;
|
||||||
for (j = i + 1; i < this.numberOfItems; ++j, ++i) {
|
for (j = i + 1; i < this.numberOfItems; ++j, ++i) {
|
||||||
newxforms[j] = this._xforms[i];
|
newxforms[j] = this._xforms[i];
|
||||||
}
|
}
|
||||||
this.numberOfItems++;
|
this.numberOfItems++;
|
||||||
this._xforms = newxforms;
|
this._xforms = newxforms;
|
||||||
retValue = newItem;
|
retValue = newItem;
|
||||||
this._list._update();
|
this._list._update();
|
||||||
} else {
|
} else {
|
||||||
retValue = this._list.appendItem(newItem);
|
retValue = this._list.appendItem(newItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return retValue;
|
return retValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.replaceItem = function (newItem, index) {
|
this.replaceItem = function (newItem, index) {
|
||||||
var retValue = null;
|
var retValue = null;
|
||||||
if (index < this.numberOfItems && index >= 0) {
|
if (index < this.numberOfItems && index >= 0) {
|
||||||
this._removeFromOtherLists(newItem);
|
this._removeFromOtherLists(newItem);
|
||||||
this._xforms[index] = newItem;
|
this._xforms[index] = newItem;
|
||||||
retValue = newItem;
|
retValue = newItem;
|
||||||
this._list._update();
|
this._list._update();
|
||||||
}
|
}
|
||||||
return retValue;
|
return retValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.removeItem = function (index) {
|
this.removeItem = function (index) {
|
||||||
if (index < this.numberOfItems && index >= 0) {
|
if (index < this.numberOfItems && index >= 0) {
|
||||||
var retValue = this._xforms[index];
|
var retValue = this._xforms[index];
|
||||||
var newxforms = new Array(this.numberOfItems - 1);
|
var newxforms = new Array(this.numberOfItems - 1);
|
||||||
var i, j;
|
var i, j;
|
||||||
for (i = 0; i < index; ++i) {
|
for (i = 0; i < index; ++i) {
|
||||||
newxforms[i] = this._xforms[i];
|
newxforms[i] = this._xforms[i];
|
||||||
}
|
}
|
||||||
for (j = i; j < this.numberOfItems - 1; ++j, ++i) {
|
for (j = i; j < this.numberOfItems - 1; ++j, ++i) {
|
||||||
newxforms[j] = this._xforms[i + 1];
|
newxforms[j] = this._xforms[i + 1];
|
||||||
}
|
}
|
||||||
this.numberOfItems--;
|
this.numberOfItems--;
|
||||||
this._xforms = newxforms;
|
this._xforms = newxforms;
|
||||||
this._list._update();
|
this._list._update();
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
var err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
var err = new Error('DOMException with code=INDEX_SIZE_ERR');
|
||||||
err.code = 1;
|
err.code = 1;
|
||||||
throw err;
|
throw err;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.appendItem = function (newItem) {
|
this.appendItem = function (newItem) {
|
||||||
this._removeFromOtherLists(newItem);
|
this._removeFromOtherLists(newItem);
|
||||||
this._xforms.push(newItem);
|
this._xforms.push(newItem);
|
||||||
this.numberOfItems++;
|
this.numberOfItems++;
|
||||||
this._list._update();
|
this._list._update();
|
||||||
return newItem;
|
return newItem;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
svgedit.transformlist.resetListMap = function () {
|
svgedit.transformlist.resetListMap = function () {
|
||||||
listMap_ = {};
|
listMap_ = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,9 +256,9 @@ svgedit.transformlist.resetListMap = function () {
|
|||||||
* elem - a DOM Element
|
* elem - a DOM Element
|
||||||
*/
|
*/
|
||||||
svgedit.transformlist.removeElementFromListMap = function (elem) {
|
svgedit.transformlist.removeElementFromListMap = function (elem) {
|
||||||
if (elem.id && listMap_[elem.id]) {
|
if (elem.id && listMap_[elem.id]) {
|
||||||
delete listMap_[elem.id];
|
delete listMap_[elem.id];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: getTransformList
|
// Function: getTransformList
|
||||||
@@ -267,26 +267,26 @@ svgedit.transformlist.removeElementFromListMap = function (elem) {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// elem - DOM element to get a transformlist from
|
// elem - DOM element to get a transformlist from
|
||||||
svgedit.transformlist.getTransformList = function (elem) {
|
svgedit.transformlist.getTransformList = function (elem) {
|
||||||
if (!svgedit.browser.supportsNativeTransformLists()) {
|
if (!svgedit.browser.supportsNativeTransformLists()) {
|
||||||
var id = elem.id || 'temp';
|
var id = elem.id || 'temp';
|
||||||
var t = listMap_[id];
|
var t = listMap_[id];
|
||||||
if (!t || id === 'temp') {
|
if (!t || id === 'temp') {
|
||||||
listMap_[id] = new svgedit.transformlist.SVGTransformList(elem);
|
listMap_[id] = new svgedit.transformlist.SVGTransformList(elem);
|
||||||
listMap_[id]._init();
|
listMap_[id]._init();
|
||||||
t = listMap_[id];
|
t = listMap_[id];
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
if (elem.transform) {
|
if (elem.transform) {
|
||||||
return elem.transform.baseVal;
|
return elem.transform.baseVal;
|
||||||
}
|
}
|
||||||
if (elem.gradientTransform) {
|
if (elem.gradientTransform) {
|
||||||
return elem.gradientTransform.baseVal;
|
return elem.gradientTransform.baseVal;
|
||||||
}
|
}
|
||||||
if (elem.patternTransform) {
|
if (elem.patternTransform) {
|
||||||
return elem.patternTransform.baseVal;
|
return elem.patternTransform.baseVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
1782
editor/svgutils.js
1782
editor/svgutils.js
File diff suppressed because it is too large
Load Diff
@@ -1,32 +1,32 @@
|
|||||||
/* eslint-disable no-var */
|
/* eslint-disable no-var */
|
||||||
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
|
// http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript/
|
||||||
function touchHandler (event) {
|
function touchHandler (event) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var simulatedEvent,
|
var simulatedEvent,
|
||||||
touches = event.changedTouches,
|
touches = event.changedTouches,
|
||||||
first = touches[0],
|
first = touches[0],
|
||||||
type = '';
|
type = '';
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case 'touchstart': type = 'mousedown'; break;
|
case 'touchstart': type = 'mousedown'; break;
|
||||||
case 'touchmove': type = 'mousemove'; break;
|
case 'touchmove': type = 'mousemove'; break;
|
||||||
case 'touchend': type = 'mouseup'; break;
|
case 'touchend': type = 'mouseup'; break;
|
||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initMouseEvent(type, canBubble, cancelable, view, clickCount,
|
// initMouseEvent(type, canBubble, cancelable, view, clickCount,
|
||||||
// screenX, screenY, clientX, clientY, ctrlKey,
|
// screenX, screenY, clientX, clientY, ctrlKey,
|
||||||
// altKey, shiftKey, metaKey, button, relatedTarget);
|
// altKey, shiftKey, metaKey, button, relatedTarget);
|
||||||
|
|
||||||
simulatedEvent = document.createEvent('MouseEvent');
|
simulatedEvent = document.createEvent('MouseEvent');
|
||||||
simulatedEvent.initMouseEvent(type, true, true, window, 1,
|
simulatedEvent.initMouseEvent(type, true, true, window, 1,
|
||||||
first.screenX, first.screenY,
|
first.screenX, first.screenY,
|
||||||
first.clientX, first.clientY, false,
|
first.clientX, first.clientY, false,
|
||||||
false, false, false, 0/* left */, null);
|
false, false, false, 0/* left */, null);
|
||||||
if (touches.length < 2) {
|
if (touches.length < 2) {
|
||||||
first.target.dispatchEvent(simulatedEvent);
|
first.target.dispatchEvent(simulatedEvent);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('touchstart', touchHandler, true);
|
document.addEventListener('touchstart', touchHandler, true);
|
||||||
|
|||||||
310
editor/units.js
310
editor/units.js
@@ -16,7 +16,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
if (!svgedit.units) {
|
if (!svgedit.units) {
|
||||||
svgedit.units = {};
|
svgedit.units = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
var NS = svgedit.NS;
|
var NS = svgedit.NS;
|
||||||
@@ -26,15 +26,15 @@ var unitAttrs = ['r', 'radius'].concat(wAttrs, hAttrs);
|
|||||||
// unused
|
// unused
|
||||||
/*
|
/*
|
||||||
var unitNumMap = {
|
var unitNumMap = {
|
||||||
'%': 2,
|
'%': 2,
|
||||||
'em': 3,
|
'em': 3,
|
||||||
'ex': 4,
|
'ex': 4,
|
||||||
'px': 5,
|
'px': 5,
|
||||||
'cm': 6,
|
'cm': 6,
|
||||||
'mm': 7,
|
'mm': 7,
|
||||||
'in': 8,
|
'in': 8,
|
||||||
'pt': 9,
|
'pt': 9,
|
||||||
'pc': 10
|
'pc': 10
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
// Container of elements.
|
// Container of elements.
|
||||||
@@ -63,31 +63,31 @@ var typeMap_ = {};
|
|||||||
* elementContainer - an object implementing the ElementContainer interface.
|
* elementContainer - an object implementing the ElementContainer interface.
|
||||||
*/
|
*/
|
||||||
svgedit.units.init = function (elementContainer) {
|
svgedit.units.init = function (elementContainer) {
|
||||||
elementContainer_ = elementContainer;
|
elementContainer_ = elementContainer;
|
||||||
|
|
||||||
// Get correct em/ex values by creating a temporary SVG.
|
// Get correct em/ex values by creating a temporary SVG.
|
||||||
var svg = document.createElementNS(NS.SVG, 'svg');
|
var svg = document.createElementNS(NS.SVG, 'svg');
|
||||||
document.body.appendChild(svg);
|
document.body.appendChild(svg);
|
||||||
var rect = document.createElementNS(NS.SVG, 'rect');
|
var rect = document.createElementNS(NS.SVG, 'rect');
|
||||||
rect.setAttribute('width', '1em');
|
rect.setAttribute('width', '1em');
|
||||||
rect.setAttribute('height', '1ex');
|
rect.setAttribute('height', '1ex');
|
||||||
rect.setAttribute('x', '1in');
|
rect.setAttribute('x', '1in');
|
||||||
svg.appendChild(rect);
|
svg.appendChild(rect);
|
||||||
var bb = rect.getBBox();
|
var bb = rect.getBBox();
|
||||||
document.body.removeChild(svg);
|
document.body.removeChild(svg);
|
||||||
|
|
||||||
var inch = bb.x;
|
var inch = bb.x;
|
||||||
typeMap_ = {
|
typeMap_ = {
|
||||||
'em': bb.width,
|
'em': bb.width,
|
||||||
'ex': bb.height,
|
'ex': bb.height,
|
||||||
'in': inch,
|
'in': inch,
|
||||||
'cm': inch / 2.54,
|
'cm': inch / 2.54,
|
||||||
'mm': inch / 25.4,
|
'mm': inch / 25.4,
|
||||||
'pt': inch / 72,
|
'pt': inch / 72,
|
||||||
'pc': inch / 6,
|
'pc': inch / 6,
|
||||||
'px': 1,
|
'px': 1,
|
||||||
'%': 0
|
'%': 0
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Group: Unit conversion functions
|
// Group: Unit conversion functions
|
||||||
@@ -95,7 +95,7 @@ svgedit.units.init = function (elementContainer) {
|
|||||||
// Function: svgedit.units.getTypeMap
|
// Function: svgedit.units.getTypeMap
|
||||||
// Returns the unit object with values for each unit
|
// Returns the unit object with values for each unit
|
||||||
svgedit.units.getTypeMap = function () {
|
svgedit.units.getTypeMap = function () {
|
||||||
return typeMap_;
|
return typeMap_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.shortFloat
|
// Function: svgedit.units.shortFloat
|
||||||
@@ -108,25 +108,25 @@ svgedit.units.getTypeMap = function () {
|
|||||||
// If a string/number was given, returns a Float. If an array, return a string
|
// If a string/number was given, returns a Float. If an array, return a string
|
||||||
// with comma-separated floats
|
// with comma-separated floats
|
||||||
svgedit.units.shortFloat = function (val) {
|
svgedit.units.shortFloat = function (val) {
|
||||||
var digits = elementContainer_.getRoundDigits();
|
var digits = elementContainer_.getRoundDigits();
|
||||||
if (!isNaN(val)) {
|
if (!isNaN(val)) {
|
||||||
// Note that + converts to Number
|
// Note that + converts to Number
|
||||||
return +((+val).toFixed(digits));
|
return +((+val).toFixed(digits));
|
||||||
}
|
}
|
||||||
if ($.isArray(val)) {
|
if ($.isArray(val)) {
|
||||||
return svgedit.units.shortFloat(val[0]) + ',' + svgedit.units.shortFloat(val[1]);
|
return svgedit.units.shortFloat(val[0]) + ',' + svgedit.units.shortFloat(val[1]);
|
||||||
}
|
}
|
||||||
return parseFloat(val).toFixed(digits) - 0;
|
return parseFloat(val).toFixed(digits) - 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.convertUnit
|
// Function: svgedit.units.convertUnit
|
||||||
// Converts the number to given unit or baseUnit
|
// Converts the number to given unit or baseUnit
|
||||||
svgedit.units.convertUnit = function (val, unit) {
|
svgedit.units.convertUnit = function (val, unit) {
|
||||||
unit = unit || elementContainer_.getBaseUnit();
|
unit = unit || elementContainer_.getBaseUnit();
|
||||||
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
|
// baseVal.convertToSpecifiedUnits(unitNumMap[unit]);
|
||||||
// var val = baseVal.valueInSpecifiedUnits;
|
// var val = baseVal.valueInSpecifiedUnits;
|
||||||
// baseVal.convertToSpecifiedUnits(1);
|
// baseVal.convertToSpecifiedUnits(1);
|
||||||
return svgedit.units.shortFloat(val / typeMap_[unit]);
|
return svgedit.units.shortFloat(val / typeMap_[unit]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.setUnitAttr
|
// Function: svgedit.units.setUnitAttr
|
||||||
@@ -137,49 +137,49 @@ svgedit.units.convertUnit = function (val, unit) {
|
|||||||
// attr - String with the name of the attribute associated with the value
|
// attr - String with the name of the attribute associated with the value
|
||||||
// val - String with the attribute value to convert
|
// val - String with the attribute value to convert
|
||||||
svgedit.units.setUnitAttr = function (elem, attr, val) {
|
svgedit.units.setUnitAttr = function (elem, attr, val) {
|
||||||
// if (!isNaN(val)) {
|
// if (!isNaN(val)) {
|
||||||
// New value is a number, so check currently used unit
|
// New value is a number, so check currently used unit
|
||||||
// var old_val = elem.getAttribute(attr);
|
// var old_val = elem.getAttribute(attr);
|
||||||
|
|
||||||
// Enable this for alternate mode
|
// Enable this for alternate mode
|
||||||
// if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) {
|
// if (old_val !== null && (isNaN(old_val) || elementContainer_.getBaseUnit() !== 'px')) {
|
||||||
// // Old value was a number, so get unit, then convert
|
// // Old value was a number, so get unit, then convert
|
||||||
// var unit;
|
// var unit;
|
||||||
// if (old_val.substr(-1) === '%') {
|
// if (old_val.substr(-1) === '%') {
|
||||||
// var res = getResolution();
|
// var res = getResolution();
|
||||||
// unit = '%';
|
// unit = '%';
|
||||||
// val *= 100;
|
// val *= 100;
|
||||||
// if (wAttrs.indexOf(attr) >= 0) {
|
// if (wAttrs.indexOf(attr) >= 0) {
|
||||||
// val = val / res.w;
|
// val = val / res.w;
|
||||||
// } else if (hAttrs.indexOf(attr) >= 0) {
|
// } else if (hAttrs.indexOf(attr) >= 0) {
|
||||||
// val = val / res.h;
|
// val = val / res.h;
|
||||||
// } else {
|
// } else {
|
||||||
// return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
|
// return val / Math.sqrt((res.w*res.w) + (res.h*res.h))/Math.sqrt(2);
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
// if (elementContainer_.getBaseUnit() !== 'px') {
|
// if (elementContainer_.getBaseUnit() !== 'px') {
|
||||||
// unit = elementContainer_.getBaseUnit();
|
// unit = elementContainer_.getBaseUnit();
|
||||||
// } else {
|
// } else {
|
||||||
// unit = old_val.substr(-2);
|
// unit = old_val.substr(-2);
|
||||||
// }
|
// }
|
||||||
// val = val / typeMap_[unit];
|
// val = val / typeMap_[unit];
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// val += unit;
|
// val += unit;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
elem.setAttribute(attr, val);
|
elem.setAttribute(attr, val);
|
||||||
};
|
};
|
||||||
|
|
||||||
var attrsToConvert = {
|
var attrsToConvert = {
|
||||||
'line': ['x1', 'x2', 'y1', 'y2'],
|
'line': ['x1', 'x2', 'y1', 'y2'],
|
||||||
'circle': ['cx', 'cy', 'r'],
|
'circle': ['cx', 'cy', 'r'],
|
||||||
'ellipse': ['cx', 'cy', 'rx', 'ry'],
|
'ellipse': ['cx', 'cy', 'rx', 'ry'],
|
||||||
'foreignObject': ['x', 'y', 'width', 'height'],
|
'foreignObject': ['x', 'y', 'width', 'height'],
|
||||||
'rect': ['x', 'y', 'width', 'height'],
|
'rect': ['x', 'y', 'width', 'height'],
|
||||||
'image': ['x', 'y', 'width', 'height'],
|
'image': ['x', 'y', 'width', 'height'],
|
||||||
'use': ['x', 'y', 'width', 'height'],
|
'use': ['x', 'y', 'width', 'height'],
|
||||||
'text': ['x', 'y']
|
'text': ['x', 'y']
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.convertAttrs
|
// Function: svgedit.units.convertAttrs
|
||||||
@@ -188,25 +188,25 @@ var attrsToConvert = {
|
|||||||
// Parameters:
|
// Parameters:
|
||||||
// element - a DOM element whose attributes should be converted
|
// element - a DOM element whose attributes should be converted
|
||||||
svgedit.units.convertAttrs = function (element) {
|
svgedit.units.convertAttrs = function (element) {
|
||||||
var elName = element.tagName;
|
var elName = element.tagName;
|
||||||
var unit = elementContainer_.getBaseUnit();
|
var unit = elementContainer_.getBaseUnit();
|
||||||
var attrs = attrsToConvert[elName];
|
var attrs = attrsToConvert[elName];
|
||||||
if (!attrs) { return; }
|
if (!attrs) { return; }
|
||||||
|
|
||||||
var len = attrs.length;
|
var len = attrs.length;
|
||||||
var i;
|
var i;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
var attr = attrs[i];
|
var attr = attrs[i];
|
||||||
var cur = element.getAttribute(attr);
|
var cur = element.getAttribute(attr);
|
||||||
if (cur) {
|
if (cur) {
|
||||||
if (!isNaN(cur)) {
|
if (!isNaN(cur)) {
|
||||||
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
|
element.setAttribute(attr, (cur / typeMap_[unit]) + unit);
|
||||||
}
|
}
|
||||||
// else {
|
// else {
|
||||||
// Convert existing?
|
// Convert existing?
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.convertToNum
|
// Function: svgedit.units.convertToNum
|
||||||
@@ -217,27 +217,27 @@ svgedit.units.convertAttrs = function (element) {
|
|||||||
// attr - String with the name of the attribute associated with the value
|
// attr - String with the name of the attribute associated with the value
|
||||||
// val - String with the attribute value to convert
|
// val - String with the attribute value to convert
|
||||||
svgedit.units.convertToNum = function (attr, val) {
|
svgedit.units.convertToNum = function (attr, val) {
|
||||||
// Return a number if that's what it already is
|
// Return a number if that's what it already is
|
||||||
if (!isNaN(val)) { return val - 0; }
|
if (!isNaN(val)) { return val - 0; }
|
||||||
var num;
|
var num;
|
||||||
if (val.substr(-1) === '%') {
|
if (val.substr(-1) === '%') {
|
||||||
// Deal with percentage, depends on attribute
|
// Deal with percentage, depends on attribute
|
||||||
num = val.substr(0, val.length - 1) / 100;
|
num = val.substr(0, val.length - 1) / 100;
|
||||||
var width = elementContainer_.getWidth();
|
var width = elementContainer_.getWidth();
|
||||||
var height = elementContainer_.getHeight();
|
var height = elementContainer_.getHeight();
|
||||||
|
|
||||||
if (wAttrs.indexOf(attr) >= 0) {
|
if (wAttrs.indexOf(attr) >= 0) {
|
||||||
return num * width;
|
return num * width;
|
||||||
}
|
}
|
||||||
if (hAttrs.indexOf(attr) >= 0) {
|
if (hAttrs.indexOf(attr) >= 0) {
|
||||||
return num * height;
|
return num * height;
|
||||||
}
|
}
|
||||||
return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);
|
return num * Math.sqrt((width * width) + (height * height)) / Math.sqrt(2);
|
||||||
}
|
}
|
||||||
var unit = val.substr(-2);
|
var unit = val.substr(-2);
|
||||||
num = val.substr(0, val.length - 2);
|
num = val.substr(0, val.length - 2);
|
||||||
// Note that this multiplication turns the string into a number
|
// Note that this multiplication turns the string into a number
|
||||||
return num * typeMap_[unit];
|
return num * typeMap_[unit];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Function: svgedit.units.isValidUnit
|
// Function: svgedit.units.isValidUnit
|
||||||
@@ -247,37 +247,37 @@ svgedit.units.convertToNum = function (attr, val) {
|
|||||||
// attr - String with the name of the attribute associated with the value
|
// attr - String with the name of the attribute associated with the value
|
||||||
// val - String with the attribute value to check
|
// val - String with the attribute value to check
|
||||||
svgedit.units.isValidUnit = function (attr, val, selectedElement) {
|
svgedit.units.isValidUnit = function (attr, val, selectedElement) {
|
||||||
var valid = false;
|
var valid = false;
|
||||||
if (unitAttrs.indexOf(attr) >= 0) {
|
if (unitAttrs.indexOf(attr) >= 0) {
|
||||||
// True if it's just a number
|
// True if it's just a number
|
||||||
if (!isNaN(val)) {
|
if (!isNaN(val)) {
|
||||||
valid = true;
|
valid = true;
|
||||||
} else {
|
} else {
|
||||||
// Not a number, check if it has a valid unit
|
// Not a number, check if it has a valid unit
|
||||||
val = val.toLowerCase();
|
val = val.toLowerCase();
|
||||||
$.each(typeMap_, function (unit) {
|
$.each(typeMap_, function (unit) {
|
||||||
if (valid) { return; }
|
if (valid) { return; }
|
||||||
var re = new RegExp('^-?[\\d\\.]+' + unit + '$');
|
var re = new RegExp('^-?[\\d\\.]+' + unit + '$');
|
||||||
if (re.test(val)) { valid = true; }
|
if (re.test(val)) { valid = true; }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (attr === 'id') {
|
} else if (attr === 'id') {
|
||||||
// if we're trying to change the id, make sure it's not already present in the doc
|
// if we're trying to change the id, make sure it's not already present in the doc
|
||||||
// and the id value is valid.
|
// and the id value is valid.
|
||||||
|
|
||||||
var result = false;
|
var result = false;
|
||||||
// because getElem() can throw an exception in the case of an invalid id
|
// because getElem() can throw an exception in the case of an invalid id
|
||||||
// (according to http://www.w3.org/TR/xml-id/ IDs must be a NCName)
|
// (according to http://www.w3.org/TR/xml-id/ IDs must be a NCName)
|
||||||
// we wrap it in an exception and only return true if the ID was valid and
|
// we wrap it in an exception and only return true if the ID was valid and
|
||||||
// not already present
|
// not already present
|
||||||
try {
|
try {
|
||||||
var elem = elementContainer_.getElement(val);
|
var elem = elementContainer_.getElement(val);
|
||||||
result = (elem == null || elem === selectedElement);
|
result = (elem == null || elem === selectedElement);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
valid = true;
|
valid = true;
|
||||||
|
|
||||||
return valid;
|
return valid;
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|||||||
Reference in New Issue
Block a user