Raphael.fn.pieChart = function(cx, cy, r, values, colors, stroke) {
	var paper = this,
		rad	  = Math.PI / 180;
	function sector(cx, cy, r, startAngle, endAngle, params) {
		var x1 = cx + r * Math.cos(-startAngle * rad),
			x2 = cx + r * Math.cos(-endAngle * rad),
			y1 = cy + r * Math.sin(-startAngle * rad),
			y2 = cy + r * Math.sin(-endAngle * rad);
		return paper.path(params).moveTo(cx, cy).lineTo(x1, y1).arcTo(r, r, (endAngle - startAngle > 180 ? 1 : 0), 0, x2, y2).andClose();
	}
	var angle = 0,
		total = 0;
		process = function(j) {
			var value	  = values[j],
				angleplus = 360 * value / total,
				popangle  = angle + (angleplus / 2),
				color	  = colors[j],
				ms		  = 200,
				delta	  = 10,
				p		  = sector(cx, cy, r, angle, angle + angleplus, {fill: color, stroke: stroke});
			angle += angleplus;
		};
	for (var i = 0, ii = values.length; i < ii; i++) {
		total += values[i];
	}
	for (var i = 0; i < ii; i++) {
		process(i);
	}
};

Raphael.fn.lineChart = function(w, h, min, max, labels, data, colors) {
	var paper = this;
	// Create key
	var keywidth    = 18,
		keyheight   = 6,
		keyY        = 8;
	for (var i = 0; i < data.length; i++) {
		var keyX = (w / data.length) * i;
		paper.rect(keyX, keyY, keywidth, keyheight).attr({
			fill:   colors[i],
			stroke: "none"
		});
		paper.text(keyX + keywidth + 12, 11, data[i].key).attr({
			"text-anchor": "start",
			font:          "normal 12px Arial",
		    fill:          "#000", 
		    stroke:        "none"
		});
	}
	// Draw grid and labels
	var topgutter    = 28,
		bottomgutter = 18,
		xgrid        = w / labels.length,
		gridcolor    = "#bfbfbf",
		yunit        = (h - topgutter - bottomgutter) / (max - min),
		xaxis        = h - bottomgutter;
	for (var j = 0; j < labels.length; j++) {
		paper.path({stroke: gridcolor, "stroke-width": 1}).moveTo(xgrid * j, topgutter).lineTo(xgrid * j, h);
		paper.text((xgrid * j) + (xgrid / 2), h - 7, labels[j]).attr({
			font:   "normal 12px Arial",
			fill:   gridcolor,
			stroke: "none"
		});
	}
	paper.path({
		stroke           : gridcolor,
		"stroke-width"   : 1
	}).moveTo(w, topgutter).lineTo(w, h);
	// Plot data
	for (k = 0; k < data.length; k++) {
		var plot = paper.path({
			stroke           : colors[k],
			"stroke-width"   : 4,
			"stroke-linecap" : "round",
			"stroke-linejoin": "round"
		}).moveTo(xgrid / 2, xaxis - ((data[k].values[0] - min) * yunit));
		for (m = 1; m < data[k].values.length; m++) {
			plot.lineTo((xgrid * m) + (xgrid / 2), xaxis - ((data[k].values[m] - min) * yunit));
		}
	}
};

Raphael.fn.vBarChart = function(w, h, min, max, labels, data, colors) {
	var paper = this;
	// Create key
	var keywidth    = 18,
		keyheight   = 6,
		keyY        = 8;
	for (var i = 0; i < data.length; i++) {
		var keyX = (w / data.length) * i;
		paper.rect(keyX, keyY, keywidth, keyheight).attr({
			fill:   colors[i],
			stroke: "none"
		});
		paper.text(keyX + keywidth + 12, 11, data[i].key).attr({
			"text-anchor": "start",
			font:          "normal 12px Arial",
		    fill:          "#000", 
		    stroke:        "none"
		});
	}
	// Draw x-axis, labels, and then plot data
	var topgutter    = 28,
		bottomgutter = 18,
		xgrid        = w / labels.length,
		gridcolor    = "#bfbfbf",
		yunit        = (h - topgutter - bottomgutter) / (max - min),
		xaxis        = h - bottomgutter,
		strokeWidth  = 8;
	paper.path({stroke: gridcolor, "stroke-width": 1}).moveTo(0, xaxis).lineTo(w, xaxis);
	var offset = -((data.length / 2) - 0.5);
	for (var j = 0; j < labels.length; j++) {
		paper.text((xgrid * j) + (xgrid / 2), h - 7, labels[j]).attr({
			font:   "normal 12px Arial",
			fill:   gridcolor,
			stroke: "none"
		});
		for (var k = 0; k < data.length; k++) {
			var plot = paper.path({
				stroke         : colors[k],
				"stroke-width" : strokeWidth
			}).moveTo(((xgrid * j) + (xgrid / 2) + ((k + offset) * strokeWidth)), xaxis).lineTo((xgrid * j) + (xgrid / 2) + ((k + offset) * strokeWidth), xaxis - ((data[k].values[j] - min) * yunit));
		}
	}
	
};

