function muestraGraficaArea(){ 

	$('div.visualize-' + activa).fadeOut('fast', function(){	

		$('li#'+activa).toggleClass('activa');
		$('div.visualize-' + activa).remove();
		activa = 'area';
		$('li#area').toggleClass('activa');			
		$('table').visualize({type: 'area', width: 910, height: 500, colors: ['#CCC','#c30']});
		$('div.visualize-area').fadeOut(0, function(){
			$('div.visualize-area').fadeIn('slow');
		});
	});
}


function muestraGraficaLineas(){ 

	$('div.visualize-' + activa).fadeOut('fast', function(){


		$('li#'+activa).toggleClass('activa');	
		$('div.visualize-' + activa).remove();
		activa = 'line';
		$('li#line').toggleClass('activa');						
		$('table').visualize({type: 'line', width: 910, height: 500, colors: ['#CCC','#c30']});
		$('div.visualize-line').fadeOut(0, function(){
			$('div.visualize-line').fadeIn('slow');
		});
	});
}

function muestraGraficaBarras(){ 


	$('div.visualize-' + activa).fadeOut('fast', function(){


		$('li#'+activa).toggleClass('activa');
		$('div.visualize-' + activa).remove();
		activa = 'bar';
		$('li#bar').toggleClass('activa');			
		$('table').visualize({type: 'bar', width: 910, height: 500, colors: ['#CCC','#c30'], barGroupMargin: 10, barMargin: 1, title: false});
		$('div.visualize-bar').fadeOut(0, function(){
			$('div.visualize-bar').fadeIn('slow');
		});
	});
}


(function($) { 	

	var bubb = '';

	$.fn.visualize = function(options, container){
		return $(this).each(function(){
			//configuration
			var o = $.extend({
				type: 'bar', //also available: area, pie, line
				width: $(this).width(), //height of canvas - defaults to table height
				height: $(this).height(), //height of canvas - defaults to table height
				appendTitle: true, //table caption text is added to chart
				title: null, //grabs from table caption if null
				appendKey: true, //color key is added to chart
				colors: ['#be1e2d','#666699','#92d5ea','#ee8310','#8d10ee','#5a3b16','#26a4ed','#f45a90','#e9e744'],
				textColors: [], //corresponds with colors array. null/undefined items will fall back to CSS
				parseDirection: 'x', //which direction to parse the table data
				pieMargin: 20, //pie charts only - spacing around pie
				pieLabelPos: 'inside',
				lineWeight: 4, //for line and area - stroke weight
				barGroupMargin: 10,
				barMargin: 1, //space around bars in bar chart (added to both sides of bar)
				yLabelInterval: 30 //distance between y labels
				},options);


				//reset width, height to numbers
				o.width = parseFloat(o.width);
				o.height = parseFloat(o.height);


				var self = $(this);

				//function to scrape data from html table
				function scrapeTable(){
					var colors = o.colors;
					var textColors = o.textColors;
					var tableData = {
						dataGroups: function(){
							var dataGroups = [];
							if(o.parseDirection == 'x'){
								self.find('tr:gt(0)').each(function(i){
									dataGroups[i] = {};
									dataGroups[i].points = [];
									dataGroups[i].color = colors[i];
									if(textColors[i]){ dataGroups[i].textColor = textColors[i]; }
									$(this).find('td').each(function(){
										dataGroups[i].points.push( parseFloat($(this).text()) );
									});
								});
							}
							else {
								var cols = self.find('tr:eq(1) td').size();
								for(var i=0; i<cols; i++){
									dataGroups[i] = {};
									dataGroups[i].points = [];
									dataGroups[i].color = colors[i];
									if(textColors[i]){ dataGroups[i].textColor = textColors[i]; }
									self.find('tr:gt(0)').each(function(){
										dataGroups[i].points.push( $(this).find('td').eq(i).text()*1 );
									});
								};
							}
							return dataGroups;
						},
						allData: function(){
							var allData = [];
							$(this.dataGroups()).each(function(){
								allData.push(this.points);
							});
							return allData;
						},
						dataSum: function(){
							var dataSum = 0;
							var allData = this.allData().join(',').split(',');
							$(allData).each(function(){
								dataSum += parseFloat(this);
							});
							return dataSum
						},	
						topValue: function(){
							var topValue = 0;
							var allData = this.allData().join(',').split(',');
							$(allData).each(function(){
								if(parseFloat(this,10)>topValue) topValue = parseFloat(this);
							});
							return topValue;
						},
						bottomValue: function(){
							var bottomValue = 0;
							var allData = this.allData().join(',').split(',');
							$(allData).each(function(){
								if(this<bottomValue) bottomValue = parseFloat(this);
							});
							return bottomValue;
						},
						memberTotals: function(){
							var memberTotals = [];
							var dataGroups = this.dataGroups();
							$(dataGroups).each(function(l){
								var count = 0;
								$(dataGroups[l].points).each(function(m){
									count +=dataGroups[l].points[m];
								});
								memberTotals.push(count);
							});
							return memberTotals;
						},
						yTotals: function(){
							var yTotals = [];
							var dataGroups = this.dataGroups();
							var loopLength = this.xLabels().length;
							for(var i = 0; i<loopLength; i++){
								yTotals[i] =[];
								var thisTotal = 0;
								$(dataGroups).each(function(l){
									yTotals[i].push(this.points[i]);
								});
								yTotals[i].join(',').split(',');
								$(yTotals[i]).each(function(){
									thisTotal += parseFloat(this);
								});
								yTotals[i] = thisTotal;

							}
							return yTotals;
						},
						topYtotal: function(){
							var topYtotal = 0;
							var yTotals = this.yTotals().join(',').split(',');
							$(yTotals).each(function(){
								if(parseFloat(this,10)>topYtotal) topYtotal = parseFloat(this);
							});
							return topYtotal;
						},
						totalYRange: function(){
							return this.topValue() - this.bottomValue();
						},
						xLabels: function(){
							var xLabels = [];
							if(o.parseDirection == 'x'){
								self.find('tr:eq(0) th').each(function(){
									xLabels.push($(this).html());
								});
							}
							else {
								self.find('tr:gt(0) th').each(function(){
									xLabels.push($(this).html());
								});
							}
							return xLabels;
						},
						yLabels: function(){
							var yLabels = [];
							yLabels.push(bottomValue); 
							var numLabels = Math.round(o.height / o.yLabelInterval);
							var loopInterval = Math.ceil(totalYRange / numLabels) || 1;
							while( yLabels[yLabels.length-1] < topValue - loopInterval){
								yLabels.push(yLabels[yLabels.length-1] + loopInterval); 
							}
							yLabels.push(topValue); 
							return yLabels;
						}			
					};

					return tableData;
				};


				//function to create a chart
				var createChart = {
					pie: function(){	

						canvasContain.addClass('visualize-pie');

						if(o.pieLabelPos == 'outside'){ canvasContain.addClass('visualize-pie-outside'); }	

						var centerx = Math.round(canvas.width()/2);
						var centery = Math.round(canvas.height()/2);
						var radius = centery - o.pieMargin;				
						var counter = 0.0;
						var toRad = function(integer){ return (Math.PI/180)*integer; };
						var labels = $('<ul class="visualize-labels"></ul>')
						.insertAfter(canvas);

						//draw the pie pieces
						$.each(memberTotals, function(i){
							var fraction = (this <= 0 || isNaN(this))? 0 : this / dataSum;
							ctx.beginPath();
							ctx.moveTo(centerx, centery);
							ctx.arc(centerx, centery, radius, 
								counter * Math.PI * 2 - Math.PI * 0.5,
								(counter + fraction) * Math.PI * 2 - Math.PI * 0.5,
								false);
								ctx.lineTo(centerx, centery);
								ctx.closePath();
								ctx.fillStyle = dataGroups[i].color;
								ctx.fill();
								// draw labels
								var sliceMiddle = (counter + fraction/2);
								var distance = o.pieLabelPos == 'inside' ? radius/1.5 : radius +  radius / 5;
								var labelx = Math.round(centerx + Math.sin(sliceMiddle * Math.PI * 2) * (distance));
								var labely = Math.round(centery - Math.cos(sliceMiddle * Math.PI * 2) * (distance));
								var leftRight = (labelx > centerx) ? 'right' : 'left';
								var topBottom = (labely > centery) ? 'bottom' : 'top';
								var labeltext = $('<span class="visualize-label">' + Math.round(fraction*100) + '%</span>')
								.css(leftRight, 0)
								.css(topBottom, 0);
								var label = $('<li class="visualize-label-pos"></li>')
								.appendTo(labels)
								.css({left: labelx, top: labely})
								.append(labeltext);	
								labeltext
								.css('font-size', radius / 8)		
								.css('margin-'+leftRight, -labeltext.width()/2)
								.css('margin-'+topBottom, -labeltext.outerHeight()/2);

								if(dataGroups[i].textColor){ labeltext.css('color', dataGroups[i].textColor); }	
								counter+=fraction;
							});
						},

						line: function(area){

							if(area){ canvasContain.addClass('visualize-area'); }
							else{ canvasContain.addClass('visualize-line'); }

							//write X labels
							var xInterval = canvas.width() / (xLabels.length -1);
							var xlabelsUL = $('<ul class="visualize-labels-x"></ul>')
							.width(canvas.width())
							.height(canvas.height())
							.insertBefore(canvas);
							$.each(xLabels, function(i){ 
								var thisLi = $('<li><span>'+this+'</span></li>')
								.prepend('<span class="line" />')
								.css('left', xInterval * i)
								.appendTo(xlabelsUL);						
								var label = thisLi.find('span:not(.line)');
								var leftOffset = label.width()/-2;
								if(i == 0){ leftOffset = 0; }
								else if(i== xLabels.length-1){ leftOffset = -label.width(); }
								label
								.css('margin-left', leftOffset)
								.addClass('label');
							});

							//write Y labels
							var yScale = canvas.height() / totalYRange;
							var liBottom = canvas.height() / (yLabels.length-1);
							var ylabelsUL = $('<ul class="visualize-labels-y"></ul>')
							.width(canvas.width())
							.height(canvas.height())
							.insertBefore(canvas);

							$.each(yLabels, function(i){  
								var thisLi = $('<li><span>'+this+'</span></li>')
								.prepend('<span class="line"  />')
								.css('bottom',liBottom*i)
								.prependTo(ylabelsUL);
								var label = thisLi.find('span:not(.line)');
								var topOffset = label.height()/-2;
								if(i == 0){ topOffset = -label.height(); }
								else if(i== yLabels.length-1){ topOffset = 0; }
								label
								.css('margin-top', topOffset)
								.addClass('label');
							});

							//start from the bottom left
							ctx.translate(0,zeroLoc);
							//iterate and draw
							$.each(dataGroups,function(h){
								ctx.beginPath();
								ctx.lineWidth = o.lineWeight;
								ctx.lineJoin = 'round';
								var points = this.points;
								var integer = 0;
								ctx.moveTo(0,-(points[0]*yScale));
								$.each(points, function(){
									ctx.lineTo(integer,-(this*yScale));
									integer+=xInterval;
								});
								ctx.strokeStyle = this.color;
								ctx.stroke();
								if(area){
									ctx.lineTo(integer,0);
									ctx.lineTo(0,0);
									ctx.closePath();
									ctx.fillStyle = this.color;
									ctx.globalAlpha = .3;
									ctx.fill();
									ctx.globalAlpha = 1.0;
								}
								else {ctx.closePath();}
							});
						},

						area: function(){
							createChart.line(true);
						},

						bar: function(){

							canvasContain.addClass('visualize-bar');

							//write X labels
							var xInterval = canvas.width() / (xLabels.length);
							var xlabelsUL = $('<ul class="visualize-labels-x"></ul>')
							.width(canvas.width())
							.height(canvas.height())
							.insertBefore(canvas);
							$.each(xLabels, function(i){ 
								var thisLi = $('<li><span class="label">'+this+'</span></li>')
								.prepend('<span class="line" />')
								.css('left', xInterval * i)
								.width(xInterval)
								.appendTo(xlabelsUL);
								var label = thisLi.find('span.label');
								label.addClass('label');
							});

							//write Y labels
							var yScale = canvas.height() / totalYRange;
							var liBottom = canvas.height() / (yLabels.length-1);
							var ylabelsUL = $('<ul class="visualize-labels-y"></ul>')
							.width(canvas.width())
							.height(canvas.height())
							.insertBefore(canvas);
							$.each(yLabels, function(i){  
								var thisLi = $('<li><span>'+this+'</span></li>')
								.prepend('<span class="line"  />')
								.css('bottom',liBottom*i)
								.prependTo(ylabelsUL);
								var label = thisLi.find('span:not(.line)');
								var topOffset = label.height()/-2;
								if(i == 0){ topOffset = -label.height(); }
								else if(i== yLabels.length-1){ topOffset = 0; }
								label
								.css('margin-top', topOffset)
								.addClass('label');
							});

							//start from the bottom left
							ctx.translate(0,zeroLoc);
							//iterate and draw
							for(var h=0; h<dataGroups.length; h++){
								ctx.beginPath();
								var linewidth = (xInterval-o.barGroupMargin*2) / dataGroups.length; //removed +1 
								var strokeWidth = linewidth - (o.barMargin*2);
								ctx.lineWidth = strokeWidth;
								var points = dataGroups[h].points;
								var integer = 0;

								bubb = bubb + '<div id="bubbles">';

								for(var i=0; i<points.length; i++){

									var xVal = (integer-o.barGroupMargin)+(h*linewidth)+linewidth/2;
									xVal += o.barGroupMargin*2;

									var nw_y_val = Math.round(-points[i]*yScale) + 485;

									ctx.moveTo(xVal, 0);
									ctx.lineTo(xVal, Math.round(-points[i]*yScale));
									integer+=xInterval;
									bubb = bubb + '<span class="bubble" style="left: '+ parseInt(xVal) +'px; top: '+ nw_y_val +'px;">'+ points[i] +'</span>';

								}
								bubb = bubb + '</div>';

								ctx.strokeStyle = dataGroups[h].color;
								ctx.stroke();
								ctx.closePath();

							}
						}
					};

					//create new canvas, set w&h attrs (not inline styles)
					var canvasNode = document.createElement("canvas"); 
					canvasNode.setAttribute('height',o.height);
					canvasNode.setAttribute('width',o.width);
					var canvas = $(canvasNode);

					//get title for chart
					var title = o.title || self.find('caption').text();

					//create canvas wrapper div, set inline w&h, append
					var canvasContain = (container || $('<div class="visualize" role="img" aria-label="Chart representing data from the table: '+ title +'" />'))
					.height(o.height)
					.width(o.width)
					.append(canvas);

					//scrape table (this should be cleaned up into an obj)
					var tableData = scrapeTable();
					var dataGroups = tableData.dataGroups();
					var allData = tableData.allData();
					var dataSum = tableData.dataSum();
					var topValue = tableData.topValue();
					var bottomValue = tableData.bottomValue();
					var memberTotals = tableData.memberTotals();
					var totalYRange = tableData.totalYRange();
					var zeroLoc = o.height * (topValue/totalYRange);
					var xLabels = tableData.xLabels();
					var yLabels = tableData.yLabels();

					//title/key container
					if(o.appendTitle || o.appendKey){
						var infoContain = $('<div class="visualize-info"></div>')
						.appendTo(canvasContain);
					}

					//append title
					if(o.appendTitle){
						$('<div class="visualize-title">'+ title +'</div>').appendTo(infoContain);
					}


					//append key
					if(o.appendKey){
						var newKey = $('<ul class="visualize-key"></ul>');
						var selector = (o.parseDirection == 'x') ? 'tr:gt(0) th' : 'tr:eq(0) th' ;
						self.find(selector).each(function(i){
							$('<li><span class="visualize-key-color" style="background: '+dataGroups[i].color+'"></span><span class="visualize-key-label">'+ $(this).text() +'</span></li>')
							.appendTo(newKey);
						});
						newKey.appendTo(infoContain);
					};		

					//append new canvas to page

					if(!container){canvasContain.insertAfter(this); }
					if( typeof(G_vmlCanvasManager) != 'undefined' ){ G_vmlCanvasManager.initElement(canvas[0]); }	

					//set up the drawing board	
					var ctx = canvas[0].getContext('2d');

					//create chart
					createChart[o.type]();

					//clean up some doubled lines that sit on top of canvas borders (done via JS due to IE)
					$('.visualize-line li:first-child span.line, .visualize-line li:last-child span.line, .visualize-area li:first-child span.line, .visualize-area li:last-child span.line, .visualize-bar li:first-child span.line,.visualize-bar .visualize-labels-y li:last-child span.line').css('border','none');
					if(!container){
						//add event for updating
						canvasContain.bind('visualizeRefresh', function(){
							self.visualize(o, $(this).empty()); 
						});
					}

					$('.visualize').append(bubb);	

					}).next(); //returns canvas(es)
				};

				})(jQuery);



