| /* |
| PlotKit SVG |
| =========== |
| SVG Renderer for PlotKit |
| |
| Copyright |
| --------- |
| Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net> |
| For use under the BSD license. <http://www.liquidx.net/plotkit> |
| */ |
| |
| // ------------------------------------------------------------------------- |
| // NOTES: - If you use XHTML1.1 strict, then you must include each MochiKit |
| // file individuall. |
| // - For IE support, you must include the AdobeSVG object hack. |
| // See tests/svg.html for details. |
| // ------------------------------------------------------------------------- |
| // ------------------------------------------------------------------------- |
| // Check required components |
| // ------------------------------------------------------------------------- |
| |
| try { |
| if (typeof(PlotKit.Layout) == 'undefined') |
| { |
| throw ""; |
| } |
| } |
| catch (e) { |
| throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout" |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // SVG Renderer |
| // --------------------------------------------------------------------------- |
| |
| PlotKit.SVGRenderer = function(element, layout, options) { |
| if (arguments.length > 0) |
| this.__init__(element, layout, options); |
| }; |
| |
| PlotKit.SVGRenderer.NAME = "PlotKit.SVGRenderer"; |
| PlotKit.SVGRenderer.VERSION = PlotKit.VERSION; |
| |
| PlotKit.SVGRenderer.__repr__ = function() { |
| return "[" + this.NAME + " " + this.VERSION + "]"; |
| }; |
| |
| PlotKit.SVGRenderer.toString = function() { |
| return this.__repr__(); |
| } |
| |
| PlotKit.SVGRenderer.isSupported = function() { |
| // TODO |
| return true; |
| }; |
| |
| PlotKit.SVGRenderer.prototype.__init__ = function(element, layout, options) { |
| var isNil = MochiKit.Base.isUndefinedOrNull; |
| |
| // default options |
| this.options = { |
| "drawBackground": true, |
| "backgroundColor": Color.whiteColor(), |
| "padding": {left: 30, right: 30, top: 5, bottom: 10}, |
| "colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[1]), |
| "strokeColor": Color.whiteColor(), |
| "strokeColorTransform": "asStrokeColor", |
| "strokeWidth": 0.5, |
| "shouldFill": true, |
| "shouldStroke": true, |
| "drawXAxis": true, |
| "drawYAxis": true, |
| "axisLineColor": Color.blackColor(), |
| "axisLineWidth": 0.5, |
| "axisTickSize": 3, |
| "axisLabelColor": Color.blackColor(), |
| "axisLabelFont": "Arial", |
| "axisLabelFontSize": 9, |
| "axisLabelWidth": 50, |
| "axisLabelUseDiv": true, |
| "pieRadius": 0.4, |
| "enableEvents": true |
| }; |
| |
| MochiKit.Base.update(this.options, options ? options : {}); |
| this.layout = layout; |
| this.style = layout.style; |
| this.element = MochiKit.DOM.getElement(element); |
| this.container = this.element.parentNode; |
| this.height = parseInt(this.element.getAttribute("height")); |
| this.width = parseInt(this.element.getAttribute("width")); |
| this.document = document; |
| this.root = this.element; |
| |
| // Adobe SVG Support: |
| // - if an exception is thrown, then no Adobe SVG Plugin support. |
| try { |
| this.document = this.element.getSVGDocument(); |
| this.root = isNil(this.document.documentElement) ? this.element : this.document.documentElement; |
| } |
| catch (e) { |
| } |
| |
| this.element.style.zIndex = 1; |
| |
| if (isNil(this.element)) |
| throw "SVGRenderer() - passed SVG object is not found"; |
| |
| if (isNil(this.container) || this.container.nodeName.toLowerCase() != "div") |
| throw "SVGRenderer() - No DIV's around the SVG."; |
| |
| // internal state |
| this.xlabels = new Array(); |
| this.ylabels = new Array(); |
| |
| // initialise some meta structures in SVG |
| this.defs = this.createSVGElement("defs"); |
| |
| this.area = { |
| x: this.options.padding.left, |
| y: this.options.padding.top, |
| w: this.width - this.options.padding.left - this.options.padding.right, |
| h: this.height - this.options.padding.top - this.options.padding.bottom |
| }; |
| |
| MochiKit.DOM.updateNodeAttributes(this.container, |
| {"style":{ "position": "relative", "width": this.width + "px"}}); |
| |
| |
| }; |
| |
| |
| PlotKit.SVGRenderer.prototype.render = function() { |
| if (this.options.drawBackground) |
| this._renderBackground(); |
| |
| if (this.style == "bar") { |
| this._renderBarChart(); |
| this._renderBarAxis(); |
| } |
| else if (this.style == "pie") { |
| this._renderPieChart(); |
| this._renderPieAxis(); |
| } |
| else if (this.style == "line") { |
| this._renderLineChart(); |
| this._renderLineAxis(); |
| } |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderBarOrLine = function(data, plotFunc, startFunc, endFunc) { |
| |
| var colorCount = this.options.colorScheme.length; |
| var colorScheme = this.options.colorScheme; |
| var setNames = MochiKit.Base.keys(this.layout.datasets); |
| var setCount = setNames.length; |
| |
| for (var i = 0; i < setCount; i++) { |
| var setName = setNames[i]; |
| var attrs = new Array(); |
| var color = colorScheme[i%colorCount]; |
| |
| if (this.options.shouldFill) |
| attrs["fill"] = color.toRGBString(); |
| else |
| attrs["fill"] = "none"; |
| |
| if (this.options.shouldStroke && |
| (this.options.strokeColor || this.options.strokeColorTransform)) { |
| if (this.options.strokeColor) |
| attrs["stroke"] = this.options.strokeColor.toRGBString(); |
| else if (this.options.strokeColorTransform) |
| attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString(); |
| attrs["strokeWidth"] = this.options.strokeWidth; |
| } |
| |
| if (startFunc) |
| startFunc(attrs); |
| |
| var forEachFunc = function(obj) { |
| if (obj.name == setName) |
| plotFunc(attrs, obj); |
| }; |
| |
| MochiKit.Iter.forEach(data, bind(forEachFunc, this)); |
| if (endFunc) |
| endFunc(attrs); |
| } |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderBarChart = function() { |
| var bind = MochiKit.Base.bind; |
| |
| var drawRect = function(attrs, bar) { |
| var x = this.area.w * bar.x + this.area.x; |
| var y = this.area.h * bar.y + this.area.y; |
| var w = this.area.w * bar.w; |
| var h = this.area.h * bar.h; |
| this._drawRect(x, y, w, h, attrs); |
| }; |
| this._renderBarOrLine(this.layout.bars, bind(drawRect, this)); |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderLineChart = function() { |
| var bind = MochiKit.Base.bind; |
| |
| var addPoint = function(attrs, point) { |
| this._tempPointsBuffer += (this.area.w * point.x + this.area.x) + "," + |
| (this.area.h * point.y + this.area.y) + " "; |
| }; |
| |
| var startLine = function(attrs) { |
| this._tempPointsBuffer = ""; |
| this._tempPointsBuffer += (this.area.x) + "," + (this.area.y+this.area.h) + " "; |
| }; |
| |
| var endLine = function(attrs) { |
| this._tempPointsBuffer += (this.area.w + this.area.x) + "," +(this.area.h + this.area.y); |
| attrs["points"] = this._tempPointsBuffer; |
| var elem = this.createSVGElement("polygon", attrs); |
| this.root.appendChild(elem); |
| }; |
| |
| this._renderBarOrLine(this.layout.points, |
| bind(addPoint, this), |
| bind(startLine, this), |
| bind(endLine, this)); |
| }; |
| |
| |
| PlotKit.SVGRenderer.prototype._renderPieChart = function() { |
| var colorCount = this.options.colorScheme.length; |
| var slices = this.layout.slices; |
| |
| var centerx = this.area.x + this.area.w * 0.5; |
| var centery = this.area.y + this.area.h * 0.5; |
| var radius = Math.min(this.area.w * this.options.pieRadius, |
| this.area.h * this.options.pieRadius); |
| |
| // NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1 |
| // so we have to subtract 90 degrees to make it start at y = 1, x = 0 |
| |
| // workaround if we only have 1 slice of 100% |
| if (slices.length == 1 && (Math.abs(slices[0].startAngle) - Math.abs(slices[0].endAngle) < 0.1)) { |
| var attrs = {"cx": centerx , "cy": centery , "r": radius }; |
| var color = this.options.colorScheme[0]; |
| if (this.options.shouldFill) |
| attrs["fill"] = color.toRGBString(); |
| else |
| attrs["fill"] = "none"; |
| |
| if (this.options.shouldStroke && |
| (this.options.strokeColor || this.options.strokeColorTransform)) { |
| if (this.options.strokeColor) |
| attrs["stroke"] = this.options.strokeColor.toRGBString(); |
| else if (this.options.strokeColorTransform) |
| attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString(); |
| attrs["style"] = "stroke-width: " + this.options.strokeWidth; |
| } |
| |
| this.root.appendChild(this.createSVGElement("circle", attrs)); |
| return; |
| } |
| |
| for (var i = 0; i < slices.length; i++) { |
| var attrs = new Array(); |
| var color = this.options.colorScheme[i%colorCount]; |
| if (this.options.shouldFill) |
| attrs["fill"] = color.toRGBString(); |
| else |
| attrs["fill"] = "none"; |
| |
| if (this.options.shouldStroke && |
| (this.options.strokeColor || this.options.strokeColorTransform)) { |
| if (this.options.strokeColor) |
| attrs["stroke"] = this.options.strokeColor.toRGBString(); |
| else if (this.options.strokeColorTransform) |
| attrs["stroke"] = color[this.options.strokeColorTransform]().toRGBString(); |
| attrs["style"] = "stroke-width:" + this.options.strokeWidth; |
| } |
| |
| var largearc = 0; |
| if (Math.abs(slices[i].endAngle - slices[i].startAngle) > Math.PI) |
| largearc = 1; |
| var x1 = Math.cos(slices[i].startAngle - Math.PI/2) * radius; |
| var y1 = Math.sin(slices[i].startAngle - Math.PI/2) * radius; |
| var x2 = Math.cos(slices[i].endAngle - Math.PI/2) * radius; |
| var y2 = Math.sin(slices[i].endAngle - Math.PI/2) * radius; |
| var rx = x2 - x1; |
| var ry = y2 - y1; |
| |
| var pathString = "M" + centerx + "," + centery + " "; |
| pathString += "l" + x1 + "," + y1 + " "; |
| pathString += "a" + radius + "," + radius + " 0 " + largearc + ",1 " + rx + "," + ry + " z"; |
| |
| attrs["d"] = pathString; |
| |
| var elem = this.createSVGElement("path", attrs); |
| this.root.appendChild(elem); |
| } |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderBarAxis = function() { |
| this._renderAxis(); |
| } |
| |
| PlotKit.SVGRenderer.prototype._renderLineAxis = function() { |
| this._renderAxis(); |
| }; |
| |
| |
| PlotKit.SVGRenderer.prototype._renderAxis = function() { |
| |
| if (!this.options.drawXAxis && !this.options.drawYAxis) |
| return; |
| |
| var labelStyle = {"style": |
| {"position": "absolute", |
| "textAlign": "center", |
| "fontSize": this.options.axisLabelFontSize + "px", |
| "zIndex": 10, |
| "color": this.options.axisLabelColor.toRGBString(), |
| "width": this.options.axisLabelWidth + "px", |
| "overflow": "hidden" |
| } |
| }; |
| |
| // axis lines |
| var lineAttrs = { |
| "stroke": this.options.axisLineColor.toRGBString(), |
| "strokeWidth": this.options.axisLineWidth |
| }; |
| |
| |
| if (this.options.drawYAxis) { |
| if (this.layout.yticks) { |
| var drawTick = function(tick) { |
| var x = this.area.x; |
| var y = this.area.y + tick[0] * this.area.h; |
| this._drawLine(x, y, x - 3, y, lineAttrs); |
| |
| if (this.options.axisLabelUseDiv) { |
| var label = DIV(labelStyle, tick[1]); |
| label.style.top = (y - this.options.axisLabelFontSize) + "px"; |
| label.style.left = (x - this.options.padding.left + this.options.axisTickSize) + "px"; |
| label.style.textAlign = "left"; |
| label.style.width = (this.options.padding.left - 3) + "px"; |
| MochiKit.DOM.appendChildNodes(this.container, label); |
| this.ylabels.push(label); |
| } |
| else { |
| var attrs = { |
| y: y + 3, |
| x: (x - this.options.padding.left + 3), |
| width: (this.options.padding.left - this.options.axisTickSize) + "px", |
| height: (this.options.axisLabelFontSize + 3) + "px", |
| fontFamily: "Arial", |
| fontSize: this.options.axisLabelFontSize + "px", |
| fill: this.options.axisLabelColor.toRGBString() |
| }; |
| |
| /* we can do clipping just like DIVs |
| http://www.xml.com/pub/a/2004/06/02/svgtype.html */ |
| /* |
| var mask = this.createSVGElement("mask", {id: "mask" + tick[0]}); |
| var maskShape = this.createSVGElement("rect", |
| {y: y + 3, |
| x: (x - this.options.padding.left + 3), |
| width: (this.options.padding.left - this.options.axisTickSize) + "px", |
| height: (this.options.axisLabelFontSize + 3) + "px", |
| style: {"fill": "#ffffff", "stroke": "#000000"}}); |
| mask.appendChild(maskShape); |
| this.defs.appendChild(mask); |
| |
| attrs["filter"] = "url(#mask" + tick[0] + ")"; |
| */ |
| |
| var label = this.createSVGElement("text", attrs); |
| label.appendChild(this.document.createTextNode(tick[1])); |
| this.root.appendChild(label); |
| } |
| }; |
| |
| MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this)); |
| } |
| |
| this._drawLine(this.area.x, this.area.y, this.area.x, this.area.y + this.area.h, lineAttrs); |
| } |
| |
| if (this.options.drawXAxis) { |
| if (this.layout.xticks) { |
| var drawTick = function(tick) { |
| var x = this.area.x + tick[0] * this.area.w; |
| var y = this.area.y + this.area.h; |
| this._drawLine(x, y, x, y + this.options.axisTickSize, lineAttrs); |
| |
| if (this.options.axisLabelUseDiv) { |
| var label = DIV(labelStyle, tick[1]); |
| label.style.top = (y + this.options.axisTickSize) + "px"; |
| label.style.left = (x - this.options.axisLabelWidth/2) + "px"; |
| label.style.textAlign = "center"; |
| label.style.width = this.options.axisLabelWidth + "px"; |
| MochiKit.DOM.appendChildNodes(this.container, label); |
| this.xlabels.push(label); |
| } |
| else { |
| var attrs = { |
| y: (y + this.options.axisTickSize + this.options.axisLabelFontSize), |
| x: x - 3, |
| width: this.options.axisLabelWidth + "px", |
| height: (this.options.axisLabelFontSize + 3) + "px", |
| fontFamily: "Arial", |
| fontSize: this.options.axisLabelFontSize + "px", |
| fill: this.options.axisLabelColor.toRGBString(), |
| textAnchor: "middle" |
| }; |
| var label = this.createSVGElement("text", attrs); |
| label.appendChild(this.document.createTextNode(tick[1])); |
| this.root.appendChild(label); |
| } |
| }; |
| |
| MochiKit.Iter.forEach(this.layout.xticks, bind(drawTick, this)); |
| } |
| |
| this._drawLine(this.area.x, this.area.y + this.area.h, this.area.x + this.area.w, this.area.y + this.area.h, lineAttrs) |
| } |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderPieAxis = function() { |
| |
| if (this.layout.xticks) { |
| // make a lookup dict for x->slice values |
| var lookup = new Array(); |
| for (var i = 0; i < this.layout.slices.length; i++) { |
| lookup[this.layout.slices[i].xval] = this.layout.slices[i]; |
| } |
| |
| var centerx = this.area.x + this.area.w * 0.5; |
| var centery = this.area.y + this.area.h * 0.5; |
| var radius = Math.min(this.area.w * this.options.pieRadius + 10, |
| this.area.h * this.options.pieRadius + 10); |
| var labelWidth = this.options.axisLabelWidth; |
| |
| for (var i = 0; i < this.layout.xticks.length; i++) { |
| var slice = lookup[this.layout.xticks[i][0]]; |
| if (MochiKit.Base.isUndefinedOrNull(slice)) |
| continue; |
| |
| |
| var angle = (slice.startAngle + slice.endAngle)/2; |
| // normalize the angle |
| var normalisedAngle = angle; |
| if (normalisedAngle > Math.PI * 2) |
| normalisedAngle = normalisedAngle - Math.PI * 2; |
| else if (normalisedAngle < 0) |
| normalisedAngle = normalisedAngle + Math.PI * 2; |
| |
| var labelx = centerx + Math.sin(normalisedAngle) * (radius + 10); |
| var labely = centery - Math.cos(normalisedAngle) * (radius + 10); |
| |
| var attrib = { |
| "position": "absolute", |
| "zIndex": 11, |
| "width": labelWidth + "px", |
| "fontSize": this.options.axisLabelFontSize + "px", |
| "overflow": "hidden", |
| "color": this.options.axisLabelColor.toHexString() |
| }; |
| |
| var svgattrib = { |
| "width": labelWidth + "px", |
| "fontSize": this.options.axisLabelFontSize + "px", |
| "height": (this.options.axisLabelFontSize + 3) + "px", |
| "fill": this.options.axisLabelColor.toRGBString() |
| }; |
| |
| if (normalisedAngle <= Math.PI * 0.5) { |
| // text on top and align left |
| MochiKit.Base.update(attrib, { |
| 'textAlign': 'left', 'verticalAlign': 'top', |
| 'left': labelx + 'px', |
| 'top': (labely - this.options.axisLabelFontSize) + "px" |
| }); |
| MochiKit.Base.update(svgattrib, { |
| "x": labelx, |
| "y" :(labely - this.options.axisLabelFontSize), |
| "textAnchor": "left" |
| }); |
| } |
| else if ((normalisedAngle > Math.PI * 0.5) && (normalisedAngle <= Math.PI)) { |
| // text on bottom and align left |
| MochiKit.Base.update(attrib, { |
| 'textAlign': 'left', 'verticalAlign': 'bottom', |
| 'left': labelx + 'px', |
| 'top': labely + "px" |
| }); |
| MochiKit.Base.update(svgattrib, { |
| 'textAnchor': 'left', |
| 'x': labelx, |
| 'y': labely |
| }); |
| } |
| else if ((normalisedAngle > Math.PI) && (normalisedAngle <= Math.PI*1.5)) { |
| // text on bottom and align right |
| MochiKit.Base.update(attrib, { |
| 'textAlign': 'right', 'verticalAlign': 'bottom', |
| 'left': labelx + 'px', |
| 'top': labely + "px" |
| }); |
| MochiKit.Base.update(svgattrib, { |
| 'textAnchor': 'right', |
| 'x': labelx - labelWidth, |
| 'y': labely |
| }); |
| } |
| else { |
| // text on top and align right |
| MochiKit.Base.update(attrib, { |
| 'textAlign': 'left', 'verticalAlign': 'bottom', |
| 'left': labelx + 'px', |
| 'top': labely + "px" |
| }); |
| MochiKit.Base.update(svgattrib, { |
| 'textAnchor': 'left', |
| 'x': labelx - labelWidth, |
| 'y': labely - this.options.axisLabelFontSize |
| }); |
| } |
| |
| if (this.options.axisLabelUseDiv) { |
| var label = DIV({'style': attrib}, this.layout.xticks[i][1]); |
| this.xlabels.push(label); |
| MochiKit.DOM.appendChildNodes(this.container, label); |
| } |
| else { |
| var label = this.createSVGElement("text", svgattrib); |
| label.appendChild(this.document.createTextNode(this.layout.xticks[i][1])) |
| this.root.appendChild(label); |
| } |
| } |
| |
| } |
| }; |
| |
| PlotKit.SVGRenderer.prototype._renderBackground = function() { |
| var opts = {"stroke": "none", |
| "fill": this.options.backgroundColor.toRGBString() |
| }; |
| this._drawRect(0, 0, this.width, this.height, opts); |
| }; |
| |
| PlotKit.SVGRenderer.prototype._drawRect = function(x, y, w, h, moreattrs) { |
| var attrs = {x: x + "px", y: y + "px", width: w + "px", height: h + "px"}; |
| if (moreattrs) |
| MochiKit.Base.update(attrs, moreattrs); |
| |
| var elem = this.createSVGElement("rect", attrs); |
| this.root.appendChild(elem); |
| }; |
| |
| PlotKit.SVGRenderer.prototype._drawLine = function(x1, y1, x2, y2, moreattrs) { |
| var attrs = {x1: x1 + "px", y1: y1 + "px", x2: x2 + "px", y2: y2 + "px"}; |
| if (moreattrs) |
| MochiKit.Base.update(attrs, moreattrs); |
| |
| var elem = this.createSVGElement("line", attrs); |
| this.root.appendChild(elem); |
| } |
| |
| PlotKit.SVGRenderer.prototype.clear = function() { |
| while(this.element.firstChild) { |
| this.element.removeChild(this.element.firstChild); |
| } |
| |
| if (this.options.axisLabelUseDiv) { |
| for (var i = 0; i < this.xlabels.length; i++) { |
| MochiKit.DOM.removeElement(this.xlabels[i]); |
| } |
| for (var i = 0; i < this.ylabels.length; i++) { |
| MochiKit.DOM.removeElement(this.ylabels[i]); |
| } |
| } |
| this.xlabels = new Array(); |
| this.ylabels = new Array(); |
| }; |
| |
| PlotKit.SVGRenderer.prototype.createSVGElement = function(name, attrs) { |
| var isNil = MochiKit.Base.isUndefinedOrNull; |
| var elem; |
| var doc = isNil(this.document) ? document : this.document; |
| |
| try { |
| elem = doc.createElementNS("http://www.w3.org/2000/svg", name); |
| } |
| catch (e) { |
| elem = doc.createElement(name); |
| elem.setAttribute("xmlns", "http://www.w3.org/2000/svg"); |
| } |
| |
| if (attrs) |
| MochiKit.DOM.updateNodeAttributes(elem, attrs); |
| |
| // TODO: we don't completely emulate the MochiKit.DOM.createElement |
| // as we don't care about nodes contained. We really should though. |
| |
| return elem; |
| |
| }; |
| |
| PlotKit.SVGRenderer.SVGNS = 'http://www.w3.org/2000/svg'; |
| |
| PlotKit.SVGRenderer.SVG = function(attrs) { |
| // we have to do things differently for IE+AdobeSVG. |
| // My guess this works (via trial and error) is that we need to |
| // have an SVG object in order to use SVGDocument.createElementNS |
| // but IE doesn't allow us to that. |
| |
| var ie = navigator.appVersion.match(/MSIE (\d\.\d)/); |
| var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1); |
| if (ie && (ie[1] >= 6) && (!opera)) { |
| var width = attrs["width"] ? attrs["width"] : "100"; |
| var height = attrs["height"] ? attrs["height"] : "100"; |
| var eid = attrs["id"] ? attrs["id"] : "notunique"; |
| |
| var html = '<svg:svg width="' + width + '" height="' + height + '" '; |
| html += 'id="' + eid + '" version="1.1" baseProfile="full">'; |
| |
| var canvas = document.createElement(html); |
| |
| // create embedded SVG inside SVG. |
| var group = canvas.getSVGDocument().createElementNS(PlotKit.SVGRenderer.SVGNS, "svg"); |
| group.setAttribute("width", width); |
| group.setAttribute("height", height); |
| canvas.getSVGDocument().appendChild(group); |
| |
| return canvas; |
| } |
| else { |
| return PlotKit.SVGRenderer.prototype.createSVGElement("svg", attrs); |
| } |
| }; |
| |
| PlotKit.SVGRenderer.isSupported = function() { |
| var isOpera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1); |
| var ieVersion = navigator.appVersion.match(/MSIE (\d\.\d)/); |
| var safariVersion = navigator.userAgent.match(/AppleWebKit\/(\d+)/); |
| var operaVersion = navigator.userAgent.match(/Opera\/(\d*\.\d*)/); |
| var mozillaVersion = navigator.userAgent.match(/rv:(\d*\.\d*).*Gecko/); |
| |
| |
| if (ieVersion && (ieVersion[1] >= 6) && !isOpera) { |
| var dummysvg = document.createElement('<svg:svg width="1" height="1" baseProfile="full" version="1.1" id="dummy">'); |
| try { |
| dummysvg.getSVGDocument(); |
| dummysvg = null; |
| return true; |
| } |
| catch (e) { |
| return false; |
| } |
| } |
| |
| /* support not really there yet. no text and paths are buggy |
| if (safariVersion && (safariVersion[1] > 419)) |
| return true; |
| */ |
| |
| if (operaVersion && (operaVersion[1] > 8.9)) |
| return true |
| |
| if (mozillaVersion && (mozillaVersion > 1.7)) |
| return true; |
| |
| return false; |
| }; |