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 @@ + + + + + + + + + + + + + + Layer 1 + + + + + + + + + + + + + + + + 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 @@
+
- +
@@ -236,6 +237,7 @@
+
@@ -398,6 +400,13 @@
+ +
+ +
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);