Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge commit 'cederberg/master'

Conflicts:
	PlotKit/EasyPlot.js
	PlotKit/Layout.js
	PlotKit/PlotKit_Packed.js
	PlotKit/SweetCanvas.js
	tests/axis.html
	tests/basic.html
	tests/debug.html
	tests/demo-svg.html
	tests/demo.html
	tests/dynamic.html
	tests/labels-img.html
	tests/labels.html
	tests/prototype_compat.html
	tests/quickstart-easy.html
	tests/quickstart-horiz.html
	tests/quickstart-neg.html
	tests/quickstart-svg.html
	tests/quickstart.html
	tests/svg-sweet.html
	tests/svg.html
	tests/sweet.html
  • Loading branch information...
commit ffc5cc5c58cd8feff5db3ea8795af4f976a60cd9 2 parents 83ae4c9 + d3936d3
Martin Kleppmann authored
View
214 PlotKit/Canvas.js
@@ -67,7 +67,7 @@ PlotKit.CanvasRenderer.prototype.__init__ = function(element, layout, options) {
"backgroundColor": Color.whiteColor(),
"padding": {left: 30, right: 30, top: 5, bottom: 10},
"colorScheme": PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),
- "strokeColor": Color.whiteColor(),
+ "strokeColor": null,
"strokeColorTransform": "asStrokeColor",
"strokeWidth": 0.5,
"fillColorTransform": null,
@@ -176,14 +176,18 @@ PlotKit.CanvasRenderer.prototype.render = function() {
if (this.layout.style == "bar") {
this._renderBarChart();
this._renderBarAxis();
- }
- else if (this.layout.style == "pie") {
+ } else if (this.layout.style == "pie") {
this._renderPieChart();
this._renderPieAxis();
- }
- else if (this.layout.style == "line") {
+ } else if (this.layout.style == "line") {
this._renderLineChart();
this._renderLineAxis();
+ } else if (this.layout.style == "point") {
+ this._renderLineAxis();
+ this._renderPointChart();
+ } else if (this.layout.style == "area") {
+ this._renderLineAxis();
+ this._renderAreaChart();
}
};
@@ -198,18 +202,8 @@ PlotKit.CanvasRenderer.prototype._renderBarChartWrap = function(data, plotFunc)
var setName = setNames[i];
var color = colorScheme[i%colorCount];
context.save();
- if (this.options.fillColorTransform && color[this.options.fillColorTransform])
- context.fillStyle = color[this.options.fillColorTransform]().toRGBString();
- else
- 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();
- else
- context.strokeStyle = color.toRGBString();
-
+ context.fillStyle = this._fillColor(color);
+ context.strokeStyle = this._strokeColor(color);
context.lineWidth = this.options.strokeWidth;
var forEachFunc = function(obj) {
if (obj.name == setName)
@@ -251,22 +245,11 @@ PlotKit.CanvasRenderer.prototype._renderLineChart = function() {
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();
- if (this.options.fillColorTransform && color[this.options.fillColorTransform])
- context.fillStyle = color[this.options.fillColorTransform]().toRGBString();
- else
- 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();
- else
- context.strokeStyle = color.toRGBString();
-
+ context.fillStyle = this._fillColor(color);
+ context.strokeStyle = this._strokeColor(color);
context.lineWidth = this.options.strokeWidth;
// create paths
@@ -280,6 +263,32 @@ PlotKit.CanvasRenderer.prototype._renderLineChart = function() {
};
MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
};
+ if (!this.options.shouldFill) {
+ // TODO: The path should be different when not being filled,
+ // but perhaps there is a cleaner way to do this that avoids
+ // some of the code duplication?
+ makePath = function(ctx) {
+ ctx.beginPath();
+ var startX = null;
+ var startY = null;
+ var addPoint = function(ctx_, point) {
+ if (point.name == setName) {
+ var x = this.area.w * point.x + this.area.x;
+ var y = this.area.h * point.y + this.area.y;
+ if (startX == null) {
+ ctx_.moveTo(x, y);
+ startX = x;
+ startY = y;
+ } else {
+ ctx_.lineTo(x, y);
+ }
+ }
+ };
+ MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+ ctx.moveTo(startX, startY);
+ ctx.closePath();
+ };
+ }
if (this.options.shouldFill) {
bind(makePath, this)(context);
@@ -320,12 +329,7 @@ PlotKit.CanvasRenderer.prototype._renderPieChart = function() {
for (var i = 0; i < slices.length; i++) {
var color = this.options.colorScheme[i%colorCount];
context.save();
-
- if (this.options.fillColorTransform && color[this.options.fillColorTransform])
- context.fillStyle = color[this.options.fillColorTransform]().toRGBString();
- else
- context.fillStyle = color.toRGBString();
-
+ context.fillStyle = this._fillColor(color);
var makePath = function() {
context.beginPath();
@@ -347,12 +351,7 @@ PlotKit.CanvasRenderer.prototype._renderPieChart = function() {
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();
- else
- context.strokeStyle = color.toRGBString();
+ context.strokeStyle = this._strokeColor(color);
context.stroke();
}
}
@@ -360,6 +359,97 @@ PlotKit.CanvasRenderer.prototype._renderPieChart = function() {
}
};
+PlotKit.CanvasRenderer.prototype._renderPointChart = 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;
+
+ for (var i = 0; i < setCount; i++) {
+ var setName = setNames[i];
+ var color = colorScheme[i%colorCount];
+
+ // setup graphics context
+ context.save();
+ context.fillStyle = this._fillColor(color);
+ context.lineWidth = this.options.strokeWidth;
+
+ // draw dots
+ var addPoint = function(ctx, point) {
+ if (point.name == setName) {
+ ctx.beginPath();
+ ctx.arc(this.area.w * point.x + this.area.x,
+ this.area.h * point.y + this.area.y,
+ this.options.strokeWidth * 5,
+ 0,
+ 2 * Math.PI,
+ false);
+ ctx.closePath();
+ ctx.fill();
+ }
+ };
+ MochiKit.Iter.forEach(this.layout.points, bind(addPoint, this, context));
+
+ context.restore();
+ }
+};
+
+PlotKit.CanvasRenderer.prototype._renderAreaChart = 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];
+
+ // setup graphics context
+ context.save();
+ context.fillStyle = this._fillColor(color);
+ context.strokeStyle = this._strokeColor(color);
+ context.lineWidth = this.options.strokeWidth;
+
+ // create paths
+ var makePath = function(ctx) {
+ ctx.beginPath();
+ var startX = null;
+ var startY = null;
+ var addPoint = function(ctx_, point) {
+ if (point.name == setName) {
+ var x = this.area.w * point.x + this.area.x;
+ var y = this.area.h * point.y + this.area.y;
+ if (startX == null) {
+ ctx_.moveTo(x, y);
+ startX = x;
+ startY = y;
+ } else {
+ ctx_.lineTo(x, y);
+ }
+ }
+ };
+ MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
+ ctx.lineTo(startX, startY);
+ 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._renderBarAxis = function() {
this._renderAxis();
}
@@ -384,7 +474,7 @@ PlotKit.CanvasRenderer.prototype._renderAxis = function() {
"zIndex": 10,
"color": this.options.axisLabelColor.toRGBString(),
"width": this.options.axisLabelWidth + "px",
- "overflow": "hidden"
+ "overflow": "visible"
}
};
@@ -500,7 +590,7 @@ PlotKit.CanvasRenderer.prototype._renderPieAxis = function() {
"zIndex": 11,
"width": labelWidth + "px",
"fontSize": this.options.axisLabelFontSize + "px",
- "overflow": "hidden",
+ "overflow": "visible",
"color": this.options.axisLabelColor.toHexString()
};
@@ -577,6 +667,42 @@ PlotKit.CanvasRenderer.prototype.clear = function() {
this.ylabels = new Array();
};
+// Returns the configured stroke color, with optional color
+// transformation applied.
+//
+// @param {Color} color the basic color scheme color
+//
+// @return {String} the stroke color RGB string
+PlotKit.CanvasRenderer.prototype._strokeColor = function (color) {
+ var opts = this.options;
+ if (opts.strokeColor) {
+ color = opts.strokeColor;
+ } else if (typeof(opts.strokeColorTransform) == "string") {
+ color = color[opts.strokeColorTransform]();
+ } else if (typeof(opts.strokeColorTransform) == "function") {
+ color = opts.strokeColorTransform(color);
+ }
+ return color.toRGBString();
+}
+
+// Returns the configured fill color, with optional color
+// transformation applied.
+//
+// @param {Color} color the basic color scheme color
+//
+// @return {String} the fill color RGB string
+PlotKit.CanvasRenderer.prototype._fillColor = function (color) {
+ var opts = this.options;
+ if (opts.fillColor) {
+ color = opts.fillColor;
+ } else if (typeof(opts.fillColorTransform) == "string") {
+ color = color[opts.fillColorTransform]();
+ } else if (typeof(opts.fillColorTransform) == "function") {
+ color = opts.fillColorTransform(color);
+ }
+ return color.toRGBString();
+}
+
// ----------------------------------------------------------------
// Everything below here is experimental and undocumented.
// ----------------------------------------------------------------
View
6 PlotKit/EasyPlot.js
@@ -45,7 +45,7 @@ PlotKit.EasyPlot.toString = function() {
// --------------------------------------------------------------------
PlotKit.EasyPlot = function(style, options, divElem, datasources) {
- this.layout = new Layout(style, options);
+ this.layout = new PlotKit.Layout(style, options);
this.divElem = divElem;
this.width = parseInt(divElem.getAttribute('width'));
this.height = parseInt(divElem.getAttribute('height'));
@@ -82,8 +82,8 @@ PlotKit.EasyPlot = function(style, options, divElem, datasources) {
if (CanvasRenderer.isSupported()) {
this.element = MochiKit.DOM.CANVAS({"id": this.divElem.getAttribute("id") + "-canvas",
- "width": this.width,
- "height": this.height}, "");
+ "width": this.width,
+ "height": this.height}, "");
this.divElem.appendChild(this.element);
this.renderer = new SweetCanvasRenderer(this.element, this.layout, options);
}
View
185 PlotKit/Layout.js
@@ -1,25 +1,25 @@
-/*
+/*
PlotKit Layout
==============
-
- Handles laying out data on to a virtual canvas square canvas between 0.0
+
+ Handles laying out data on to a virtual canvas square canvas between 0.0
and 1.0. If you want to add new chart/plot types such as point plots,
you need to add them here.
-
+
Copyright
---------
Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
For use under the BSD license. <http://www.liquidx.net/plotkit>
-
+
*/
-try {
+try {
if (typeof(PlotKit.Base) == 'undefined')
{
throw ""
}
-}
-catch (e) {
+}
+catch (e) {
throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base"
}
@@ -49,7 +49,7 @@ PlotKit.Layout.valid_styles = ["bar", "line", "pie", "point"];
// --------------------------------------------------------------------
PlotKit.Layout = function(style, options) {
-
+
this.options = {
"barWidthFillFraction": 0.75,
"barOrientation": "vertical",
@@ -68,7 +68,7 @@ PlotKit.Layout = function(style, options) {
};
// valid external options : TODO: input verification
- this.style = style;
+ this.style = style;
MochiKit.Base.update(this.options, options ? options : {});
// externally visible states
@@ -76,7 +76,7 @@ PlotKit.Layout = function(style, options) {
if (!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)) {
this.minxval = this.options.xAxis[0];
this.maxxval = this.options.xAxis[1];
- this.xscale = this.maxxval - this.minxval;
+ this.xscale = this.maxxval - this.minxval;
}
else {
this.minxval = 0;
@@ -110,6 +110,7 @@ PlotKit.Layout = function(style, options) {
this.yrange = 1;
this.hitTestCache = {x2maxy: null};
+
};
// --------------------------------------------------------------------
@@ -139,11 +140,11 @@ PlotKit.Layout.prototype.addDatasetFromTable = function(name, tableElement, xcol
ycol = 1;
if (isNil(lcol))
lcol = -1;
-
+
var rows = tableElement.tBodies[0].rows;
var data = new Array();
var labels = new Array();
-
+
if (!isNil(rows)) {
for (var i = 0; i < rows.length; i++) {
data.push([parseFloat(strip(scrapeText(rows[i].cells[xcol]))),
@@ -177,14 +178,12 @@ PlotKit.Layout.prototype.evaluate = function() {
this._evaluateBarCharts();
}
this._evaluateBarTicks();
- }
- else if (this.style == "line") {
- this._evaluateLineCharts();
- this._evaluateLineTicks();
- }
- else if (this.style == "pie") {
+ } else if (this.style == "pie") {
this._evaluatePieCharts();
this._evaluatePieTicks();
+ } else {
+ this._evaluateLineCharts();
+ this._evaluateLineTicks();
}
};
@@ -201,7 +200,7 @@ PlotKit.Layout.prototype.hitTest = function(x, y) {
if ((this.style == "bar") && this.bars && (this.bars.length > 0)) {
for (var i = 0; i < this.bars.length; i++) {
var bar = this.bars[i];
- if ((x >= bar.x) && (x <= bar.x + bar.w)
+ if ((x >= bar.x) && (x <= bar.x + bar.w)
&& (y >= bar.y) && (y - bar.y <= bar.h))
return bar;
}
@@ -253,7 +252,14 @@ PlotKit.Layout.prototype.hitTest = function(x, y) {
// TODO: actually doesn't work if we don't know how the Canvas
// lays it out, need to fix!
- var angle = Math.atan2(y - 0.5, x - 0.5) - Math.PI/2;
+ var angle = 0.0;
+ if (y < 0.5 && x < 0.5) {
+ angle = Math.atan2(y - 0.5, x - 0.5) + 5 * Math.PI/2;
+ }
+ else {
+ angle = Math.atan2(y - 0.5, x - 0.5) + Math.PI/2;
+ }
+
for (var i = 0; i < this.slices.length; i++) {
var slice = this.slices[i];
if (slice.startAngle < angle && slice.endAngle >= angle)
@@ -303,7 +309,7 @@ PlotKit.Layout.prototype._evaluateLimits = function() {
this.maxxval = this.options.xAxis[1];
this.xscale = this.maxval - this.minxval;
}
-
+
if (isNil(this.options.yAxis)) {
if (this.options.yOriginIsZero)
this.minyval = 0;
@@ -336,57 +342,50 @@ PlotKit.Layout.prototype._evaluateScales = function() {
this.yscale = 1/this.yrange;
};
-PlotKit.Layout.prototype._uniqueXValues = function() {
+PlotKit.Layout.prototype._uniqueXValues = function(includeArray) {
var collapse = PlotKit.Base.collapse;
var map = PlotKit.Base.map;
var uniq = PlotKit.Base.uniq;
var getter = MochiKit.Base.itemgetter;
var items = PlotKit.Base.items;
-
+
var xvalues = map(parseFloat, map(getter(0), collapse(map(getter(1), items(this.datasets)))));
+ // concatenate any passed iterable object to the xvalues
+ try {
+ xvalues = MochiKit.Base.concat(xvalues, includeArray);
+ } catch (e) {}
xvalues.sort(MochiKit.Base.compare);
return uniq(xvalues);
};
+PlotKit.Layout.prototype._barChartXDelta = function() {
+ /*
+ Work out the maximum bin size where each bin has at most one data point per bin per data set.
+ The maximum possible bin size for any set is the range for sets with more than one element or the value of the element for sets with one element. Start with that value and work down.
+ */
+ var xbin = (this.xrange == 0) ? this.maxxval : this.xrange;
+ // get the sorted bag of x values, make sure to include the min and max values.
+ var xvalues = this._uniqueXValues([this.minxval, this.maxxval]);
+ // find the smallest difference between x values, this corresponds to the maximum bin size.
+ for (var i = 1; i < xvalues.length; i++) {
+ xbin = Math.min(Math.abs(xvalues[i] - xvalues[i-1]), xbin);
+ }
+
+ return xbin;
+};
+
// Create the bars
PlotKit.Layout.prototype._evaluateBarCharts = function() {
var setCount = this.datasetNames.length;
+ var xdelta = this._barChartXDelta();
- // work out how far separated values are
- var xdelta = 10000000;
- var xvalues = this._uniqueXValues();
- for (var i = 1; i < xvalues.length; i++) {
- xdelta = Math.min(Math.abs(xvalues[i] - xvalues[i-1]), xdelta);
- }
+ // Now that we have the maximum bin size we need to re-adjust the xscale to take this into account.
+ this.xscale = 1 / (this.xrange + xdelta);
+
+ var barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
+ var barWidthForSet = barWidth / setCount;
+ var barMargin = (xdelta * this.xscale - barWidth) / 2;
- var barWidth = 0;
- var barWidthForSet = 0;
- var barMargin = 0;
- if (xvalues.length == 1) {
- // note we have to do something smarter if we only plot one value
- xdelta = 1.0;
- this.xscale = 1.0;
- this.minxval = xvalues[0];
- barWidth = 1.0 * this.options.barWidthFillFraction;
- barWidthForSet = barWidth/setCount;
- barMargin = (1.0 - this.options.barWidthFillFraction)/2;
- }
- else {
- // readjust xscale to fix with bar charts
- if (this.xrange == 1) {
- this.xscale = 0.5;
- }
- else if (this.xrange == 2) {
- this.xscale = 1/3.0;
- }
- else {
- this.xscale = (1.0 - xdelta/this.xrange)/this.xrange;
- }
- barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
- barWidthForSet = barWidth / setCount;
- barMargin = xdelta * this.xscale * (1.0 - this.options.barWidthFillFraction)/2;
- }
-
this.minxdelta = xdelta; // need this for tick positions
// add all the rects
@@ -406,7 +405,7 @@ PlotKit.Layout.prototype._evaluateBarCharts = function() {
yval: parseFloat(item[1]),
name: setName
};
- if ((rect.x >= 0.0) && (rect.x <= 1.0) &&
+ if ((rect.x >= 0.0) && (rect.x <= 1.0) &&
(rect.y >= 0.0) && (rect.y <= 1.0)) {
this.bars.push(rect);
}
@@ -417,35 +416,14 @@ PlotKit.Layout.prototype._evaluateBarCharts = function() {
// Create the horizontal bars
PlotKit.Layout.prototype._evaluateHorizBarCharts = function() {
var setCount = this.datasetNames.length;
+ var xdelta = this._barChartXDelta();
- // work out how far separated values are
- var xdelta = 10000000;
- var xvalues = this._uniqueXValues();
- for (var i = 1; i < xvalues.length; i++) {
- xdelta = Math.min(Math.abs(xvalues[i] - xvalues[i-1]), xdelta);
- }
+ // re-adjust the xscale to take xdelta into account.
+ this.xscale = 1 / (this.xrange + xdelta);
- var barWidth = 0;
- var barWidthForSet = 0;
- var barMargin = 0;
-
- // work out how far each far each bar is separated
- if (xvalues.length == 1) {
- // do something smarter if we only plot one value
- xdelta = 1.0;
- this.xscale = 1.0;
- this.minxval = xvalues[0];
- barWidth = 1.0 * this.options.barWidthFillFraction;
- barWidthForSet = barWidth/setCount;
- barMargin = (1.0 - this.options.barWidthFillFraction)/2;
- }
- else {
- // readjust yscale to fix with bar charts
- this.xscale = (1.0 - xdelta/this.xrange)/this.xrange;
- barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
- barWidthForSet = barWidth / setCount;
- barMargin = xdelta * this.xscale * (1.0 - this.options.barWidthFillFraction)/2;
- }
+ var barWidth = xdelta * this.xscale * this.options.barWidthFillFraction;
+ var barWidthForSet = barWidth / setCount;
+ var barMargin = (xdelta * this.xscale - barWidth) / 2;
this.minxdelta = xdelta; // need this for tick positions
@@ -492,7 +470,11 @@ PlotKit.Layout.prototype._evaluateLineCharts = function() {
var setName = this.datasetNames[i];
var dataset = this.datasets[setName];
if (PlotKit.Base.isFuncLike(dataset)) continue;
- dataset.sort(function(a, b) { return MochiKit.Base.compare(parseFloat(a[0]), parseFloat(b[0])); });
+ if (this.style != "area") {
+ dataset.sort(function(a, b) {
+ return MochiKit.Base.compare(parseFloat(a[0]), parseFloat(b[0]));
+ });
+ }
for (var j = 0; j < dataset.length; j++) {
var item = dataset[j];
var point = {
@@ -551,7 +533,7 @@ PlotKit.Layout.prototype._evaluatePieCharts = function() {
PlotKit.Layout.prototype._evaluateLineTicksForXAxis = function() {
var isNil = MochiKit.Base.isUndefinedOrNull;
-
+
if (this.options.xTicks) {
// we use use specified ticks with optional labels
@@ -560,12 +542,14 @@ PlotKit.Layout.prototype._evaluateLineTicksForXAxis = function() {
var label = tick.label;
if (isNil(label))
label = tick.v.toString();
+ if (!isNil(tick.tooltip))
+ label = MochiKit.DOM.SPAN({ title: tick.tooltip }, label);
var pos = this.xscale * (tick.v - this.minxval);
if ((pos >= 0.0) && (pos <= 1.0)) {
this.xticks.push([pos, label]);
}
};
- MochiKit.Iter.forEach(this.options.xTicks,
+ MochiKit.Iter.forEach(this.options.xTicks,
MochiKit.Base.bind(makeTicks, this));
}
else if (this.options.xNumberOfTicks) {
@@ -599,6 +583,8 @@ PlotKit.Layout.prototype._evaluateLineTicksForYAxis = function() {
var label = tick.label;
if (isNil(label))
label = tick.v.toString();
+ if (!isNil(tick.tooltip))
+ label = MochiKit.DOM.SPAN({ title: tick.tooltip }, label);
var pos = 1.0 - (this.yscale * (tick.v - this.minyval));
if ((pos >= 0.0) && (pos <= 1.0)) {
this.yticks.push([pos, label]);
@@ -608,13 +594,13 @@ PlotKit.Layout.prototype._evaluateLineTicksForYAxis = function() {
MochiKit.Base.bind(makeTicks, this));
}
else if (this.options.yNumberOfTicks) {
- // We use the optionally defined number of ticks as a guide
+ // We use the optionally defined number of ticks as a guide
this.yticks = new Array();
// if we get this separation right, we'll have good looking graphs
var roundInt = PlotKit.Base.roundInterval;
var prec = this.options.yTickPrecision;
- var roughSeparation = roundInt(this.yrange,
+ var roughSeparation = roundInt(this.yrange,
this.options.yNumberOfTicks, prec);
// round off each value of the y-axis to the precision
@@ -640,7 +626,7 @@ PlotKit.Layout.prototype._evaluateBarTicks = function() {
return [tick[0] + (this.minxdelta * this.xscale)/2, tick[1]];
};
this.xticks = MochiKit.Base.map(MochiKit.Base.bind(centerInBar, this), this.xticks);
-
+
if (this.options.barOrientation == "horizontal") {
// swap scales
var tempticks = this.xticks;
@@ -669,12 +655,18 @@ PlotKit.Layout.prototype._evaluatePieTicks = function() {
for (var i =0; i < this.options.xTicks.length; i++) {
var tick = this.options.xTicks[i];
- var slice = lookup[tick.v];
+ var slice = lookup[tick.v];
var label = tick.label;
if (slice) {
if (isNil(label))
label = tick.v.toString();
- if (this.options.piePercentages) label += " (" + formatter(slice.fraction) + ")";
+ if (this.options.pieValue == "value") {
+ label += " (" + slice.yval + ")";
+ } else if (this.options.pieValue != "none") {
+ label += " (" + formatter(slice.fraction) + ")";
+ }
+ if (!isNil(tick.tooltip))
+ label = MochiKit.DOM.SPAN({ title: tick.tooltip }, label);
this.xticks.push([tick.v, label]);
}
}
@@ -697,6 +689,7 @@ PlotKit.Layout.prototype._regenerateHitTestCache = function() {
var listMax = MochiKit.Base.listMax;
var itemgetter = MochiKit.Base.itemgetter;
var map = MochiKit.Base.map;
+ var keys = MochiKit.Base.keys;
// generate a lookup table for x values to y values
for (var i = 0; i < this.datasetNames.length; i++) {
@@ -735,9 +728,9 @@ PlotKit.LayoutModule.EXPORT_OK = [];
PlotKit.LayoutModule.__new__ = function() {
var m = MochiKit.Base;
-
+
m.nameFunctions(this);
-
+
this.EXPORT_TAGS = {
":common": this.EXPORT,
":all": m.concat(this.EXPORT, this.EXPORT_OK)
View
19 PlotKit/Legend.js
@@ -140,10 +140,11 @@ document.createTextNode(title));
PlotKit.LegendRenderer.prototype._renderListTable =
function(colorScheme, setNames) {
- var tabhead = THEAD(null);
- var tabfoot = TFOOT(null);
+ var tabhead = MochiKit.DOM.THEAD(null);
+ var tabfoot = MochiKit.DOM.TFOOT(null);
+ var partial = MochiKit.Base.partial;
- var tabbody = partial(TBODY, null);
+ var tabbody = partial(MochiKit.DOM.TBODY, null);
var i = 0;
var colorcount = colorScheme.length;
var tabrow;
@@ -151,7 +152,7 @@ function(colorScheme, setNames) {
for (var label in setNames)
{
var legendcolor = colorScheme[i%colorcount];
- var legendbox = DIV({'class': 'legendbox', 'className':
+ var legendbox = MochiKit.DOM.DIV({'class': 'legendbox', 'className':
'legendbox'});
legendbox.style.width = "10px";
legendbox.style.height = "10px";
@@ -159,15 +160,15 @@ function(colorScheme, setNames) {
legendbox.style.borderWidth = "1px";
legendbox.style.borderStyle = "solid";
legendbox.style.borderColor = "#000000";
- var boxcell = TD(null, legendbox);
+ var boxcell = MochiKit.DOM.TD(null, legendbox);
- var labelcell = TD({'class': 'legendlabel', 'className':
+ var labelcell = MochiKit.DOM.TD({'class': 'legendlabel', 'className':
'legendlabel'}, setNames[i]);
labelcell.style.font = 'normal 10pt arial';
if (!(i % columns))
{
- tabrow = partial(TR, null);
+ tabrow = partial(MochiKit.DOM.TR, null);
}
tabrow = partial(tabrow, boxcell, labelcell);
if (i % columns)
@@ -179,12 +180,12 @@ function(colorScheme, setNames) {
}
if ((setNames % columns))
{
- tabrow = tabrow(TD(null), TD(null));
+ tabrow = tabrow(MochiKit.DOM.TD(), MochiKit.DOM.TD());
tabbody = partial(tabbody, tabrow);
}
tabbody = tabbody(null);
- tab = TABLE({'class': 'legendcontainer', 'className':
+ tab = MochiKit.DOM.TABLE({'class': 'legendcontainer', 'className':
'legendcontainer'}, tabhead, tabfoot, tabbody);
tab.style.marginTop = '1em';
tab.style.marginLeft = '1.5em';
View
8,064 PlotKit/MochiKit.js
8,064 additions, 0 deletions not shown
View
2,439 PlotKit/PlotKit_Packed.js
@@ -0,0 +1,2439 @@
+/***
+
+ PlotKit.PlotKit 0.9.2 : PACKED VERSION
+
+ THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please
+ diff against the source tree, not this file.
+
+ For more information, <http://www.liquidx.net/plotkit/>.
+
+ Copyright (c) 2006. Alastair Tse.
+
+***/
+
+try{
+if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Color)=="undefined"||typeof (MochiKit.Format)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format}";
+}
+MochiKit.Base.update(MochiKit.Color.Color.prototype,{asFillColor:function(){
+return this.lighterColorWithLevel(0.3);
+},asStrokeColor:function(){
+return this.darkerColorWithLevel(0.1);
+},asPointColor:function(){
+return this.lighterColorWithLevel(0.1);
+},asTransparent:function(){
+return this.colorWithAlpha(0.1);
+}});
+if(typeof (PlotKit)=="undefined"){
+PlotKit={};
+}
+PlotKit.NAME="PlotKit";
+PlotKit.VERSION="0.9.2";
+PlotKit.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.toString=function(){
+return this.__repr__();
+};
+if(typeof (PlotKit.Base)=="undefined"){
+PlotKit.Base={};
+}
+PlotKit.Base.NAME="PlotKit.Base";
+PlotKit.Base.VERSION=PlotKit.VERSION;
+PlotKit.Base.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.Base.toString=function(){
+return this.__repr__();
+};
+PlotKit.Base.usingPrototype=function(){
+try{
+return (typeof (Object.extend)=="function");
+}
+catch(e){
+return false;
+}
+};
+MochiKit.Base.update(PlotKit.Base,{roundInterval:function(_1,_2,_3){
+var _4=MochiKit.Format.roundToFixed;
+var _5=_1/_2;
+return parseFloat(_4(_5,_3));
+},collapse:function(_6){
+var m=MochiKit.Base;
+var _8=new Array();
+for(var i=0;i<_6.length;i++){
+_8=m.concat(_8,_6[i]);
+}
+if(PlotKit.Base.usingPrototype()){
+delete _8.extend;
+delete _8.from;
+delete _8.inspect;
+}
+return _8;
+},uniq:function(_10){
+var m=MochiKit.Base;
+if(!m.isArrayLike(_10)||(_10.length<1)){
+return new Array();
+}
+var _11=new Array();
+var _12=_10[0];
+_11.push(_10[0]);
+for(var i=1;i<_10.length;i++){
+if(m.compare(_10[i],_12)!=0){
+_12=_10[i];
+_11.push(_10[i]);
+}
+}
+return _11;
+},colorScheme:function(){
+var mb=MochiKit.Base;
+var mc=MochiKit.Color;
+var _15=["red","orange","yellow","green","cyan","blue","purple","magenta"];
+var _16=function(_17){
+return mc.Color[_17+"Color"]();
+};
+return mb.map(_16,_15);
+},baseDarkPrimaryColors:function(){
+var _18=MochiKit.Color.Color.fromHexString;
+return [_18("#ad3f40"),_18("#ddac2c"),_18("#dfdd0c"),_18("#5276c4"),_18("#739c5a")];
+},basePrimaryColors:function(){
+var _19=MochiKit.Color.Color.fromHexString;
+return [_19("#d24c4d"),_19("#f2b32f"),_19("#ece90e"),_19("#5d83da"),_19("#78a15d")];
+},baseBlueColors:function(){
+var _20=MochiKit.Color.Color.fromHexString;
+return [_20("#4b6b94"),_20("#5d81b4"),_20("#acbad2")];
+},palette:function(_21,_22,_23,_24){
+var _25=MochiKit.Base.isUndefinedOrNull;
+var _26=new Array();
+if(_25(_24)){
+_24=0.1;
+}
+if(_25(_23)){
+_23=0.4;
+}
+if(_25(_22)){
+_22=-0.2;
+}
+var _27=_22;
+while(_27<=_23){
+_26.push(_27);
+_27+=_24;
+}
+var _28=function(_29,_30){
+return _29.lighterColorWithLevel(_30);
+};
+return MochiKit.Base.map(MochiKit.Base.partial(_28,_21),_26);
+},excanvasSupported:function(){
+if(/MSIE/.test(navigator.userAgent)&&!window.opera){
+return true;
+}
+return false;
+},findPosX:function(obj){
+var _32=0;
+if(obj.offsetParent){
+while(obj.offsetParent){
+_32+=obj.offsetLeft;
+obj=obj.offsetParent;
+}
+}else{
+if(obj.x){
+_32+=obj.x;
+}
+}
+return _32;
+},findPosY:function(obj){
+var _33=0;
+if(obj.offsetParent){
+while(obj.offsetParent){
+_33+=obj.offsetTop;
+obj=obj.offsetParent;
+}
+}else{
+if(obj.y){
+_33+=obj.y;
+}
+}
+return _33;
+},isFuncLike:function(obj){
+return (typeof (obj)=="function");
+}});
+PlotKit.Base.map=function(fn,lst){
+if(PlotKit.Base.usingPrototype()){
+var _36=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_36.push(fn(lst[x]));
+}
+return _36;
+}else{
+return MochiKit.Base.map(fn,lst);
+}
+};
+PlotKit.Base.items=function(lst){
+if(PlotKit.Base.usingPrototype()){
+var _38=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_38.push([x,lst[x]]);
+}
+return _38;
+}else{
+return MochiKit.Base.items(lst);
+}
+};
+PlotKit.Base.keys=function(lst){
+if(PlotKit.Base.usingPrototype()){
+var _39=[];
+for(var x in lst){
+if(typeof (lst[x])=="function"){
+continue;
+}
+_39.push(x);
+}
+return _39;
+}else{
+return MochiKit.Base.keys(lst);
+}
+};
+PlotKit.Base.baseColors=function(){
+var _40=MochiKit.Color.Color.fromHexString;
+return [_40("#476fb2"),_40("#be2c2b"),_40("#85b730"),_40("#734a99"),_40("#26a1c5"),_40("#fb8707"),_40("#000000")];
+};
+PlotKit.Base.googleColors=function(){
+var _41=MochiKit.Color.Color.fromHexString;
+return [_41("#0066dd"),_41("#dc3912"),_41("#ff9900"),_41("#008000"),_41("#4942cc"),_41("#990099")];
+};
+PlotKit.Base.googleStyle=function(){
+var r={"colorScheme":PlotKit.Base.googleColors(),"backgroundColor":MochiKit.Color.Color.whiteColor(),"strokeWidth":2,"axisLineWidth":2,"strokeColor":null,"strokeColorTransform":null,"fillColorTransform":"asTransparent","shouldFill":true};
+return r;
+};
+PlotKit.Base.officeBaseStyle={"axisLineWidth":2,"axisLabelColor":MochiKit.Color.Color.grayColor(),"axisLineColor":MochiKit.Color.Color.whiteColor(),"padding":{top:5,bottom:10,left:30,right:30}};
+MochiKit.Base.update(PlotKit.Base,{officeBlue:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"backgroundColor":PlotKit.Base.baseColors()[0].lighterColorWithLevel(0.45)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeRed:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[1]),"backgroundColor":PlotKit.Base.baseColors()[1].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeGreen:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[2]),"backgroundColor":PlotKit.Base.baseColors()[2].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officePurple:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[3]),"backgroundColor":PlotKit.Base.baseColors()[3].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeCyan:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[4]),"backgroundColor":PlotKit.Base.baseColors()[4].lighterColorWithLevel(0.5)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeOrange:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[5]),"backgroundColor":PlotKit.Base.baseColors()[5].lighterColorWithLevel(0.4)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+},officeBlack:function(){
+var r={"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[6],0,0.6),"backgroundColor":PlotKit.Base.baseColors()[6].lighterColorWithLevel(0.9)};
+MochiKit.Base.update(r,PlotKit.Base.officeBaseStyle);
+return r;
+}});
+PlotKit.Base.EXPORT=["baseColors","collapse","colorScheme","findPosX","findPosY","officeBaseStyle","officeBlue","officeRed","officeGreen","officePurple","officeCyan","officeOrange","officeBlack","roundInterval","uniq","isFuncLike","excanvasSupported"];
+PlotKit.Base.EXPORT_OK=[];
+PlotKit.Base.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.Base.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.Base);
+try{
+if(typeof (PlotKit.Base)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit.Layout depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Base";
+}
+if(typeof (PlotKit.Layout)=="undefined"){
+PlotKit.Layout={};
+}
+PlotKit.Layout.NAME="PlotKit.Layout";
+PlotKit.Layout.VERSION=PlotKit.VERSION;
+PlotKit.Layout.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+PlotKit.Layout.toString=function(){
+return this.__repr__();
+};
+PlotKit.Layout.valid_styles=["bar","line","pie","point"];
+PlotKit.Layout=function(_43,_44){
+this.options={"barWidthFillFraction":0.75,"barOrientation":"vertical","xOriginIsZero":true,"yOriginIsZero":true,"xAxis":null,"yAxis":null,"xTicks":null,"yTicks":null,"xNumberOfTicks":10,"yNumberOfTicks":5,"xTickPrecision":1,"yTickPrecision":1,"pieRadius":0.4};
+this.style=_43;
+MochiKit.Base.update(this.options,_44?_44:{});
+if(!MochiKit.Base.isUndefinedOrNull(this.options.xAxis)){
+this.minxval=this.options.xAxis[0];
+this.maxxval=this.options.xAxis[1];
+this.xscale=this.maxxval-this.minxval;
+}else{
+this.minxval=0;
+this.maxxval=null;
+this.xscale=null;
+}
+if(!MochiKit.Base.isUndefinedOrNull(this.options.yAxis)){
+this.minyval=this.options.yAxis[0];
+this.maxyval=this.options.yAxis[1];
+this.yscale=this.maxyval-this.minyval;
+}else{
+this.minyval=0;
+this.maxyval=null;
+this.yscale=null;
+}
+this.bars=new Array();
+this.points=new Array();
+this.slices=new Array();
+this.xticks=new Array();
+this.yticks=new Array();
+this.datasets=new Array();
+this.minxdelta=0;
+this.xrange=1;
+this.yrange=1;
+this.hitTestCache={x2maxy:null};
+};
+PlotKit.Layout.prototype.addDataset=function(_45,_46){
+this.datasets[_45]=_46;
+};
+PlotKit.Layout.prototype.removeDataset=function(_47,_48){
+delete this.datasets[_47];
+};
+PlotKit.Layout.prototype.addDatasetFromTable=function(_49,_50,_51,_52,_53){
+var _54=MochiKit.Base.isUndefinedOrNull;
+var _55=MochiKit.DOM.scrapeText;
+var _56=MochiKit.Format.strip;
+if(_54(_51)){
+_51=0;
+}
+if(_54(_52)){
+_52=1;
+}
+if(_54(_53)){
+_53=-1;
+}
+var _57=_50.tBodies[0].rows;
+var _58=new Array();
+var _59=new Array();
+if(!_54(_57)){
+for(var i=0;i<_57.length;i++){
+_58.push([parseFloat(_56(_55(_57[i].cells[_51]))),parseFloat(_56(_55(_57[i].cells[_52])))]);
+if(_53>=0){
+_59.push({v:parseFloat(_56(_55(_57[i].cells[_51]))),label:_56(_55(_57[i].cells[_53]))});
+}
+}
+this.addDataset(_49,_58);
+if(_53>=0){
+this.options.xTicks=_59;
+}
+return true;
+}
+return false;
+};
+PlotKit.Layout.prototype.evaluate=function(){
+this._evaluateLimits();
+this._evaluateScales();
+if(this.style=="bar"){
+if(this.options.barOrientation=="horizontal"){
+this._evaluateHorizBarCharts();
+}else{
+this._evaluateBarCharts();
+}
+this._evaluateBarTicks();
+}else{
+if(this.style=="pie"){
+this._evaluatePieCharts();
+this._evaluatePieTicks();
+}else{
+this._evaluateLineCharts();
+this._evaluateLineTicks();
+}
+}
+};
+PlotKit.Layout.prototype.hitTest=function(x,y){
+var f=MochiKit.Format.twoDigitFloat;
+if((this.style=="bar")&&this.bars&&(this.bars.length>0)){
+for(var i=0;i<this.bars.length;i++){
+var bar=this.bars[i];
+if((x>=bar.x)&&(x<=bar.x+bar.w)&&(y>=bar.y)&&(y-bar.y<=bar.h)){
+return bar;
+}
+}
+}else{
+if(this.style=="line"){
+if(this.hitTestCache.x2maxy==null){
+this._regenerateHitTestCache();
+}
+var _63=x/this.xscale;
+var _64=this.hitTestCache.xvalues;
+var _65=null;
+var _66=null;
+for(var i=1;i<_64.length;i++){
+if(_64[i]>_63){
+_65=_64[i-1];
+_66=_64[i];
+break;
+}
+}
+if((_65!=null)){
+var _67=this.hitTestCache.x2maxy[_65];
+var _68=this.hitTestCache.x2maxy[_66];
+var _69=(1-y)/this.yscale;
+var _70=(_68-_67)/(_66-_65);
+var _71=_67+_70*(_63-_65);
+if(_71>=_69){
+var obj={xval:_63,yval:_69,xafter:_66,yafter:_68,xbefore:_65,ybefore:_67,yprojected:_71};
+return obj;
+}
+}
+}else{
+if(this.style=="pie"){
+x=2*x-0.5;
+var _72=Math.sqrt((y-0.5)*(y-0.5)+(x-0.5)*(x-0.5));
+if(_72>this.options.pieRadius){
+return null;
+}
+var _73=0;
+if(y<0.5&&x<0.5){
+_73=Math.atan2(y-0.5,x-0.5)+5*Math.PI/2;
+}else{
+_73=Math.atan2(y-0.5,x-0.5)+Math.PI/2;
+}
+for(var i=0;i<this.slices.length;i++){
+var _74=this.slices[i];
+if(_74.startAngle<_73&&_74.endAngle>=_73){
+return _74;
+}
+}
+}
+}
+}
+return null;
+};
+PlotKit.Layout.prototype.rectForX=function(x){
+return null;
+};
+PlotKit.Layout.prototype.angleRangeForX=function(x){
+return null;
+};
+PlotKit.Layout.prototype._evaluateLimits=function(){
+var map=PlotKit.Base.map;
+var _76=PlotKit.Base.items;
+var _77=MochiKit.Base.itemgetter;
+var _78=PlotKit.Base.collapse;
+var _79=MochiKit.Base.listMin;
+var _80=MochiKit.Base.listMax;
+var _81=MochiKit.Base.isUndefinedOrNull;
+var all=_78(map(_77(1),_76(this.datasets)));
+if(_81(this.options.xAxis)){
+if(this.options.xOriginIsZero){
+this.minxval=0;
+}else{
+this.minxval=_79(map(parseFloat,map(_77(0),all)));
+}
+this.maxxval=_80(map(parseFloat,map(_77(0),all)));
+}else{
+this.minxval=this.options.xAxis[0];
+this.maxxval=this.options.xAxis[1];
+this.xscale=this.maxval-this.minxval;
+}
+if(_81(this.options.yAxis)){
+if(this.options.yOriginIsZero){
+this.minyval=0;
+}else{
+this.minyval=_79(map(parseFloat,map(_77(1),all)));
+}
+this.maxyval=_80(map(parseFloat,map(_77(1),all)));
+}else{
+this.minyval=this.options.yAxis[0];
+this.maxyval=this.options.yAxis[1];
+this.yscale=this.maxyval-this.minyval;
+}
+};
+PlotKit.Layout.prototype._evaluateScales=function(){
+var _83=MochiKit.Base.isUndefinedOrNull;
+this.xrange=this.maxxval-this.minxval;
+if(this.xrange==0){
+this.xscale=1;
+}else{
+this.xscale=1/this.xrange;
+}
+this.yrange=this.maxyval-this.minyval;
+if(this.yrange==0){
+this.yscale=1;
+}else{
+this.yscale=1/this.yrange;
+}
+};
+PlotKit.Layout.prototype._uniqueXValues=function(_84){
+var _85=PlotKit.Base.collapse;
+var map=PlotKit.Base.map;
+var _86=PlotKit.Base.uniq;
+var _87=MochiKit.Base.itemgetter;
+var _88=PlotKit.Base.items;
+var _89=map(parseFloat,map(_87(0),_85(map(_87(1),_88(this.datasets)))));
+try{
+_89=MochiKit.Base.concat(_89,_84);
+}
+catch(e){
+}
+_89.sort(MochiKit.Base.compare);
+return _86(_89);
+};
+PlotKit.Layout.prototype._barChartXDelta=function(){
+var _90=(this.xrange==0)?this.maxxval:this.xrange;
+var _91=this._uniqueXValues([this.minxval,this.maxxval]);
+for(var i=1;i<_91.length;i++){
+_90=Math.min(Math.abs(_91[i]-_91[i-1]),_90);
+}
+return _90;
+};
+PlotKit.Layout.prototype._evaluateBarCharts=function(){
+var _92=PlotKit.Base.items;
+var _93=_92(this.datasets).length;
+var _94=this._barChartXDelta();
+this.xscale=1/(this.xrange+_94);
+var _95=_94*this.xscale*this.options.barWidthFillFraction;
+var _96=_95/_93;
+var _97=(_94*this.xscale-_95)/2;
+this.minxdelta=_94;
+this.bars=new Array();
+var i=0;
+for(var _98 in this.datasets){
+var _99=this.datasets[_98];
+if(PlotKit.Base.isFuncLike(_99)){
+continue;
+}
+for(var j=0;j<_99.length;j++){
+var item=_99[j];
+var rect={x:((parseFloat(item[0])-this.minxval)*this.xscale)+(i*_96)+_97,y:1-((parseFloat(item[1])-this.minyval)*this.yscale),w:_96,h:((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_98};
+if((rect.x>=0)&&(rect.x<=1)&&(rect.y>=0)&&(rect.y<=1)){
+this.bars.push(rect);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluateHorizBarCharts=function(){
+var _103=PlotKit.Base.items;
+var _104=_103(this.datasets).length;
+var _105=this._barChartXDelta();
+this.xscale=1/(this.xrange+_105);
+var _106=_105*this.xscale*this.options.barWidthFillFraction;
+var _107=_106/_104;
+var _108=(_105*this.xscale-_106)/2;
+this.minxdelta=_105;
+this.bars=new Array();
+var i=0;
+for(var _109 in this.datasets){
+var _110=this.datasets[_109];
+if(PlotKit.Base.isFuncLike(_110)){
+continue;
+}
+for(var j=0;j<_110.length;j++){
+var item=_110[j];
+var rect={y:((parseFloat(item[0])-this.minxval)*this.xscale)+(i*_107)+_108,x:0,h:_107,w:((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_109};
+if(rect.y<=0){
+rect.y=0;
+}
+if(rect.y>=1){
+rect.y=1;
+}
+if((rect.x>=0)&&(rect.x<=1)){
+this.bars.push(rect);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluateLineCharts=function(){
+var _111=PlotKit.Base.items;
+var _112=_111(this.datasets).length;
+this.points=new Array();
+var i=0;
+for(var _113 in this.datasets){
+var _114=this.datasets[_113];
+if(PlotKit.Base.isFuncLike(_114)){
+continue;
+}
+if(this.style!="area"){
+_114.sort(function(a,b){
+return MochiKit.Base.compare(parseFloat(a[0]),parseFloat(b[0]));
+});
+}
+for(var j=0;j<_114.length;j++){
+var item=_114[j];
+var _117={x:((parseFloat(item[0])-this.minxval)*this.xscale),y:1-((parseFloat(item[1])-this.minyval)*this.yscale),xval:parseFloat(item[0]),yval:parseFloat(item[1]),name:_113};
+if(_117.y<=0){
+_117.y=0;
+}
+if(_117.y>=1){
+_117.y=1;
+}
+if((_117.x>=0)&&(_117.x<=1)){
+this.points.push(_117);
+}
+}
+i++;
+}
+};
+PlotKit.Layout.prototype._evaluatePieCharts=function(){
+var map=PlotKit.Base.map;
+var _118=PlotKit.Base.items;
+var sum=MochiKit.Iter.sum;
+var _120=MochiKit.Base.itemgetter;
+var _121=_118(this.datasets).length;
+var _122=_118(this.datasets)[0][1];
+var _123=sum(map(_120(1),_122));
+this.slices=new Array();
+var _124=0;
+for(var i=0;i<_122.length;i++){
+var _125=_122[i][1]/_123;
+var _126=_124*Math.PI*2;
+var _127=(_124+_125)*Math.PI*2;
+var _128={fraction:_125,xval:_122[i][0],yval:_122[i][1],startAngle:_126,endAngle:_127};
+if(_122[i][1]!=0){
+this.slices.push(_128);
+}
+_124+=_125;
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicksForXAxis=function(){
+var _129=MochiKit.Base.isUndefinedOrNull;
+if(this.options.xTicks){
+this.xticks=new Array();
+var _130=function(tick){
+var _132=tick.label;
+if(_129(_132)){
+_132=tick.v.toString();
+}
+if(!_129(tick.tooltip)){
+_132=MochiKit.DOM.SPAN({title:tick.tooltip},_132);
+}
+var pos=this.xscale*(tick.v-this.minxval);
+if((pos>=0)&&(pos<=1)){
+this.xticks.push([pos,_132]);
+}
+};
+MochiKit.Iter.forEach(this.options.xTicks,MochiKit.Base.bind(_130,this));
+}else{
+if(this.options.xNumberOfTicks){
+var _134=this._uniqueXValues();
+var _135=this.xrange/this.options.xNumberOfTicks;
+var _136=0;
+this.xticks=new Array();
+for(var i=0;i<=_134.length;i++){
+if((_134[i]-this.minxval)>=(_136*_135)){
+var pos=this.xscale*(_134[i]-this.minxval);
+if((pos>1)||(pos<0)){
+continue;
+}
+this.xticks.push([pos,_134[i]]);
+_136++;
+}
+if(_136>this.options.xNumberOfTicks){
+break;
+}
+}
+}
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicksForYAxis=function(){
+var _137=MochiKit.Base.isUndefinedOrNull;
+if(this.options.yTicks){
+this.yticks=new Array();
+var _138=function(tick){
+var _139=tick.label;
+if(_137(_139)){
+_139=tick.v.toString();
+}
+if(!_137(tick.tooltip)){
+_139=MochiKit.DOM.SPAN({title:tick.tooltip},_139);
+}
+var pos=1-(this.yscale*(tick.v-this.minyval));
+if((pos>=0)&&(pos<=1)){
+this.yticks.push([pos,_139]);
+}
+};
+MochiKit.Iter.forEach(this.options.yTicks,MochiKit.Base.bind(_138,this));
+}else{
+if(this.options.yNumberOfTicks){
+this.yticks=new Array();
+var _140=PlotKit.Base.roundInterval;
+var prec=this.options.yTickPrecision;
+var _142=_140(this.yrange,this.options.yNumberOfTicks,prec);
+for(var i=0;i<=this.options.yNumberOfTicks;i++){
+var yval=this.minyval+(i*_142);
+var pos=1-((yval-this.minyval)*this.yscale);
+if((pos>1)||(pos<0)){
+continue;
+}
+this.yticks.push([pos,MochiKit.Format.roundToFixed(yval,prec)]);
+}
+}
+}
+};
+PlotKit.Layout.prototype._evaluateLineTicks=function(){
+this._evaluateLineTicksForXAxis();
+this._evaluateLineTicksForYAxis();
+};
+PlotKit.Layout.prototype._evaluateBarTicks=function(){
+this._evaluateLineTicks();
+var _144=function(tick){
+return [tick[0]+(this.minxdelta*this.xscale)/2,tick[1]];
+};
+this.xticks=MochiKit.Base.map(MochiKit.Base.bind(_144,this),this.xticks);
+if(this.options.barOrientation=="horizontal"){
+var _145=this.xticks;
+this.xticks=this.yticks;
+this.yticks=_145;
+var _146=function(tick){
+return [1-tick[0],tick[1]];
+};
+this.xticks=MochiKit.Base.map(_146,this.xticks);
+}
+};
+PlotKit.Layout.prototype._evaluatePieTicks=function(){
+var _147=MochiKit.Base.isUndefinedOrNull;
+var _148=MochiKit.Format.numberFormatter("#%");
+this.xticks=new Array();
+if(this.options.xTicks){
+var _149=new Array();
+for(var i=0;i<this.slices.length;i++){
+_149[this.slices[i].xval]=this.slices[i];
+}
+for(var i=0;i<this.options.xTicks.length;i++){
+var tick=this.options.xTicks[i];
+var _150=_149[tick.v];
+var _151=tick.label;
+if(_150){
+if(_147(_151)){
+_151=tick.v.toString();
+}
+if(this.options.pieValue=="value"){
+_151+=" ("+_150.yval+")";
+}else{
+if(this.options.pieValue!="none"){
+_151+=" ("+_148(_150.fraction)+")";
+}
+}
+if(!_147(tick.tooltip)){
+_151=MochiKit.DOM.SPAN({title:tick.tooltip},_151);
+}
+this.xticks.push([tick.v,_151]);
+}
+}
+}else{
+for(var i=0;i<this.slices.length;i++){
+var _150=this.slices[i];
+var _151=_150.xval+" ("+_148(_150.fraction)+")";
+this.xticks.push([_150.xval,_151]);
+}
+}
+};
+PlotKit.Layout.prototype._regenerateHitTestCache=function(){
+this.hitTestCache.xvalues=this._uniqueXValues();
+this.hitTestCache.xlookup=new Array();
+this.hitTestCache.x2maxy=new Array();
+var _152=MochiKit.Base.listMax;
+var _153=MochiKit.Base.itemgetter;
+var map=MochiKit.Base.map;
+var keys=MochiKit.Base.keys;
+var _155=keys(this.datasets);
+for(var i=0;i<_155.length;i++){
+var _156=this.datasets[_155[i]];
+for(var j=0;j<_156.length;j++){
+var xval=_156[j][0];
+var yval=_156[j][1];
+if(this.hitTestCache.xlookup[xval]){
+this.hitTestCache.xlookup[xval].push([yval,_155[i]]);
+}else{
+this.hitTestCache.xlookup[xval]=[[yval,_155[i]]];
+}
+}
+}
+for(var x in this.hitTestCache.xlookup){
+var _158=this.hitTestCache.xlookup[x];
+this.hitTestCache.x2maxy[x]=_152(map(_153(0),_158));
+}
+};
+PlotKit.LayoutModule={};
+PlotKit.LayoutModule.Layout=PlotKit.Layout;
+PlotKit.LayoutModule.EXPORT=["Layout"];
+PlotKit.LayoutModule.EXPORT_OK=[];
+PlotKit.LayoutModule.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+PlotKit.LayoutModule.__new__();
+MochiKit.Base._exportSymbols(this,PlotKit.LayoutModule);
+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}";
+}
+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(_159,_160,_161){
+if(arguments.length>0){
+this.__init__(_159,_160,_161);
+}
+};
+PlotKit.CanvasRenderer.prototype.__init__=function(_162,_163,_164){
+var _165=MochiKit.Base.isUndefinedOrNull;
+var _166=MochiKit.Color.Color;
+this.options={"drawBackground":true,"backgroundColor":_166.whiteColor(),"padding":{left:30,right:30,top:5,bottom:10},"colorScheme":PlotKit.Base.palette(PlotKit.Base.baseColors()[0]),"strokeColor":null,"strokeColorTransform":"asStrokeColor","strokeWidth":0.5,"fillColorTransform":null,"shouldFill":true,"shouldStroke":true,"drawXAxis":true,"drawYAxis":true,"axisLineColor":_166.blackColor(),"axisLineWidth":0.5,"axisTickSize":3,"axisLabelColor":_166.blackColor(),"axisLabelFont":"Arial","axisLabelFontSize":9,"axisLabelWidth":50,"pieRadius":0.4,"enableEvents":true};
+MochiKit.Base.update(this.options,_164?_164:{});
+this.layout=_163;
+this.element=MochiKit.DOM.getElement(_162);
+this.container=this.element.parentNode;
+this.isIE=PlotKit.Base.excanvasSupported();
+if(this.isIE&&!_165(G_vmlCanvasManager)){
+this.IEDelay=0.5;
+this.maxTries=5;
+this.renderDelay=null;
+this.clearDelay=null;
+this.element=G_vmlCanvasManager.initElement(this.element);
+}
+this.height=MochiKit.DOM.elementDimensions(this.element).h;
+this.width=MochiKit.DOM.elementDimensions(this.element).w;
+this.element.width=this.width;
+this.element.height=this.height;
+if(_165(this.element)){
+throw "CanvasRenderer() - passed canvas is not found";
+}
+if(!this.isIE&&!(PlotKit.CanvasRenderer.isSupported(this.element))){
+throw "CanvasRenderer() - Canvas is not supported.";
+}
+if(_165(this.container)||(this.container.nodeName.toLowerCase()!="div")){
+throw "CanvasRenderer() - <canvas> needs to be enclosed in <div>";
+}
+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"}});
+try{
+this.event_isinside=null;
+if(MochiKit.Signal&&this.options.enableEvents){
+this._initialiseEvents();
+}
+}
+catch(e){
+}
+};
+PlotKit.CanvasRenderer.prototype.render=function(){
+if(this.isIE){
+try{
+if(this.renderDelay){
+this.renderDelay.cancel();
+this.renderDelay=null;
+}
+var _167=this.element.getContext("2d");
+}
+catch(e){
+this.isFirstRender=false;
+if(this.maxTries-->0){
+this.renderDelay=MochiKit.Async.wait(this.IEDelay);
+this.renderDelay.addCallback(MochiKit.Base.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();
+}else{
+if(this.layout.style=="point"){
+this._renderLineAxis();
+this._renderPointChart();
+}else{
+if(this.layout.style=="area"){
+this._renderLineAxis();
+this._renderAreaChart();
+}
+}
+}
+}
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBarChartWrap=function(data,_169){
+var _170=this.element.getContext("2d");
+var _171=this.options.colorScheme.length;
+var _172=this.options.colorScheme;
+var _173=MochiKit.Base.keys(this.layout.datasets);
+var _174=_173.length;
+for(var i=0;i<_174;i++){
+var _175=_173[i];
+var _176=_172[i%_171];
+_170.save();
+_170.fillStyle=this._fillColor(_176);
+_170.strokeStyle=this._strokeColor(_176);
+_170.lineWidth=this.options.strokeWidth;
+var _177=function(obj){
+if(obj.name==_175){
+_169(_170,obj);
+}
+};
+MochiKit.Iter.forEach(data,MochiKit.Base.bind(_177,this));
+_170.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBarChart=function(){
+var bind=MochiKit.Base.bind;
+var _179=function(_180,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){
+_180.fillRect(x,y,w,h);
+}
+if(this.options.shouldStroke){
+_180.strokeRect(x,y,w,h);
+}
+};
+this._renderBarChartWrap(this.layout.bars,bind(_179,this));
+};
+PlotKit.CanvasRenderer.prototype._renderLineChart=function(){
+var _183=this.element.getContext("2d");
+var _184=this.options.colorScheme.length;
+var _185=this.options.colorScheme;
+var _186=MochiKit.Base.keys(this.layout.datasets);
+var _187=_186.length;
+var bind=MochiKit.Base.bind;
+var _188=MochiKit.Base.partial;
+for(var i=0;i<_187;i++){
+var _189=_186[i];
+var _190=_185[i%_184];
+_183.save();
+_183.fillStyle=this._fillColor(_190);
+_183.strokeStyle=this._strokeColor(_190);
+_183.lineWidth=this.options.strokeWidth;
+var _191=function(ctx){
+ctx.beginPath();
+ctx.moveTo(this.area.x,this.area.y+this.area.h);
+var _193=function(ctx_,_195){
+if(_195.name==_189){
+ctx_.lineTo(this.area.w*_195.x+this.area.x,this.area.h*_195.y+this.area.y);
+}
+};
+MochiKit.Iter.forEach(this.layout.points,_188(_193,ctx),this);
+if(this.options.shouldFill){
+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){
+_191=function(ctx){
+ctx.beginPath();
+var _196=null;
+var _197=null;
+var _198=function(ctx_,_199){
+if(_199.name==_189){
+var x=this.area.w*_199.x+this.area.x;
+var y=this.area.h*_199.y+this.area.y;
+if(_196==null){
+ctx_.moveTo(x,y);
+_196=x;
+_197=y;
+}else{
+ctx_.lineTo(x,y);
+}
+}
+};
+MochiKit.Iter.forEach(this.layout.points,_188(_198,ctx),this);
+ctx.moveTo(_196,_197);
+ctx.closePath();
+};
+}
+if(this.options.shouldFill){
+bind(_191,this)(_183);
+_183.fill();
+}
+if(this.options.shouldStroke){
+bind(_191,this)(_183);
+_183.stroke();
+}
+_183.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderPieChart=function(){
+var _200=this.element.getContext("2d");
+var _201=this.options.colorScheme.length;
+var _202=this.layout.slices;
+var _203=this.area.x+this.area.w*0.5;
+var _204=this.area.y+this.area.h*0.5;
+var _205=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+if(this.isIE){
+_203=parseInt(_203);
+_204=parseInt(_204);
+_205=parseInt(_205);
+}
+for(var i=0;i<_202.length;i++){
+var _206=this.options.colorScheme[i%_201];
+_200.save();
+_200.fillStyle=this._fillColor(_206);
+var _207=function(){
+_200.beginPath();
+_200.moveTo(_203,_204);
+_200.arc(_203,_204,_205,_202[i].startAngle-Math.PI/2,_202[i].endAngle-Math.PI/2,false);
+_200.lineTo(_203,_204);
+_200.closePath();
+};
+if(Math.abs(_202[i].startAngle-_202[i].endAngle)>0.001){
+if(this.options.shouldFill){
+_207();
+_200.fill();
+}
+if(this.options.shouldStroke){
+_207();
+_200.lineWidth=this.options.strokeWidth;
+_200.strokeStyle=this._strokeColor(_206);
+_200.stroke();
+}
+}
+_200.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderPointChart=function(){
+var _208=this.element.getContext("2d");
+var _209=this.options.colorScheme.length;
+var _210=this.options.colorScheme;
+var _211=MochiKit.Base.keys(this.layout.datasets);
+var _212=_211.length;
+var bind=MochiKit.Base.bind;
+for(var i=0;i<_212;i++){
+var _213=_211[i];
+var _214=_210[i%_209];
+_208.save();
+_208.fillStyle=this._fillColor(_214);
+_208.lineWidth=this.options.strokeWidth;
+var _215=function(ctx,_216){
+if(_216.name==_213){
+ctx.beginPath();
+ctx.arc(this.area.w*_216.x+this.area.x,this.area.h*_216.y+this.area.y,this.options.strokeWidth*5,0,2*Math.PI,false);
+ctx.closePath();
+ctx.fill();
+}
+};
+MochiKit.Iter.forEach(this.layout.points,bind(_215,this,_208));
+_208.restore();
+}
+};
+PlotKit.CanvasRenderer.prototype._renderAreaChart=function(){
+var _217=this.element.getContext("2d");
+var _218=this.options.colorScheme.length;
+var _219=this.options.colorScheme;
+var _220=MochiKit.Base.keys(this.layout.datasets);
+var _221=_220.length;
+var bind=MochiKit.Base.bind;
+var _222=MochiKit.Base.partial;
+for(var i=0;i<_221;i++){
+var _223=_220[i];
+var _224=_219[i%_218];
+_217.save();
+_217.fillStyle=this._fillColor(_224);
+_217.strokeStyle=this._strokeColor(_224);
+_217.lineWidth=this.options.strokeWidth;
+var _225=function(ctx){
+ctx.beginPath();
+var _226=null;
+var _227=null;
+var _228=function(ctx_,_229){
+if(_229.name==_223){
+var x=this.area.w*_229.x+this.area.x;
+var y=this.area.h*_229.y+this.area.y;
+if(_226==null){
+ctx_.moveTo(x,y);
+_226=x;
+_227=y;
+}else{
+ctx_.lineTo(x,y);
+}
+}
+};
+MochiKit.Iter.forEach(this.layout.points,_222(_228,ctx),this);
+ctx.lineTo(_226,_227);
+ctx.closePath();
+};
+if(this.options.shouldFill){
+bind(_225,this)(_217);
+_217.fill();
+}
+if(this.options.shouldStroke){
+bind(_225,this)(_217);
+_217.stroke();
+}
+_217.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 DIV=MochiKit.DOM.DIV;
+var _231=this.element.getContext("2d");
+var _232={"style":{"position":"absolute","fontSize":this.options.axisLabelFontSize+"px","zIndex":10,"color":this.options.axisLabelColor.toRGBString(),"width":this.options.axisLabelWidth+"px","overflow":"visible"}};
+_231.save();
+_231.strokeStyle=this.options.axisLineColor.toRGBString();
+_231.lineWidth=this.options.axisLineWidth;
+if(this.options.drawYAxis){
+if(this.layout.yticks){
+var _233=function(tick){
+if(typeof (tick)=="function"){
+return;
+}
+var x=this.area.x;
+var y=this.area.y+tick[0]*this.area.h;
+_231.beginPath();
+_231.moveTo(x,y);
+_231.lineTo(x-this.options.axisTickSize,y);
+_231.closePath();
+_231.stroke();
+var _234=DIV(_232,tick[1]);
+_234.style.top=(y-this.options.axisLabelFontSize)+"px";
+_234.style.left=(x-this.options.padding.left-this.options.axisTickSize)+"px";
+_234.style.textAlign="right";
+_234.style.width=(this.options.padding.left-this.options.axisTickSize*2)+"px";
+MochiKit.DOM.appendChildNodes(this.container,_234);
+this.ylabels.push(_234);
+};
+MochiKit.Iter.forEach(this.layout.yticks,MochiKit.Base.bind(_233,this));
+}
+_231.beginPath();
+_231.moveTo(this.area.x,this.area.y);
+_231.lineTo(this.area.x,this.area.y+this.area.h);
+_231.closePath();
+_231.stroke();
+}
+if(this.options.drawXAxis){
+if(this.layout.xticks){
+var _233=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;
+_231.beginPath();
+_231.moveTo(x,y);
+_231.lineTo(x,y+this.options.axisTickSize);
+_231.closePath();
+_231.stroke();
+var _235=DIV(_232,tick[1]);
+_235.style.top=(y+this.options.axisTickSize)+"px";
+_235.style.left=(x-this.options.axisLabelWidth/2)+"px";
+_235.style.textAlign="center";
+_235.style.width=this.options.axisLabelWidth+"px";
+MochiKit.DOM.appendChildNodes(this.container,_235);
+this.xlabels.push(_235);
+};
+MochiKit.Iter.forEach(this.layout.xticks,MochiKit.Base.bind(_233,this));
+}
+_231.beginPath();
+_231.moveTo(this.area.x,this.area.y+this.area.h);
+_231.lineTo(this.area.x+this.area.w,this.area.y+this.area.h);
+_231.closePath();
+_231.stroke();
+}
+_231.restore();
+};
+PlotKit.CanvasRenderer.prototype._renderPieAxis=function(){
+if(!this.options.drawXAxis){
+return;
+}
+if(this.layout.xticks){
+var _236=new Array();
+for(var i=0;i<this.layout.slices.length;i++){
+_236[this.layout.slices[i].xval]=this.layout.slices[i];
+}
+var _237=this.area.x+this.area.w*0.5;
+var _238=this.area.y+this.area.h*0.5;
+var _239=Math.min(this.area.w*this.options.pieRadius,this.area.h*this.options.pieRadius);
+var _240=this.options.axisLabelWidth;
+for(var i=0;i<this.layout.xticks.length;i++){
+var _241=_236[this.layout.xticks[i][0]];
+if(MochiKit.Base.isUndefinedOrNull(_241)){
+continue;
+}
+var _242=(_241.startAngle+_241.endAngle)/2;
+var _243=_242;
+if(_243>Math.PI*2){
+_243=_243-Math.PI*2;
+}else{
+if(_243<0){
+_243=_243+Math.PI*2;
+}
+}
+var _244=_237+Math.sin(_243)*(_239+10);
+var _245=_238-Math.cos(_243)*(_239+10);
+var _246={"position":"absolute","zIndex":11,"width":_240+"px","fontSize":this.options.axisLabelFontSize+"px","overflow":"visible","color":this.options.axisLabelColor.toHexString()};
+if(_243<=Math.PI*0.5){
+_246["textAlign"]="left";
+_246["verticalAlign"]="top";
+_246["left"]=_244+"px";
+_246["top"]=(_245-this.options.axisLabelFontSize)+"px";
+}else{
+if((_243>Math.PI*0.5)&&(_243<=Math.PI)){
+_246["textAlign"]="left";
+_246["verticalAlign"]="bottom";
+_246["left"]=_244+"px";
+_246["top"]=_245+"px";
+}else{
+if((_243>Math.PI)&&(_243<=Math.PI*1.5)){
+_246["textAlign"]="right";
+_246["verticalAlign"]="bottom";
+_246["left"]=(_244-_240)+"px";
+_246["top"]=_245+"px";
+}else{
+_246["textAlign"]="right";
+_246["verticalAlign"]="bottom";
+_246["left"]=(_244-_240)+"px";
+_246["top"]=(_245-this.options.axisLabelFontSize)+"px";
+}
+}
+}
+var _247=MochiKit.DOM.DIV({"style":_246},this.layout.xticks[i][1]);
+this.xlabels.push(_247);
+MochiKit.DOM.appendChildNodes(this.container,_247);
+}
+}
+};
+PlotKit.CanvasRenderer.prototype._renderBackground=function(){
+var _248=this.element.getContext("2d");
+_248.save();
+_248.fillStyle=this.options.backgroundColor.toRGBString();
+_248.fillRect(0,0,this.width,this.height);
+_248.restore();
+};
+PlotKit.CanvasRenderer.prototype.clear=function(){
+if(this.isIE){
+try{
+if(this.clearDelay){
+this.clearDelay.cancel();
+this.clearDelay=null;
+}
+var _249=this.element.getContext("2d");
+}
+catch(e){
+this.isFirstRender=false;
+this.clearDelay=MochiKit.Async.wait(this.IEDelay);
+this.clearDelay.addCallback(MochiKit.Base.bind(this.clear,this));
+return;
+}
+}
+var _249=this.element.getContext("2d");
+_249.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();
+};
+PlotKit.CanvasRenderer.prototype._strokeColor=function(_250){
+var opts=this.options;
+if(opts.strokeColor){
+_250=opts.strokeColor;
+}else{
+if(typeof (opts.strokeColorTransform)=="string"){
+_250=_250[opts.strokeColorTransform]();
+}else{
+if(typeof (opts.strokeColorTransform)=="function"){
+_250=opts.strokeColorTransform(_250);
+}
+}
+}
+return _250.toRGBString();
+};
+PlotKit.CanvasRenderer.prototype._fillColor=function(_252){
+var opts=this.options;
+if(opts.fillColor){
+_252=opts.fillColor;
+}else{
+if(typeof (opts.fillColorTransform)=="string"){
+_252=_252[opts.fillColorTransform]();
+}else{
+if(typeof (opts.fillColorTransform)=="function"){
+_252=opts.fillColorTransform(_252);
+}
+}
+}
+return _252.toRGBString();
+};
+PlotKit.CanvasRenderer.prototype._initialiseEvents=function(){
+var _253=MochiKit.Signal.connect;
+var bind=MochiKit.Base.bind;
+_253(this.element,"onclick",bind(this.onclick,this));
+};
+PlotKit.CanvasRenderer.prototype._resolveObject=function(e){
+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;
+var _255=this.layout.hitTest(x,y);
+if(_255){
+return _255;
+}
+return null;
+};
+PlotKit.CanvasRenderer.prototype._createEventObject=function(_256,e){
+if(_256==null){
+return null;
+}
+e.chart=_256;
+return e;
+};
+PlotKit.CanvasRenderer.prototype.onclick=function(e){
+var _257=this._resolveObject(e);
+var _258=this._createEventObject(_257,e);
+if(_258!=null){
+MochiKit.Signal.signal(this,"onclick",_258);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmouseover=function(e){
+var _259=this._resolveObject(e);
+var _260=this._createEventObject(_259,e);
+if(_260!=null){
+MochiKit.Signal.signal(this,"onmouseover",_260);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmouseout=function(e){
+var _261=this._resolveObject(e);
+var _262=this._createEventObject(_261,e);
+if(_262==null){
+MochiKit.Signal.signal(this,"onmouseout",e);
+}else{
+MochiKit.Signal.signal(this,"onmouseout",_262);
+}
+};
+PlotKit.CanvasRenderer.prototype.onmousemove=function(e){
+var _263=this._resolveObject(e);
+var _264=this._createEventObject(_263,e);
+if((_263==null)&&(this.event_isinside==null)){
+return;
+}
+if((_263!=null)&&(this.event_isinside==null)){
+MochiKit.Signal.signal(this,"onmouseover",_264);
+}
+if((_263==null)&&(this.event_isinside!=null)){
+MochiKit.Signal.signal(this,"onmouseout",_264);
+}
+if((_263!=null)&&(this.event_isinside!=null)){
+MochiKit.Signal.signal(this,"onmousemove",_264);
+}
+this.event_isinside=_263;
+};
+PlotKit.CanvasRenderer.isSupported=function(_265){
+var _266=null;
+try{
+if(MochiKit.Base.isUndefinedOrNull(_265)){
+_266=MochiKit.DOM.CANVAS({});
+}else{
+_266=MochiKit.DOM.getElement(_265);
+}
+var _267=_266.getContext("2d");
+}
+catch(e){
+var ie=navigator.appVersion.match(/MSIE (\d\.\d)/);
+var _269=(navigator.userAgent.toLowerCase().indexOf("opera")!=-1);
+if((!ie)||(ie[1]<6)||(_269)){
+return false;
+}
+return true;
+}
+return true;
+};
+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);
+try{
+if(typeof (PlotKit.Layout)=="undefined"){
+throw "";
+}
+}
+catch(e){
+throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout";
+}
+PlotKit.SVGRenderer=function(_270,_271,_272){
+if(arguments.length>0){
+this.__init__(_270,_271,_272);
+}
+};
+PlotKit.SVGRenderer.NAME="PlotKit.SVGRenderer";