diff --git a/editor/draw.js b/editor/draw.js index f79b8032..a81f5718 100644 --- a/editor/draw.js +++ b/editor/draw.js @@ -20,6 +20,8 @@ if (!svgedit.draw) { } // alias var NS = svgedit.NS; +var LAYER_CLASS = svgedit.LAYER_CLASS; +var LAYER_CLASS_REGEX = svgedit.LAYER_CLASS_REGEX; var visElems = 'a,circle,ellipse,foreignObject,g,image,line,path,polygon,polyline,rect,svg,text,tspan,use'.split(','); @@ -30,6 +32,21 @@ var RandomizeModes = { }; var randomize_ids = RandomizeModes.LET_DOCUMENT_DECIDE; +/** + * Add class 'layer' to the element + * + * Parameters: + * @param {SVGGElement} elem - The SVG element to update + */ +function addLayerClass(elem) { + var classes = elem.getAttribute('class') + if (classes === null || classes === undefined || classes.length === 0) { + elem.setAttribute('class', LAYER_CLASS); + } else if (! LAYER_CLASS_REGEX.test(classes)) { + elem.setAttribute('class', classes + ' ' + LAYER_CLASS); + } +} + /** * This class encapsulates the concept of a layer in the drawing * @param {String} name - Layer name @@ -386,6 +403,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { a_layer = child; svgedit.utilities.walkTree(child, function(e){e.setAttribute("style", "pointer-events:inherit");}); a_layer.setAttribute("style", "pointer-events:none"); + addLayerClass(a_layer) } // if group did not have a name, it is an orphan else { @@ -407,22 +425,36 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { // TODO(codedread): What about internationalization of "Layer"? while (layernames.indexOf(("Layer " + i)) >= 0) { i++; } var newname = "Layer " + i; - a_layer = svgdoc.createElementNS(NS.SVG, "g"); - var layer_title = svgdoc.createElementNS(NS.SVG, "title"); - layer_title.textContent = newname; - a_layer.appendChild(layer_title); + a_layer = this._doCreateLayer(newname); var j; for (j = 0; j < orphans.length; ++j) { a_layer.appendChild(orphans[j]); } - this.svgElem_.appendChild(a_layer); - this.all_layers.push( [newname, a_layer] ); + this.all_layers.push([newname, a_layer] ); } svgedit.utilities.walkTree(a_layer, function(e){e.setAttribute("style", "pointer-events:inherit");}); this.current_layer = a_layer; this.current_layer.setAttribute("style", "pointer-events:all"); }; + /** + * Private function that actually creates a new top-level layer in the drawing + * with the given name and sets the current layer to it. + * @param {string} name - The given name + * @returns {SVGGElement} The SVGGElement of the new layer, which is + * also the current layer of this drawing. + */ + svgedit.draw.Drawing.prototype._doCreateLayer = function(name) { + var svgdoc = this.svgElem_.ownerDocument; + var new_layer = svgdoc.createElementNS(NS.SVG, "g"); + addLayerClass(new_layer); + var layer_title = svgdoc.createElementNS(NS.SVG, "title"); + layer_title.textContent = name; + new_layer.appendChild(layer_title); + this.svgElem_.appendChild(new_layer); + return new_layer; + }; + /** * Creates a new top-level layer in the drawing with the given name and * sets the current layer to it. @@ -431,12 +463,7 @@ svgedit.draw.Drawing.prototype.identifyLayers = function() { * also the current layer of this drawing. */ svgedit.draw.Drawing.prototype.createLayer = function(name) { - var svgdoc = this.svgElem_.ownerDocument; - var new_layer = svgdoc.createElementNS(NS.SVG, "g"); - var layer_title = svgdoc.createElementNS(NS.SVG, "title"); - layer_title.textContent = name; - new_layer.appendChild(layer_title); - this.svgElem_.appendChild(new_layer); + var new_layer = this._doCreateLayer(name); this.identifyLayers(); return new_layer; }; diff --git a/editor/svg-editor.js b/editor/svg-editor.js index 25bbbb2c..868f6fc8 100644 --- a/editor/svg-editor.js +++ b/editor/svg-editor.js @@ -1835,6 +1835,15 @@ TODOS }); }; + /** + * Test whether an element is a layer or not. + * @param {SVGGElement} elem - The SVGGElement to test. + * @returns {boolean} True if the element is a layer + */ + function isLayer(elem) { + return elem && elem.tagName === 'g' && svgedit.LAYER_CLASS_REGEX.test(elem.getAttribute('class')) + } + // called when any element has changed var elementChanged = function(win, elems) { var i, @@ -1846,10 +1855,13 @@ TODOS for (i = 0; i < elems.length; ++i) { var elem = elems[i]; - // if the element changed was the svg, then it could be a resolution change - if (elem && elem.tagName === 'svg') { + var isSvgElem = (elem && elem.tagName === 'svg'); + if (isSvgElem || isLayer(elem)) { populateLayers(); - updateCanvas(); + // if the element changed was the svg, then it could be a resolution change + if (isSvgElem) { + updateCanvas(); + } } // Update selectedElement if element is no longer part of the image. // This occurs for the text elements in Firefox diff --git a/editor/svgedit.js b/editor/svgedit.js index 6149b2de..cf2fcb87 100644 --- a/editor/svgedit.js +++ b/editor/svgedit.js @@ -15,8 +15,10 @@ svgedit = { XLINK: 'http://www.w3.org/1999/xlink', XML: 'http://www.w3.org/XML/1998/namespace', XMLNS: 'http://www.w3.org/2000/xmlns/' // see http://www.w3.org/TR/REC-xml-names/#xmlReserved - } + }, + LAYER_CLASS: 'layer' }; +svgedit.LAYER_CLASS_REGEX = new RegExp('(\\s|^)' + svgedit.LAYER_CLASS + '(\\s|$)'); // return the svgedit.NS with key values switched and lowercase svgedit.getReverseNS = function() {'use strict'; diff --git a/test/draw_test.html b/test/draw_test.html index b1555c86..b84dd706 100644 --- a/test/draw_test.html +++ b/test/draw_test.html @@ -19,12 +19,16 @@ } }; var NS = svgedit.NS; + var LAYER_CLASS = svgedit.LAYER_CLASS; var NONCE = 'foo'; var LAYER1 = 'Layer 1'; var LAYER2 = 'Layer 2'; var LAYER3 = 'Layer 3'; var svg = document.createElementNS(NS.SVG, 'svg'); + var sandbox = document.getElementById('sandbox'); + // Firefox throws exception in getBBox() when svg is not attached to DOM. + sandbox.appendChild(svg); // Set up with nonce. var svg_n = document.createElementNS(NS.SVG, 'svg'); @@ -244,7 +248,7 @@ }); test('Test identifyLayers() with empty document', function() { - expect(9); + expect(10); var drawing = new svgedit.draw.Drawing(svg); // By default, an empty document gets an empty group created. @@ -260,6 +264,7 @@ ok(empty_layer); equals(empty_layer, drawing.getSvgElem().firstChild); equals(empty_layer.tagName, 'g'); + equals(empty_layer.getAttribute('class'), LAYER_CLASS); ok(empty_layer.hasChildNodes()); equals(empty_layer.childNodes.length, 1); var firstChild = empty_layer.childNodes.item(0); @@ -269,7 +274,7 @@ }); test('Test identifyLayers() with some layers', function() { - expect(5); + expect(8); var drawing = new svgedit.draw.Drawing(svg); setupSvgWith3Layers(svg); @@ -283,11 +288,15 @@ equals(drawing.all_layers[1][1], svg.childNodes.item(1)); equals(drawing.all_layers[2][1], svg.childNodes.item(2)); + equals(drawing.all_layers[0][1].getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[1][1].getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[2][1].getAttribute('class'), LAYER_CLASS); + cleanupSvg(svg); }); test('Test identifyLayers() with some layers and orphans', function() { - expect(10); + expect(14); setupSvgWith3Layers(svg); @@ -307,6 +316,11 @@ equals(drawing.all_layers[2][1], svg.childNodes.item(2)); equals(drawing.all_layers[3][1], svg.childNodes.item(3)); + equals(drawing.all_layers[0][1].getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[1][1].getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[2][1].getAttribute('class'), LAYER_CLASS); + equals(drawing.all_layers[3][1].getAttribute('class'), LAYER_CLASS); + var layer4 = drawing.all_layers[3][1]; equals(layer4.tagName, 'g'); equals(layer4.childNodes.length, 3); @@ -367,7 +381,7 @@ }); test('Test createLayer()', function() { - expect(6); + expect(7); var drawing = new svgedit.draw.Drawing(svg); setupSvgWith3Layers(svg); @@ -380,6 +394,7 @@ var layer_g = drawing.createLayer(NEW_LAYER_NAME); equals(4, drawing.getNumLayers()); equals(layer_g, drawing.getCurrentLayer()); + equals(layer_g.getAttribute('class'), LAYER_CLASS); equals(NEW_LAYER_NAME, drawing.getCurrentLayerName()); equals(NEW_LAYER_NAME, drawing.getLayerName(3)); @@ -530,6 +545,6 @@

    - +