Commit 4a6de9e8 authored by Vincent Bechu's avatar Vincent Bechu

[erp5_web_editor_svgedit] Add svgedit

From https://github.com/SVG-Edit/svgedit
parent af3fb549
<registered_skin_selection>
<skin_folder_selection>
<skin_folder>erp5_web_editor_svgedit</skin_folder>
<skin_selection>RJS,View</skin_selection>
</skin_folder_selection>
</registered_skin_selection>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_web_editor_svgedit</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>svgedit</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1"/>
<link rel="icon" type="image/png" href="images/logo.png"/>
<link rel="stylesheet" href="svg-editor.css" type="text/css"/>
<script src="jquery.js"></script>
<title>Browser does not support SVG | SVG-edit</title>
</head>
<body>
<div id="browser-not-supported">
<img style="float:left;padding:10px;" src="images/logo.png" width="48" height="48" alt="SVG-edit logo" /><br />
<p>Sorry, but your browser does not support SVG. Below is a list of alternate browsers and versions that support SVG and SVG-edit (from <a href="http://caniuse.com/#cats=SVG">caniuse.com</a>).</p>
<p>Try the latest version of <a href="http://www.getfirefox.com">Firefox</a>, <a href="http://www.google.com/chrome/">Google Chrome</a>, <a href="http://www.apple.com/safari/download/">Safari</a>, <a href="http://www.opera.com/download/">Opera</a> or <a href="http://windows.microsoft.com/ie9">Internet Explorer</a>.</p>
<p>If you are unable to install one of these and must use an old version of Internet Explorer, you can install the <a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame plugin</a>.</p>
</div>
<script>
/*globals $*/
var viewportHeight = window.innerHeight || ($(window).height() - 140);
var iframe = document.createElement('iframe');
iframe.style.width = '100%';
iframe.style.height = viewportHeight + 'px';
iframe.src = 'http://caniuse.com/#cats=SVG';
document.body.appendChild(iframe);
</script>
</body>
</html>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>browser-not-supported.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals $, svgedit*/
/*jslint vars: true, eqeq: true*/
/**
* Package: svgedit.browser
*
* Licensed under the MIT License
*
* Copyright(c) 2010 Jeff Schiller
* Copyright(c) 2010 Alexis Deveria
*/
// Dependencies:
// 1) jQuery (for $.alert())
(function() {'use strict';
if (!svgedit.browser) {
svgedit.browser = {};
}
// alias
var NS = svgedit.NS;
var supportsSvg_ = (function() {
return !!document.createElementNS && !!document.createElementNS(NS.SVG, 'svg').createSVGRect;
}());
svgedit.browser.supportsSvg = function() { return supportsSvg_; };
if(!svgedit.browser.supportsSvg()) {
window.location = 'browser-not-supported.html';
return;
}
var userAgent = navigator.userAgent;
var svg = document.createElementNS(NS.SVG, 'svg');
// Note: Browser sniffing should only be used if no other detection method is possible
var isOpera_ = !!window.opera;
var isWebkit_ = userAgent.indexOf('AppleWebKit') >= 0;
var isGecko_ = userAgent.indexOf('Gecko/') >= 0;
var isIE_ = userAgent.indexOf('MSIE') >= 0;
var isChrome_ = userAgent.indexOf('Chrome/') >= 0;
var isWindows_ = userAgent.indexOf('Windows') >= 0;
var isMac_ = userAgent.indexOf('Macintosh') >= 0;
var isTouch_ = 'ontouchstart' in window;
var supportsSelectors_ = (function() {
return !!svg.querySelector;
}());
var supportsXpath_ = (function() {
return !!document.evaluate;
}());
// segList functions (for FF1.5 and 2.0)
var supportsPathReplaceItem_ = (function() {
var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 10,10');
var seglist = path.pathSegList;
var seg = path.createSVGPathSegLinetoAbs(5,5);
try {
seglist.replaceItem(seg, 1);
return true;
} catch(err) {}
return false;
}());
var supportsPathInsertItemBefore_ = (function() {
var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 10,10');
var seglist = path.pathSegList;
var seg = path.createSVGPathSegLinetoAbs(5,5);
try {
seglist.insertItemBefore(seg, 1);
return true;
} catch(err) {}
return false;
}());
// text character positioning (for IE9)
var supportsGoodTextCharPos_ = (function() {
var svgroot = document.createElementNS(NS.SVG, 'svg');
var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgroot);
svgcontent.setAttribute('x', 5);
svgroot.appendChild(svgcontent);
var text = document.createElementNS(NS.SVG, 'text');
text.textContent = 'a';
svgcontent.appendChild(text);
var pos = text.getStartPositionOfChar(0).x;
document.documentElement.removeChild(svgroot);
return (pos === 0);
}());
var supportsPathBBox_ = (function() {
var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgcontent);
var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 C0,0 10,10 10,0');
svgcontent.appendChild(path);
var bbox = path.getBBox();
document.documentElement.removeChild(svgcontent);
return (bbox.height > 4 && bbox.height < 5);
}());
// Support for correct bbox sizing on groups with horizontal/vertical lines
var supportsHVLineContainerBBox_ = (function() {
var svgcontent = document.createElementNS(NS.SVG, 'svg');
document.documentElement.appendChild(svgcontent);
var path = document.createElementNS(NS.SVG, 'path');
path.setAttribute('d', 'M0,0 10,0');
var path2 = document.createElementNS(NS.SVG, 'path');
path2.setAttribute('d', 'M5,0 15,0');
var g = document.createElementNS(NS.SVG, 'g');
g.appendChild(path);
g.appendChild(path2);
svgcontent.appendChild(g);
var bbox = g.getBBox();
document.documentElement.removeChild(svgcontent);
// Webkit gives 0, FF gives 10, Opera (correctly) gives 15
return (bbox.width == 15);
}());
var supportsEditableText_ = (function() {
// TODO: Find better way to check support for this
return isOpera_;
}());
var supportsGoodDecimals_ = (function() {
// Correct decimals on clone attributes (Opera < 10.5/win/non-en)
var rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('x', 0.1);
var crect = rect.cloneNode(false);
var retValue = (crect.getAttribute('x').indexOf(',') == -1);
if(!retValue) {
$.alert('NOTE: This version of Opera is known to contain bugs in SVG-edit.\n'+
'Please upgrade to the <a href="http://opera.com">latest version</a> in which the problems have been fixed.');
}
return retValue;
}());
var supportsNonScalingStroke_ = (function() {
var rect = document.createElementNS(NS.SVG, 'rect');
rect.setAttribute('style', 'vector-effect:non-scaling-stroke');
return rect.style.vectorEffect === 'non-scaling-stroke';
}());
var supportsNativeSVGTransformLists_ = (function() {
var rect = document.createElementNS(NS.SVG, 'rect');
var rxform = rect.transform.baseVal;
var t1 = svg.createSVGTransform();
rxform.appendItem(t1);
return rxform.getItem(0) == t1;
}());
// Public API
svgedit.browser.isOpera = function() { return isOpera_; };
svgedit.browser.isWebkit = function() { return isWebkit_; };
svgedit.browser.isGecko = function() { return isGecko_; };
svgedit.browser.isIE = function() { return isIE_; };
svgedit.browser.isChrome = function() { return isChrome_; };
svgedit.browser.isWindows = function() { return isWindows_; };
svgedit.browser.isMac = function() { return isMac_; };
svgedit.browser.isTouch = function() { return isTouch_; };
svgedit.browser.supportsSelectors = function() { return supportsSelectors_; };
svgedit.browser.supportsXpath = function() { return supportsXpath_; };
svgedit.browser.supportsPathReplaceItem = function() { return supportsPathReplaceItem_; };
svgedit.browser.supportsPathInsertItemBefore = function() { return supportsPathInsertItemBefore_; };
svgedit.browser.supportsPathBBox = function() { return supportsPathBBox_; };
svgedit.browser.supportsHVLineContainerBBox = function() { return supportsHVLineContainerBBox_; };
svgedit.browser.supportsGoodTextCharPos = function() { return supportsGoodTextCharPos_; };
svgedit.browser.supportsEditableText = function() { return supportsEditableText_; };
svgedit.browser.supportsGoodDecimals = function() { return supportsGoodDecimals_; };
svgedit.browser.supportsNonScalingStroke = function() { return supportsNonScalingStroke_; };
svgedit.browser.supportsNativeTransformLists = function() { return supportsNativeSVGTransformLists_; };
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>browser.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>canvg</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>canvg.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*jslint vars: true*/
/**
* A class to parse color values
* @author Stoyan Stefanov <sstoo@gmail.com>
* @link http://www.phpied.com/rgb-color-parser-in-javascript/
* @license Use it if you like it
*/
function RGBColor(color_string) { 'use strict';
this.ok = false;
// strip any leading #
if (color_string.charAt(0) === '#') { // remove # if any
color_string = color_string.substr(1,6);
}
color_string = color_string.replace(/ /g,'');
color_string = color_string.toLowerCase();
// before getting into regexps, try simple matches
// and overwrite the input
var simple_colors = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred : 'cd5c5c',
indigo : '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
var key;
for (key in simple_colors) {
if (simple_colors.hasOwnProperty(key)) {
if (color_string == key) {
color_string = simple_colors[key];
}
}
}
// emd of simple type-in colors
// array of color definition objects
var color_defs = [
{
re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
process: function (bits){
return [
parseInt(bits[1], 10),
parseInt(bits[2], 10),
parseInt(bits[3], 10)
];
}
},
{
re: /^(\w{2})(\w{2})(\w{2})$/,
example: ['#00ff00', '336699'],
process: function (bits){
return [
parseInt(bits[1], 16),
parseInt(bits[2], 16),
parseInt(bits[3], 16)
];
}
},
{
re: /^(\w{1})(\w{1})(\w{1})$/,
example: ['#fb0', 'f0f'],
process: function (bits){
return [
parseInt(bits[1] + bits[1], 16),
parseInt(bits[2] + bits[2], 16),
parseInt(bits[3] + bits[3], 16)
];
}
}
];
var i;
// search through the definitions to find a match
for (i = 0; i < color_defs.length; i++) {
var re = color_defs[i].re;
var processor = color_defs[i].process;
var bits = re.exec(color_string);
if (bits) {
var channels = processor(bits);
this.r = channels[0];
this.g = channels[1];
this.b = channels[2];
this.ok = true;
}
}
// validate/cleanup values
this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);
// some getters
this.toRGB = function () {
return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
};
this.toHex = function () {
var r = this.r.toString(16);
var g = this.g.toString(16);
var b = this.b.toString(16);
if (r.length === 1) {r = '0' + r;}
if (g.length === 1) {g = '0' + g;}
if (b.length === 1) {b = '0' + b;}
return '#' + r + g + b;
};
// help
this.getHelpXML = function () {
var i, j;
var examples = [];
// add regexps
for (i = 0; i < color_defs.length; i++) {
var example = color_defs[i].example;
for (j = 0; j < example.length; j++) {
examples[examples.length] = example[j];
}
}
// add type-in colors
var sc;
for (sc in simple_colors) {
if (simple_colors.hasOwnProperty(sc)) {
examples[examples.length] = sc;
}
}
var xml = document.createElement('ul');
xml.setAttribute('id', 'rgbcolor-examples');
for (i = 0; i < examples.length; i++) {
try {
var list_item = document.createElement('li');
var list_color = new RGBColor(examples[i]);
var example_div = document.createElement('div');
example_div.style.cssText =
'margin: 3px; '
+ 'border: 1px solid black; '
+ 'background:' + list_color.toHex() + '; '
+ 'color:' + list_color.toHex()
;
example_div.appendChild(document.createTextNode('test'));
var list_item_value = document.createTextNode(
' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
);
list_item.appendChild(example_div);
list_item.appendChild(list_item_value);
xml.appendChild(list_item);
} catch(e){}
}
return xml;
};
}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>rgbcolor.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
// DO NOT EDIT THIS FILE!
// THIS FILE IS JUST A SAMPLE; TO APPLY, YOU MUST
// CREATE A NEW FILE config.js AND ADD CONTENTS
// SUCH AS SHOWN BELOW INTO THAT FILE.
/*globals svgEditor*/
/*
The config.js file is intended for the setting of configuration or
preferences which must run early on; if this is not needed, it is
recommended that you create an extension instead (for greater
reusability and modularity).
*/
// CONFIG AND EXTENSION SETTING
/*
See defaultConfig and defaultExtensions in svg-editor.js for a list
of possible configuration settings.
See svg-editor.js for documentation on using setConfig().
*/
// URL OVERRIDE CONFIG
svgEditor.setConfig({
/**
To override the ability for URLs to set URL-based SVG content,
uncomment the following:
*/
// preventURLContentLoading: true,
/**
To override the ability for URLs to set other configuration (including
extension config), uncomment the following:
*/
// preventAllURLConfig: true,
/**
To override the ability for URLs to set their own extensions,
uncomment the following (note that if setConfig() is used in
extension code, it will still be additive to extensions,
however):
*/
// lockExtensions: true,
});
svgEditor.setConfig({
/*
Provide default values here which differ from that of the editor but
which the URL can override
*/
}, {allowInitialUserOverride: true});
// EXTENSION CONFIG
svgEditor.setConfig({
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'
]
// , noDefaultExtensions: false, // noDefaultExtensions can only be meaningfully used in config.js or in the URL
});
// OTHER CONFIG
svgEditor.setConfig({
// canvasName: 'default',
// canvas_expansion: 3,
// initFill: {
// color: 'FF0000', // solid red
// opacity: 1
// },
// initStroke: {
// width: 5,
// color: '000000', // solid black
// opacity: 1
// },
// initOpacity: 1,
// colorPickerCSS: null,
// initTool: 'select',
// exportWindowType: 'new', // 'same'
// wireframe: false,
// showlayers: false,
// no_save_warning: false,
// PATH CONFIGURATION
// imgPath: 'images/',
// langPath: 'locale/',
// extPath: 'extensions/',
// jGraduatePath: 'jgraduate/images/',
/*
Uncomment the following to allow at least same domain (embedded) access,
including file:// access.
Setting as `['*']` would allow any domain to access but would be unsafe to
data privacy and integrity.
*/
// allowedOrigins: [window.location.origin || 'null'], // May be 'null' (as a string) when used as a file:// URL
// DOCUMENT PROPERTIES
// dimensions: [640, 480],
// EDITOR OPTIONS
// gridSnapping: false,
// gridColor: '#000',
// baseUnit: 'px',
// snappingStep: 10,
// showRulers: true,
// EXTENSION-RELATED (GRID)
// showGrid: false, // Set by ext-grid.js
// EXTENSION-RELATED (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
// emptyStorageOnDecline: true, // Used by ext-storage.js; empty any prior storage if the user declines to store
});
// PREF CHANGES
/**
setConfig() can also be used to set preferences in addition to
configuration (see defaultPrefs in svg-editor.js for a list of
possible settings), but at least if you are using ext-storage.js
to store preferences, it will probably be better to let your
users control these.
As with configuration, one may use allowInitialUserOverride, but
in the case of preferences, any previously stored preferences
will also thereby be enabled to override this setting (and at a
higher priority than any URL preference setting overrides).
Failing to use allowInitialUserOverride will ensure preferences
are hard-coded here regardless of URL or prior user storage setting.
*/
svgEditor.setConfig(
{
// 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
/**
* When showing the preferences dialog, svg-editor.js currently relies
* 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
* far as determining which color shows initially in the preferences
* dialog (though it can be changed and saved).
*/
// bkgd_color: '#FFF',
// bkgd_url: '',
// img_save: 'embed',
// Only shows in UI as far as alert notices
// save_notice_done: false,
// export_notice_done: false
}
);
svgEditor.setConfig(
{
// 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
// have already explicitly prevented one or the other)
},
{allowInitialUserOverride: true}
);
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>config-sample.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals $, svgEditor*/
/*jslint vars: true, eqeq: true*/
/**
* Package: svgedit.contextmenu
*
* Licensed under the Apache License, Version 2
*
* Author: Adam Bender
*/
// Dependencies:
// 1) jQuery (for dom injection of context menus)
var svgedit = svgedit || {};
(function() {
var self = this;
if (!svgedit.contextmenu) {
svgedit.contextmenu = {};
}
self.contextMenuExtensions = {};
var menuItemIsValid = function(menuItem) {
return menuItem && menuItem.id && menuItem.label && menuItem.action && typeof menuItem.action == 'function';
};
var addContextMenuItem = function(menuItem) {
// menuItem: {id, label, shortcut, action}
if (!menuItemIsValid(menuItem)) {
console.error("Menu items must be defined and have at least properties: id, label, action, where action must be a function");
return;
}
if (menuItem.id in self.contextMenuExtensions) {
console.error('Cannot add extension "' + menuItem.id + '", an extension by that name already exists"');
return;
}
// Register menuItem action, see below for deferred menu dom injection
console.log("Registed contextmenu item: {id:"+ menuItem.id+", label:"+menuItem.label+"}");
self.contextMenuExtensions[menuItem.id] = menuItem;
//TODO: Need to consider how to handle custom enable/disable behavior
};
var hasCustomHandler = function(handlerKey) {
return self.contextMenuExtensions[handlerKey] && true;
};
var getCustomHandler = function(handlerKey) {
return self.contextMenuExtensions[handlerKey].action;
};
var injectExtendedContextMenuItemIntoDom = function(menuItem) {
if (Object.keys(self.contextMenuExtensions).length === 0) {
// all menuItems appear at the bottom of the menu in their own container.
// if this is the first extension menu we need to add the separator.
$("#cmenu_canvas").append("<li class='separator'>");
}
var shortcut = menuItem.shortcut || "";
$("#cmenu_canvas").append("<li class='disabled'><a href='#" + menuItem.id + "'>"
+ menuItem.label + "<span class='shortcut'>"
+ shortcut + "</span></a></li>");
};
// Defer injection to wait out initial menu processing. This probably goes away once all context
// menu behavior is brought here.
svgEditor.ready(function() {
var menuItem;
for (menuItem in contextMenuExtensions) {
injectExtendedContextMenuItemIntoDom(contextMenuExtensions[menuItem]);
}
});
svgedit.contextmenu.resetCustomMenus = function(){self.contextMenuExtensions = {};};
svgedit.contextmenu.add = addContextMenuItem;
svgedit.contextmenu.hasCustomHandler = hasCustomHandler;
svgedit.contextmenu.getCustomHandler = getCustomHandler;
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>contextmenu.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>contextmenu</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
// jQuery Context Menu Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// Modified by Alexis Deveria
//
// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/
//
// Terms of Use
//
// This plugin is dual-licensed under the GNU General Public License
// and the MIT License and is copyright A Beautiful Site, LLC.
//
if(jQuery)( function() {
var win = $(window);
var doc = $(document);
$.extend($.fn, {
contextMenu: function(o, callback) {
// Defaults
if( o.menu == undefined ) return false;
if( o.inSpeed == undefined ) o.inSpeed = 150;
if( o.outSpeed == undefined ) o.outSpeed = 75;
// 0 needs to be -1 for expected results (no fade)
if( o.inSpeed == 0 ) o.inSpeed = -1;
if( o.outSpeed == 0 ) o.outSpeed = -1;
// Loop each context menu
$(this).each( function() {
var el = $(this);
var offset = $(el).offset();
var menu = $('#' + o.menu);
// Add contextMenu class
menu.addClass('contextMenu');
// Simulate a true right click
$(this).bind( "mousedown", function(e) {
var evt = e;
$(this).mouseup( function(e) {
var srcElement = $(this);
srcElement.unbind('mouseup');
if( evt.button === 2 || o.allowLeft || (evt.ctrlKey && svgedit.browser.isMac()) ) {
e.stopPropagation();
// Hide context menus that may be showing
$(".contextMenu").hide();
// Get this context menu
if( el.hasClass('disabled') ) return false;
// Detect mouse position
var d = {}, x = e.pageX, y = e.pageY;
var x_off = win.width() - menu.width(),
y_off = win.height() - menu.height();
if(x > x_off - 15) x = x_off-15;
if(y > y_off - 30) y = y_off-30; // 30 is needed to prevent scrollbars in FF
// Show the menu
doc.unbind('click');
menu.css({ top: y, left: x }).fadeIn(o.inSpeed);
// Hover events
menu.find('A').mouseover( function() {
menu.find('LI.hover').removeClass('hover');
$(this).parent().addClass('hover');
}).mouseout( function() {
menu.find('LI.hover').removeClass('hover');
});
// Keyboard
doc.keypress( function(e) {
switch( e.keyCode ) {
case 38: // up
if( !menu.find('LI.hover').length ) {
menu.find('LI:last').addClass('hover');
} else {
menu.find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');
if( !menu.find('LI.hover').length ) menu.find('LI:last').addClass('hover');
}
break;
case 40: // down
if( menu.find('LI.hover').length == 0 ) {
menu.find('LI:first').addClass('hover');
} else {
menu.find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');
if( !menu.find('LI.hover').length ) menu.find('LI:first').addClass('hover');
}
break;
case 13: // enter
menu.find('LI.hover A').trigger('click');
break;
case 27: // esc
doc.trigger('click');
break
}
});
// When items are selected
menu.find('A').unbind('mouseup');
menu.find('LI:not(.disabled) A').mouseup( function() {
doc.unbind('click').unbind('keypress');
$(".contextMenu").hide();
// Callback
if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );
return false;
});
// Hide bindings
setTimeout( function() { // Delay for Mozilla
doc.click( function() {
doc.unbind('click').unbind('keypress');
menu.fadeOut(o.outSpeed);
return false;
});
}, 0);
}
});
});
// Disable text selection
if( $.browser.mozilla ) {
$('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });
} else if( $.browser.msie ) {
$('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });
} else {
$('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });
}
// Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)
$(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });
});
return $(this);
},
// Disable context menu items on the fly
disableContextMenuItems: function(o) {
if( o == undefined ) {
// Disable all
$(this).find('LI').addClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');
}
}
});
return( $(this) );
},
// Enable context menu items on the fly
enableContextMenuItems: function(o) {
if( o == undefined ) {
// Enable all
$(this).find('LI.disabled').removeClass('disabled');
return( $(this) );
}
$(this).each( function() {
if( o != undefined ) {
var d = o.split(',');
for( var i = 0; i < d.length; i++ ) {
$(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');
}
}
});
return( $(this) );
},
// Disable context menu(s)
disableContextMenu: function() {
$(this).each( function() {
$(this).addClass('disabled');
});
return( $(this) );
},
// Enable context menu(s)
enableContextMenu: function() {
$(this).each( function() {
$(this).removeClass('disabled');
});
return( $(this) );
},
// Destroy context menu(s)
destroyContextMenu: function() {
// Destroy specified context menus
$(this).each( function() {
// Disable action
$(this).unbind('mousedown').unbind('mouseup');
});
return( $(this) );
}
});
})(jQuery);
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>jquery.contextMenu.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>coords.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>draw.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals $, EmbeddedSVGEdit*/
/*jslint vars: true */
var initEmbed;
// Todo: Get rid of frame.contentWindow dependencies so can be more easily adjusted to work cross-domain
$(function () {'use strict';
var svgCanvas = null;
var frame;
initEmbed = function () {
var doc, mainButton;
svgCanvas = new EmbeddedSVGEdit(frame);
// Hide main button, as we will be controlling new, load, save, etc. from the host document
doc = frame.contentDocument || frame.contentWindow.document;
mainButton = doc.getElementById('main_button');
mainButton.style.display = 'none';
};
function handleSvgData(data, error) {
if (error) {
alert('error ' + error);
} else {
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
}
}
function loadSvg() {
var svgexample = '<svg width="640" height="480" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><g><title>Layer 1</title><rect stroke-width="5" stroke="#000000" fill="#FF0000" id="svg_1" height="35" width="51" y="35" x="32"/><ellipse ry="15" rx="24" stroke-width="5" stroke="#000000" fill="#0000ff" id="svg_2" cy="60" cx="66"/></g></svg>';
svgCanvas.setSvgString(svgexample);
}
function saveSvg() {
svgCanvas.getSvgString()(handleSvgData);
}
function exportPNG() {
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
var exportWindow = window.open(
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
'svg-edit-exportWindow'
);
svgCanvas.rasterExport('PNG', null, exportWindow.name);
}
function exportPDF() {
var str = frame.contentWindow.svgEditor.uiStrings.notification.loadingImage;
/**
// If you want to handle the PDF blob yourself, do as follows
svgCanvas.bind('exportedPDF', function (win, data) {
alert(data.dataurlstring);
});
svgCanvas.exportPDF(); // Accepts two args: optionalWindowName supplied back to bound exportPDF handler and optionalOutputType (defaults to dataurlstring)
return;
*/
var exportWindow = window.open(
'data:text/html;charset=utf-8,' + encodeURIComponent('<title>' + str + '</title><h1>' + str + '</h1>'),
'svg-edit-exportWindow'
);
svgCanvas.exportPDF(exportWindow.name);
}
// Add event handlers
$('#load').click(loadSvg);
$('#save').click(saveSvg);
$('#exportPNG').click(exportPNG);
$('#exportPDF').click(exportPDF);
$('body').append(
$('<iframe src="svg-editor.html?extensions=ext-xdomain-messaging.js' +
window.location.href.replace(/\?(.*)$/, '&$1') + // Append arguments to this file onto the iframe
'" width="900px" height="600px" id="svgedit" onload="initEmbed();"></iframe>'
)
);
frame = document.getElementById('svgedit');
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>embedapi-dom.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Embed API</title>
<script src="jquery.js"></script>
<script src="embedapi.js"></script>
<script src="embedapi-dom.js"></script>
</head>
<body>
<button id="load">Load example</button>
<button id="save">Save data</button>
<button id="exportPNG">Export data to PNG</button>
<button id="exportPDF">Export data to PDF</button>
<br/>
</body>
</html>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>embedapi.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*
Embedded SVG-edit API
General usage:
- Have an iframe somewhere pointing to a version of svg-edit > r1000
- Initialize the magic with:
var svgCanvas = new EmbeddedSVGEdit(window.frames.svgedit);
- Pass functions in this format:
svgCanvas.setSvgString('string')
- Or if a callback is needed:
svgCanvas.setSvgString('string')(function(data, error){
if (error){
// There was an error
} else{
// Handle data
}
})
Everything is done with the same API as the real svg-edit,
and all documentation is unchanged.
However, this file depends on the postMessage API which
can only support JSON-serializable arguments and
return values, so, for example, arguments whose value is
'undefined', a function, a non-finite number, or a built-in
object like Date(), RegExp(), etc. will most likely not behave
as expected. In such a case one may need to host
the SVG editor on the same domain and reference the
JavaScript methods on the frame itself.
The only other difference is
when handling returns: the callback notation is used instead.
var blah = new EmbeddedSVGEdit(window.frames.svgedit);
blah.clearSelection('woot', 'blah', 1337, [1, 2, 3, 4, 5, 'moo'], -42, {a: 'tree',b:6, c: 9})(function(){console.log('GET DATA',arguments)})
*/
(function () {'use strict';
var cbid = 0;
function getCallbackSetter (d) {
return function () {
var t = this, // New callback
args = [].slice.call(arguments),
cbid = t.send(d, args, function(){}); // The callback (currently it's nothing, but will be set later)
return function(newcallback){
t.callbacks[cbid] = newcallback; // Set callback
};
};
}
/*
* Having this separate from messageListener allows us to
* avoid using JSON parsing (and its limitations) in the case
* of same domain control
*/
function addCallback (t, data) {
var result = data.result || data.error,
cbid = data.id;
if (t.callbacks[cbid]) {
if (data.result) {
t.callbacks[cbid](result);
} else {
t.callbacks[cbid](result, 'error');
}
}
}
function messageListener (e) {
// We accept and post strings as opposed to objects for the sake of IE9 support; this
// will most likely be changed in the future
if (typeof e.data !== 'string') {
return;
}
var allowedOrigins = this.allowedOrigins,
data = e.data && JSON.parse(e.data);
if (!data || typeof data !== 'object' || data.namespace !== 'svg-edit' ||
e.source !== this.frame.contentWindow ||
(allowedOrigins.indexOf('*') === -1 && allowedOrigins.indexOf(e.origin) === -1)
) {
return;
}
addCallback(this, data);
}
function getMessageListener (t) {
return function (e) {
messageListener.call(t, e);
};
}
/**
* @param {HTMLIFrameElement} frame
* @param {array} [allowedOrigins=[]] Array of origins from which incoming
* messages will be allowed when same origin is not used; defaults to none.
* If supplied, it should probably be the same as svgEditor's allowedOrigins
*/
function EmbeddedSVGEdit (frame, allowedOrigins) {
if (!(this instanceof EmbeddedSVGEdit)) { // Allow invocation without 'new' keyword
return new EmbeddedSVGEdit(frame);
}
this.allowedOrigins = allowedOrigins || [];
// Initialize communication
this.frame = frame;
this.callbacks = {};
// List of functions extracted with this:
// Run in firebug on http://svg-edit.googlecode.com/svn/trunk/docs/files/svgcanvas-js.html
// for (var i=0,q=[],f = document.querySelectorAll('div.CFunction h3.CTitle a'); i < f.length; i++) { q.push(f[i].name); }; q
// var functions = ['clearSelection', 'addToSelection', 'removeFromSelection', 'open', 'save', 'getSvgString', 'setSvgString',
// 'createLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility',
// 'moveSelectedToLayer', 'clear'];
// Newer, well, it extracts things that aren't documented as well. All functions accessible through the normal thingy can now be accessed though the API
// var svgCanvas = frame.contentWindow.svgCanvas;
// var l = []; for (var i in svgCanvas){ if (typeof svgCanvas[i] == 'function') { l.push(i);} };
// alert("['" + l.join("', '") + "']");
// Run in svgedit itself
var i,
functions = [
'clearSvgContentElement', 'setIdPrefix', 'getCurrentDrawing', 'addSvgElementFromJson', 'getTransformList', 'matrixMultiply', 'hasMatrixTransform', 'transformListToTransform', 'convertToNum', 'findDefs', 'getUrlFromAttr', 'getHref', 'setHref', 'getBBox', 'getRotationAngle', 'getElem', 'getRefElem', 'assignAttributes', 'cleanupElement', 'remapElement', 'recalculateDimensions', 'sanitizeSvg', 'runExtensions', 'addExtension', 'round', 'getIntersectionList', 'getStrokedBBox', 'getVisibleElements', 'getVisibleElementsAndBBoxes', 'groupSvgElem', 'getId', 'getNextId', 'call', 'bind', 'prepareSvg', 'setRotationAngle', 'recalculateAllSelectedDimensions', 'clearSelection', 'addToSelection', 'selectOnly', 'removeFromSelection', 'selectAllInCurrentLayer', 'getMouseTarget', 'removeUnusedDefElems', 'svgCanvasToString', 'svgToString', 'embedImage', 'setGoodImage', 'open', 'save', 'rasterExport', 'exportPDF', 'getSvgString', 'randomizeIds', 'uniquifyElems', 'setUseData', 'convertGradients', 'convertToGroup', 'setSvgString', 'importSvgString', 'identifyLayers', 'createLayer', 'cloneLayer', 'deleteCurrentLayer', 'setCurrentLayer', 'renameCurrentLayer', 'setCurrentLayerPosition', 'setLayerVisibility', 'moveSelectedToLayer', 'mergeLayer', 'mergeAllLayers', 'leaveContext', 'setContext', 'clear', 'linkControlPoints', 'getContentElem', 'getRootElem', 'getSelectedElems', 'getResolution', 'getZoom', 'getVersion', 'setUiStrings', 'setConfig', 'getTitle', 'setGroupTitle', 'getDocumentTitle', 'setDocumentTitle', 'getEditorNS', 'setResolution', 'getOffset', 'setBBoxZoom', 'setZoom', 'getMode', 'setMode', 'getColor', 'setColor', 'setGradient', 'setPaint', 'setStrokePaint', 'setFillPaint', 'getStrokeWidth', 'setStrokeWidth', 'setStrokeAttr', 'getStyle', 'getOpacity', 'setOpacity', 'getFillOpacity', 'getStrokeOpacity', 'setPaintOpacity', 'getPaintOpacity', 'getBlur', 'setBlurNoUndo', 'setBlurOffsets', 'setBlur', 'getBold', 'setBold', 'getItalic', 'setItalic', 'getFontFamily', 'setFontFamily', 'setFontColor', 'getFontColor', 'getFontSize', 'setFontSize', 'getText', 'setTextContent', 'setImageURL', 'setLinkURL', 'setRectRadius', 'makeHyperlink', 'removeHyperlink', 'setSegType', 'convertToPath', 'changeSelectedAttribute', 'deleteSelectedElements', 'cutSelectedElements', 'copySelectedElements', 'pasteElements', 'groupSelectedElements', 'pushGroupProperties', 'ungroupSelectedElement', 'moveToTopSelectedElement', 'moveToBottomSelectedElement', 'moveUpDownSelected', 'moveSelectedElements', 'cloneSelectedElements', 'alignSelectedElements', 'updateCanvas', 'setBackground', 'cycleElement', 'getPrivateMethods', 'zoomChanged', 'ready'
];
// TODO: rewrite the following, it's pretty scary.
for (i = 0; i < functions.length; i++) {
this[functions[i]] = getCallbackSetter(functions[i]);
}
// Older IE may need a polyfill for addEventListener, but so it would for SVG
window.addEventListener('message', getMessageListener(this), false);
}
EmbeddedSVGEdit.prototype.send = function (name, args, callback){
var t = this;
cbid++;
this.callbacks[cbid] = callback;
setTimeout((function (cbid) {
return function () { // Delay for the callback to be set in case its synchronous
/*
* Todo: Handle non-JSON arguments and return values (undefined,
* nonfinite numbers, functions, and built-in objects like Date,
* RegExp), etc.? Allow promises instead of callbacks? Review
* SVG-Edit functions for whether JSON-able parameters can be
* made compatile with all API functionality
*/
// We accept and post strings for the sake of IE9 support
if (window.location.origin === t.frame.contentWindow.location.origin) {
// Although we do not really need this API if we are working same
// domain, it could allow us to write in a way that would work
// cross-domain as well, assuming we stick to the argument limitations
// of the current JSON-based communication API (e.g., not passing
// callbacks). We might be able to address these shortcomings; see
// the todo elsewhere in this file.
var message = {id: cbid},
svgCanvas = t.frame.contentWindow.svgCanvas;
try {
message.result = svgCanvas[name].apply(svgCanvas, args);
}
catch (err) {
message.error = err.message;
}
addCallback(t, message);
}
else { // Requires the ext-xdomain-messaging.js extension
t.frame.contentWindow.postMessage(JSON.stringify({namespace: 'svgCanvas', id: cbid, name: name, args: args}), '*');
}
};
}(cbid)), 0);
return cbid;
};
window.embedded_svg_edit = EmbeddedSVGEdit; // Export old, deprecated API
window.EmbeddedSVGEdit = EmbeddedSVGEdit; // Follows common JS convention of CamelCase and, as enforced in JSLint, of initial caps for constructors
}());
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>embedapi.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>extensions</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?php
$allowedMimeTypesBySuffix = array(
'svg' => 'image/svg+xml;charset=UTF-8',
'png' => 'image/png',
'jpeg' => 'image/jpeg',
'bmp' => 'image/bmp',
'webp' => 'image/webp',
'pdf' => 'application/pdf'
);
?>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>allowedMimeTypes.php</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/octet-stream</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="tool_closepath">
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>Layer 1</title>
<path stroke="#000" stroke-width="15" fill="#ffc8c8" d="m121.5,40l-84,106l27,115l166,2l29,-111"/>
<line x1="240" y1="136" x2="169.5" y2="74" stroke="#A00" stroke-width="25" fill="none"/>
<path stroke="none" fill ="#A00" d="m158,65l31,74l-3,-50l51,-3z"/>
<g stroke-width="15" stroke="#00f" fill="#0ff">
<circle r="30" cy="41" cx="123"/>
<circle r="30" cy="146" cx="40"/>
<circle r="30" cy="260" cx="69"/>
<circle r="30" cy="260" cx="228"/>
<circle r="30" cy="148" cx="260"/>
</g>
</g>
</svg>
</g>
<g id="tool_openpath">
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>Layer 1</title>
<path stroke="#000" stroke-width="15" fill="#ffc8c8" d="m123.5,38l-84,106l27,115l166,2l29,-111"/>
<line x1="276.5" y1="153" x2="108.5" y2="24" stroke="#000" stroke-width="10" fill="none"/>
<g stroke-width="15" stroke="#00f" fill="#0ff">
<circle r="30" cy="41" cx="123"/>
<circle r="30" cy="146" cx="40"/>
<circle r="30" cy="260" cx="69"/>
<circle r="30" cy="260" cx="228"/>
<circle r="30" cy="148" cx="260"/>
</g>
<g stroke="#A00" stroke-width="15" fill="none">
<line x1="168" y1="24" x2="210" y2="150"/>
<line x1="210" y1="24" x2="168" y2="150"/>
</g>
</g>
</svg>
</g>
<g id="svg_eof"/>
</svg>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>closepath_icons.svg</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>image/svg+xml</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, svgCanvas, $*/
/*jslint vars: true, eqeq: true*/
/*
* ext-arrows.js
*
* Licensed under the MIT License
*
* Copyright(c) 2010 Alexis Deveria
*
*/
svgEditor.addExtension('Arrows', function(S) {
var svgcontent = S.svgcontent,
addElem = S.addSvgElementFromJson,
nonce = S.nonce,
randomize_ids = S.randomize_ids,
selElems, pathdata,
lang_list = {
'en':[
{'id': 'arrow_none', 'textContent': 'No arrow' }
],
'fr':[
{'id': 'arrow_none', 'textContent': 'Sans flèche' }
]
},
arrowprefix,
prefix = 'se_arrow_';
function setArrowNonce(window, n) {
randomize_ids = true;
arrowprefix = prefix + n + '_';
pathdata.fw.id = arrowprefix + 'fw';
pathdata.bk.id = arrowprefix + 'bk';
}
function unsetArrowNonce(window) {
randomize_ids = false;
arrowprefix = prefix;
pathdata.fw.id = arrowprefix + 'fw';
pathdata.bk.id = arrowprefix + 'bk';
}
svgCanvas.bind('setnonce', setArrowNonce);
svgCanvas.bind('unsetnonce', unsetArrowNonce);
if (randomize_ids) {
arrowprefix = prefix + nonce + '_';
} else {
arrowprefix = prefix;
}
pathdata = {
fw: {d: 'm0,0l10,5l-10,5l5,-5l-5,-5z', refx: 8, id: arrowprefix + 'fw'},
bk: {d: 'm10,0l-10,5l10,5l-5,-5l5,-5z', refx: 2, id: arrowprefix + 'bk'}
};
function getLinked(elem, attr) {
var str = elem.getAttribute(attr);
if(!str) {return null;}
var m = str.match(/\(\#(.*)\)/);
if(!m || m.length !== 2) {
return null;
}
return S.getElem(m[1]);
}
function showPanel(on) {
$('#arrow_panel').toggle(on);
if(on) {
var el = selElems[0];
var end = el.getAttribute('marker-end');
var start = el.getAttribute('marker-start');
var mid = el.getAttribute('marker-mid');
var val;
if (end && start) {
val = 'both';
} else if (end) {
val = 'end';
} else if (start) {
val = 'start';
} else if (mid) {
val = 'mid';
if (mid.indexOf('bk') !== -1) {
val = 'mid_bk';
}
}
if (!start && !mid && !end) {
val = 'none';
}
$('#arrow_list').val(val);
}
}
function resetMarker() {
var el = selElems[0];
el.removeAttribute('marker-start');
el.removeAttribute('marker-mid');
el.removeAttribute('marker-end');
}
function addMarker(dir, type, id) {
// TODO: Make marker (or use?) per arrow type, since refX can be different
id = id || arrowprefix + dir;
var marker = S.getElem(id);
var data = pathdata[dir];
if (type == 'mid') {
data.refx = 5;
}
if (!marker) {
marker = addElem({
'element': 'marker',
'attr': {
'viewBox': '0 0 10 10',
'id': id,
'refY': 5,
'markerUnits': 'strokeWidth',
'markerWidth': 5,
'markerHeight': 5,
'orient': 'auto',
'style': 'pointer-events:none' // Currently needed for Opera
}
});
var arrow = addElem({
'element': 'path',
'attr': {
'd': data.d,
'fill': '#000000'
}
});
marker.appendChild(arrow);
S.findDefs().appendChild(marker);
}
marker.setAttribute('refX', data.refx);
return marker;
}
function setArrow() {
var type = this.value;
resetMarker();
if (type == 'none') {
return;
}
// Set marker on element
var dir = 'fw';
if (type == 'mid_bk') {
type = 'mid';
dir = 'bk';
} else if (type == 'both') {
addMarker('bk', type);
svgCanvas.changeSelectedAttribute('marker-start', 'url(#' + pathdata.bk.id + ')');
type = 'end';
dir = 'fw';
} else if (type == 'start') {
dir = 'bk';
}
addMarker(dir, type);
svgCanvas.changeSelectedAttribute('marker-' + type, 'url(#' + pathdata[dir].id + ')');
S.call('changed', selElems);
}
function colorChanged(elem) {
var color = elem.getAttribute('stroke');
var mtypes = ['start', 'mid', 'end'];
var defs = S.findDefs();
$.each(mtypes, function(i, type) {
var marker = getLinked(elem, 'marker-'+type);
if(!marker) {return;}
var cur_color = $(marker).children().attr('fill');
var cur_d = $(marker).children().attr('d');
var new_marker = null;
if(cur_color === color) {return;}
var all_markers = $(defs).find('marker');
// Different color, check if already made
all_markers.each(function() {
var attrs = $(this).children().attr(['fill', 'd']);
if(attrs.fill === color && attrs.d === cur_d) {
// Found another marker with this color and this path
new_marker = this;
}
});
if(!new_marker) {
// Create a new marker with this color
var last_id = marker.id;
var dir = last_id.indexOf('_fw') !== -1?'fw':'bk';
new_marker = addMarker(dir, type, arrowprefix + dir + all_markers.length);
$(new_marker).children().attr('fill', color);
}
$(elem).attr('marker-'+type, 'url(#' + new_marker.id + ')');
// Check if last marker can be removed
var remove = true;
$(S.svgcontent).find('line, polyline, path, polygon').each(function() {
var elem = this;
$.each(mtypes, function(j, mtype) {
if($(elem).attr('marker-' + mtype) === 'url(#' + marker.id + ')') {
remove = false;
return remove;
}
});
if(!remove) {return false;}
});
// Not found, so can safely remove
if(remove) {
$(marker).remove();
}
});
}
return {
name: 'Arrows',
context_tools: [{
type: 'select',
panel: 'arrow_panel',
title: 'Select arrow type',
id: 'arrow_list',
options: {
none: 'No arrow',
end: '----&gt;',
start: '&lt;----',
both: '&lt;---&gt;',
mid: '--&gt;--',
mid_bk: '--&lt;--'
},
defval: 'none',
events: {
change: setArrow
}
}],
callback: function() {
$('#arrow_panel').hide();
// Set ID so it can be translated in locale file
$('#arrow_list option')[0].id = 'connector_no_arrow';
},
addLangData: function(lang) {
return {
data: lang_list[lang]
};
},
selectedChanged: function(opts) {
// Use this to update the current selected elements
selElems = opts.elems;
var i = selElems.length;
var marker_elems = ['line', 'path', 'polyline', 'polygon'];
while(i--) {
var elem = selElems[i];
if(elem && $.inArray(elem.tagName, marker_elems) !== -1) {
if(opts.selectedElement && !opts.multiselected) {
showPanel(true);
} else {
showPanel(false);
}
} else {
showPanel(false);
}
}
},
elementChanged: function(opts) {
var elem = opts.elems[0];
if(elem && (
elem.getAttribute('marker-start') ||
elem.getAttribute('marker-mid') ||
elem.getAttribute('marker-end')
)) {
// var start = elem.getAttribute('marker-start');
// var mid = elem.getAttribute('marker-mid');
// var end = elem.getAttribute('marker-end');
// Has marker, so see if it should match color
colorChanged(elem);
}
}
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-arrows.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, $*/
/*jslint vars: true, eqeq: true*/
/*
* ext-closepath.js
*
* Licensed under the MIT License
*
* Copyright(c) 2010 Jeff Schiller
*
*/
// This extension adds a simple button to the contextual panel for paths
// The button toggles whether the path is open or closed
svgEditor.addExtension('ClosePath', function() {'use strict';
var selElems,
updateButton = function(path) {
var seglist = path.pathSegList,
closed = seglist.getItem(seglist.numberOfItems - 1).pathSegType == 1,
showbutton = closed ? '#tool_openpath' : '#tool_closepath',
hidebutton = closed ? '#tool_closepath' : '#tool_openpath';
$(hidebutton).hide();
$(showbutton).show();
},
showPanel = function(on) {
$('#closepath_panel').toggle(on);
if (on) {
var path = selElems[0];
if (path) {updateButton(path);}
}
},
toggleClosed = function() {
var path = selElems[0];
if (path) {
var seglist = path.pathSegList,
last = seglist.numberOfItems - 1;
// is closed
if (seglist.getItem(last).pathSegType == 1) {
seglist.removeItem(last);
} else {
seglist.appendItem(path.createSVGPathSegClosePath());
}
updateButton(path);
}
};
return {
name: 'ClosePath',
svgicons: svgEditor.curConfig.extPath + 'closepath_icons.svg',
buttons: [{
id: 'tool_openpath',
type: 'context',
panel: 'closepath_panel',
title: 'Open path',
events: {
click: function() {
toggleClosed();
}
}
},
{
id: 'tool_closepath',
type: 'context',
panel: 'closepath_panel',
title: 'Close path',
events: {
click: function() {
toggleClosed();
}
}
}],
callback: function() {
$('#closepath_panel').hide();
},
selectedChanged: function(opts) {
selElems = opts.elems;
var i = selElems.length;
while (i--) {
var elem = selElems[i];
if (elem && elem.tagName == 'path') {
if (opts.selectedElement && !opts.multiselected) {
showPanel(true);
} else {
showPanel(false);
}
} else {
showPanel(false);
}
}
}
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-closepath.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-connector.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, svgedit, $*/
/*jslint vars: true, eqeq: true*/
/*
* ext-eyedropper.js
*
* Licensed under the MIT License
*
* Copyright(c) 2010 Jeff Schiller
*
*/
// Dependencies:
// 1) jQuery
// 2) history.js
// 3) svg_editor.js
// 4) svgcanvas.js
svgEditor.addExtension("eyedropper", function(S) {'use strict';
var // NS = svgedit.NS,
// svgcontent = S.svgcontent,
// svgdoc = S.svgroot.parentNode.ownerDocument,
svgCanvas = svgEditor.canvas,
ChangeElementCommand = svgedit.history.ChangeElementCommand,
addToHistory = function(cmd) { svgCanvas.undoMgr.addCommandToHistory(cmd); },
currentStyle = {
fillPaint: "red", fillOpacity: 1.0,
strokePaint: "black", strokeOpacity: 1.0,
strokeWidth: 5, strokeDashArray: null,
opacity: 1.0,
strokeLinecap: 'butt',
strokeLinejoin: 'miter'
};
function getStyle(opts) {
// if we are in eyedropper mode, we don't want to disable the eye-dropper tool
var mode = svgCanvas.getMode();
if (mode == "eyedropper") {return;}
var elem = null;
var tool = $('#tool_eyedropper');
// enable-eye-dropper if one element is selected
if (!opts.multiselected && opts.elems[0] &&
$.inArray(opts.elems[0].nodeName, ['svg', 'g', 'use']) === -1
) {
elem = opts.elems[0];
tool.removeClass('disabled');
// grab the current style
currentStyle.fillPaint = elem.getAttribute("fill") || "black";
currentStyle.fillOpacity = elem.getAttribute("fill-opacity") || 1.0;
currentStyle.strokePaint = elem.getAttribute("stroke");
currentStyle.strokeOpacity = elem.getAttribute("stroke-opacity") || 1.0;
currentStyle.strokeWidth = elem.getAttribute("stroke-width");
currentStyle.strokeDashArray = elem.getAttribute("stroke-dasharray");
currentStyle.strokeLinecap = elem.getAttribute("stroke-linecap");
currentStyle.strokeLinejoin = elem.getAttribute("stroke-linejoin");
currentStyle.opacity = elem.getAttribute("opacity") || 1.0;
}
// disable eye-dropper tool
else {
tool.addClass('disabled');
}
}
return {
name: "eyedropper",
svgicons: svgEditor.curConfig.extPath + "eyedropper-icon.xml",
buttons: [{
id: "tool_eyedropper",
type: "mode",
title: "Eye Dropper Tool",
key: "I",
events: {
"click": function() {
svgCanvas.setMode("eyedropper");
}
}
}],
// if we have selected an element, grab its paint and enable the eye dropper button
selectedChanged: getStyle,
elementChanged: getStyle,
mouseDown: function(opts) {
var mode = svgCanvas.getMode();
if (mode == "eyedropper") {
var e = opts.event;
var target = e.target;
if ($.inArray(target.nodeName, ['svg', 'g', 'use']) === -1) {
var changes = {};
var change = function(elem, attrname, newvalue) {
changes[attrname] = elem.getAttribute(attrname);
elem.setAttribute(attrname, newvalue);
};
if (currentStyle.fillPaint) {change(target, "fill", currentStyle.fillPaint);}
if (currentStyle.fillOpacity) {change(target, "fill-opacity", currentStyle.fillOpacity);}
if (currentStyle.strokePaint) {change(target, "stroke", currentStyle.strokePaint);}
if (currentStyle.strokeOpacity) {change(target, "stroke-opacity", currentStyle.strokeOpacity);}
if (currentStyle.strokeWidth) {change(target, "stroke-width", currentStyle.strokeWidth);}
if (currentStyle.strokeDashArray) {change(target, "stroke-dasharray", currentStyle.strokeDashArray);}
if (currentStyle.opacity) {change(target, "opacity", currentStyle.opacity);}
if (currentStyle.strokeLinecap) {change(target, "stroke-linecap", currentStyle.strokeLinecap);}
if (currentStyle.strokeLinejoin) {change(target, "stroke-linejoin", currentStyle.strokeLinejoin);}
addToHistory(new ChangeElementCommand(target, changes));
}
}
}
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-eyedropper.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, svgedit, svgCanvas, $*/
/*jslint vars: true, eqeq: true, todo: true*/
/*
* ext-foreignobject.js
*
* Licensed under the Apache License, Version 2
*
* Copyright(c) 2010 Jacques Distler
* Copyright(c) 2010 Alexis Deveria
*
*/
svgEditor.addExtension("foreignObject", function(S) {
var NS = svgedit.NS,
Utils = svgedit.utilities,
svgcontent = S.svgcontent,
addElem = S.addSvgElementFromJson,
selElems,
editingforeign = false,
svgdoc = S.svgroot.parentNode.ownerDocument,
started,
newFO;
var properlySourceSizeTextArea = function () {
// TODO: remove magic numbers here and get values from CSS
var height = $('#svg_source_container').height() - 80;
$('#svg_source_textarea').css('height', height);
};
function showPanel(on) {
var fc_rules = $('#fc_rules');
if(!fc_rules.length) {
fc_rules = $('<style id="fc_rules"></style>').appendTo('head');
}
fc_rules.text(!on?"":" #tool_topath { display: none !important; }");
$('#foreignObject_panel').toggle(on);
}
function toggleSourceButtons(on) {
$('#tool_source_save, #tool_source_cancel').toggle(!on);
$('#foreign_save, #foreign_cancel').toggle(on);
}
// Function: setForeignString(xmlString, elt)
// This function sets the content of element elt to the input XML.
//
// Parameters:
// xmlString - The XML text.
// elt - the parent element to append to
//
// Returns:
// This function returns false if the set was unsuccessful, true otherwise.
function setForeignString(xmlString) {
var elt = selElems[0];
try {
// convert string into XML document
var newDoc = Utils.text2xml('<svg xmlns="' + NS.SVG + '" xmlns:xlink="' + NS.XLINK + '">' + xmlString + '</svg>');
// run it through our sanitizer to remove anything we do not support
S.sanitizeSvg(newDoc.documentElement);
elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
S.call("changed", [elt]);
svgCanvas.clearSelection();
} catch(e) {
console.log(e);
return false;
}
return true;
}
function showForeignEditor() {
var elt = selElems[0];
if (!elt || editingforeign) {return;}
editingforeign = true;
toggleSourceButtons(true);
elt.removeAttribute('fill');
var str = S.svgToString(elt, 0);
$('#svg_source_textarea').val(str);
$('#svg_source_editor').fadeIn();
properlySourceSizeTextArea();
$('#svg_source_textarea').focus();
}
function setAttr(attr, val) {
svgCanvas.changeSelectedAttribute(attr, val);
S.call("changed", selElems);
}
return {
name: "foreignObject",
svgicons: svgEditor.curConfig.extPath + "foreignobject-icons.xml",
buttons: [{
id: "tool_foreign",
type: "mode",
title: "Foreign Object Tool",
events: {
'click': function() {
svgCanvas.setMode('foreign');
}
}
},{
id: "edit_foreign",
type: "context",
panel: "foreignObject_panel",
title: "Edit ForeignObject Content",
events: {
'click': function() {
showForeignEditor();
}
}
}],
context_tools: [{
type: "input",
panel: "foreignObject_panel",
title: "Change foreignObject's width",
id: "foreign_width",
label: "w",
size: 3,
events: {
change: function() {
setAttr('width', this.value);
}
}
},{
type: "input",
panel: "foreignObject_panel",
title: "Change foreignObject's height",
id: "foreign_height",
label: "h",
events: {
change: function() {
setAttr('height', this.value);
}
}
}, {
type: "input",
panel: "foreignObject_panel",
title: "Change foreignObject's font size",
id: "foreign_font_size",
label: "font-size",
size: 2,
defval: 16,
events: {
change: function() {
setAttr('font-size', this.value);
}
}
}
],
callback: function() {
$('#foreignObject_panel').hide();
var endChanges = function() {
$('#svg_source_editor').hide();
editingforeign = false;
$('#svg_source_textarea').blur();
toggleSourceButtons(false);
};
// TODO: Needs to be done after orig icon loads
setTimeout(function() {
// Create source save/cancel buttons
var save = $('#tool_source_save').clone()
.hide().attr('id', 'foreign_save').unbind()
.appendTo("#tool_source_back").click(function() {
if (!editingforeign) {return;}
if (!setForeignString($('#svg_source_textarea').val())) {
$.confirm("Errors found. Revert to original?", function(ok) {
if(!ok) {return false;}
endChanges();
});
} else {
endChanges();
}
// setSelectMode();
});
var cancel = $('#tool_source_cancel').clone()
.hide().attr('id', 'foreign_cancel').unbind()
.appendTo("#tool_source_back").click(function() {
endChanges();
});
}, 3000);
},
mouseDown: function(opts) {
var e = opts.event;
if(svgCanvas.getMode() == "foreign") {
started = true;
newFO = S.addSvgElementFromJson({
"element": "foreignObject",
"attr": {
"x": opts.start_x,
"y": opts.start_y,
"id": S.getNextId(),
"font-size": 16, //cur_text.font_size,
"width": "48",
"height": "20",
"style": "pointer-events:inherit"
}
});
var m = svgdoc.createElementNS(NS.MATH, 'math');
m.setAttributeNS(NS.XMLNS, 'xmlns', NS.MATH);
m.setAttribute('display', 'inline');
var mi = svgdoc.createElementNS(NS.MATH, 'mi');
mi.setAttribute('mathvariant', 'normal');
mi.textContent = "\u03A6";
var mo = svgdoc.createElementNS(NS.MATH, 'mo');
mo.textContent = "\u222A";
var mi2 = svgdoc.createElementNS(NS.MATH, 'mi');
mi2.textContent = "\u2133";
m.appendChild(mi);
m.appendChild(mo);
m.appendChild(mi2);
newFO.appendChild(m);
return {
started: true
};
}
},
mouseUp: function(opts) {
var e = opts.event;
if(svgCanvas.getMode() == "foreign" && started) {
var attrs = $(newFO).attr(["width", "height"]);
var keep = (attrs.width != 0 || attrs.height != 0);
svgCanvas.addToSelection([newFO], true);
return {
keep: keep,
element: newFO
};
}
},
selectedChanged: function(opts) {
// Use this to update the current selected elements
selElems = opts.elems;
var i = selElems.length;
while(i--) {
var elem = selElems[i];
if(elem && elem.tagName === 'foreignObject') {
if(opts.selectedElement && !opts.multiselected) {
$('#foreign_font_size').val(elem.getAttribute("font-size"));
$('#foreign_width').val(elem.getAttribute("width"));
$('#foreign_height').val(elem.getAttribute("height"));
showPanel(true);
} else {
showPanel(false);
}
} else {
showPanel(false);
}
}
},
elementChanged: function(opts) {
var elem = opts.elems[0];
}
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-foreignobject.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, svgedit, svgCanvas, $*/
/*jslint vars: true*/
/*
* ext-grid.js
*
* Licensed under the Apache License, Version 2
*
* Copyright(c) 2010 Redou Mine
* Copyright(c) 2010 Alexis Deveria
*
*/
// Dependencies:
// 1) units.js
// 2) everything else
svgEditor.addExtension('view_grid', function() { 'use strict';
var NS = svgedit.NS,
svgdoc = document.getElementById('svgcanvas').ownerDocument,
showGrid = svgEditor.curConfig.showGrid || false,
assignAttributes = svgCanvas.assignAttributes,
hcanvas = document.createElement('canvas'),
canvBG = $('#canvasBackground'),
units = svgedit.units.getTypeMap(),
intervals = [0.01, 0.1, 1, 10, 100, 1000];
$(hcanvas).hide().appendTo('body');
var canvasGrid = svgdoc.createElementNS(NS.SVG, 'svg');
assignAttributes(canvasGrid, {
'id': 'canvasGrid',
'width': '100%',
'height': '100%',
'x': 0,
'y': 0,
'overflow': 'visible',
'display': 'none'
});
canvBG.append(canvasGrid);
// grid-pattern
var gridPattern = svgdoc.createElementNS(NS.SVG, 'pattern');
assignAttributes(gridPattern, {
'id': 'gridpattern',
'patternUnits': 'userSpaceOnUse',
'x': 0, //-(value.strokeWidth / 2), // position for strokewidth
'y': 0, //-(value.strokeWidth / 2), // position for strokewidth
'width': 100,
'height': 100
});
var gridimg = svgdoc.createElementNS(NS.SVG, 'image');
assignAttributes(gridimg, {
'x': 0,
'y': 0,
'width': 100,
'height': 100
});
gridPattern.appendChild(gridimg);
$('#svgroot defs').append(gridPattern);
// grid-box
var gridBox = svgdoc.createElementNS(NS.SVG, 'rect');
assignAttributes(gridBox, {
'width': '100%',
'height': '100%',
'x': 0,
'y': 0,
'stroke-width': 0,
'stroke': 'none',
'fill': 'url(#gridpattern)',
'style': 'pointer-events: none; display:visible;'
});
$('#canvasGrid').append(gridBox);
function updateGrid(zoom) {
var i;
// TODO: Try this with <line> elements, then compare performance difference
var unit = units[svgEditor.curConfig.baseUnit]; // 1 = 1px
var u_multi = unit * zoom;
// Calculate the main number interval
var raw_m = 100 / u_multi;
var multi = 1;
for (i = 0; i < intervals.length; i++) {
var num = intervals[i];
multi = num;
if (raw_m <= num) {
break;
}
}
var big_int = multi * u_multi;
// Set the canvas size to the width of the container
hcanvas.width = big_int;
hcanvas.height = big_int;
var ctx = hcanvas.getContext('2d');
var cur_d = 0.5;
var part = big_int / 10;
ctx.globalAlpha = 0.2;
ctx.strokeStyle = svgEditor.curConfig.gridColor;
for (i = 1; i < 10; i++) {
var sub_d = Math.round(part * i) + 0.5;
// var line_num = (i % 2)?12:10;
var line_num = 0;
ctx.moveTo(sub_d, big_int);
ctx.lineTo(sub_d, line_num);
ctx.moveTo(big_int, sub_d);
ctx.lineTo(line_num ,sub_d);
}
ctx.stroke();
ctx.beginPath();
ctx.globalAlpha = 0.5;
ctx.moveTo(cur_d, big_int);
ctx.lineTo(cur_d, 0);
ctx.moveTo(big_int, cur_d);
ctx.lineTo(0, cur_d);
ctx.stroke();
var datauri = hcanvas.toDataURL('image/png');
gridimg.setAttribute('width', big_int);
gridimg.setAttribute('height', big_int);
gridimg.parentNode.setAttribute('width', big_int);
gridimg.parentNode.setAttribute('height', big_int);
svgCanvas.setHref(gridimg, datauri);
}
function gridUpdate () {
if (showGrid) {
updateGrid(svgCanvas.getZoom());
}
$('#canvasGrid').toggle(showGrid);
$('#view_grid').toggleClass('push_button_pressed tool_button');
}
return {
name: 'view_grid',
svgicons: svgEditor.curConfig.extPath + 'grid-icon.xml',
zoomChanged: function(zoom) {
if (showGrid) {updateGrid(zoom);}
},
callback: function () {
if (showGrid) {
gridUpdate();
}
},
buttons: [{
id: 'view_grid',
type: 'context',
panel: 'editor_panel',
title: 'Show/Hide Grid',
events: {
click: function() {
svgEditor.curConfig.showGrid = showGrid = !showGrid;
gridUpdate();
}
}
}]
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-grid.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals svgEditor, svgCanvas, $*/
/*jslint vars: true, eqeq: true*/
/*
* ext-helloworld.js
*
* Licensed under the MIT License
*
* Copyright(c) 2010 Alexis Deveria
*
*/
/*
This is a very basic SVG-Edit extension. It adds a "Hello World" button in
the left panel. Clicking on the button, and then the canvas will show the
user the point on the canvas that was clicked on.
*/
svgEditor.addExtension("Hello World", function() {'use strict';
return {
name: "Hello World",
// For more notes on how to make an icon file, see the source of
// the helloworld-icon.xml
svgicons: svgEditor.curConfig.extPath + "helloworld-icon.xml",
// Multiple buttons can be added in this array
buttons: [{
// Must match the icon ID in helloworld-icon.xml
id: "hello_world",
// This indicates that the button will be added to the "mode"
// button panel on the left side
type: "mode",
// Tooltip text
title: "Say 'Hello World'",
// Events
events: {
'click': function() {
// The action taken when the button is clicked on.
// For "mode" buttons, any other button will
// automatically be de-pressed.
svgCanvas.setMode("hello_world");
}
}
}],
// This is triggered when the main mouse button is pressed down
// on the editor canvas (not the tool panels)
mouseDown: function() {
// Check the mode on mousedown
if(svgCanvas.getMode() == "hello_world") {
// The returned object must include "started" with
// a value of true in order for mouseUp to be triggered
return {started: true};
}
},
// This is triggered from anywhere, but "started" must have been set
// to true (see above). Note that "opts" is an object with event info
mouseUp: function(opts) {
// Check the mode on mouseup
if(svgCanvas.getMode() == "hello_world") {
var zoom = svgCanvas.getZoom();
// Get the actual coordinate by dividing by the zoom value
var x = opts.mouse_x / zoom;
var y = opts.mouse_y / zoom;
var text = "Hello World!\n\nYou clicked here: "
+ x + ", " + y;
// Show the text using the custom alert function
$.alert(text);
}
}
};
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-helloworld.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-imagelib.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="tool_imagelib">
<svg width="201" height="211" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m2.75,49.51761l56.56,-46.26761c12.73,8.25 25.71001,7 46.44,0.75l-56.03999,47.23944l-22.72002,25.01056l-24.23999,-26.73239z" id="svg_2" stroke-width="7"/>
<path fill="#a03333" stroke="#3f3f3f" d="m3.75,203.25002c14.33301,7 30.66699,7 46,0l0,-152.00002c-14.66699,8 -32.33301,8 -47,0l1,152.00002zm45.75,-152.25002l56.25,-46.75l0,151l-56,48.00002m-47.25,-154.25002l57.25,-46.5" id="svg_1" stroke-width="7" stroke-linecap="round"/>
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m49.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_5"/>
<path fill="#2f8e2f" stroke="#3f3f3f" d="m50.75,202.25c14.33301,7 30.66699,7.04253 46,0.04253l0,-151.04253c-14.66699,8 -32.33301,8 -47,0l1,151zm45.75,-151.25l56.25,-46.75l0,144.01219l-56,51.98782m-47.25,-151.25002l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_6"/>
<path fill="#efe8b8" stroke="#d6c47c" stroke-linecap="round" d="m95.75,49.51801l56.56,-46.26801c12.72998,8.25 25.71002,7 46.44,0.75l-56.03998,47.239l-22.72003,25.011l-24.23999,-26.73199z" stroke-width="7" id="svg_10"/>
<path fill="#336393" stroke="#3f3f3f" d="m96.75,200.29445c14.33301,7 30.66699,7 46,0l0,-149.04445c-14.66699,8 -32.33301,8 -47,0l1,149.04445zm45.75,-149.29445l56.25,-46.75l0,148.04445l-56,48m-47.25,-151.29445l57.25,-46.5" stroke-width="7" stroke-linecap="round" id="svg_11"/>
</g>
</svg>
</g>
</svg>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-imagelib.xml</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/xml</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>ext-markers.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
/*globals MathJax, svgEditor, svgCanvas, $*/
/*jslint es5: true, todo: true, vars: true*/
/*
* ext-mathjax.js
*
* Licensed under the Apache License
*
* Copyright(c) 2013 Jo Segaert
*
*/
svgEditor.addExtension("mathjax", function() {'use strict';
// Configuration of the MathJax extention.
// This will be added to the head tag before MathJax is loaded.
var /*mathjaxConfiguration = '<script type="text/x-mathjax-config">\
MathJax.Hub.Config({\
extensions: ["tex2jax.js"],\
jax: ["input/TeX","output/SVG"],\
showProcessingMessages: true,\
showMathMenu: false,\
showMathMenuMSIE: false,\
errorSettings: {\
message: ["[Math Processing Error]"],\
style: {color: "#CC0000", "font-style":"italic"}\
},\
elements: [],\
tex2jax: {\
ignoreClass: "tex2jax_ignore2", processClass: "tex2jax_process2",\
},\
TeX: {\
extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"]\
},\
"SVG": {\
}\
});\
</script>',*/
// mathjaxSrc = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js',
mathjaxSrcSecure = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG.js',
math,
locationX,
locationY,
mathjaxLoaded = false,
uiStrings = svgEditor.uiStrings;
// TODO: Implement language support. Move these uiStrings to the locale files and the code to the langReady callback.
$.extend(uiStrings, {
mathjax: {
embed_svg: 'Save as mathematics',
embed_mathml: 'Save as figure',
svg_save_warning: 'The math will be transformed into a figure is manipulatable like everything else. You will not be able to manipulate the TeX-code anymore. ',
mathml_save_warning: 'Advised. The math will be saved as a figure.',
title: 'Mathematics code editor'
}
});
function saveMath() {
var code = $('#mathjax_code_textarea').val();
// displaystyle to force MathJax NOT to use the inline style. Because it is
// less fancy!
MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']);
/*
* The MathJax library doesn't want to bloat your webpage so it creates
* every symbol (glymph) you need only once. These are saved in a <svg> on
* the top of your html document, just under the body tag. Each glymph has
* its unique id and is saved as a <path> in the <defs> tag of the <svg>
*
* Then when the symbols are needed in the rest of your html document they
* are refferd to by a <use> tag.
* Because of bug 1076 we can't just grab the defs tag on the top and add it
* to your formula's <svg> and copy the lot. So we have to replace each
* <use> tag by it's <path>.
*/
MathJax.Hub.queue.Push(
function() {
var mathjaxMath = $('.MathJax_SVG');
var svg = $(mathjaxMath.html());
svg.find('use').each(function() {
var x, y, id, transform;
// TODO: find a less pragmatic and more elegant solution to this.
if ($(this).attr('href')) {
id = $(this).attr('href').slice(1); // Works in Chrome.
} else {
id = $(this).attr('xlink:href').slice(1); // Works in Firefox.
}
var glymph = $('#' + id).clone().removeAttr('id');
x = $(this).attr('x');
y = $(this).attr('y');
transform = $(this).attr('transform');
if (transform && ( x || y )) {
glymph.attr('transform', transform + ' translate(' + x + ',' + y + ')');
}
else if (transform) {
glymph.attr('transform', transform);
}
else if (x || y) {
glymph.attr('transform', 'translate(' + x + ',' + y + ')');
}
$(this).replaceWith(glymph);
});
// Remove the style tag because it interferes with SVG-Edit.
svg.removeAttr('style');
svg.attr('xmlns', 'http://www.w3.org/2000/svg');
svgCanvas.importSvgString($('<div>').append(svg.clone()).html(), true);
svgCanvas.ungroupSelectedElement();
// TODO: To undo the adding of the Formula you now have to undo twice.
// This should only be once!
svgCanvas.moveSelectedElements(locationX, locationY, true);
}
);
}
return {
name: "MathJax",
svgicons: svgEditor.curConfig.extPath + "mathjax-icons.xml",
buttons: [{
id: "tool_mathjax",
type: "mode",
title: "Add Mathematics",
events: {
click: function() {
// Only load Mathjax when needed, we don't want to strain Svg-Edit any more.
// From this point on it is very probable that it will be needed, so load it.
if (mathjaxLoaded === false) {
$('<div id="mathjax">\
<!-- Here is where MathJax creates the math -->\
<div id="mathjax_creator" class="tex2jax_process" style="display:none">\
$${}$$\
</div>\
<div id="mathjax_overlay"></div>\
<div id="mathjax_container">\
<div id="tool_mathjax_back" class="toolbar_button">\
<button id="tool_mathjax_save">OK</button>\
<button id="tool_mathjax_cancel">Cancel</button>\
</div>\
<fieldset>\
<legend id="mathjax_legend">Mathematics Editor</legend>\
<label>\
<span id="mathjax_explication">Please type your mathematics in \
<a href="http://en.wikipedia.org/wiki/Help:Displaying_a_formula" target="_blank">TeX</a> code.</span></label>\
<textarea id="mathjax_code_textarea" spellcheck="false"></textarea>\
</fieldset>\
</div>\
</div>'
).insertAfter('#svg_prefs').hide();
// Make the MathEditor draggable.
$('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'});
// Add functionality and picture to cancel button.
$('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true))
.on("click touched", function() {
$('#mathjax').hide();
});
// Add functionality and picture to the save button.
$('#tool_mathjax_save').prepend($.getSvgIcon('ok', true))
.on("click touched", function() {
saveMath();
$('#mathjax').hide();
});
// MathJax preprocessing has to ignore most of the page.
$('body').addClass('tex2jax_ignore');
// Now get (and run) the MathJax Library.
$.getScript(mathjaxSrcSecure)
.done(function(script, textStatus) {
// When MathJax is loaded get the div where the math will be rendered.
MathJax.Hub.queue.Push(function() {
math = MathJax.Hub.getAllJax('#mathjax_creator')[0];
console.log(math);
mathjaxLoaded = true;
console.log('MathJax Loaded');
});
})
// If it fails.
.fail(function() {
console.log("Failed loadeing MathJax.");
$.alert("Failed loading MathJax. You will not be able to change the mathematics.");
});
}
// Set the mode.
svgCanvas.setMode("mathjax");
}
}
}],
mouseDown: function() {
if (svgCanvas.getMode() === "mathjax") {
return {started: true};
}
},
mouseUp: function(opts) {
if (svgCanvas.getMode() === "mathjax") {
// Get the coordinates from your mouse.
var zoom = svgCanvas.getZoom();
// Get the actual coordinate by dividing by the zoom value
locationX = opts.mouse_x / zoom;
locationY = opts.mouse_y / zoom;
$('#mathjax').show();
return {started: false}; // Otherwise the last selected object dissapears.
}
},
callback: function() {
$('<style>').text('\
#mathjax fieldset{\
padding: 5px;\
margin: 5px;\
border: 1px solid #DDD;\
}\
#mathjax label{\
display: block;\
margin: .5em;\
}\
#mathjax legend {\
max-width:195px;\
}\
#mathjax_overlay {\
position: absolute;\
top: 0;\
left: 0;\
right: 0;\
bottom: 0;\
background-color: black;\
opacity: 0.6;\
z-index: 20000;\
}\
\
#mathjax_container {\
position: absolute;\
top: 50px;\
padding: 10px;\
background-color: #B0B0B0;\
border: 1px outset #777;\
opacity: 1.0;\
font-family: Verdana, Helvetica, sans-serif;\
font-size: .8em;\
z-index: 20001;\
}\
\
#tool_mathjax_back {\
margin-left: 1em;\
overflow: auto;\
}\
\
#mathjax_legend{\
font-weight: bold;\
font-size:1.1em;\
}\
\
#mathjax_code_textarea {\\n\
margin: 5px .7em;\
overflow: hidden;\
width: 416px;\
display: block;\
height: 100px;\
}\
').appendTo('head');
// Add the MathJax configuration.
//$(mathjaxConfiguration).appendTo('head');
}
};
});
<svg xmlns="http://www.w3.org/2000/svg">
<g id="ext-panning">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<path fill="#7f0000" stroke="#000000" stroke-width="10" d="m1.00037,150.34581l55.30305,-55.30267l0,27.65093l22.17356,0l0,-44.21833l44.21825,0l0,-22.17357l-27.65095,0l55.30267,-55.30292l55.3035,55.30292l-27.65175,0l0,22.17357l44.21835,0l0,44.21833l22.17357,0l0,-27.65093l55.30345,55.30267l-55.30345,55.3035l0,-27.65175l-22.17357,0l0,44.21834l-44.21835,0l0,22.17355l27.65175,0l-55.3035,55.30348l-55.30267,-55.30348l27.65095,0l0,-22.17355l-44.21825,0l0,-44.21834l-22.17356,0l0,27.65175l-55.30305,-55.3035z"></path>
</svg>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="tool_shapelib">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,194.72501l0,0c0,-10.30901 35.8172,-18.666 80,-18.666c44.18298,0 80,8.35699 80,18.666l0,74.66699c0,10.30899 -35.81702,18.66699 -80,18.66699c-44.1828,0 -80,-8.358 -80,-18.66699l0,-74.66699z"/>
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,114.608l0,0c0,-10.309 35.8172,-18.6668 80,-18.6668c44.18298,0 80,8.3578 80,18.6668l0,74.66699c0,10.30901 -35.81702,18.666 -80,18.666c-44.1828,0 -80,-8.35699 -80,-18.666l0,-74.66699z"/>
<path fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m70,33.6667l0,0c0,-10.3094 35.8172,-18.6667 80,-18.6667c44.18298,0 80,8.3573 80,18.6667l0,74.6663c0,10.31 -35.81702,18.667 -80,18.667c-44.1828,0 -80,-8.357 -80,-18.667l0,-74.6663z"/>
<path id="svg_1" fill="#c0c0c0" stroke-linejoin="round" stroke-width="14" stroke="#202020" fill-rule="nonzero" d="m230,32.33334c0,10.30931 -35.81726,18.66666 -80,18.66666c-44.1828,0 -80,-8.35735 -80,-18.66666"/>
</svg>
</g>
</svg>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment