diff --git a/editor/draw.js b/editor/draw.js index eca6e6e7..4c4c3ad6 100644 --- a/editor/draw.js +++ b/editor/draw.js @@ -21,6 +21,9 @@ if (!svgedit.draw) { var svg_ns = "http://www.w3.org/2000/svg"; var se_ns = "http://svg-edit.googlecode.com"; +var xmlns_ns = "http://www.w3.org/2000/xmlns/"; + +var randomize_ids = false; /** * This class encapsulates the concept of a layer in the drawing @@ -41,6 +44,12 @@ svgedit.draw.Layer.prototype.getGroup = function() { }; +// Called to ensure that drawings will or will not have +// randomized ids. +svgedit.draw.randomizeIds = function(enableRandomization) { + randomize_ids = enableRandomization; +}; + /** * This class encapsulates the concept of a SVG-edit drawing * @@ -99,7 +108,17 @@ svgedit.draw.Drawing = function(svgElem, opt_idPrefix) { * The nonce to use to uniquely identify elements across drawings. * @type {!String} */ - this.nonce_ = this.svgElem_.getAttributeNS(se_ns, 'nonce') || ""; + this.nonce_ = ""; + var n = this.svgElem_.getAttributeNS(se_ns, 'nonce'); + // If already set in the DOM, use the nonce throughout the document + // else, if randomizeIds(true) has been called, create and set the nonce. + if (!!n) { + this.nonce_ = n; + } else if (randomize_ids) { + this.nonce_ = Math.floor(Math.random() * 100001); + this.svgElem_.setAttributeNS(xmlns_ns, 'xmlns:se', se_ns); + this.svgElem_.setAttributeNS(se_ns, 'se:nonce', this.nonce_); + } }; svgedit.draw.Drawing.prototype.getElem_ = function(id) { diff --git a/editor/extensions/ext-arrows.js b/editor/extensions/ext-arrows.js index ebc3930c..4bb5cd25 100644 --- a/editor/extensions/ext-arrows.js +++ b/editor/extensions/ext-arrows.js @@ -15,8 +15,8 @@ svgEditor.addExtension("Arrows", function(S) { randomize_ids = S.randomize_ids, selElems; - svgCanvas.bind('setarrownonce', setArrowNonce); - svgCanvas.bind('unsetsetarrownonce', unsetArrowNonce); + svgCanvas.bind('setnonce', setArrowNonce); + svgCanvas.bind('unsetnonce', unsetArrowNonce); var lang_list = { "en":[ diff --git a/editor/svgcanvas.js b/editor/svgcanvas.js index 35343acb..8c2f729c 100644 --- a/editor/svgcanvas.js +++ b/editor/svgcanvas.js @@ -151,17 +151,28 @@ container.appendChild(svgroot); // The actual element that represents the final output SVG element var svgcontent = svgdoc.createElementNS(svgns, "svg"); -$(svgcontent).attr({ - id: 'svgcontent', - width: dimensions[0], - height: dimensions[1], - x: dimensions[0], - y: dimensions[1], - overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden', - xmlns: svgns, - "xmlns:se": se_ns, - "xmlns:xlink": xlinkns -}).appendTo(svgroot); +// This function resets the svgcontent element while keeping it in the DOM. +var clearSvgContentElement = canvas.clearSvgContentElement = function() { + while (svgcontent.firstChild) { svgcontent.removeChild(svgcontent.firstChild); } + + // TODO: Clear out all other attributes first? + $(svgcontent).attr({ + id: 'svgcontent', + width: dimensions[0], + height: dimensions[1], + x: dimensions[0], + y: dimensions[1], + overflow: curConfig.show_outside_canvas ? 'visible' : 'hidden', + xmlns: svgns, + "xmlns:se": se_ns, + "xmlns:xlink": xlinkns + }).appendTo(svgroot); + + // TODO: make this string optional and set by the client + var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ "); + svgcontent.appendChild(comment); +}; +clearSvgContentElement(); // Prefix string for element IDs var idprefix = "svg_"; @@ -175,24 +186,15 @@ canvas.setIdPrefix = function(p) { idprefix = p; }; -// nonce to uniquify id's -var nonce = Math.floor(Math.random() * 100001); - -// Boolean to indicate whether or not IDs given to elements should be random -var randomize_ids = false; - -// Set nonce if randomize_ids = true -if (randomize_ids) svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce); - // Current svgedit.draw.Drawing object // @type {svgedit.draw.Drawing} -var current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix); +canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix); // Function: getCurrentDrawing // Returns the current Drawing. // @return {svgedit.draw.Drawing} var getCurrentDrawing = canvas.getCurrentDrawing = function() { - return current_drawing; + return canvas.current_drawing_; }; // Float displaying the current zoom level (1 = 100%, .5 = 50%, etc) @@ -524,10 +526,6 @@ var restoreRefElems = function(elem) { }; (function() { - // TODO: make this string optional and set by the client - var comment = svgdoc.createComment(" Created with SVG-edit - http://svg-edit.googlecode.com/ "); - svgcontent.appendChild(comment); - // TODO For Issue 208: this is a start on a thumbnail // var svgthumb = svgdoc.createElementNS(svgns, "use"); // svgthumb.setAttribute('width', '100'); @@ -624,7 +622,7 @@ this.addExtension = function(name, ext_func) { var ext = ext_func($.extend(canvas.getPrivateMethods(), { svgroot: svgroot, svgcontent: svgcontent, - nonce: nonce, + nonce: getCurrentDrawing().getNonce(), selectorManager: selectorManager })); } else { @@ -6346,9 +6344,9 @@ this.getSvgString = function() { return this.svgCanvasToString(); }; -//function randomizeIds -// This function determines whether to add a nonce to the prefix, when -// generating IDs in SVG-Edit +// Function: randomizeIds +// This function determines whether to use a nonce in the prefix, when +// generating IDs for future documents in SVG-Edit. // // Parameters: // an opional boolean, which, if true, adds a nonce to the prefix. Thus @@ -6358,17 +6356,12 @@ this.getSvgString = function() { // this BEFORE calling svgCanvas.setSvgString // this.randomizeIds = function() { - if (arguments.length > 0 && arguments[0] == false) { - randomize_ids = false; - if (extensions["Arrows"]) call("unsetarrownonce") ; - } else { - randomize_ids = true; - if (!svgcontent.getAttributeNS(se_ns, 'nonce')) { - svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce); - if (extensions["Arrows"]) call("setarrownonce", nonce) ; - } - } -} + if (arguments.length > 0 && arguments[0] == false) { + svgedit.draw.randomizeIds(false); + } else { + svgedit.draw.randomizeIds(true); + } +}; // Function: uniquifyElems // Ensure each element has a unique ID @@ -6701,20 +6694,16 @@ this.setSvgString = function(xmlString) { var content = $(svgcontent); + canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent, idprefix); + // retrieve or set the nonce - n = svgcontent.getAttributeNS(se_ns, 'nonce'); - if (n) { - randomize_ids = true; - nonce = n; - if (extensions["Arrows"]) call("setarrownonce", n) ; - } else if (randomize_ids) { - svgcontent.setAttributeNS(xmlnsns, 'xmlns:se', se_ns); - svgcontent.setAttributeNS(se_ns, 'se:nonce', nonce); - if (extensions["Arrows"]) call("setarrownonce", nonce) ; + var nonce = getCurrentDrawing().getNonce(); + if (nonce) { + call("setnonce", nonce); + } else { + call("unsetnonce"); } - current_drawing = new svgedit.draw.Drawing(svgcontent, idprefix); - // change image href vals if possible content.find('image').each(function() { var image = this; @@ -7038,10 +7027,10 @@ this.cloneLayer = function(name) { // Deletes the current layer from the drawing and then clears the selection. This function // then calls the 'changed' handler. This is an undoable action. this.deleteCurrentLayer = function() { - var current_layer = current_drawing.getCurrentLayer(); + var current_layer = getCurrentDrawing().getCurrentLayer(); var nextSibling = current_layer.nextSibling; var parent = current_layer.parentNode; - current_layer = current_drawing.deleteCurrentLayer(); + current_layer = getCurrentDrawing().deleteCurrentLayer(); if (current_layer) { var batchCmd = new BatchCommand("Delete Layer"); // store in our Undo History @@ -7082,18 +7071,19 @@ this.setCurrentLayer = function(name) { // Returns: // true if the rename succeeded, false otherwise. this.renameCurrentLayer = function(newname) { - if (current_drawing.current_layer) { - var oldLayer = current_drawing.current_layer; + var drawing = getCurrentDrawing(); + if (drawing.current_layer) { + var oldLayer = drawing.current_layer; // setCurrentLayer will return false if the name doesn't already exist // this means we are free to rename our oldLayer if (!canvas.setCurrentLayer(newname)) { var batchCmd = new BatchCommand("Rename Layer"); // find the index of the layer - for (var i = 0; i < current_drawing.getNumLayers(); ++i) { - if (current_drawing.all_layers[i][1] == oldLayer) break; + for (var i = 0; i < drawing.getNumLayers(); ++i) { + if (drawing.all_layers[i][1] == oldLayer) break; } - var oldname = current_drawing.getLayerName(i); - current_drawing.all_layers[i][0] = svgedit.utilities.toXml(newname); + var oldname = drawing.getLayerName(i); + drawing.all_layers[i][0] = svgedit.utilities.toXml(newname); // now change the underlying title element contents var len = oldLayer.childNodes.length; @@ -7112,7 +7102,7 @@ this.renameCurrentLayer = function(newname) { } } } - current_drawing.current_layer = oldLayer; + drawing.current_layer = oldLayer; } return false; }; @@ -7129,31 +7119,32 @@ this.renameCurrentLayer = function(newname) { // Returns: // true if the current layer position was changed, false otherwise. this.setCurrentLayerPosition = function(newpos) { - if (current_drawing.current_layer && newpos >= 0 && newpos < current_drawing.getNumLayers()) { - for (var oldpos = 0; oldpos < current_drawing.getNumLayers(); ++oldpos) { - if (current_drawing.all_layers[oldpos][1] == current_drawing.current_layer) break; + var drawing = getCurrentDrawing(); + if (drawing.current_layer && newpos >= 0 && newpos < drawing.getNumLayers()) { + for (var oldpos = 0; oldpos < drawing.getNumLayers(); ++oldpos) { + if (drawing.all_layers[oldpos][1] == drawing.current_layer) break; } // some unknown error condition (current_layer not in all_layers) - if (oldpos == current_drawing.getNumLayers()) { return false; } + if (oldpos == drawing.getNumLayers()) { return false; } if (oldpos != newpos) { // if our new position is below us, we need to insert before the node after newpos var refLayer = null; - var oldNextSibling = current_drawing.current_layer.nextSibling; + var oldNextSibling = drawing.current_layer.nextSibling; if (newpos > oldpos ) { - if (newpos < current_drawing.getNumLayers()-1) { - refLayer = current_drawing.all_layers[newpos+1][1]; + if (newpos < drawing.getNumLayers()-1) { + refLayer = drawing.all_layers[newpos+1][1]; } } // if our new position is above us, we need to insert before the node at newpos else { - refLayer = current_drawing.all_layers[newpos][1]; + refLayer = drawing.all_layers[newpos][1]; } - svgcontent.insertBefore(current_drawing.current_layer, refLayer); - addCommandToHistory(new MoveElementCommand(current_drawing.current_layer, oldNextSibling, svgcontent)); + svgcontent.insertBefore(drawing.current_layer, refLayer); + addCommandToHistory(new MoveElementCommand(drawing.current_layer, oldNextSibling, svgcontent)); identifyLayers(); - canvas.setCurrentLayer(current_drawing.getLayerName(newpos)); + canvas.setCurrentLayer(drawing.getLayerName(newpos)); return true; } @@ -7203,9 +7194,10 @@ this.setLayerVisibility = function(layername, bVisible) { this.moveSelectedToLayer = function(layername) { // find the layer var layer = null; - for (var i = 0; i < current_drawing.getNumLayers(); ++i) { - if (current_drawing.getLayerName(i) == layername) { - layer = current_drawing.all_layers[i][1]; + var drawing = getCurrentDrawing(); + for (var i = 0; i < drawing.getNumLayers(); ++i) { + if (drawing.getLayerName(i) == layername) { + layer = drawing.all_layers[i][1]; break; } } @@ -7233,28 +7225,29 @@ this.moveSelectedToLayer = function(layername) { this.mergeLayer = function(skipHistory) { var batchCmd = new BatchCommand("Merge Layer"); - var prev = $(current_drawing.current_layer).prev()[0]; + var drawing = getCurrentDrawing(); + var prev = $(drawing.current_layer).prev()[0]; if(!prev) return; - var childs = current_drawing.current_layer.childNodes; + var childs = drawing.current_layer.childNodes; var len = childs.length; - var layerNextSibling = current_drawing.current_layer.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(current_drawing.current_layer, layerNextSibling, svgcontent)); + var layerNextSibling = drawing.current_layer.nextSibling; + batchCmd.addSubCommand(new RemoveElementCommand(drawing.current_layer, layerNextSibling, svgcontent)); - while(current_drawing.current_layer.firstChild) { - var ch = current_drawing.current_layer.firstChild; + while(drawing.current_layer.firstChild) { + var ch = drawing.current_layer.firstChild; if(ch.localName == 'title') { var chNextSibling = ch.nextSibling; - batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, current_drawing.current_layer)); - current_drawing.current_layer.removeChild(ch); + batchCmd.addSubCommand(new RemoveElementCommand(ch, chNextSibling, drawing.current_layer)); + drawing.current_layer.removeChild(ch); continue; } var oldNextSibling = ch.nextSibling; prev.appendChild(ch); - batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, current_drawing.current_layer)); + batchCmd.addSubCommand(new MoveElementCommand(ch, oldNextSibling, drawing.current_layer)); } // Remove current layer - svgcontent.removeChild(current_drawing.current_layer); + svgcontent.removeChild(drawing.current_layer); if(!skipHistory) { clearSelection(); @@ -7265,13 +7258,14 @@ this.mergeLayer = function(skipHistory) { addCommandToHistory(batchCmd); } - current_drawing.current_layer = prev; + drawing.current_layer = prev; return batchCmd; } this.mergeAllLayers = function() { var batchCmd = new BatchCommand("Merge all Layers"); - current_drawing.current_layer = current_drawing.all_layers[current_drawing.getNumLayers()-1][1]; + var drawing = getCurrentDrawing(); + drawing.current_layer = drawing.all_layers[drawing.getNumLayers()-1][1]; while($(svgcontent).children('g').length > 1) { batchCmd.addSubCommand(canvas.mergeLayer(true)); } @@ -7339,28 +7333,23 @@ this.clear = function() { pathActions.clear(); // clear the svgcontent node - var nodes = svgcontent.childNodes; - var len = svgcontent.childNodes.length; - var i = 0; - clearSelection(); - for(var rep = 0; rep < len; rep++){ - if (nodes[i].nodeType == 1) { // element node - svgcontent.removeChild(nodes[i]); - } else { - i++; - } - } + canvas.clearSvgContentElement(); + + // create new document + canvas.current_drawing_ = new svgedit.draw.Drawing(svgcontent); + // create empty first layer - current_drawing.all_layers = []; - canvas.createLayer("Layer 1"); // clear the undo stack canvas.undoMgr.resetUndoStack(); + // reset the selector manager selectorManager.initGroup(); + // reset the rubber band box rubberBox = selectorManager.getRubberBandBox(); + call("cleared"); }; diff --git a/test/draw_test.html b/test/draw_test.html index eceecfb3..ff65b80f 100644 --- a/test/draw_test.html +++ b/test/draw_test.html @@ -86,7 +86,7 @@ test('Test nonce', function() { expect(2); - + var doc = new svgedit.draw.Drawing(svg); equals(doc.getNonce(), ""); @@ -479,6 +479,18 @@ equals(LAYER3, drawing.all_layers[1][0]); equals(drawing.getCurrentLayer(), drawing.all_layers[1][1]); }); + + test('Test svgedit.draw.randomizeIds()', function() { + expect(2); + + svgedit.draw.randomizeIds(true); + var drawing = new svgedit.draw.Drawing(svg.cloneNode(true)); + ok(!!drawing.getNonce()); + + svgedit.draw.randomizeIds(false); + var drawing = new svgedit.draw.Drawing(svg); + ok(!drawing.getNonce()); + }); });