Index: static/js/plotkit/Canvas.js |
diff --git a/static/js/plotkit/Canvas.js b/static/js/plotkit/Canvas.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c4b61cce8d82c4b6f2e79a281fcf9117daf10d17 |
--- /dev/null |
+++ b/static/js/plotkit/Canvas.js |
@@ -0,0 +1,682 @@ |
+/* |
+ ======= |
+ PlotKit is a collection of Javascript classes that allows |
+ you to quickly visualise data using different types of charts. |
+ |
+ http://www.liquidx.net/plotkit/ |
+ |
+ See LICENSE file for copyright information. |
+ |
+ ======= |
+ Provides HTML Canvas Renderer. This is supported under: |
+ |
+ - Safari 2.0 |
+ - Mozilla Firefox 1.5 |
+ - Opera 9.0 preview 2 |
+ - IE 6 (via VML Emulation) |
+ |
+ It uses DIVs for labels. |
+*/ |
+// -------------------------------------------------------------------- |
+// Check required components |
+// -------------------------------------------------------------------- |
+ |
+try { |
+ if ((typeof(PlotKit.Base) == 'undefined') || |
+ (typeof(PlotKit.Layout) == 'undefined')) |
+ { |
+ throw ""; |
+ } |
+} |
+catch (e) { |
+ throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Base,Layout}" |
+} |
+ |
+ |
+// ------------------------------------------------------------------------ |
+// Defines the renderer class |
+// ------------------------------------------------------------------------ |
+ |
+if (typeof(PlotKit.CanvasRenderer) == 'undefined') { |
+ PlotKit.CanvasRenderer = {}; |
+} |
+ |
+PlotKit.CanvasRenderer.NAME = "PlotKit.CanvasRenderer"; |
+PlotKit.CanvasRenderer.VERSION = PlotKit.VERSION; |
+ |
+PlotKit.CanvasRenderer.__repr__ = function() { |
+ return "[" + this.NAME + " " + this.VERSION + "]"; |
+}; |
+ |
+PlotKit.CanvasRenderer.toString = function() { |
+ return this.__repr__(); |
+} |
+ |
+PlotKit.CanvasRenderer = function(element, layout, options) { |
+ if (arguments.length > 0) |
+ this.__init__(element, layout, options); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) { |
+ var isNil = MochiKit.Base.isUndefinedOrNull; |
+ var Color = MochiKit.Color.Color; |
+ |
+ // 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()[0]), |
+ "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, |
+ "pieRadius": 0.4, |
+ "enableEvents": true |
+ }; |
+ MochiKit.Base.update(this.options, options ? options : {}); |
+ |
+ this.layout = layout; |
+ this.element = MochiKit.DOM.getElement(element); |
+ this.container = this.element.parentNode; |
+ |
+ // Stuff relating to Canvas on IE support |
+ this.isIE = PlotKit.Base.excanvasSupported(); |
+ |
+ if (this.isIE && !isNil(G_vmlCanvasManager)) { |
+ this.IEDelay = 0.5; |
+ this.maxTries = 5; |
+ this.renderDelay = null; |
+ this.clearDelay = null; |
+ this.element = G_vmlCanvasManager.initElement(this.element); |
+ } |
+ |
+ this.height = this.element.height; |
+ this.width = this.element.width; |
+ |
+ // --- check whether everything is ok before we return |
+ |
+ if (isNil(this.element)) |
+ throw "CanvasRenderer() - passed canvas is not found"; |
+ |
+ if (!this.isIE && !(PlotKit.CanvasRenderer.isSupported(this.element))) |
+ throw "CanvasRenderer() - Canvas is not supported."; |
+ |
+ if (isNil(this.container) || (this.container.nodeName.toLowerCase() != "div")) |
+ throw "CanvasRenderer() - <canvas> needs to be enclosed in <div>"; |
+ |
+ // internal state |
+ this.xlabels = new Array(); |
+ this.ylabels = new Array(); |
+ this.isFirstRender = true; |
+ |
+ 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"}}); |
+ |
+ // load event system if we have Signals |
+ /* Disabled until we have a proper implementation |
+ try { |
+ this.event_isinside = null; |
+ if (MochiKit.Signal && this.options.enableEvents) { |
+ this._initialiseEvents(); |
+ } |
+ } |
+ catch (e) { |
+ // still experimental |
+ } |
+ */ |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.render = function() { |
+ if (this.isIE) { |
+ // VML takes a while to start up, so we just poll every this.IEDelay |
+ try { |
+ if (this.renderDelay) { |
+ this.renderDelay.cancel(); |
+ this.renderDelay = null; |
+ } |
+ var context = this.element.getContext("2d"); |
+ } |
+ catch (e) { |
+ this.isFirstRender = false; |
+ if (this.maxTries-- > 0) { |
+ this.renderDelay = MochiKit.Async.wait(this.IEDelay); |
+ this.renderDelay.addCallback(bind(this.render, this)); |
+ } |
+ return; |
+ } |
+ } |
+ |
+ if (this.options.drawBackground) |
+ this._renderBackground(); |
+ |
+ if (this.layout.style == "bar") { |
+ this._renderBarChart(); |
+ this._renderBarAxis(); |
+ } |
+ else if (this.layout.style == "pie") { |
+ this._renderPieChart(); |
+ this._renderPieAxis(); |
+ } |
+ else if (this.layout.style == "line") { |
+ this._renderLineChart(); |
+ this._renderLineAxis(); |
+ } |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderBarChartWrap = function(data, plotFunc) { |
+ var context = this.element.getContext("2d"); |
+ 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 color = colorScheme[i%colorCount]; |
+ context.save(); |
+ context.fillStyle = color.toRGBString(); |
+ if (this.options.strokeColor) |
+ context.strokeStyle = this.options.strokeColor.toRGBString(); |
+ else if (this.options.strokeColorTransform) |
+ context.strokeStyle = color[this.options.strokeColorTransform]().toRGBString(); |
+ |
+ context.lineWidth = this.options.strokeWidth; |
+ var forEachFunc = function(obj) { |
+ if (obj.name == setName) |
+ plotFunc(context, obj); |
+ }; |
+ |
+ MochiKit.Iter.forEach(data, bind(forEachFunc, this)); |
+ context.restore(); |
+ } |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderBarChart = function() { |
+ var bind = MochiKit.Base.bind; |
+ |
+ var drawRect = function(context, 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; |
+ if ((w < 1) || (h < 1)) |
+ return; |
+ if (this.options.shouldFill) |
+ context.fillRect(x, y, w, h); |
+ if (this.options.shouldStroke) |
+ context.strokeRect(x, y, w, h); |
+ }; |
+ this._renderBarChartWrap(this.layout.bars, bind(drawRect, this)); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderLineChart = function() { |
+ var context = this.element.getContext("2d"); |
+ var colorCount = this.options.colorScheme.length; |
+ var colorScheme = this.options.colorScheme; |
+ var setNames = MochiKit.Base.keys(this.layout.datasets); |
+ var setCount = setNames.length; |
+ var bind = MochiKit.Base.bind; |
+ var partial = MochiKit.Base.partial; |
+ |
+ for (var i = 0; i < setCount; i++) { |
+ var setName = setNames[i]; |
+ var color = colorScheme[i%colorCount]; |
+ var strokeX = this.options.strokeColorTransform; |
+ |
+ // setup graphics context |
+ context.save(); |
+ context.fillStyle = color.toRGBString(); |
+ if (this.options.strokeColor) |
+ context.strokeStyle = this.options.strokeColor.toRGBString(); |
+ else if (this.options.strokeColorTransform) |
+ context.strokeStyle = color[strokeX]().toRGBString(); |
+ |
+ context.lineWidth = this.options.strokeWidth; |
+ |
+ // create paths |
+ var makePath = function(ctx) { |
+ ctx.beginPath(); |
+ ctx.moveTo(this.area.x, this.area.y + this.area.h); |
+ var addPoint = function(ctx_, point) { |
+ if (point.name == setName) |
+ ctx_.lineTo(this.area.w * point.x + this.area.x, |
+ this.area.h * point.y + this.area.y); |
+ }; |
+ MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this); |
+ ctx.lineTo(this.area.w + this.area.x, |
+ this.area.h + this.area.y); |
+ ctx.lineTo(this.area.x, this.area.y + this.area.h); |
+ ctx.closePath(); |
+ }; |
+ |
+ if (this.options.shouldFill) { |
+ bind(makePath, this)(context); |
+ context.fill(); |
+ } |
+ if (this.options.shouldStroke) { |
+ bind(makePath, this)(context); |
+ context.stroke(); |
+ } |
+ |
+ context.restore(); |
+ } |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderPieChart = function() { |
+ var context = this.element.getContext("2d"); |
+ 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); |
+ |
+ if (this.isIE) { |
+ centerx = parseInt(centerx); |
+ centery = parseInt(centery); |
+ radius = parseInt(radius); |
+ } |
+ |
+ |
+ // 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 |
+ |
+ for (var i = 0; i < slices.length; i++) { |
+ var color = this.options.colorScheme[i%colorCount]; |
+ context.save(); |
+ context.fillStyle = color.toRGBString(); |
+ |
+ var makePath = function() { |
+ context.beginPath(); |
+ context.moveTo(centerx, centery); |
+ context.arc(centerx, centery, radius, |
+ slices[i].startAngle - Math.PI/2, |
+ slices[i].endAngle - Math.PI/2, |
+ false); |
+ context.lineTo(centerx, centery); |
+ context.closePath(); |
+ }; |
+ |
+ if (Math.abs(slices[i].startAngle - slices[i].endAngle) > 0.001) { |
+ if (this.options.shouldFill) { |
+ makePath(); |
+ context.fill(); |
+ } |
+ |
+ if (this.options.shouldStroke) { |
+ makePath(); |
+ context.lineWidth = this.options.strokeWidth; |
+ if (this.options.strokeColor) |
+ context.strokeStyle = this.options.strokeColor.toRGBString(); |
+ else if (this.options.strokeColorTransform) |
+ context.strokeStyle = color[this.options.strokeColorTransform]().toRGBString(); |
+ context.stroke(); |
+ } |
+ } |
+ context.restore(); |
+ } |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderBarAxis = function() { |
+ this._renderAxis(); |
+} |
+ |
+PlotKit.CanvasRenderer.prototype._renderLineAxis = function() { |
+ this._renderAxis(); |
+}; |
+ |
+ |
+PlotKit.CanvasRenderer.prototype._renderAxis = function() { |
+ if (!this.options.drawXAxis && !this.options.drawYAxis) |
+ return; |
+ |
+ var context = this.element.getContext("2d"); |
+ |
+ var labelStyle = {"style": |
+ {"position": "absolute", |
+ "fontSize": this.options.axisLabelFontSize + "px", |
+ "zIndex": 10, |
+ "color": this.options.axisLabelColor.toRGBString(), |
+ "width": this.options.axisLabelWidth + "px", |
+ "overflow": "hidden" |
+ } |
+ }; |
+ |
+ // axis lines |
+ context.save(); |
+ context.strokeStyle = this.options.axisLineColor.toRGBString(); |
+ context.lineWidth = this.options.axisLineWidth; |
+ |
+ |
+ if (this.options.drawYAxis) { |
+ if (this.layout.yticks) { |
+ var drawTick = function(tick) { |
+ if (typeof(tick) == "function") return; |
+ var x = this.area.x; |
+ var y = this.area.y + tick[0] * this.area.h; |
+ context.beginPath(); |
+ context.moveTo(x, y); |
+ context.lineTo(x - this.options.axisTickSize, y); |
+ context.closePath(); |
+ context.stroke(); |
+ |
+ 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 = "right"; |
+ label.style.width = (this.options.padding.left - this.options.axisTickSize * 2) + "px"; |
+ MochiKit.DOM.appendChildNodes(this.container, label); |
+ this.ylabels.push(label); |
+ }; |
+ |
+ MochiKit.Iter.forEach(this.layout.yticks, bind(drawTick, this)); |
+ } |
+ |
+ context.beginPath(); |
+ context.moveTo(this.area.x, this.area.y); |
+ context.lineTo(this.area.x, this.area.y + this.area.h); |
+ context.closePath(); |
+ context.stroke(); |
+ } |
+ |
+ if (this.options.drawXAxis) { |
+ if (this.layout.xticks) { |
+ var drawTick = function(tick) { |
+ if (typeof(dataset) == "function") return; |
+ |
+ var x = this.area.x + tick[0] * this.area.w; |
+ var y = this.area.y + this.area.h; |
+ context.beginPath(); |
+ context.moveTo(x, y); |
+ context.lineTo(x, y + this.options.axisTickSize); |
+ context.closePath(); |
+ context.stroke(); |
+ |
+ 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); |
+ }; |
+ |
+ MochiKit.Iter.forEach(this.layout.xticks, bind(drawTick, this)); |
+ } |
+ |
+ context.beginPath(); |
+ context.moveTo(this.area.x, this.area.y + this.area.h); |
+ context.lineTo(this.area.x + this.area.w, this.area.y + this.area.h); |
+ context.closePath(); |
+ context.stroke(); |
+ } |
+ |
+ context.restore(); |
+ |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderPieAxis = function() { |
+ if (!this.options.drawXAxis) |
+ return; |
+ |
+ 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, |
+ this.area.h * this.options.pieRadius); |
+ 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() |
+ }; |
+ |
+ if (normalisedAngle <= Math.PI * 0.5) { |
+ // text on top and align left |
+ attrib["textAlign"] = "left"; |
+ attrib["verticalAlign"] = "top"; |
+ attrib["left"] = labelx + "px"; |
+ attrib["top"] = (labely - this.options.axisLabelFontSize) + "px"; |
+ } |
+ else if ((normalisedAngle > Math.PI * 0.5) && (normalisedAngle <= Math.PI)) { |
+ // text on bottom and align left |
+ attrib["textAlign"] = "left"; |
+ attrib["verticalAlign"] = "bottom"; |
+ attrib["left"] = labelx + "px"; |
+ attrib["top"] = labely + "px"; |
+ |
+ } |
+ else if ((normalisedAngle > Math.PI) && (normalisedAngle <= Math.PI*1.5)) { |
+ // text on bottom and align right |
+ attrib["textAlign"] = "right"; |
+ attrib["verticalAlign"] = "bottom"; |
+ attrib["left"] = (labelx - labelWidth) + "px"; |
+ attrib["top"] = labely + "px"; |
+ } |
+ else { |
+ // text on top and align right |
+ attrib["textAlign"] = "right"; |
+ attrib["verticalAlign"] = "bottom"; |
+ attrib["left"] = (labelx - labelWidth) + "px"; |
+ attrib["top"] = (labely - this.options.axisLabelFontSize) + "px"; |
+ } |
+ |
+ var label = DIV({'style': attrib}, this.layout.xticks[i][1]); |
+ this.xlabels.push(label); |
+ MochiKit.DOM.appendChildNodes(this.container, label); |
+ } |
+ |
+ } |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._renderBackground = function() { |
+ var context = this.element.getContext("2d"); |
+ context.save(); |
+ context.fillStyle = this.options.backgroundColor.toRGBString(); |
+ context.fillRect(0, 0, this.width, this.height); |
+ context.restore(); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.clear = function() { |
+ if (this.isIE) { |
+ // VML takes a while to start up, so we just poll every this.IEDelay |
+ try { |
+ if (this.clearDelay) { |
+ this.clearDelay.cancel(); |
+ this.clearDelay = null; |
+ } |
+ var context = this.element.getContext("2d"); |
+ } |
+ catch (e) { |
+ this.isFirstRender = false; |
+ this.clearDelay = MochiKit.Async.wait(this.IEDelay); |
+ this.clearDelay.addCallback(bind(this.clear, this)); |
+ return; |
+ } |
+ } |
+ |
+ var context = this.element.getContext("2d"); |
+ context.clearRect(0, 0, this.width, this.height); |
+ |
+ MochiKit.Iter.forEach(this.xlabels, MochiKit.DOM.removeElement); |
+ MochiKit.Iter.forEach(this.ylabels, MochiKit.DOM.removeElement); |
+ this.xlabels = new Array(); |
+ this.ylabels = new Array(); |
+}; |
+ |
+// ---------------------------------------------------------------- |
+// Everything below here is experimental and undocumented. |
+// ---------------------------------------------------------------- |
+ |
+PlotKit.CanvasRenderer.prototype._initialiseEvents = function() { |
+ var connect = MochiKit.Signal.connect; |
+ var bind = MochiKit.Base.bind; |
+ //MochiKit.Signal.registerSignals(this, ['onmouseover', 'onclick', 'onmouseout', 'onmousemove']); |
+ //connect(this.element, 'onmouseover', bind(this.onmouseover, this)); |
+ //connect(this.element, 'onmouseout', bind(this.onmouseout, this)); |
+ //connect(this.element, 'onmousemove', bind(this.onmousemove, this)); |
+ connect(this.element, 'onclick', bind(this.onclick, this)); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._resolveObject = function(e) { |
+ // does not work in firefox |
+ //var x = (e.event().offsetX - this.area.x) / this.area.w; |
+ //var y = (e.event().offsetY - this.area.y) / this.area.h; |
+ |
+ var x = (e.mouse().page.x - PlotKit.Base.findPosX(this.element) - this.area.x) / this.area.w; |
+ var y = (e.mouse().page.y - PlotKit.Base.findPosY(this.element) - this.area.y) / this.area.h; |
+ |
+ //log(x, y); |
+ |
+ var isHit = this.layout.hitTest(x, y); |
+ if (isHit) |
+ return isHit; |
+ return null; |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype._createEventObject = function(layoutObj, e) { |
+ if (layoutObj == null) { |
+ return null; |
+ } |
+ |
+ e.chart = layoutObj |
+ return e; |
+}; |
+ |
+ |
+PlotKit.CanvasRenderer.prototype.onclick = function(e) { |
+ var layoutObject = this._resolveObject(e); |
+ var eventObject = this._createEventObject(layoutObject, e); |
+ if (eventObject != null) |
+ MochiKit.Signal.signal(this, "onclick", eventObject); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.onmouseover = function(e) { |
+ var layoutObject = this._resolveObject(e); |
+ var eventObject = this._createEventObject(layoutObject, e); |
+ if (eventObject != null) |
+ signal(this, "onmouseover", eventObject); |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.onmouseout = function(e) { |
+ var layoutObject = this._resolveObject(e); |
+ var eventObject = this._createEventObject(layoutObject, e); |
+ if (eventObject == null) |
+ signal(this, "onmouseout", e); |
+ else |
+ signal(this, "onmouseout", eventObject); |
+ |
+}; |
+ |
+PlotKit.CanvasRenderer.prototype.onmousemove = function(e) { |
+ var layoutObject = this._resolveObject(e); |
+ var eventObject = this._createEventObject(layoutObject, e); |
+ |
+ if ((layoutObject == null) && (this.event_isinside == null)) { |
+ // TODO: should we emit an event anyway? |
+ return; |
+ } |
+ |
+ if ((layoutObject != null) && (this.event_isinside == null)) |
+ signal(this, "onmouseover", eventObject); |
+ |
+ if ((layoutObject == null) && (this.event_isinside != null)) |
+ signal(this, "onmouseout", eventObject); |
+ |
+ if ((layoutObject != null) && (this.event_isinside != null)) |
+ signal(this, "onmousemove", eventObject); |
+ |
+ this.event_isinside = layoutObject; |
+ //log("move", x, y); |
+}; |
+ |
+PlotKit.CanvasRenderer.isSupported = function(canvasName) { |
+ var canvas = null; |
+ try { |
+ if (MochiKit.Base.isUndefinedOrNull(canvasName)) |
+ canvas = MochiKit.DOM.CANVAS({}); |
+ else |
+ canvas = MochiKit.DOM.getElement(canvasName); |
+ var context = canvas.getContext("2d"); |
+ } |
+ catch (e) { |
+ var ie = navigator.appVersion.match(/MSIE (\d\.\d)/); |
+ var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1); |
+ if ((!ie) || (ie[1] < 6) || (opera)) |
+ return false; |
+ return true; |
+ } |
+ return true; |
+}; |
+ |
+// Namespace Iniitialisation |
+ |
+PlotKit.Canvas = {} |
+PlotKit.Canvas.CanvasRenderer = PlotKit.CanvasRenderer; |
+ |
+PlotKit.Canvas.EXPORT = [ |
+ "CanvasRenderer" |
+]; |
+ |
+PlotKit.Canvas.EXPORT_OK = [ |
+ "CanvasRenderer" |
+]; |
+ |
+PlotKit.Canvas.__new__ = function() { |
+ var m = MochiKit.Base; |
+ |
+ m.nameFunctions(this); |
+ |
+ this.EXPORT_TAGS = { |
+ ":common": this.EXPORT, |
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK) |
+ }; |
+}; |
+ |
+PlotKit.Canvas.__new__(); |
+MochiKit.Base._exportSymbols(this, PlotKit.Canvas); |