Rewrote connector extension to use SVG-Edit namespace attrs instead of ids/classes, removed extendWhitelist function, moved extensions to subfolder

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@1326 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
Alexis Deveria
2010-02-02 18:42:43 +00:00
parent 05179ee739
commit cf84f45d60
4 changed files with 109 additions and 103 deletions

View File

@@ -1,131 +0,0 @@
/*
* ext-arrows.js
*
* Licensed under the Apache License, Version 2
*
* Copyright(c) 2010 Alexis Deveria
*
*/
$(function() {
svgCanvas.addExtension("Arrows", function(S) {
var svgcontent = S.content,
getElem = S.getElem,
addElem = S.addSvgElementFromJson,
selElems;
var lang_list = {
"en":[
{"id": "arrow_none", "textContent": "No arrow" },
{"id": "arrow_arrow", "textContent": "Arrow" }
],
"fr":[
{"id": "arrow_none", "textContent": "Sans flèche" },
{"id": "arrow_arrow", "textContent": "Flèche" }
]
};
function showPanel(on) {
$('#arrow_panel').toggle(on);
if(on) {
var has_arrow = selElems[0].getAttribute("marker-mid");
$("#arrow_list").val(has_arrow?"arrow":"none");
}
}
function addArrow() {
var defs = S.findDefs();
var m_id = "se_arrow";
var marker = getElem(m_id);
if(!marker) {
marker = addElem({
"element": "marker",
"attr": {
"viewBox": "0 0 10 10",
"id": m_id,
"refX": 5,
"refY": 5,
"markerUnits": "strokeWidth",
"markerWidth": 5,
"markerHeight": 5,
"orient": "auto"
}
});
var arrow = addElem({
"element": "path",
"attr": {
"d": "m0,0l10,5l-10,5l5,-5l-5,-5z",
"fill": "#000"
}
});
marker.appendChild(arrow);
defs.appendChild(marker);
}
selElems[0].setAttribute("marker-mid", "url(#" + m_id + ")");
}
function remArrow() {
selElems[0].removeAttribute("marker-mid");
}
// Init code
(function() {
var conn_tools = $('<div id="arrow_panel">\
<label><select id="arrow_list">\
<option id="arrow_none" value="none">No arrow</option>\
<option id="arrow_arrow" value="arrow">Arrow</option>\
</select></label></div>"').hide().appendTo("#tools_top");
$('#arrow_list').change(function() {
switch ( this.value ) {
case "arrow":
addArrow();
break;
case "none":
remArrow();
break;
}
});
S.extendWhitelist({
"marker": ["viewBox", "id", "refX", "refY", "markerUnits", "markerWidth", "markerHeight", "orient"],
"polyline": ["class", "marker-mid"]
});
}());
return {
name: "Arrows",
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);
}
}
}
};
});
});

View File

@@ -1,401 +0,0 @@
/*
* ext-connector.js
*
* Licensed under the Apache License, Version 2
*
* Copyright(c) 2010 Alexis Deveria
*
*/
$(function() {
svgCanvas.addExtension("Connector", function(S) {
var svgcontent = S.content,
svgroot = S.root,
getNextId = S.getNextId,
getElem = S.getElem,
addElem = S.addSvgElementFromJson,
selManager = S.selectorManager,
started = false,
start_x,
start_y,
cur_line,
start_elem,
end_elem,
connections = [],
conn_class = "se_connect",
connect_str = "-SE_CONNECT-",
selElems = [];
var lang_list = {
"en":[
{"id": "mode_connect", "title": "Connect two objects" }
],
"fr":[
{"id": "mode_connect", "title": "Connecter deux objets"}
]
};
function showPanel(on) {
var conn_rules = $('#connector_rules');
if(!conn_rules.length) {
conn_rules = $('<style id="connector_rules"><\/style>').appendTo('head');
}
conn_rules.text(!on?"":"#tool_clone, #tool_topath, #tool_angle, #xy_panel { display: none !important; }");
$('#connector_panel').toggle(on);
}
function setPoint(elem, pos, x, y, setMid) {
var pts = elem.points;
var pt = svgroot.createSVGPoint();
pt.x = x;
pt.y = y;
if(pos === 'end') pos = pts.numberOfItems-1;
// TODO: Test for this on init, then use alt only if needed
try {
pts.replaceItem(pt, pos);
} catch(err) {
// Should only occur in FF which formats points attr as "n,n n,n", so just split
var pt_arr = elem.getAttribute("points").split(" ");
for(var i=0; i< pt_arr.length; i++) {
if(i == pos) {
pt_arr[i] = x + ',' + y;
}
}
elem.setAttribute("points",pt_arr.join(" "));
}
if(setMid) {
// Add center point
var pt_start = pts.getItem(0);
var pt_end = pts.getItem(pts.numberOfItems-1);
setPoint(elem, 1, (pt_end.x + pt_start.x)/2, (pt_end.y + pt_start.y)/2);
}
}
function findConnectors() {
// Check if selected elements have connections
var elems = selElems;
var i = elems.length;
var connectors = $(svgcontent).find("." + conn_class);
if(!connectors.length) return;
connections = [];
var sel = ':not(a,g,svg,.'+conn_class+')';
var all_els = [];
// Get children from groups
while(i--) {
var elem = elems[i];
if(!elem) continue;
// Get all children that cannot contain children
var solid_elems = $(elem).find(sel);
// Include self if okay
if($(elem).filter(sel).length) {
solid_elems.push(elem);
}
$.merge(all_els, solid_elems);
}
i = all_els.length;
if(i > 1) {
// Multiselected, so unselect connector
svgCanvas.removeFromSelection($("." + conn_class).toArray());
}
while(i--) {
var elem = all_els[i];
if(!elem) continue;
if(elem.getAttribute('class') == conn_class) continue;
var elem_id = elem.id;
connectors.each(function() {
var con_id = this.id;
if(con_id.indexOf(elem_id) != -1) {
var is_start = true;
if(con_id.indexOf(connect_str + elem_id) != -1) {
// Found connector (selected is end elem)
is_start = false;
}
var bb = svgCanvas.getStrokedBBox([elem]);
var x = bb.x + bb.width/2;
var y = bb.y + bb.height/2;
connections.push({
elem: elem,
connector: this,
is_start: is_start,
start_x: x,
start_y: y
});
}
});
}
}
function updateConnectors() {
// Updates connector lines based on selected elements
// Is not used on mousemove, as it runs getStrokedBBox every time,
// which isn't necessary there.
findConnectors();
if(connections.length) {
// Update line with element
var i = connections.length;
while(i--) {
var conn = connections[i];
var line = conn.connector;
var elem = conn.elem;
var bb = svgCanvas.getStrokedBBox([elem]);
var pt_x = bb.x + bb.width/2;
var pt_y = bb.y + bb.height/2;
setPoint(line, conn.is_start?0:'end', pt_x, pt_y, true);
}
}
}
// Init code
(function() {
// var conn_tools = $('<div id="connector_panel">\
// <label><select id="connector_arrow">\
// <option id="conn_arrow_none" value="none">No arrow</option>\
// <option id="conn_arrow_arrow" value="arrow">Arrow</option>\
// </select></label></div>"').hide().appendTo("#tools_top");
//
// $('#connector_arrow').change(function() {
// switch ( this.value ) {
// case "arrow":
// addArrow();
// break;
// case "none":
// remArrow();
// break;
// }
// });
S.extendWhitelist({
"marker": ["viewBox", "id", "refX", "refY", "markerUnits", "markerWidth", "markerHeight", "orient"],
"polyline": ["class", "marker-mid"]
});
var gse = svgCanvas.groupSelectedElements;
svgCanvas.groupSelectedElements = function() {
svgCanvas.removeFromSelection($("." + conn_class).toArray());
gse();
}
var mse = svgCanvas.moveSelectedElements;
svgCanvas.moveSelectedElements = function() {
svgCanvas.removeFromSelection($("." + conn_class).toArray());
mse.apply(this, arguments);
updateConnectors();
}
}());
return {
name: "Connector",
svgicons: "images/conn.svg",
buttons: [{
id: "mode_connect",
type: "mode",
icon: "images/cut.png",
title: "Connect two objects",
key: "Shift+3",
includeWith: {
button: '#tool_line',
isDefault: false,
position: 1
},
events: {
'click': function() {
svgCanvas.setMode("connector");
}
}
}],
addLangData: function(lang) {
return {
data: lang_list[lang]
};
},
mouseDown: function(opts) {
var e = opts.event;
start_x = opts.start_x,
start_y = opts.start_y;
var mode = svgCanvas.getMode();
if(mode == "connector") {
if(started) return;
var mouse_target = e.target;
var parents = $(mouse_target).parents();
if($.inArray(svgcontent, parents) != -1) {
// Connectable element
start_elem = mouse_target;
// Get center of source element
var bb = svgCanvas.getStrokedBBox([start_elem]);
var x = bb.x + bb.width/2;
var y = bb.y + bb.height/2;
started = true;
cur_line = addElem({
"element": "polyline",
"attr": {
"points": (x+','+y+' '+x+','+y+' '+start_x+','+start_y),
"stroke": '#000',
"stroke-width": 1,
"fill": "none",
"opacity": .5,
"style": "pointer-events:none"
}
});
}
return {
started: true
};
} else if(mode == "select") {
findConnectors();
}
},
mouseMove: function(opts) {
var zoom = svgCanvas.getZoom();
var e = opts.event;
var x = opts.mouse_x/zoom;
var y = opts.mouse_y/zoom;
var diff_x = x - start_x,
diff_y = y - start_y;
var mode = svgCanvas.getMode();
if(mode == "connector" && started) {
// Set middle point for marker
setPoint(cur_line, 'end', x, y, true);
} else if(mode == "select") {
var slen = selElems.length;
while(slen--) {
var elem = selElems[slen];
// Look for selected connector elements
if(elem && elem.getAttribute('class') == conn_class) {
// Remove the "translate" transform given to move
svgCanvas.removeFromSelection([elem]);
svgCanvas.getTransformList(elem).clear();
}
}
if(connections.length) {
// Update line with element
var i = connections.length;
while(i--) {
var conn = connections[i];
var line = conn.connector;
var elem = conn.elem;
var pt_x = conn.start_x + diff_x;
var pt_y = conn.start_y + diff_y;
setPoint(line, conn.is_start?0:'end', pt_x, pt_y, true);
}
}
}
},
mouseUp: function(opts) {
var zoom = svgCanvas.getZoom();
var e = opts.event,
x = opts.mouse_x/zoom,
y = opts.mouse_y/zoom;
if(svgCanvas.getMode() == "connector") {
if(e.target.parentNode.parentNode != svgcontent) {
// Not a valid target element, so remove line
$(cur_line).remove();
started = false;
return {
keep: false,
element: null,
started: started
}
} else if(e.target == start_elem) {
// Start line through click
started = true;
return {
keep: true,
element: null,
started: started
}
} else {
// Valid end element
end_elem = e.target;
var line_id = start_elem.id + connect_str + end_elem.id;
var alt_line_id = end_elem.id + connect_str + start_elem.id;
// Don't create connector if one already exists
if($('#'+line_id + ', #' + alt_line_id).length) {
$(cur_line).remove();
return {
keep: false,
element: null,
started: false
}
}
var bb = svgCanvas.getStrokedBBox([end_elem]);
var x = bb.x + bb.width/2;
var y = bb.y + bb.height/2;
setPoint(cur_line, 'end', x, y, true);
cur_line.id = line_id;
cur_line.setAttribute("class", conn_class);
svgCanvas.addToSelection([cur_line]);
svgCanvas.moveToBottomSelectedElement();
started = false;
return {
keep: true,
element: cur_line,
started: started
}
}
}
},
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.getAttribute('class') == conn_class) {
selManager.requestSelector(elem).showGrips(false);
if(opts.selectedElement && !opts.multiselected) {
// TODO: Set up context tools and hide most regular line tools
showPanel(true);
} else {
showPanel(false);
}
} else {
showPanel(false);
}
}
},
elementChanged: function(opts) {
var elem = opts.elems[0];
if (elem && elem.tagName == 'svg' && elem.id == "svgcontent") {
// Update svgcontent (can change on import)
svgcontent = elem;
}
updateConnectors();
}
};
});
});

View File

@@ -18,8 +18,8 @@
<script type="text/javascript" src="locale/locale.js"></script>
<script type="text/javascript" src="svgcanvas.js"></script>
<script type="text/javascript" src="svg-editor.js"></script>
<script type="text/javascript" src="ext-arrows.js"></script>
<script type="text/javascript" src="ext-connector.js"></script>
<script type="text/javascript" src="../extensions/ext-arrows.js"></script>
<script type="text/javascript" src="../extensions/ext-connector.js"></script>
<!-- Release version of script tags: >
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>

View File

@@ -31,32 +31,32 @@ var isOpera = !!window.opera,
// TODO: add <symbol> to this
// TODO: add <tspan> to this
svgWhiteList = {
"a": ["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": ["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": ["clipPathUnits", "id"],
"a": ["clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "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": ["clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "mask", "opacity", "r", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"],
"clipPath": ["clipPathUnits", "id", "class"],
"defs": [],
"desc": [],
"ellipse": ["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": ["id", "requiredFeatures", "stdDeviation"],
"filter": ["filterRes", "filterUnits", "height", "id", "primitiveUnits", "requiredFeatures", "width", "x", "xlink:href", "y"],
"g": ["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"],
"image": ["clip-path", "clip-rule", "filter", "height", "id", "mask", "opacity", "requiredFeatures", "style", "systemLanguage", "transform", "width", "x", "xlink:href", "xlink:title", "y"],
"line": ["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": ["id", "gradientTransform", "gradientUnits", "requiredFeatures", "spreadMethod", "systemLanguage", "x1", "x2", "xlink:href", "y1", "y2"],
"marker": ["id", "markerHeight", "markerUnits", "markerWidth", "orient", "preserveAspectRatio", "refX", "refY", "systemLanguage", "viewBox"],
"mask": ["height", "id", "maskContentUnits", "maskUnits", "width", "x", "y"],
"metadata": ["id"],
"path": ["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"],
"polygon": ["clip-path", "clip-rule", "id", "fill", "fill-opacity", "fill-rule", "filter", "id", "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": ["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": ["id", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "r", "requiredFeatures", "spreadMethod", "systemLanguage", "xlink:href"],
"rect": ["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": ["id", "offset", "requiredFeatures", "stop-color", "stop-opacity", "style", "systemLanguage"],
"switch": ["id", "requiredFeatures", "systemLanguage"],
"svg": ["clip-path", "clip-rule", "filter", "id", "height", "mask", "requiredFeatures", "style", "systemLanguage", "transform", "viewBox", "width", "xmlns", "xmlns:xlink"],
"text": ["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", "transform", "text-anchor", "x", "xml:space", "y"],
"ellipse": ["clip-path", "clip-rule", "cx", "cy", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "mask", "opacity", "requiredFeatures", "rx", "ry", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform"],
"feGaussianBlur": ["id", "class", "requiredFeatures", "stdDeviation"],
"filter": ["filterRes", "filterUnits", "height", "id", "class", "primitiveUnits", "requiredFeatures", "width", "x", "xlink:href", "y"],
"g": ["clip-path", "clip-rule", "id", "class", "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"],
"image": ["clip-path", "clip-rule", "filter", "height", "id", "class", "mask", "opacity", "requiredFeatures", "style", "systemLanguage", "transform", "width", "x", "xlink:href", "xlink:title", "y"],
"line": ["clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "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": ["id", "class", "gradientTransform", "gradientUnits", "requiredFeatures", "spreadMethod", "systemLanguage", "x1", "x2", "xlink:href", "y1", "y2"],
"marker": ["id", "class", "markerHeight", "markerUnits", "markerWidth", "orient", "preserveAspectRatio", "refX", "refY", "systemLanguage", "viewBox"],
"mask": ["height", "id", "class", "maskContentUnits", "maskUnits", "width", "x", "y"],
"metadata": ["id", "class"],
"path": ["clip-path", "clip-rule", "d", "fill", "fill-opacity", "fill-rule", "filter", "id", "class", "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"],
"polygon": ["clip-path", "clip-rule", "id", "class", "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": ["clip-path", "clip-rule", "id", "class", "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": ["id", "class", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "r", "requiredFeatures", "spreadMethod", "systemLanguage", "xlink:href"],
"rect": ["clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "height", "id", "class", "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": ["id", "class", "offset", "requiredFeatures", "stop-color", "stop-opacity", "style", "systemLanguage"],
"switch": ["id", "class", "requiredFeatures", "systemLanguage"],
"svg": ["clip-path", "clip-rule", "filter", "id", "class", "height", "mask", "requiredFeatures", "style", "systemLanguage", "transform", "viewBox", "width", "xmlns", "xmlns:xlink"],
"text": ["clip-path", "clip-rule", "fill", "fill-opacity", "fill-rule", "filter", "font-family", "font-size", "font-style", "font-weight", "id", "class", "mask", "opacity", "requiredFeatures", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "systemLanguage", "transform", "text-anchor", "x", "xml:space", "y"],
"title": [],
"use": ["clip-path", "clip-rule", "filter", "height", "id", "mask", "style", "transform", "width", "x", "xlink:href", "y"]
"use": ["clip-path", "clip-rule", "filter", "height", "id", "class", "mask", "style", "transform", "width", "x", "xlink:href", "y"]
},
@@ -876,6 +876,7 @@ function BatchCommand(text) {
svgns = "http://www.w3.org/2000/svg",
xlinkns = "http://www.w3.org/1999/xlink",
xmlns = "http://www.w3.org/XML/1998/namespace",
se_ns = "http://svg-edit.googlecode.com",
idprefix = "svg_",
svgdoc = container.ownerDocument,
svgroot = svgdoc.createElementNS(svgns, "svg");
@@ -993,25 +994,7 @@ function BatchCommand(text) {
addSvgElementFromJson: addSvgElementFromJson,
selectorManager: selectorManager,
findDefs: findDefs,
recalculateDimensions: recalculateDimensions,
// Probably only needed for extensions, so no need to make public?
// Also, should we prevent extensions from allowing <script> elements to be added?
extendWhitelist: function(new_data) {
$.each(new_data, function(elname, attrs) {
// add element
if(!(elname in svgWhiteList)) {
svgWhiteList[elname] = attrs;
} else {
$.each(attrs, function(i, attr) {
// add attributes
if($.inArray(attr, svgWhiteList[elname]) == -1) {
svgWhiteList[elname].push(attr);
}
});
}
});
}
recalculateDimensions: recalculateDimensions
});
extensions[name] = ext;
call("extension_added", ext);
@@ -1123,8 +1106,11 @@ function BatchCommand(text) {
if (!doc || !parent) return;
var allowedAttrs = svgWhiteList[node.nodeName];
// if this element is allowed
if (allowedAttrs != undefined) {
var se_attrs = [];
var i = node.attributes.length;
while (i--) {
// if the attribute is not in our whitelist, then remove it
@@ -1136,6 +1122,11 @@ function BatchCommand(text) {
// "href" and that namespaceURI matches the XLINK namespace
var attrName = attr.nodeName;
if (allowedAttrs.indexOf(attrName) == -1) {
// Bypassing the whitelist to allow se: prefixes. Is there
// a more appropriate way to do this?
if(attrName.indexOf('se:') == 0) {
se_attrs.push([attrName, attr.nodeValue]);
}
node.removeAttribute(attrName);
}
// special handling for path d attribute
@@ -1156,6 +1147,11 @@ function BatchCommand(text) {
}
}
}
$.each(se_attrs, function(i, attr) {
node.setAttributeNS(se_ns, attr[0], attr[1]);
});
// for filters, uses and gradients, ensure the xlink:href refers to a local element
var href = node.getAttributeNS(xlinkns,"href");
if(href &&
@@ -1283,11 +1279,14 @@ function BatchCommand(text) {
// keep calling it until there are none to remove
while (removeUnusedGrads() > 0) {};
pathActions.clear(true);
// Keep SVG-Edit comment on top
$.each(svgcontent.childNodes, function(i, node) {
if(i && node.nodeType == 8 && node.data.indexOf('Created with') != -1) {
svgcontent.insertBefore(node, svgcontent.firstChild);
}
});
var output = svgToString(svgcontent, 0);
return output;
}
@@ -1309,6 +1308,10 @@ function BatchCommand(text) {
var res = canvas.getResolution();
out.push(' width="' + res.w + '" height="' + res.h
+ '" xmlns:xlink="'+xlinkns+'" xmlns="'+svgns+'"');
if(svgcontent.getAttribute("xmlns:se")) {
// TODO: Check if any se: attributes are actually used
out.push(' xmlns:se="'+se_ns+'"');
}
} else {
for (var i=attrs.length-1; i>=0; i--) {
attr = attrs.item(i);
@@ -1316,6 +1319,7 @@ function BatchCommand(text) {
if (attrVal != "") {
if(attrVal.indexOf('pointer-events') == 0) continue;
if(attr.localName == "class" && attrVal.indexOf('se_') == 0) continue;
out.push(" ");
if(attr.localName == 'd') attrVal = pathActions.convertPath(elem, true);
if(!isNaN(attrVal)) {
@@ -1342,6 +1346,9 @@ function BatchCommand(text) {
}
else if(attr.namespaceURI == xmlns) {
out.push('xml:');
}
else if(attr.namespaceURI == se_ns) {
out.push('se:');
}
out.push(attr.localName); out.push("=\"");
out.push(attrVal); out.push("\"");
@@ -5757,6 +5764,13 @@ function BatchCommand(text) {
addCommandToHistory(batchCmd);
}
this.getEditorNS = function(add) {
if(add) {
svgcontent.setAttribute('xmlns:se', se_ns);
}
return se_ns;
}
this.setResolution = function(x, y) {
var res = canvas.getResolution();
var w = res.w, h = res.h;