| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| dojo.provide("dojo.gfx.svg"); |
| |
| dojo.require("dojo.lang.declare"); |
| dojo.require("dojo.svg"); |
| |
| dojo.require("dojo.gfx.color"); |
| dojo.require("dojo.gfx.common"); |
| dojo.require("dojo.gfx.shape"); |
| dojo.require("dojo.gfx.path"); |
| |
| dojo.require("dojo.experimental"); |
| dojo.experimental("dojo.gfx.svg"); |
| |
| dojo.gfx.svg.getRef = function(fill){ |
| // summary: returns a DOM Node specified by the fill argument or null |
| // fill: String: an SVG fill |
| if(!fill || fill == "none") return null; |
| if(fill.match(/^url\(#.+\)$/)){ |
| return dojo.byId(fill.slice(5, -1)); // Node |
| } |
| // Opera's bug: incorrect representation of a reference |
| if(dojo.render.html.opera && fill.match(/^#dj_unique_.+$/)){ |
| // we assume here that a reference was generated by dojo.gfx |
| return dojo.byId(fill.slice(1)); // Node |
| } |
| return null; // Node |
| }; |
| |
| dojo.lang.extend(dojo.gfx.Shape, { |
| // summary: SVG-specific implementation of dojo.gfx.Shape methods |
| |
| setFill: function(fill){ |
| // summary: sets a fill object (SVG) |
| // fill: Object: a fill object |
| // (see dojo.gfx.defaultLinearGradient, |
| // dojo.gfx.defaultRadialGradient, |
| // dojo.gfx.defaultPattern, |
| // or dojo.gfx.color.Color) |
| |
| if(!fill){ |
| // don't fill |
| this.fillStyle = null; |
| this.rawNode.setAttribute("fill", "none"); |
| this.rawNode.setAttribute("fill-opacity", 0); |
| return this; |
| } |
| if(typeof(fill) == "object" && "type" in fill){ |
| // gradient |
| switch(fill.type){ |
| case "linear": |
| var f = dojo.gfx.makeParameters(dojo.gfx.defaultLinearGradient, fill); |
| var gradient = this._setFillObject(f, "linearGradient"); |
| dojo.lang.forEach(["x1", "y1", "x2", "y2"], function(x){ |
| gradient.setAttribute(x, f[x].toFixed(8)); |
| }); |
| break; |
| case "radial": |
| var f = dojo.gfx.makeParameters(dojo.gfx.defaultRadialGradient, fill); |
| var gradient = this._setFillObject(f, "radialGradient"); |
| dojo.lang.forEach(["cx", "cy", "r"], function(x){ |
| gradient.setAttribute(x, f[x].toFixed(8)); |
| }); |
| break; |
| case "pattern": |
| var f = dojo.gfx.makeParameters(dojo.gfx.defaultPattern, fill); |
| var pattern = this._setFillObject(f, "pattern"); |
| dojo.lang.forEach(["x", "y", "width", "height"], function(x){ |
| pattern.setAttribute(x, f[x].toFixed(8)); |
| }); |
| break; |
| } |
| return this; |
| } |
| // color object |
| var f = dojo.gfx.normalizeColor(fill); |
| this.fillStyle = f; |
| this.rawNode.setAttribute("fill", f.toCss()); |
| this.rawNode.setAttribute("fill-opacity", f.a); |
| return this; // self |
| }, |
| |
| setStroke: function(stroke){ |
| // summary: sets a stroke object (SVG) |
| // stroke: Object: a stroke object |
| // (see dojo.gfx.defaultStroke) |
| |
| if(!stroke){ |
| // don't stroke |
| this.strokeStyle = null; |
| this.rawNode.setAttribute("stroke", "none"); |
| this.rawNode.setAttribute("stroke-opacity", 0); |
| return this; |
| } |
| // normalize the stroke |
| this.strokeStyle = dojo.gfx.makeParameters(dojo.gfx.defaultStroke, stroke); |
| this.strokeStyle.color = dojo.gfx.normalizeColor(this.strokeStyle.color); |
| // generate attributes |
| var s = this.strokeStyle; |
| var rn = this.rawNode; |
| if(s){ |
| rn.setAttribute("stroke", s.color.toCss()); |
| rn.setAttribute("stroke-opacity", s.color.a); |
| rn.setAttribute("stroke-width", s.width); |
| rn.setAttribute("stroke-linecap", s.cap); |
| if(typeof(s.join) == "number"){ |
| rn.setAttribute("stroke-linejoin", "miter"); |
| rn.setAttribute("stroke-miterlimit", s.join); |
| }else{ |
| rn.setAttribute("stroke-linejoin", s.join); |
| } |
| } |
| return this; // self |
| }, |
| |
| _setFillObject: function(f, nodeType){ |
| var def_elems = this.rawNode.parentNode.getElementsByTagName("defs"); |
| if(def_elems.length == 0){ return this; } |
| this.fillStyle = f; |
| var defs = def_elems[0]; |
| var fill = this.rawNode.getAttribute("fill"); |
| var ref = dojo.gfx.svg.getRef(fill); |
| if(ref){ |
| fill = ref; |
| if(fill.tagName.toLowerCase() != nodeType.toLowerCase()){ |
| var id = fill.id; |
| fill.parentNode.removeChild(fill); |
| fill = document.createElementNS(dojo.svg.xmlns.svg, nodeType); |
| fill.setAttribute("id", id); |
| defs.appendChild(fill); |
| }else{ |
| while(fill.childNodes.length){ |
| fill.removeChild(fill.lastChild); |
| } |
| } |
| }else{ |
| fill = document.createElementNS(dojo.svg.xmlns.svg, nodeType); |
| fill.setAttribute("id", dojo.dom.getUniqueId()); |
| defs.appendChild(fill); |
| } |
| if(nodeType == "pattern"){ |
| fill.setAttribute("patternUnits", "userSpaceOnUse"); |
| var img = document.createElementNS(dojo.svg.xmlns.svg, "image"); |
| img.setAttribute("x", 0); |
| img.setAttribute("y", 0); |
| img.setAttribute("width", f.width .toFixed(8)); |
| img.setAttribute("height", f.height.toFixed(8)); |
| img.setAttributeNS(dojo.svg.xmlns.xlink, "href", f.src); |
| fill.appendChild(img); |
| }else{ |
| fill.setAttribute("gradientUnits", "userSpaceOnUse"); |
| for(var i = 0; i < f.colors.length; ++i){ |
| f.colors[i].color = dojo.gfx.normalizeColor(f.colors[i].color); |
| var t = document.createElementNS(dojo.svg.xmlns.svg, "stop"); |
| t.setAttribute("offset", f.colors[i].offset.toFixed(8)); |
| t.setAttribute("stop-color", f.colors[i].color.toCss()); |
| fill.appendChild(t); |
| } |
| } |
| this.rawNode.setAttribute("fill", "url(#" + fill.getAttribute("id") +")"); |
| this.rawNode.removeAttribute("fill-opacity"); |
| return fill; |
| }, |
| |
| _applyTransform: function() { |
| var matrix = this._getRealMatrix(); |
| if(matrix){ |
| var tm = this.matrix; |
| this.rawNode.setAttribute("transform", "matrix(" + |
| tm.xx.toFixed(8) + "," + tm.yx.toFixed(8) + "," + |
| tm.xy.toFixed(8) + "," + tm.yy.toFixed(8) + "," + |
| tm.dx.toFixed(8) + "," + tm.dy.toFixed(8) + ")"); |
| }else{ |
| this.rawNode.removeAttribute("transform"); |
| } |
| return this; |
| }, |
| |
| setRawNode: function(rawNode){ |
| // summary: |
| // assigns and clears the underlying node that will represent this |
| // shape. Once set, transforms, gradients, etc, can be applied. |
| // (no fill & stroke by default) |
| with(rawNode){ |
| setAttribute("fill", "none"); |
| setAttribute("fill-opacity", 0); |
| setAttribute("stroke", "none"); |
| setAttribute("stroke-opacity", 0); |
| setAttribute("stroke-width", 1); |
| setAttribute("stroke-linecap", "butt"); |
| setAttribute("stroke-linejoin", "miter"); |
| setAttribute("stroke-miterlimit", 4); |
| } |
| this.rawNode = rawNode; |
| }, |
| |
| moveToFront: function(){ |
| // summary: moves a shape to front of its parent's list of shapes (SVG) |
| this.rawNode.parentNode.appendChild(this.rawNode); |
| return this; // self |
| }, |
| moveToBack: function(){ |
| // summary: moves a shape to back of its parent's list of shapes (SVG) |
| this.rawNode.parentNode.insertBefore(this.rawNode, this.rawNode.parentNode.firstChild); |
| return this; // self |
| }, |
| |
| setShape: function(newShape){ |
| // summary: sets a shape object (SVG) |
| // newShape: Object: a shape object |
| // (see dojo.gfx.defaultPath, |
| // dojo.gfx.defaultPolyline, |
| // dojo.gfx.defaultRect, |
| // dojo.gfx.defaultEllipse, |
| // dojo.gfx.defaultCircle, |
| // dojo.gfx.defaultLine, |
| // or dojo.gfx.defaultImage) |
| this.shape = dojo.gfx.makeParameters(this.shape, newShape); |
| for(var i in this.shape){ |
| if(i != "type"){ this.rawNode.setAttribute(i, this.shape[i]); } |
| } |
| return this; // self |
| }, |
| |
| attachFill: function(rawNode){ |
| // summary: deduces a fill style from a Node. |
| // rawNode: Node: an SVG node |
| var fillStyle = null; |
| if(rawNode){ |
| var fill = rawNode.getAttribute("fill"); |
| if(fill == "none"){ return; } |
| var ref = dojo.gfx.svg.getRef(fill); |
| if(ref){ |
| var gradient = ref; |
| switch(gradient.tagName.toLowerCase()){ |
| case "lineargradient": |
| fillStyle = this._getGradient(dojo.gfx.defaultLinearGradient, gradient); |
| dojo.lang.forEach(["x1", "y1", "x2", "y2"], function(x){ |
| fillStyle[x] = gradient.getAttribute(x); |
| }); |
| break; |
| case "radialgradient": |
| fillStyle = this._getGradient(dojo.gfx.defaultRadialGradient, gradient); |
| dojo.lang.forEach(["cx", "cy", "r"], function(x){ |
| fillStyle[x] = gradient.getAttribute(x); |
| }); |
| fillStyle.cx = gradient.getAttribute("cx"); |
| fillStyle.cy = gradient.getAttribute("cy"); |
| fillStyle.r = gradient.getAttribute("r"); |
| break; |
| case "pattern": |
| fillStyle = dojo.lang.shallowCopy(dojo.gfx.defaultPattern, true); |
| dojo.lang.forEach(["x", "y", "width", "height"], function(x){ |
| fillStyle[x] = gradient.getAttribute(x); |
| }); |
| fillStyle.src = gradient.firstChild.getAttributeNS(dojo.svg.xmlns.xlink, "href"); |
| break; |
| } |
| }else{ |
| fillStyle = new dojo.gfx.color.Color(fill); |
| var opacity = rawNode.getAttribute("fill-opacity"); |
| if(opacity != null) fillStyle.a = opacity; |
| } |
| } |
| return fillStyle; // Object |
| }, |
| |
| _getGradient: function(defaultGradient, gradient){ |
| var fillStyle = dojo.lang.shallowCopy(defaultGradient, true); |
| fillStyle.colors = []; |
| for(var i = 0; i < gradient.childNodes.length; ++i){ |
| fillStyle.colors.push({ |
| offset: gradient.childNodes[i].getAttribute("offset"), |
| color: new dojo.gfx.color.Color(gradient.childNodes[i].getAttribute("stop-color")) |
| }); |
| } |
| return fillStyle; |
| }, |
| |
| attachStroke: function(rawNode){ |
| // summary: deduces a stroke style from a Node. |
| // rawNode: Node: an SVG node |
| if(!rawNode){ return; } |
| var stroke = rawNode.getAttribute("stroke"); |
| if(stroke == null || stroke == "none") return null; |
| var strokeStyle = dojo.lang.shallowCopy(dojo.gfx.defaultStroke, true); |
| var color = new dojo.gfx.color.Color(stroke); |
| if(color){ |
| strokeStyle.color = color; |
| strokeStyle.color.a = rawNode.getAttribute("stroke-opacity"); |
| strokeStyle.width = rawNode.getAttribute("stroke-width"); |
| strokeStyle.cap = rawNode.getAttribute("stroke-linecap"); |
| strokeStyle.join = rawNode.getAttribute("stroke-linejoin"); |
| if(strokeStyle.join == "miter"){ |
| strokeStyle.join = rawNode.getAttribute("stroke-miterlimit"); |
| } |
| } |
| return strokeStyle; // Object |
| }, |
| |
| attachTransform: function(rawNode){ |
| // summary: deduces a transformation matrix from a Node. |
| // rawNode: Node: an SVG node |
| var matrix = null; |
| if(rawNode){ |
| matrix = rawNode.getAttribute("transform"); |
| if(matrix.match(/^matrix\(.+\)$/)){ |
| var t = matrix.slice(7, -1).split(","); |
| matrix = dojo.gfx.matrix.normalize({ |
| xx: parseFloat(t[0]), xy: parseFloat(t[2]), |
| yx: parseFloat(t[1]), yy: parseFloat(t[3]), |
| dx: parseFloat(t[4]), dy: parseFloat(t[5]) |
| }); |
| } |
| } |
| return matrix; // dojo.gfx.matrix.Matrix |
| }, |
| |
| attachShape: function(rawNode){ |
| // summary: builds a shape from a Node. |
| // rawNode: Node: an SVG node |
| var shape = null; |
| if(rawNode){ |
| shape = dojo.lang.shallowCopy(this.shape, true); |
| for(var i in shape) { |
| shape[i] = rawNode.getAttribute(i); |
| } |
| } |
| return shape; // dojo.gfx.Shape |
| }, |
| |
| attach: function(rawNode){ |
| // summary: reconstructs all shape parameters from a Node. |
| // rawNode: Node: an SVG node |
| if(rawNode) { |
| this.rawNode = rawNode; |
| this.fillStyle = this.attachFill(rawNode); |
| this.strokeStyle = this.attachStroke(rawNode); |
| this.matrix = this.attachTransform(rawNode); |
| this.shape = this.attachShape(rawNode); |
| } |
| } |
| }); |
| |
| dojo.declare("dojo.gfx.Group", dojo.gfx.Shape, { |
| // summary: a group shape (SVG), which can be used |
| // to logically group shapes (e.g, to propagate matricies) |
| |
| setRawNode: function(rawNode){ |
| // summary: sets a raw SVG node to be used by this shape |
| // rawNode: Node: an SVG node |
| this.rawNode = rawNode; |
| } |
| }); |
| dojo.gfx.Group.nodeType = "g"; |
| |
| dojo.declare("dojo.gfx.Rect", dojo.gfx.shape.Rect, { |
| // summary: a rectangle shape (SVG) |
| |
| attachShape: function(rawNode){ |
| // summary: builds a rectangle shape from a Node. |
| // rawNode: Node: an SVG node |
| var shape = null; |
| if(rawNode){ |
| shape = dojo.gfx.Rect.superclass.attachShape.apply(this, arguments); |
| shape.r = Math.min(rawNode.getAttribute("rx"), rawNode.getAttribute("ry")); |
| } |
| return shape; // dojo.gfx.shape.Rect |
| }, |
| setShape: function(newShape){ |
| // summary: sets a rectangle shape object (SVG) |
| // newShape: Object: a rectangle shape object |
| this.shape = dojo.gfx.makeParameters(this.shape, newShape); |
| this.bbox = null; |
| for(var i in this.shape){ |
| if(i != "type" && i != "r"){ this.rawNode.setAttribute(i, this.shape[i]); } |
| } |
| this.rawNode.setAttribute("rx", this.shape.r); |
| this.rawNode.setAttribute("ry", this.shape.r); |
| return this; // self |
| } |
| }); |
| dojo.gfx.Rect.nodeType = "rect"; |
| |
| dojo.gfx.Ellipse = dojo.gfx.shape.Ellipse; |
| dojo.gfx.Ellipse.nodeType = "ellipse"; |
| |
| dojo.gfx.Circle = dojo.gfx.shape.Circle; |
| dojo.gfx.Circle.nodeType = "circle"; |
| |
| dojo.gfx.Line = dojo.gfx.shape.Line; |
| dojo.gfx.Line.nodeType = "line"; |
| |
| dojo.declare("dojo.gfx.Polyline", dojo.gfx.shape.Polyline, { |
| // summary: a polyline/polygon shape (SVG) |
| |
| setShape: function(points){ |
| // summary: sets a polyline/polygon shape object (SVG) |
| // points: Object: a polyline/polygon shape object |
| if(points && points instanceof Array){ |
| // branch |
| // points: Array: an array of points |
| this.shape = dojo.gfx.makeParameters(this.shape, { points: points }); |
| if(closed && this.shape.points.length){ |
| this.shape.points.push(this.shape.points[0]); |
| } |
| }else{ |
| this.shape = dojo.gfx.makeParameters(this.shape, points); |
| } |
| this.box = null; |
| var attr = []; |
| var p = this.shape.points; |
| for(var i = 0; i < p.length; ++i){ |
| attr.push(p[i].x.toFixed(8)); |
| attr.push(p[i].y.toFixed(8)); |
| } |
| this.rawNode.setAttribute("points", attr.join(" ")); |
| return this; // self |
| } |
| }); |
| dojo.gfx.Polyline.nodeType = "polyline"; |
| |
| dojo.declare("dojo.gfx.Image", dojo.gfx.shape.Image, { |
| // summary: an image (SVG) |
| |
| setShape: function(newShape){ |
| // summary: sets an image shape object (SVG) |
| // newShape: Object: an image shape object |
| this.shape = dojo.gfx.makeParameters(this.shape, newShape); |
| this.bbox = null; |
| var rawNode = this.rawNode; |
| for(var i in this.shape){ |
| if(i != "type" && i != "src"){ rawNode.setAttribute(i, this.shape[i]); } |
| } |
| rawNode.setAttributeNS(dojo.svg.xmlns.xlink, "href", this.shape.src); |
| return this; // self |
| }, |
| setStroke: function(){ |
| // summary: ignore setting a stroke style |
| return this; // self |
| }, |
| setFill: function(){ |
| // summary: ignore setting a fill style |
| return this; // self |
| }, |
| attachStroke: function(rawNode){ |
| // summary: ignore attaching a stroke style |
| return null; |
| }, |
| attachFill: function(rawNode){ |
| // summary: ignore attaching a fill style |
| return null; |
| } |
| }); |
| dojo.gfx.Image.nodeType = "image"; |
| |
| dojo.declare("dojo.gfx.Path", dojo.gfx.path.Path, { |
| // summary: a path shape (SVG) |
| |
| _updateWithSegment: function(segment){ |
| // summary: updates the bounding box of path with new segment |
| // segment: Object: a segment |
| dojo.gfx.Path.superclass._updateWithSegment.apply(this, arguments); |
| if(typeof(this.shape.path) == "string"){ |
| this.rawNode.setAttribute("d", this.shape.path); |
| } |
| }, |
| setShape: function(newShape){ |
| // summary: forms a path using a shape (SVG) |
| // newShape: Object: an SVG path string or a path object (see dojo.gfx.defaultPath) |
| dojo.gfx.Path.superclass.setShape.apply(this, arguments); |
| this.rawNode.setAttribute("d", this.shape.path); |
| return this; // self |
| } |
| }); |
| dojo.gfx.Path.nodeType = "path"; |
| |
| dojo.gfx._creators = { |
| // summary: SVG shape creators |
| createPath: function(path){ |
| // summary: creates an SVG path shape |
| // path: Object: a path object (see dojo.gfx.defaultPath) |
| return this.createObject(dojo.gfx.Path, path); // dojo.gfx.Path |
| }, |
| createRect: function(rect){ |
| // summary: creates an SVG rectangle shape |
| // rect: Object: a path object (see dojo.gfx.defaultRect) |
| return this.createObject(dojo.gfx.Rect, rect); // dojo.gfx.Rect |
| }, |
| createCircle: function(circle){ |
| // summary: creates an SVG circle shape |
| // circle: Object: a circle object (see dojo.gfx.defaultCircle) |
| return this.createObject(dojo.gfx.Circle, circle); // dojo.gfx.Circle |
| }, |
| createEllipse: function(ellipse){ |
| // summary: creates an SVG ellipse shape |
| // ellipse: Object: an ellipse object (see dojo.gfx.defaultEllipse) |
| return this.createObject(dojo.gfx.Ellipse, ellipse); // dojo.gfx.Ellipse |
| }, |
| createLine: function(line){ |
| // summary: creates an SVG line shape |
| // line: Object: a line object (see dojo.gfx.defaultLine) |
| return this.createObject(dojo.gfx.Line, line); // dojo.gfx.Line |
| }, |
| createPolyline: function(points){ |
| // summary: creates an SVG polyline/polygon shape |
| // points: Object: a points object (see dojo.gfx.defaultPolyline) |
| // or an Array of points |
| return this.createObject(dojo.gfx.Polyline, points); // dojo.gfx.Polyline |
| }, |
| createImage: function(image){ |
| // summary: creates an SVG image shape |
| // image: Object: an image object (see dojo.gfx.defaultImage) |
| return this.createObject(dojo.gfx.Image, image); // dojo.gfx.Image |
| }, |
| createGroup: function(){ |
| // summary: creates an SVG group shape |
| return this.createObject(dojo.gfx.Group); // dojo.gfx.Group |
| }, |
| createObject: function(shapeType, rawShape){ |
| // summary: creates an instance of the passed shapeType class |
| // shapeType: Function: a class constructor to create an instance of |
| // rawShape: Object: properties to be passed in to the classes "setShape" method |
| if(!this.rawNode){ return null; } |
| var shape = new shapeType(); |
| var node = document.createElementNS(dojo.svg.xmlns.svg, shapeType.nodeType); |
| shape.setRawNode(node); |
| this.rawNode.appendChild(node); |
| shape.setShape(rawShape); |
| this.add(shape); |
| return shape; // dojo.gfx.Shape |
| }, |
| // group control |
| add: function(shape){ |
| // summary: adds a shape to a group/surface |
| // shape: dojo.gfx.Shape: an SVG shape object |
| var oldParent = shape.getParent(); |
| if(oldParent){ |
| oldParent.remove(shape, true); |
| } |
| shape._setParent(this, null); |
| this.rawNode.appendChild(shape.rawNode); |
| return this; // self |
| }, |
| remove: function(shape, silently){ |
| // summary: remove a shape from a group/surface |
| // shape: dojo.gfx.Shape: an SVG shape object |
| // silently: Boolean?: if true, regenerate a picture |
| if(this.rawNode == shape.rawNode.parentNode){ |
| this.rawNode.removeChild(shape.rawNode); |
| } |
| shape._setParent(null, null); |
| return this; // self |
| } |
| }; |
| |
| dojo.gfx.attachNode = function(node){ |
| // summary: creates a shape from a Node |
| // node: Node: an SVG node |
| if(!node) return null; |
| var s = null; |
| switch(node.tagName.toLowerCase()){ |
| case dojo.gfx.Rect.nodeType: |
| s = new dojo.gfx.Rect(); |
| break; |
| case dojo.gfx.Ellipse.nodeType: |
| s = new dojo.gfx.Ellipse(); |
| break; |
| case dojo.gfx.Polyline.nodeType: |
| s = new dojo.gfx.Polyline(); |
| break; |
| case dojo.gfx.Path.nodeType: |
| s = new dojo.gfx.Path(); |
| break; |
| case dojo.gfx.Circle.nodeType: |
| s = new dojo.gfx.Circle(); |
| break; |
| case dojo.gfx.Line.nodeType: |
| s = new dojo.gfx.Line(); |
| break; |
| case dojo.gfx.Image.nodeType: |
| s = new dojo.gfx.Image(); |
| break; |
| default: |
| dojo.debug("FATAL ERROR! tagName = " + node.tagName); |
| } |
| s.attach(node); |
| return s; // dojo.gfx.Shape |
| }; |
| |
| dojo.lang.extend(dojo.gfx.Surface, { |
| // summary: a surface object to be used for drawings (SVG) |
| |
| setDimensions: function(width, height){ |
| // summary: sets the width and height of the rawNode |
| // width: String: width of surface, e.g., "100px" |
| // height: String: height of surface, e.g., "100px" |
| if(!this.rawNode){ return this; } |
| this.rawNode.setAttribute("width", width); |
| this.rawNode.setAttribute("height", height); |
| return this; // self |
| }, |
| getDimensions: function(){ |
| // summary: returns an object with properties "width" and "height" |
| return this.rawNode ? {width: this.rawNode.getAttribute("width"), height: this.rawNode.getAttribute("height")} : null; // Object |
| } |
| }); |
| |
| dojo.gfx.createSurface = function(parentNode, width, height){ |
| // summary: creates a surface (SVG) |
| // parentNode: Node: a parent node |
| // width: String: width of surface, e.g., "100px" |
| // height: String: height of surface, e.g., "100px" |
| |
| var s = new dojo.gfx.Surface(); |
| s.rawNode = document.createElementNS(dojo.svg.xmlns.svg, "svg"); |
| s.rawNode.setAttribute("width", width); |
| s.rawNode.setAttribute("height", height); |
| |
| var defs = new dojo.gfx.svg.Defines(); |
| var node = document.createElementNS(dojo.svg.xmlns.svg, dojo.gfx.svg.Defines.nodeType); |
| defs.setRawNode(node); |
| s.rawNode.appendChild(node); |
| |
| dojo.byId(parentNode).appendChild(s.rawNode); |
| return s; // dojo.gfx.Surface |
| }; |
| |
| dojo.gfx.attachSurface = function(node){ |
| // summary: creates a surface from a Node |
| // node: Node: an SVG node |
| var s = new dojo.gfx.Surface(); |
| s.rawNode = node; |
| return s; // dojo.gfx.Surface |
| }; |
| |
| dojo.lang.extend(dojo.gfx.Group, dojo.gfx._creators); |
| dojo.lang.extend(dojo.gfx.Surface, dojo.gfx._creators); |
| |
| delete dojo.gfx._creators; |
| |
| // Gradient and pattern |
| |
| dojo.gfx.svg.Defines = function(){ |
| this.rawNode = null; |
| }; |
| dojo.lang.extend(dojo.gfx.svg.Defines, { |
| setRawNode: function(rawNode){ |
| this.rawNode = rawNode; |
| } |
| }); |
| dojo.gfx.svg.Defines.nodeType = "defs"; |