Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(724)

Unified Diff: static/js/plotkit/Canvas.js

Issue 22969002: Add stats js files to static dir (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/chromium-build
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « static/js/plotkit/Base.js ('k') | static/js/plotkit/LICENSE » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « static/js/plotkit/Base.js ('k') | static/js/plotkit/LICENSE » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698