(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,lineDots:'double',lineMargin:0,dotInteraction:false,dotInnerColor:"#ffffff",barGroupMargin:10,barMargin:1,yLabelInterval:30,topValue:null,xTitle:false,yTitle:false},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=o.topValue;if(topValue==null){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/dataSum;if(fraction<=0||isNaN(fraction))
return;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.35: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()/2);}
else if(i==yLabels.length-1){topOffset=label.height()/-2;}
label
.css('margin-top',topOffset)
.addClass('label');});var drawPoint=function(ctx,x,y,color,size){ctx.moveTo(x,y);ctx.beginPath();ctx.arc(x,y,size/2,0,2*Math.PI,false);ctx.closePath();ctx.fillStyle=color;ctx.fill();}
var pointQueue=[];var keyPoint=function(x,y,color,myInfo){var size=o.lineWeight*Math.PI;pointQueue.push(function(){drawPoint(ctx,x,y,color,size);if(o.lineDots==='double'){drawPoint(ctx,x,y,o.dotInnerColor,size-o.lineWeight*Math.PI/2);}});};ctx.translate(0,zeroLoc);$.each(dataGroups,function(h){ctx.beginPath();ctx.lineWidth=o.lineWeight;ctx.lineJoin='round';var points=this.points;var integer=0;var myInfo=[0,0];var color=this.color;ctx.moveTo(0,-(points[0]*yScale));if(o.lineDots){keyPoint(0,-(points[0]*yScale),color,myInfo);}
$.each(points,function(g){myInfo=[h,g];if(o.lineDots){keyPoint(integer,-(this*yScale),color,myInfo);}
ctx.lineTo(integer,-(this*yScale));integer+=xInterval;});ctx.strokeStyle=color;ctx.stroke();if(area){ctx.lineTo(integer,0);ctx.lineTo(0,0);ctx.closePath();ctx.fillStyle=color;ctx.globalAlpha=.3;ctx.fill();ctx.globalAlpha=1.0;}
else{ctx.closePath();}
$.each(pointQueue,function(){pointQueue.shift().call();});});},area:function(){createChart.line(true);},bar:function(){var horizontal=(o.barDirection=='horizontal');canvasContain.addClass('visualize-bar');var bottomLabels=horizontal?yLabels:xLabels;var xInterval=canvas.width()/(bottomLabels.length-(horizontal?1:0));var xlabelsUL=$('<ul class="visualize-labels-x"></ul>')
.width(canvas.width())
.height(canvas.height())
.insertBefore(canvas);$.each(bottomLabels,function(i){var thisLi=$('<li><span class="label">'+this+'</span></li>')
.prepend('<span class="line" />')
.css('left',xInterval*i)
.width(xInterval)
.appendTo(xlabelsUL);if(horizontal){var label=thisLi.find('span.label');label.css("margin-left",-label.width()/2);}});var leftLabels=horizontal?xLabels:yLabels;var liBottom=canvas.height()/(leftLabels.length-(horizontal?0:1));var ylabelsUL=$('<ul class="visualize-labels-y"></ul>')
.width(canvas.width())
.height(canvas.height())
.insertBefore(canvas);$.each(leftLabels,function(i){var thisLi=$('<li><span>'+this+'</span></li>').prependTo(ylabelsUL);var label=thisLi.find('span:not(.line)').addClass('label');if(horizontal){label.css({'min-height':liBottom,'max-height':liBottom+1,'vertical-align':'middle'});thisLi.css({'top':liBottom*i,'min-height':liBottom});var r=label[0].getClientRects()[0];if(r.bottom-r.top==liBottom){label.css('line-height',parseInt(liBottom)+'px');}
else{label.css("overflow","hidden");}}
else{thisLi.css('bottom',liBottom*i).prepend('<span class="line" />');label.css('margin-top',-label.height()/2)}});if(horizontal){ctx.rotate(Math.PI/2);}
else{ctx.translate(0,zeroLoc);}
if(totalYRange<=0)
return;var yScale=(horizontal?canvas.width():canvas.height())/totalYRange;var barWidth=horizontal?(canvas.height()/xLabels.length):(canvas.width()/(bottomLabels.length));var linewidth=(barWidth-o.barGroupMargin*2)/dataGroups.length;for(var h=0;h<dataGroups.length;h++){ctx.beginPath();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++){if(points[i]!=0){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+=barWidth;}
ctx.strokeStyle=dataGroups[h].color;ctx.stroke();ctx.closePath();}}};var canvasNode=document.createElement("canvas");var canvas=$(canvasNode)
.attr({'height':o.height,'width':o.width});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.xTitle){$('<div class="visualize-xtitle">'+self.attr('data-xtitle')+'</div>').appendTo(infoContain);}
if(o.yTitle){$('<div class="visualize-ytitle">'+self.attr('data-ytitle')+'</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){if(o.lineDots==='double'){$('<li><span class="visualize-key-color" style="border: solid '+o.lineWeight+'px '+dataGroups[i].color+'; -moz-border-radius: 100%; height: '+o.lineWeight*1.5+'px; width: '+o.lineWeight*1.5+'px; background-color: '+o.dotInnerColor+'"></span><span class="visualize-key-label">'+$(this).text()+'</span></li>')
.appendTo(newKey);}else{$('<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]();self.hide();$('.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);
