diff --git a/editor/extensions/ext-connector.js b/editor/extensions/ext-connector.js
index cb6c2d45..adcc80d1 100644
--- a/editor/extensions/ext-connector.js
+++ b/editor/extensions/ext-connector.js
@@ -251,7 +251,7 @@ svgEditor.addExtension("Connector", function(S) {
svgCanvas.groupSelectedElements = function() {
svgCanvas.removeFromSelection($(conn_sel).toArray());
- gse();
+ return gse.apply(this, arguments);
}
var mse = svgCanvas.moveSelectedElements;
diff --git a/editor/images/svg_edit_icons.svg b/editor/images/svg_edit_icons.svg
index 2b1a3780..0ada459d 100644
--- a/editor/images/svg_edit_icons.svg
+++ b/editor/images/svg_edit_icons.svg
@@ -999,6 +999,36 @@
+
+
+
+
diff --git a/editor/svg-editor.css b/editor/svg-editor.css
index 6e55caf5..f0860a9d 100644
--- a/editor/svg-editor.css
+++ b/editor/svg-editor.css
@@ -163,6 +163,11 @@
padding-top: 4px
}
+#svg_editor #linkLabel > svg {
+ height: 20px;
+ padding-top: 4px;
+}
+
#color_tools .icon_label > * {
position: relative;
top: 1px;
diff --git a/editor/svg-editor.html b/editor/svg-editor.html
index bfbe919c..dca8b294 100644
--- a/editor/svg-editor.html
+++ b/editor/svg-editor.html
@@ -189,6 +189,7 @@
diff --git a/editor/svg-editor.js b/editor/svg-editor.js
index 04cb19b6..4e460a9e 100644
--- a/editor/svg-editor.js
+++ b/editor/svg-editor.js
@@ -392,6 +392,7 @@
'#rheightLabel, #iheightLabel':'height',
'#cornerRadiusLabel span':'c_radius',
'#angleLabel':'angle',
+ '#linkLabel,#tool_make_link,#tool_make_link_multi':'globe_link',
'#zoomLabel':'zoom',
'#tool_fill label': 'fill',
'#tool_stroke .icon_label': 'stroke',
@@ -1424,7 +1425,7 @@
var is_node = currentMode == 'pathedit'; //elem ? (elem.id && elem.id.indexOf('pathpointgrip') == 0) : false;
var menu_items = $('#cmenu_canvas li');
$('#selected_panel, #multiselected_panel, #g_panel, #rect_panel, #circle_panel,\
- #ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel, #use_panel').hide();
+ #ellipse_panel, #line_panel, #text_panel, #image_panel, #container_panel, #use_panel, #a_panel').hide();
if (elem != null) {
var elname = elem.nodeName;
@@ -1517,6 +1518,7 @@
// update contextual tools here
var panels = {
g: [],
+ a: [],
rect: ['rx','width','height'],
image: ['width','height'],
circle: ['cx','cy','r'],
@@ -1532,10 +1534,29 @@
// $('#g_panel').show();
// }
+ var link_href = null;
+ if (el_name === 'a') {
+ link_href = svgCanvas.getHref(elem);
+ $('#g_panel').show();
+ }
+
+ if(elem.parentNode.tagName === 'a') {
+ if(!$(elem).siblings().length) {
+ $('#a_panel').show();
+ link_href = svgCanvas.getHref(elem.parentNode);
+ }
+ }
+
+ // Hide/show the make_link buttons
+ $('#tool_make_link, #tool_make_link').toggle(!link_href);
+
+ if(link_href) {
+ $('#link_url').val(link_href);
+ }
+
if(panels[el_name]) {
var cur_panel = panels[el_name];
-
$('#' + el_name + '_panel').show();
$.each(cur_panel, function(i, item) {
@@ -1798,10 +1819,12 @@
setImageURL(this.value);
});
- $('#g_title').change(function() {
- svgCanvas.setGroupTitle(this.value);
- setInputWidth(this);
-
+ $('#link_url').change(function() {
+ if(this.value.length) {
+ svgCanvas.setLinkURL(this.value);
+ } else {
+ svgCanvas.removeHyperlink();
+ }
});
$('.attr_changer').change(function() {
@@ -2392,6 +2415,14 @@
}
}
+ var makeHyperlink = function() {
+ if (selectedElement != null || multiselected) {
+ $.prompt("Set URL for hyperlink", "http://", function(url) {
+ if(url) svgCanvas.makeHyperlink(url);
+ });
+ }
+ }
+
var moveSelected = function(dx,dy) {
if (selectedElement != null || multiselected) {
if(curConfig.gridSnapping) {
@@ -3819,6 +3850,7 @@
{sel:'#tool_move_top', fn: moveToTopSelected, evt: 'click', key: 'ctrl+shift+]'},
{sel:'#tool_move_bottom', fn: moveToBottomSelected, evt: 'click', key: 'ctrl+shift+['},
{sel:'#tool_topath', fn: convertToPath, evt: 'click'},
+ {sel:'#tool_make_link,#tool_make_link_multi', fn: makeHyperlink, evt: 'click'},
{sel:'#tool_undo', fn: clickUndo, evt: 'click', key: ['Z', true]},
{sel:'#tool_redo', fn: clickRedo, evt: 'click', key: ['Y', true]},
{sel:'#tool_clone,#tool_clone_multi', fn: clickClone, evt: 'click', key: ['C', true]},
diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js
index b9ff34eb..0bf5fc14 100644
--- a/editor/svgcanvas.js
+++ b/editor/svgcanvas.js
@@ -3539,7 +3539,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
textActions.select(mouse_target, pt.x, pt.y);
}
- if(tagName === "g" && getRotationAngle(mouse_target)) {
+ if((tagName === "g" || tagName === "a") && getRotationAngle(mouse_target)) {
// TODO: Allow method of in-group editing without having to do
// this (similar to editing rotated paths)
@@ -3553,7 +3553,7 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
leaveContext();
}
- if(parent.tagName !== 'g' || parent === current_layer || mouse_target === selectorManager.selectorParentGroup) {
+ if((parent.tagName !== 'g' && parent.tagName !== 'a') || parent === current_layer || mouse_target === selectorManager.selectorParentGroup) {
// Escape from in-group edit
return;
}
@@ -8433,6 +8433,39 @@ this.setImageURL = function(val) {
}
};
+// Function: setLinkURL
+// Sets the new link URL for the selected anchor element.
+//
+// Parameters:
+// val - String with the link URL/path
+this.setLinkURL = function(val) {
+ var elem = selectedElements[0];
+ if(!elem) return;
+ if(elem.tagName !== 'a') {
+ // See if parent is an anchor
+ var parents_a = $(elem).parents('a');
+ if(parents_a.length) {
+ elem = parents_a[0];
+ } else {
+ return;
+ }
+ }
+
+ var cur_href = getHref(elem);
+
+ if(cur_href === val) return;
+
+ var batchCmd = new BatchCommand("Change Link URL");
+
+ setHref(elem, val);
+ batchCmd.addSubCommand(new ChangeElementCommand(elem, {
+ "#href": cur_href
+ }));
+
+ addCommandToHistory(batchCmd);
+};
+
+
// Function: setRectRadius
// Sets the rx & ry values to the selected rect element to change its corner radius
//
@@ -8451,6 +8484,21 @@ this.setRectRadius = function(val) {
}
};
+// Function: makeHyperlink
+// Wraps the selected element(s) in an anchor element or converts group to one
+this.makeHyperlink = function(url) {
+ canvas.groupSelectedElements('a', url);
+
+ // TODO: If element is a single "g", convert to "a"
+ // if(selectedElements.length > 1 && selectedElements[1]) {
+
+}
+
+// Function: removeHyperlink
+this.removeHyperlink = function() {
+ canvas.ungroupSelectedElement();
+}
+
// Group: Element manipulation
// Function: setSegType
@@ -8899,16 +8947,39 @@ this.pasteElements = function(type) {
// Function: groupSelectedElements
// Wraps all the selected elements in a group (g) element
-this.groupSelectedElements = function() {
- var batchCmd = new BatchCommand("Group Elements");
+
+// Parameters:
+// type - type of element to group into, defaults to
+this.groupSelectedElements = function(type) {
+ if(!type) type = 'g';
+ var cmd_str = '';
+
+ switch ( type ) {
+ case "a":
+ cmd_str = "Make hyperlink";
+ var url = '';
+ if(arguments.length > 1) {
+ url = arguments[1];
+ }
+ break;
+ default:
+ type = 'g';
+ cmd_str = "Group Elements";
+ break;
+ }
+
+ var batchCmd = new BatchCommand(cmd_str);
// create and insert the group element
var g = addSvgElementFromJson({
- "element": "g",
+ "element": type,
"attr": {
"id": getNextId()
}
});
+ if(type === 'a') {
+ setHref(g, url);
+ }
batchCmd.addSubCommand(new InsertElementCommand(g));
// now move all children into the group
@@ -8916,6 +8987,11 @@ this.groupSelectedElements = function() {
while (i--) {
var elem = selectedElements[i];
if (elem == null) continue;
+
+ if (elem.parentNode.tagName === 'a' && elem.parentNode.childNodes.length === 1) {
+ elem = elem.parentNode;
+ }
+
var oldNextSibling = elem.nextSibling;
var oldParent = elem.parentNode;
g.appendChild(elem);
@@ -9125,8 +9201,14 @@ this.ungroupSelectedElement = function() {
convertToGroup(g);
return;
}
- if (g.tagName === "g") {
+ var parents_a = $(g).parents('a');
+ if(parents_a.length) {
+ g = parents_a[0];
+ }
+ // Look for parent "a"
+ if (g.tagName === "g" || g.tagName === "a") {
+
var batchCmd = new BatchCommand("Ungroup Elements");
var cmd = pushGroupProperties(g, true);
if(cmd) batchCmd.addSubCommand(cmd);