(function($){$.fn.visualize=function(options,container){return $(this).each(function(){var o=$.extend({type:'bar',width:$(this).width(),height:$(this).height(),appendTitle:true,title:null,appendKey:true,colors:['#be1e2d','#666699','#92d5ea','#ee8310','#8d10ee','#5a3b16','#26a4ed','#f45a90','#e9e744'],textColors:[],parseDirection:'x',pieMargin:20,pieLabelPos:'inside',lineWeight:4,barGroupMargin:10,barMargin:1,yLabelInterval:30},options);o.width=parseFloat(o.width);o.height=parseFloat(o.height);var self=$(this);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;};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);$.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();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');}
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');});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');});ctx.translate(0,zeroLoc);$.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');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');});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');});ctx.translate(0,zeroLoc);for(var h=0;h<dataGroups.length;h++){ctx.beginPath();var linewidth=(xInterval-o.barGroupMargin*2)/dataGroups.length;var strokeWidth=linewidth-(o.barMargin*2);ctx.lineWidth=strokeWidth;var points=dataGroups[h].points;var integer=0;for(var i=0;i<points.length;i++){var xVal=(integer-o.barGroupMargin)+(h*linewidth)+linewidth/2;xVal+=o.barGroupMargin*2;ctx.moveTo(xVal,0);ctx.lineTo(xVal,Math.round(-points[i]*yScale));integer+=xInterval;}
ctx.strokeStyle=dataGroups[h].color;ctx.stroke();ctx.closePath();}}};var canvasNode=document.createElement("canvas");canvasNode.setAttribute('height',o.height);canvasNode.setAttribute('width',o.width);var canvas=$(canvasNode);var title=o.title||self.find('caption').text();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);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();if(o.appendTitle||o.appendKey){var infoContain=$('<div class="visualize-info"></div>').appendTo(canvasContain);}
if(o.appendTitle){$('<div class="visualize-title">'+title+'</div>').appendTo(infoContain);}
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);};if(!container){canvasContain.insertAfter(this);}
if(typeof(G_vmlCanvasManager)!='undefined'){G_vmlCanvasManager.initElement(canvas[0]);}
var ctx=canvas[0].getContext('2d');createChart[o.type]();$('.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){canvasContain.bind('visualizeRefresh',function(){self.visualize(o,$(this).empty());});}}).next();};})(jQuery);
