Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixes handling of zero values

  • Loading branch information...
commit 617fb84a8297842b89bd1c499bef80464c42d1bd 1 parent 3b4e51a
Alex Young authored
View
3  History.md
@@ -2,6 +2,9 @@
==================
* Added `stroke_width` option (defaults to `3px`, can be set to `0` to make scatter plots)
+ * Clarified documentation
+ * Added support for jQuery objects passed in as the graph's container element option
+ * Improves handling of graphs with all zero values
0.3.8 / 2012-02-06
==================
View
2  docs/examples.html
@@ -71,6 +71,7 @@
<div id="linegraph_2" class="linegraph"></div>
<div id="linegraph_3" class="linegraph"></div>
<div id="linegraph_5" class="linegraph"></div>
+ <div id="linegraph_zero" class="linegraph"></div>
<h2>Horizontal Bar Graph</h2>
<div id="bargraph_5" class="linegraph"></div>
@@ -132,6 +133,7 @@
new Ico.LineGraph($('linegraph_4'), $random(1, 25));
new Ico.LineGraph($('linegraph_5'), { shoe_size: [15,14,10]},{ markers: 'circle', colours: { shoe_size: '#990000' }, grid: true });
+new Ico.LineGraph($('linegraph_zero'), [0, 0, 0], { markers: 'circle', grid: true });
// TODO: Grid isn't tall enough here:
new Ico.HorizontalBarGraph($('bargraph_5'), [2, 5, 1, 10, 15, 33, 20, 25, 1], { font_size: 20, grid: true, labels: ['label one', 'label two', 'label three', 'four', 'five', 'six', 'seven', 'eight', 'nine'], colour: '#ff0099', background_colour: '#fff' });
View
22 docs/ico.js
@@ -399,11 +399,17 @@ Helpers.extend(Ico.BaseGraph.prototype, {
if (options.label_count) {
this.y_label_count = options.label_count;
} else {
- this.y_label_count = Math.ceil(this.range / this.label_step);
- if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
- this.y_label_count += 1;
+ if (this.range === 0) {
+ this.y_label_count = 1;
+ this.label_step = 1;
+ } else {
+ this.y_label_count = Math.ceil(this.range / this.label_step);
+ if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
+ this.y_label_count += 1;
+ }
}
}
+
this.value_labels = this.makeValueLabels(this.y_label_count);
this.top_value = this.value_labels[this.value_labels.length - 1];
@@ -527,6 +533,10 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.range;
return ((value / total) * (this.graph_height));
},
@@ -744,7 +754,7 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
drawVerticalLabels: function() {
- var y_step = this.graph_height / this.y_label_count;
+ var y_step = this.graph_height / this.y_label_count;
this.drawMarkers(this.value_labels, [0, -1], y_step, y_step, [-8, -2], { 'text-anchor': 'end' });
},
@@ -1000,6 +1010,10 @@ Ico.LineGraph = function() { this.initialize.apply(this, arguments); };
Helpers.extend(Ico.LineGraph.prototype, Ico.BaseGraph.prototype);
Helpers.extend(Ico.LineGraph.prototype, {
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.top_value - this.start_value;
return ((value / total) * (this.graph_height));
},
View
2  docs/ico.min.js
@@ -4,4 +4,4 @@
* MIT Licensed
*//**
* The Ico object.
- */(function(global){var Ico={VERSION:"0.3.9",round:function(num,dec){var result=Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);return result}};function validStepDivider(value){return value>1?value-1:1}function getStyle(el,styleProp){if(typeof window=="undefined")return;var style;return el.currentStyle?style=el.currentStyle[styleProp]:window.getComputedStyle&&(style=document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp)),style&&style.length===0&&(style=null),style}var Helpers={};Helpers.sum=function(a){var i,sum;for(i=0,sum=0;i<a.length;sum+=a[i++]);return sum},typeof Array.prototype.max=="undefined"?Helpers.max=function(a){return Math.max.apply({},a)}:Helpers.max=function(a){return a.max()},typeof Array.prototype.min=="undefined"?Helpers.min=function(a){return Math.min.apply({},a)}:Helpers.min=function(a){return a.min()},Helpers.mean=function(a){return Helpers.sum(a)/a.length},Helpers.variance=function(a){var mean=Helpers.mean(a),variance=0;for(var i=0;i<a.length;i++)variance+=Math.pow(a[i]-mean,2);return variance/(a.length-1)},Helpers.standard_deviation=function(a){return Math.sqrt(Helpers.variance(a))},typeof Object.extend=="undefined"?Helpers.extend=function(destination,source){for(var property in source)source.hasOwnProperty(property)&&(destination[property]=source[property]);return destination}:Helpers.extend=Object.extend,Object.keys?Helpers.keys=Object.keys:Helpers.keys=function(o){if(o!==Object(o))throw new TypeError("Object.keys called on non-object");var ret=[],p;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&ret.push(p);return ret},Ico.Normaliser=function(data,options){this.options={start_value:null},typeof options!="undefined"&&(this.options=options),this.min=Helpers.min(data),this.max=this.options.max||Helpers.max(data),this.standard_deviation=Helpers.standard_deviation(data),this.range=0,this.step=this.labelStep(this.max-this.min),this.start_value=this.calculateStart(),this.process()},Ico.Normaliser.prototype={calculateStart:function(){var min=typeof this.options.start_value!="undefined"&&this.min>=0?this.options.start_value:this.min,start_value=this.round(min,1);return this.min>0&&start_value>this.min?0:this.min===this.max?0:start_value},round:function(value,offset){offset=offset||1;var roundedValue=value;if(this.standard_deviation>.1){var multiplier=Math.pow(10,-offset);roundedValue=Math.round(value*multiplier)/multiplier;if(roundedValue>this.min)return this.round(value-this.step)}return roundedValue},process:function(){this.range=this.max-this.start_value,this.step=this.labelStep(this.range)},labelStep:function(value){return Math.pow(10,Math.round(Math.log(value)/Math.LN10)-1)}},Ico.Base={normaliseData:function(data){var values=[],i=0;for(i=0;i<data.length;i++)values.push(this.normalise(data[i]));return values},flatten:function(data){var flat_data=[];if(typeof data.length=="undefined"){if(typeof data!="object")return[];for(var key in data)data.hasOwnProperty(key)&&(flat_data=flat_data.concat(this.flatten(data[key])))}for(var i=0;i<data.length;i++)typeof data[i].length=="number"?flat_data=flat_data.concat(this.flatten(data[i])):flat_data.push(data[i]);return flat_data},makeRange:function(start,end,options){var values=[],i;for(i=start;i<end;i++)options&&options.skip?i%options.skip===0?values.push(i):values.push(undefined):values.push(i);return values}},Ico.BaseGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BaseGraph.prototype,Ico.Base),Helpers.extend(Ico.BaseGraph.prototype,{initialize:function(element,data,options){options=options||{},this.element=element.length?element[0]:element,this.data_sets=this.buildDataSets(data,options),this.flat_data=this.flatten(data),this.data_size=this.longestDataSetLength(),this.plottedCoords=[];if(options&&options.colour){options.colours={};for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(options.colours[key]=options.colour)}this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),plot_padding:10,font_size:10,show_horizontal_labels:!0,show_vertical_labels:!0,background_colour:getStyle(element,"backgroundColor")||"#ffffff",label_colour:"#666",markers:!1,marker_size:5,meanline:!1,grid:!1,grid_colour:"#ccc",y_padding_top:20,draw:!0,bar_labels:!1},Helpers.extend(this.options,this.chartDefaults()||{}),Helpers.extend(this.options,options),this.font_options={font:this.options.font_size+'px "Arial"',stroke:"none",fill:"#000"},this.normaliser=new Ico.Normaliser(this.flat_data,this.normaliserOptions()),this.label_step=options.label_step||this.normaliser.step,this.range=this.normaliser.range,this.start_value=options.start_value||this.normaliser.start_value,this.x_padding_left=10+this.paddingLeftOffset(),this.x_padding_right=20,this.x_padding=this.x_padding_left+this.x_padding_right,this.y_padding_top=this.options.y_padding_top,this.y_padding_bottom=20+this.paddingBottomOffset(),this.y_padding=this.y_padding_top+this.y_padding_bottom,this.graph_width=this.options.width-this.x_padding,this.graph_height=this.options.height-this.y_padding,this.step=this.calculateStep(),this.grid_step=this.step,this.options.labels?this.grouped||(this.grid_step=this.graph_width/this.options.labels.length,this.snap_to_grid=!0):this.options.labels=this.makeRange(1,this.data_size+1),this.options.bar_labels&&(this.range+=this.normaliser.step),options.label_count?this.y_label_count=options.label_count:(this.y_label_count=Math.ceil(this.range/this.label_step),this.normaliser.min+this.y_label_count*this.normaliser.step<this.normaliser.max&&(this.y_label_count+=1)),this.value_labels=this.makeValueLabels(this.y_label_count),this.top_value=this.value_labels[this.value_labels.length-1],this.grid_start_offset=-1,this.options.draw&&(typeof this.options.colours=="undefined"&&(this.options.colours=this.makeRandomColours()),this.paper=Raphael(this.element,this.options.width,this.options.height),this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.options.meanline===!0&&(this.options.meanline={"stroke-width":"2px",stroke:"#BBBBBB"}),this.setChartSpecificOptions(),this.lastPoint={x:0,y:0},this.draw())},buildDataSets:function(data,options){return typeof data.length!="undefined"?{one:data}:data},normaliserOptions:function(){return{}},chartDefaults:function(){return{}},drawPlot:function(index,pathString,x,y,colour){},calculateStep:function(){},makeRandomColours:function(){var colours;if(this.grouped){colours=[];for(var i=0;i<this.group_size;i++)colours.push(Raphael.hsb2rgb(Math.random(),1,.75).hex)}else{colours={};for(var key in this.data_sets)colours.hasOwnProperty(key)||(colours[key]=Raphael.hsb2rgb(Math.random(),1,.75).hex)}return colours},longestDataSetLength:function(){if(this.grouped)return this.flat_data.length;var length=0;for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(length=this.data_sets[key].length>length?this.data_sets[key].length:length);return length},roundValue:function(value,length){var multiplier=Math.pow(10,length);return value*=multiplier,value=Math.round(value)/multiplier,value},roundValues:function(data,length){var roundedData=[],i;for(i=0;i<data.length;i++)roundedData.push(this.roundValue(data[i],length));return roundedData},longestLabel:function(values){var labels=Array.prototype.slice.call(values||this.options.labels,0);return labels.length?labels.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length:0},paddingLeftOffset:function(){var data=this.roundValues(this.flat_data,2),longest_label_length=0;return longest_label_length=data.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length,longest_label_length=longest_label_length>2?longest_label_length-1:longest_label_length,10+longest_label_length*this.options.font_size},paddingBottomOffset:function(){return this.options.font_size},normalise:function(value){var total=this.start_value===0?this.top_value:this.range;return value/total*this.graph_height},draw:function(){this.options.grid&&this.drawGrid(),this.options.meanline&&this.drawMeanLine(this.normaliseData(this.flat_data)),this.drawAxis(),this.options.show_vertical_labels&&this.drawVerticalLabels(),this.options.show_horizontal_labels&&this.drawHorizontalLabels();if(this.grouped)this.drawLines(key,null,this.normaliseData(this.flat_data));else for(var key in this.data_sets)if(this.data_sets.hasOwnProperty(key)){var data=this.data_sets[key];this.drawLines(key,this.options.colours[key],this.normaliseData(data))}this.start_value!==0&&this.drawFocusHint()},drawGrid:function(){var pathString="",i,y;if(this.options.show_vertical_labels){y=this.graph_height+this.y_padding_top;for(i=0;i<this.y_label_count;i++)y-=this.graph_height/this.y_label_count,pathString+="M"+this.x_padding_left+","+y,pathString+="L"+(this.x_padding_left+this.graph_width)+","+y}if(this.options.show_horizontal_labels){var x=this.x_padding_left+this.options.plot_padding+this.grid_start_offset,x_labels=this.grouped?this.flat_data.length:this.options.labels.length,i,step=this.grid_step||this.step;for(i=0;i<x_labels;i++)pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height),x+=step;x=x-this.options.plot_padding-1,pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height)}this.paper.path(pathString).attr({stroke:this.options.grid_colour,"stroke-width":"1px"})},drawLines:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y;for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&this.options.colours&&(colour=this.options.colours[i%this.group_size]),this.plottedCoords.push([x+this.bar_padding,y]),pathString=this.drawPlot(i,pathString,x,y,colour);this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.options.stroke_width}),this.options.bar_labels&&this.drawBarMarkers(),this.options.line&&this.additionalLine(label,colour,this.normaliseData(this.options.line))},additionalLine:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y,step,lineWidth=3;this.grouped&&(step=this.step*(this.group_size-1));for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&(x+=step*i+this.roundValue(step/2,0)),x+=lineWidth,pathString=Ico.LineGraph.prototype.drawPlot.apply(this,[i,pathString,this.roundValue(x,0),y,colour]);this.paper.path(pathString).attr({stroke:"#ff0000","stroke-width":lineWidth+"px"})},calculateCoords:function(data){var x=this.x_padding_left+this.options.plot_padding-this.step,y_offset=this.graph_height+this.y_padding_top+this.normalise(this.start_value),y=0,coords=[],i;for(i=0;i<data.length;i++)y=y_offset-data[i],x+=this.step,coords.push([x,y]);return coords},drawFocusHint:function(){var length=5,x=this.x_padding_left+length/2-1,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y-length),pathString+="M"+x+","+(y-length),pathString+="L"+(x-length)+","+(y-length*2),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawMeanLine:function(data){var offset=Helpers.sum(data)/data.length,pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom-offset),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom-offset),this.paper.path(pathString).attr(this.options.meanline)},drawAxis:function(){var pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom),pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.x_padding_left-1)+","+this.y_padding_top,this.paper.path(pathString).attr({stroke:this.options.label_colour})},makeValueLabels:function(steps){var step=this.label_step,label=this.start_value,labels=[];for(var i=0;i<steps;i++)label=this.roundValue(label+step,2),labels.push(label);return labels},drawMarkers:function(labels,direction,step,start_offset,font_offsets,extra_font_options){function x_offset(value){return value*direction[0]}function y_offset(value){return value*direction[1]}var x=this.x_padding_left-1+x_offset(start_offset),y=this.options.height-this.y_padding_bottom+y_offset(start_offset),pathString="",i,font_options={};Helpers.extend(font_options,this.font_options),Helpers.extend(font_options,extra_font_options||{});for(i=0;i<labels.length;i++)pathString+="M"+x+","+y,typeof labels[i]!="undefined"&&(labels[i]+"").length>0&&(pathString+="L"+(x+y_offset(5))+","+(y+x_offset(5)),this.paper.text(x+font_offsets[0],y-font_offsets[1],labels[i]).attr(font_options).toFront()),x+=x_offset(step),y+=y_offset(step);this.paper.path(pathString).attr({stroke:this.options.label_colour})},drawVerticalLabels:function(){var y_step=this.graph_height/this.y_label_count;this.drawMarkers(this.value_labels,[0,-1],y_step,y_step,[-8,-2],{"text-anchor":"end"})},drawHorizontalLabels:function(){var step=this.snap_to_grid?this.grid_step:this.step;this.drawMarkers(this.options.labels,[1,0],step,this.options.plot_padding,[0,(this.options.font_size+7)*-1])}}),Ico.BarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.BarGraph.prototype,{buildDataSets:function(data,options){if(typeof data.length!="undefined"){if(typeof data[0].length!="undefined"){this.grouped=!0,this.group_size=data[0].length;var o={},k,i=0;for(k in options.labels)k=options.labels[k],o[k]=data[i],i++;return o}return{one:data}}return data},chartDefaults:function(){return{plot_padding:0}},normaliserOptions:function(){return this.options.line?{start_value:0,max:Helpers.max([Helpers.max(this.options.line),Helpers.max(this.flat_data)])}:{start_value:0}},setChartSpecificOptions:function(){this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarWidth(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_width/this.data_size),this.options.plot_padding=this.bar_width/2-this.bar_padding/2,this.step=this.calculateStep(),this.grid_start_offset=this.bar_padding-1,this.start_y=this.options.height-this.y_padding_bottom},calculateBarWidth:function(){var width=this.graph_width/this.data_size-this.bar_padding;return!this.grouped,this.options.max_bar_size&&width>this.options.max_bar_size&&(width=this.options.max_bar_size,this.bar_padding=this.graph_width/this.data_size),width},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2-this.bar_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){return x+=this.bar_padding,pathString+="M"+x+","+this.start_y,pathString+="L"+x+","+y,this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"}),pathString="",x+=this.step,pathString+="M"+x+","+this.start_y,pathString},drawHorizontalLabels:function(){var x_start=this.bar_padding+this.options.plot_padding,step=this.step;this.grouped&&(step*=this.group_size,x_start=(this.bar_width*this.group_size+this.bar_padding*this.group_size)/2,x_start=this.roundValue(x_start,0)),this.drawMarkers(this.options.labels,[1,0],step,x_start,[0,(this.options.font_size+7)*-1])},drawBarMarkers:function(){if(this.plottedCoords.length===0)return;var i,length=this.flat_data.length,x,y,label,font_options={};Helpers.extend(font_options,this.font_options),font_options["text-anchor"]="center";for(i=0;i<length;i++)label=this.roundValue(this.flat_data[i],2).toString(),x=this.plottedCoords[i][0],y=this.roundValue(this.plottedCoords[i][1],0),this.paper.text(x,y-this.options.font_size,label).attr(font_options).toFront()}}),Ico.HorizontalBarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.HorizontalBarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.HorizontalBarGraph.prototype,{setChartSpecificOptions:function(){this.y_padding_top=0,this.x_padding_left=20+this.longestLabel()*(this.options.font_size/2),this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarHeight(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_height/this.data_size),this.options.plot_padding=0,this.step=this.calculateStep()},normalise:function(value){var offset=this.x_padding_left;return value/this.range*(this.graph_width-offset)},calculateBarHeight:function(){var height=this.graph_height/this.data_size-this.bar_padding;return this.options.max_bar_size&&height>this.options.max_bar_size&&(height=this.options.max_bar_size,this.bar_padding=this.graph_height/this.data_size),height},calculateStep:function(){return(this.options.height-this.y_padding_bottom)/validStepDivider(this.data_size)},drawLines:function(label,colour,data){var x=this.x_padding_left+this.options.plot_padding*2,y=this.options.height-this.y_padding_bottom-this.step/2,pathString="M"+x+","+y,i;for(i=0;i<data.length;i++)pathString+="L"+(x+data[i]-this.normalise(this.start_value))+","+y,y-=this.step,pathString+="M"+x+","+y;this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"})},drawFocusHint:function(){var length=5,x=this.x_padding_left+this.step*2,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y+length),pathString+="M"+(x-length)+","+y,pathString+="L"+(x-length*2)+","+(y+length),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawVerticalLabels:function(){var y_start=this.step/2-this.options.plot_padding*2;this.drawMarkers(this.options.labels,[0,-1],this.step,y_start,[-8,this.options.font_size/8],{"text-anchor":"end"})},drawHorizontalLabels:function(){var x_step=this.graph_width/this.y_label_count,x_labels=this.makeValueLabels(this.y_label_count);this.drawMarkers(x_labels,[1,0],x_step,x_step,[0,(this.options.font_size+7)*-1])}}),Ico.LineGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.LineGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.LineGraph.prototype,{normalise:function(value){var total=this.start_value===0?this.top_value:this.top_value-this.start_value;return value/total*this.graph_height},chartDefaults:function(){return{plot_padding:10,stroke_width:"3px"}},setChartSpecificOptions:function(){var longestLabel=this.longestLabel(this.value_labels);this.x_padding_left=30+longestLabel*(this.options.font_size/2),typeof this.options.curve_amount=="undefined"&&(this.options.curve_amount=10)},normaliserOptions:function(){return{start_value:this.options.start_value}},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){var w=this.options.curve_amount;if(this.options.markers==="circle"){var circle=this.paper.circle(x,y,this.options.marker_size);circle.attr({"stroke-width":"1px",stroke:this.options.background_colour,fill:colour})}return index===0?(this.lastPoint={x:x,y:y},pathString+"M"+x+","+y):(w?pathString+=["C",this.lastPoint.x+w,this.lastPoint.y,x-w,y,x,y]:pathString+="L"+x+","+y,this.lastPoint={x:x,y:y},pathString)}}),Ico.SparkLine=function(){this.initialize.apply(this,arguments)},Ico.SparkLine.prototype={initialize:function(element,data,options){this.element=element,this.data=data,this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),highlight:!1,background_colour:getStyle(element,"backgroundColor")||"#ffffff",colour:"#036"},Helpers.extend(this.options,options||{}),this.step=this.calculateStep(),this.paper=Raphael(this.element,this.options.width,this.options.height),this.options.acceptable_range?this.background=this.paper.rect(0,this.options.height-this.normalise(this.options.acceptable_range[1]),this.options.width,this.options.height-this.normalise(this.options.acceptable_range[0])):this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.draw()},calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},normalise:function(value){return this.options.height/Helpers.max(this.data)*value},draw:function(){var data=this.normaliseData(this.data);this.drawLines("",this.options.colour,data),this.options.highlight&&this.showHighlight(data)},drawLines:function(label,colour,data){var pathString="",x=0,values=data.slice(1),i=0;pathString="M0,"+(this.options.height-data[0]);for(i=1;i<data.length;i++)x+=this.step,pathString+="L"+x+","+Ico.round(this.options.height-data[i],2);this.paper.path(pathString).attr({stroke:colour}),this.lastPoint={x:0,y:this.options.height-data[0]}},showHighlight:function(data){var size=2,x=this.options.width-size,i=this.options.highlight.index||data.length-1,y=data[i]+Math.round(size/2);typeof this.options.highlight.index!="undefined"&&(x=this.step*this.options.highlight.index);var circle=this.paper.circle(x,this.options.height-y,size);circle.attr({stroke:!1,fill:this.options.highlight.colour})}},Helpers.extend(Ico.SparkLine.prototype,Ico.Base),Ico.SparkBar=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.SparkBar.prototype,Ico.SparkLine.prototype),Helpers.extend(Ico.SparkBar.prototype,{calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},drawLines:function(label,colour,data){var width=this.step>2?this.step-1:this.step,x=width,pathString="",i=0;for(i=0;i<data.length;i++)pathString+="M"+x+","+(this.options.height-data[i]),pathString+="L"+x+","+this.options.height,x+=this.step;this.paper.path(pathString).attr({stroke:colour,"stroke-width":width})}}),global.Ico=Ico,typeof exports!="undefined"&&(module.exports=Ico)})(typeof window=="undefined"?this:window);
+ */(function(global){var Ico={VERSION:"0.3.9",round:function(num,dec){var result=Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);return result}};function validStepDivider(value){return value>1?value-1:1}function getStyle(el,styleProp){if(typeof window=="undefined")return;var style;return el.currentStyle?style=el.currentStyle[styleProp]:window.getComputedStyle&&(style=document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp)),style&&style.length===0&&(style=null),style}var Helpers={};Helpers.sum=function(a){var i,sum;for(i=0,sum=0;i<a.length;sum+=a[i++]);return sum},typeof Array.prototype.max=="undefined"?Helpers.max=function(a){return Math.max.apply({},a)}:Helpers.max=function(a){return a.max()},typeof Array.prototype.min=="undefined"?Helpers.min=function(a){return Math.min.apply({},a)}:Helpers.min=function(a){return a.min()},Helpers.mean=function(a){return Helpers.sum(a)/a.length},Helpers.variance=function(a){var mean=Helpers.mean(a),variance=0;for(var i=0;i<a.length;i++)variance+=Math.pow(a[i]-mean,2);return variance/(a.length-1)},Helpers.standard_deviation=function(a){return Math.sqrt(Helpers.variance(a))},typeof Object.extend=="undefined"?Helpers.extend=function(destination,source){for(var property in source)source.hasOwnProperty(property)&&(destination[property]=source[property]);return destination}:Helpers.extend=Object.extend,Object.keys?Helpers.keys=Object.keys:Helpers.keys=function(o){if(o!==Object(o))throw new TypeError("Object.keys called on non-object");var ret=[],p;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&ret.push(p);return ret},Ico.Normaliser=function(data,options){this.options={start_value:null},typeof options!="undefined"&&(this.options=options),this.min=Helpers.min(data),this.max=this.options.max||Helpers.max(data),this.standard_deviation=Helpers.standard_deviation(data),this.range=0,this.step=this.labelStep(this.max-this.min),this.start_value=this.calculateStart(),this.process()},Ico.Normaliser.prototype={calculateStart:function(){var min=typeof this.options.start_value!="undefined"&&this.min>=0?this.options.start_value:this.min,start_value=this.round(min,1);return this.min>0&&start_value>this.min?0:this.min===this.max?0:start_value},round:function(value,offset){offset=offset||1;var roundedValue=value;if(this.standard_deviation>.1){var multiplier=Math.pow(10,-offset);roundedValue=Math.round(value*multiplier)/multiplier;if(roundedValue>this.min)return this.round(value-this.step)}return roundedValue},process:function(){this.range=this.max-this.start_value,this.step=this.labelStep(this.range)},labelStep:function(value){return Math.pow(10,Math.round(Math.log(value)/Math.LN10)-1)}},Ico.Base={normaliseData:function(data){var values=[],i=0;for(i=0;i<data.length;i++)values.push(this.normalise(data[i]));return values},flatten:function(data){var flat_data=[];if(typeof data.length=="undefined"){if(typeof data!="object")return[];for(var key in data)data.hasOwnProperty(key)&&(flat_data=flat_data.concat(this.flatten(data[key])))}for(var i=0;i<data.length;i++)typeof data[i].length=="number"?flat_data=flat_data.concat(this.flatten(data[i])):flat_data.push(data[i]);return flat_data},makeRange:function(start,end,options){var values=[],i;for(i=start;i<end;i++)options&&options.skip?i%options.skip===0?values.push(i):values.push(undefined):values.push(i);return values}},Ico.BaseGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BaseGraph.prototype,Ico.Base),Helpers.extend(Ico.BaseGraph.prototype,{initialize:function(element,data,options){options=options||{},this.element=element.length?element[0]:element,this.data_sets=this.buildDataSets(data,options),this.flat_data=this.flatten(data),this.data_size=this.longestDataSetLength(),this.plottedCoords=[];if(options&&options.colour){options.colours={};for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(options.colours[key]=options.colour)}this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),plot_padding:10,font_size:10,show_horizontal_labels:!0,show_vertical_labels:!0,background_colour:getStyle(element,"backgroundColor")||"#ffffff",label_colour:"#666",markers:!1,marker_size:5,meanline:!1,grid:!1,grid_colour:"#ccc",y_padding_top:20,draw:!0,bar_labels:!1},Helpers.extend(this.options,this.chartDefaults()||{}),Helpers.extend(this.options,options),this.font_options={font:this.options.font_size+'px "Arial"',stroke:"none",fill:"#000"},this.normaliser=new Ico.Normaliser(this.flat_data,this.normaliserOptions()),this.label_step=options.label_step||this.normaliser.step,this.range=this.normaliser.range,this.start_value=options.start_value||this.normaliser.start_value,this.x_padding_left=10+this.paddingLeftOffset(),this.x_padding_right=20,this.x_padding=this.x_padding_left+this.x_padding_right,this.y_padding_top=this.options.y_padding_top,this.y_padding_bottom=20+this.paddingBottomOffset(),this.y_padding=this.y_padding_top+this.y_padding_bottom,this.graph_width=this.options.width-this.x_padding,this.graph_height=this.options.height-this.y_padding,this.step=this.calculateStep(),this.grid_step=this.step,this.options.labels?this.grouped||(this.grid_step=this.graph_width/this.options.labels.length,this.snap_to_grid=!0):this.options.labels=this.makeRange(1,this.data_size+1),this.options.bar_labels&&(this.range+=this.normaliser.step),options.label_count?this.y_label_count=options.label_count:this.range===0?(this.y_label_count=1,this.label_step=1):(this.y_label_count=Math.ceil(this.range/this.label_step),this.normaliser.min+this.y_label_count*this.normaliser.step<this.normaliser.max&&(this.y_label_count+=1)),this.value_labels=this.makeValueLabels(this.y_label_count),this.top_value=this.value_labels[this.value_labels.length-1],this.grid_start_offset=-1,this.options.draw&&(typeof this.options.colours=="undefined"&&(this.options.colours=this.makeRandomColours()),this.paper=Raphael(this.element,this.options.width,this.options.height),this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.options.meanline===!0&&(this.options.meanline={"stroke-width":"2px",stroke:"#BBBBBB"}),this.setChartSpecificOptions(),this.lastPoint={x:0,y:0},this.draw())},buildDataSets:function(data,options){return typeof data.length!="undefined"?{one:data}:data},normaliserOptions:function(){return{}},chartDefaults:function(){return{}},drawPlot:function(index,pathString,x,y,colour){},calculateStep:function(){},makeRandomColours:function(){var colours;if(this.grouped){colours=[];for(var i=0;i<this.group_size;i++)colours.push(Raphael.hsb2rgb(Math.random(),1,.75).hex)}else{colours={};for(var key in this.data_sets)colours.hasOwnProperty(key)||(colours[key]=Raphael.hsb2rgb(Math.random(),1,.75).hex)}return colours},longestDataSetLength:function(){if(this.grouped)return this.flat_data.length;var length=0;for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(length=this.data_sets[key].length>length?this.data_sets[key].length:length);return length},roundValue:function(value,length){var multiplier=Math.pow(10,length);return value*=multiplier,value=Math.round(value)/multiplier,value},roundValues:function(data,length){var roundedData=[],i;for(i=0;i<data.length;i++)roundedData.push(this.roundValue(data[i],length));return roundedData},longestLabel:function(values){var labels=Array.prototype.slice.call(values||this.options.labels,0);return labels.length?labels.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length:0},paddingLeftOffset:function(){var data=this.roundValues(this.flat_data,2),longest_label_length=0;return longest_label_length=data.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length,longest_label_length=longest_label_length>2?longest_label_length-1:longest_label_length,10+longest_label_length*this.options.font_size},paddingBottomOffset:function(){return this.options.font_size},normalise:function(value){if(value===0)return 0;var total=this.start_value===0?this.top_value:this.range;return value/total*this.graph_height},draw:function(){this.options.grid&&this.drawGrid(),this.options.meanline&&this.drawMeanLine(this.normaliseData(this.flat_data)),this.drawAxis(),this.options.show_vertical_labels&&this.drawVerticalLabels(),this.options.show_horizontal_labels&&this.drawHorizontalLabels();if(this.grouped)this.drawLines(key,null,this.normaliseData(this.flat_data));else for(var key in this.data_sets)if(this.data_sets.hasOwnProperty(key)){var data=this.data_sets[key];this.drawLines(key,this.options.colours[key],this.normaliseData(data))}this.start_value!==0&&this.drawFocusHint()},drawGrid:function(){var pathString="",i,y;if(this.options.show_vertical_labels){y=this.graph_height+this.y_padding_top;for(i=0;i<this.y_label_count;i++)y-=this.graph_height/this.y_label_count,pathString+="M"+this.x_padding_left+","+y,pathString+="L"+(this.x_padding_left+this.graph_width)+","+y}if(this.options.show_horizontal_labels){var x=this.x_padding_left+this.options.plot_padding+this.grid_start_offset,x_labels=this.grouped?this.flat_data.length:this.options.labels.length,i,step=this.grid_step||this.step;for(i=0;i<x_labels;i++)pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height),x+=step;x=x-this.options.plot_padding-1,pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height)}this.paper.path(pathString).attr({stroke:this.options.grid_colour,"stroke-width":"1px"})},drawLines:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y;for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&this.options.colours&&(colour=this.options.colours[i%this.group_size]),this.plottedCoords.push([x+this.bar_padding,y]),pathString=this.drawPlot(i,pathString,x,y,colour);this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.options.stroke_width}),this.options.bar_labels&&this.drawBarMarkers(),this.options.line&&this.additionalLine(label,colour,this.normaliseData(this.options.line))},additionalLine:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y,step,lineWidth=3;this.grouped&&(step=this.step*(this.group_size-1));for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&(x+=step*i+this.roundValue(step/2,0)),x+=lineWidth,pathString=Ico.LineGraph.prototype.drawPlot.apply(this,[i,pathString,this.roundValue(x,0),y,colour]);this.paper.path(pathString).attr({stroke:"#ff0000","stroke-width":lineWidth+"px"})},calculateCoords:function(data){var x=this.x_padding_left+this.options.plot_padding-this.step,y_offset=this.graph_height+this.y_padding_top+this.normalise(this.start_value),y=0,coords=[],i;for(i=0;i<data.length;i++)y=y_offset-data[i],x+=this.step,coords.push([x,y]);return coords},drawFocusHint:function(){var length=5,x=this.x_padding_left+length/2-1,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y-length),pathString+="M"+x+","+(y-length),pathString+="L"+(x-length)+","+(y-length*2),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawMeanLine:function(data){var offset=Helpers.sum(data)/data.length,pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom-offset),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom-offset),this.paper.path(pathString).attr(this.options.meanline)},drawAxis:function(){var pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom),pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.x_padding_left-1)+","+this.y_padding_top,this.paper.path(pathString).attr({stroke:this.options.label_colour})},makeValueLabels:function(steps){var step=this.label_step,label=this.start_value,labels=[];for(var i=0;i<steps;i++)label=this.roundValue(label+step,2),labels.push(label);return labels},drawMarkers:function(labels,direction,step,start_offset,font_offsets,extra_font_options){function x_offset(value){return value*direction[0]}function y_offset(value){return value*direction[1]}var x=this.x_padding_left-1+x_offset(start_offset),y=this.options.height-this.y_padding_bottom+y_offset(start_offset),pathString="",i,font_options={};Helpers.extend(font_options,this.font_options),Helpers.extend(font_options,extra_font_options||{});for(i=0;i<labels.length;i++)pathString+="M"+x+","+y,typeof labels[i]!="undefined"&&(labels[i]+"").length>0&&(pathString+="L"+(x+y_offset(5))+","+(y+x_offset(5)),this.paper.text(x+font_offsets[0],y-font_offsets[1],labels[i]).attr(font_options).toFront()),x+=x_offset(step),y+=y_offset(step);this.paper.path(pathString).attr({stroke:this.options.label_colour})},drawVerticalLabels:function(){var y_step=this.graph_height/this.y_label_count;this.drawMarkers(this.value_labels,[0,-1],y_step,y_step,[-8,-2],{"text-anchor":"end"})},drawHorizontalLabels:function(){var step=this.snap_to_grid?this.grid_step:this.step;this.drawMarkers(this.options.labels,[1,0],step,this.options.plot_padding,[0,(this.options.font_size+7)*-1])}}),Ico.BarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.BarGraph.prototype,{buildDataSets:function(data,options){if(typeof data.length!="undefined"){if(typeof data[0].length!="undefined"){this.grouped=!0,this.group_size=data[0].length;var o={},k,i=0;for(k in options.labels)k=options.labels[k],o[k]=data[i],i++;return o}return{one:data}}return data},chartDefaults:function(){return{plot_padding:0}},normaliserOptions:function(){return this.options.line?{start_value:0,max:Helpers.max([Helpers.max(this.options.line),Helpers.max(this.flat_data)])}:{start_value:0}},setChartSpecificOptions:function(){this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarWidth(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_width/this.data_size),this.options.plot_padding=this.bar_width/2-this.bar_padding/2,this.step=this.calculateStep(),this.grid_start_offset=this.bar_padding-1,this.start_y=this.options.height-this.y_padding_bottom},calculateBarWidth:function(){var width=this.graph_width/this.data_size-this.bar_padding;return!this.grouped,this.options.max_bar_size&&width>this.options.max_bar_size&&(width=this.options.max_bar_size,this.bar_padding=this.graph_width/this.data_size),width},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2-this.bar_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){return x+=this.bar_padding,pathString+="M"+x+","+this.start_y,pathString+="L"+x+","+y,this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"}),pathString="",x+=this.step,pathString+="M"+x+","+this.start_y,pathString},drawHorizontalLabels:function(){var x_start=this.bar_padding+this.options.plot_padding,step=this.step;this.grouped&&(step*=this.group_size,x_start=(this.bar_width*this.group_size+this.bar_padding*this.group_size)/2,x_start=this.roundValue(x_start,0)),this.drawMarkers(this.options.labels,[1,0],step,x_start,[0,(this.options.font_size+7)*-1])},drawBarMarkers:function(){if(this.plottedCoords.length===0)return;var i,length=this.flat_data.length,x,y,label,font_options={};Helpers.extend(font_options,this.font_options),font_options["text-anchor"]="center";for(i=0;i<length;i++)label=this.roundValue(this.flat_data[i],2).toString(),x=this.plottedCoords[i][0],y=this.roundValue(this.plottedCoords[i][1],0),this.paper.text(x,y-this.options.font_size,label).attr(font_options).toFront()}}),Ico.HorizontalBarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.HorizontalBarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.HorizontalBarGraph.prototype,{setChartSpecificOptions:function(){this.y_padding_top=0,this.x_padding_left=20+this.longestLabel()*(this.options.font_size/2),this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarHeight(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_height/this.data_size),this.options.plot_padding=0,this.step=this.calculateStep()},normalise:function(value){var offset=this.x_padding_left;return value/this.range*(this.graph_width-offset)},calculateBarHeight:function(){var height=this.graph_height/this.data_size-this.bar_padding;return this.options.max_bar_size&&height>this.options.max_bar_size&&(height=this.options.max_bar_size,this.bar_padding=this.graph_height/this.data_size),height},calculateStep:function(){return(this.options.height-this.y_padding_bottom)/validStepDivider(this.data_size)},drawLines:function(label,colour,data){var x=this.x_padding_left+this.options.plot_padding*2,y=this.options.height-this.y_padding_bottom-this.step/2,pathString="M"+x+","+y,i;for(i=0;i<data.length;i++)pathString+="L"+(x+data[i]-this.normalise(this.start_value))+","+y,y-=this.step,pathString+="M"+x+","+y;this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"})},drawFocusHint:function(){var length=5,x=this.x_padding_left+this.step*2,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y+length),pathString+="M"+(x-length)+","+y,pathString+="L"+(x-length*2)+","+(y+length),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawVerticalLabels:function(){var y_start=this.step/2-this.options.plot_padding*2;this.drawMarkers(this.options.labels,[0,-1],this.step,y_start,[-8,this.options.font_size/8],{"text-anchor":"end"})},drawHorizontalLabels:function(){var x_step=this.graph_width/this.y_label_count,x_labels=this.makeValueLabels(this.y_label_count);this.drawMarkers(x_labels,[1,0],x_step,x_step,[0,(this.options.font_size+7)*-1])}}),Ico.LineGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.LineGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.LineGraph.prototype,{normalise:function(value){if(value===0)return 0;var total=this.start_value===0?this.top_value:this.top_value-this.start_value;return value/total*this.graph_height},chartDefaults:function(){return{plot_padding:10,stroke_width:"3px"}},setChartSpecificOptions:function(){var longestLabel=this.longestLabel(this.value_labels);this.x_padding_left=30+longestLabel*(this.options.font_size/2),typeof this.options.curve_amount=="undefined"&&(this.options.curve_amount=10)},normaliserOptions:function(){return{start_value:this.options.start_value}},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){var w=this.options.curve_amount;if(this.options.markers==="circle"){var circle=this.paper.circle(x,y,this.options.marker_size);circle.attr({"stroke-width":"1px",stroke:this.options.background_colour,fill:colour})}return index===0?(this.lastPoint={x:x,y:y},pathString+"M"+x+","+y):(w?pathString+=["C",this.lastPoint.x+w,this.lastPoint.y,x-w,y,x,y]:pathString+="L"+x+","+y,this.lastPoint={x:x,y:y},pathString)}}),Ico.SparkLine=function(){this.initialize.apply(this,arguments)},Ico.SparkLine.prototype={initialize:function(element,data,options){this.element=element,this.data=data,this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),highlight:!1,background_colour:getStyle(element,"backgroundColor")||"#ffffff",colour:"#036"},Helpers.extend(this.options,options||{}),this.step=this.calculateStep(),this.paper=Raphael(this.element,this.options.width,this.options.height),this.options.acceptable_range?this.background=this.paper.rect(0,this.options.height-this.normalise(this.options.acceptable_range[1]),this.options.width,this.options.height-this.normalise(this.options.acceptable_range[0])):this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.draw()},calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},normalise:function(value){return this.options.height/Helpers.max(this.data)*value},draw:function(){var data=this.normaliseData(this.data);this.drawLines("",this.options.colour,data),this.options.highlight&&this.showHighlight(data)},drawLines:function(label,colour,data){var pathString="",x=0,values=data.slice(1),i=0;pathString="M0,"+(this.options.height-data[0]);for(i=1;i<data.length;i++)x+=this.step,pathString+="L"+x+","+Ico.round(this.options.height-data[i],2);this.paper.path(pathString).attr({stroke:colour}),this.lastPoint={x:0,y:this.options.height-data[0]}},showHighlight:function(data){var size=2,x=this.options.width-size,i=this.options.highlight.index||data.length-1,y=data[i]+Math.round(size/2);typeof this.options.highlight.index!="undefined"&&(x=this.step*this.options.highlight.index);var circle=this.paper.circle(x,this.options.height-y,size);circle.attr({stroke:!1,fill:this.options.highlight.colour})}},Helpers.extend(Ico.SparkLine.prototype,Ico.Base),Ico.SparkBar=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.SparkBar.prototype,Ico.SparkLine.prototype),Helpers.extend(Ico.SparkBar.prototype,{calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},drawLines:function(label,colour,data){var width=this.step>2?this.step-1:this.step,x=width,pathString="",i=0;for(i=0;i<data.length;i++)pathString+="M"+x+","+(this.options.height-data[i]),pathString+="L"+x+","+this.options.height,x+=this.step;this.paper.path(pathString).attr({stroke:colour,"stroke-width":width})}}),global.Ico=Ico,typeof exports!="undefined"&&(module.exports=Ico)})(typeof window=="undefined"?this:window);
View
6 docs/index.html
@@ -214,6 +214,12 @@
<li><code>line</code>: Provide an array to plot a line alongside a bar graph</li>
</ul>
+<h3>Options for <code>Ico.LineGraph</code></h3>
+
+<ul>
+<li><code>stroke_width</code>: Sets the stroke width, defaults to <code>3px</code>. Set to <code>0</code> to get a scatter plot</li>
+</ul>
+
<h3>Grouped Bar Graphs</h3>
<p>Multidimensional arrays will be rendered as 'grouped' bar graphs. Notice that two colours are specified, one for each bar in the group. This is still a work in progress and hasn't been tested thoroughly yet.</p>
View
22 ico.js
@@ -399,11 +399,17 @@ Helpers.extend(Ico.BaseGraph.prototype, {
if (options.label_count) {
this.y_label_count = options.label_count;
} else {
- this.y_label_count = Math.ceil(this.range / this.label_step);
- if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
- this.y_label_count += 1;
+ if (this.range === 0) {
+ this.y_label_count = 1;
+ this.label_step = 1;
+ } else {
+ this.y_label_count = Math.ceil(this.range / this.label_step);
+ if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
+ this.y_label_count += 1;
+ }
}
}
+
this.value_labels = this.makeValueLabels(this.y_label_count);
this.top_value = this.value_labels[this.value_labels.length - 1];
@@ -527,6 +533,10 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.range;
return ((value / total) * (this.graph_height));
},
@@ -744,7 +754,7 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
drawVerticalLabels: function() {
- var y_step = this.graph_height / this.y_label_count;
+ var y_step = this.graph_height / this.y_label_count;
this.drawMarkers(this.value_labels, [0, -1], y_step, y_step, [-8, -2], { 'text-anchor': 'end' });
},
@@ -1000,6 +1010,10 @@ Ico.LineGraph = function() { this.initialize.apply(this, arguments); };
Helpers.extend(Ico.LineGraph.prototype, Ico.BaseGraph.prototype);
Helpers.extend(Ico.LineGraph.prototype, {
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.top_value - this.start_value;
return ((value / total) * (this.graph_height));
},
View
2  ico.min.js
@@ -4,4 +4,4 @@
* MIT Licensed
*//**
* The Ico object.
- */(function(global){var Ico={VERSION:"0.3.9",round:function(num,dec){var result=Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);return result}};function validStepDivider(value){return value>1?value-1:1}function getStyle(el,styleProp){if(typeof window=="undefined")return;var style;return el.currentStyle?style=el.currentStyle[styleProp]:window.getComputedStyle&&(style=document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp)),style&&style.length===0&&(style=null),style}var Helpers={};Helpers.sum=function(a){var i,sum;for(i=0,sum=0;i<a.length;sum+=a[i++]);return sum},typeof Array.prototype.max=="undefined"?Helpers.max=function(a){return Math.max.apply({},a)}:Helpers.max=function(a){return a.max()},typeof Array.prototype.min=="undefined"?Helpers.min=function(a){return Math.min.apply({},a)}:Helpers.min=function(a){return a.min()},Helpers.mean=function(a){return Helpers.sum(a)/a.length},Helpers.variance=function(a){var mean=Helpers.mean(a),variance=0;for(var i=0;i<a.length;i++)variance+=Math.pow(a[i]-mean,2);return variance/(a.length-1)},Helpers.standard_deviation=function(a){return Math.sqrt(Helpers.variance(a))},typeof Object.extend=="undefined"?Helpers.extend=function(destination,source){for(var property in source)source.hasOwnProperty(property)&&(destination[property]=source[property]);return destination}:Helpers.extend=Object.extend,Object.keys?Helpers.keys=Object.keys:Helpers.keys=function(o){if(o!==Object(o))throw new TypeError("Object.keys called on non-object");var ret=[],p;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&ret.push(p);return ret},Ico.Normaliser=function(data,options){this.options={start_value:null},typeof options!="undefined"&&(this.options=options),this.min=Helpers.min(data),this.max=this.options.max||Helpers.max(data),this.standard_deviation=Helpers.standard_deviation(data),this.range=0,this.step=this.labelStep(this.max-this.min),this.start_value=this.calculateStart(),this.process()},Ico.Normaliser.prototype={calculateStart:function(){var min=typeof this.options.start_value!="undefined"&&this.min>=0?this.options.start_value:this.min,start_value=this.round(min,1);return this.min>0&&start_value>this.min?0:this.min===this.max?0:start_value},round:function(value,offset){offset=offset||1;var roundedValue=value;if(this.standard_deviation>.1){var multiplier=Math.pow(10,-offset);roundedValue=Math.round(value*multiplier)/multiplier;if(roundedValue>this.min)return this.round(value-this.step)}return roundedValue},process:function(){this.range=this.max-this.start_value,this.step=this.labelStep(this.range)},labelStep:function(value){return Math.pow(10,Math.round(Math.log(value)/Math.LN10)-1)}},Ico.Base={normaliseData:function(data){var values=[],i=0;for(i=0;i<data.length;i++)values.push(this.normalise(data[i]));return values},flatten:function(data){var flat_data=[];if(typeof data.length=="undefined"){if(typeof data!="object")return[];for(var key in data)data.hasOwnProperty(key)&&(flat_data=flat_data.concat(this.flatten(data[key])))}for(var i=0;i<data.length;i++)typeof data[i].length=="number"?flat_data=flat_data.concat(this.flatten(data[i])):flat_data.push(data[i]);return flat_data},makeRange:function(start,end,options){var values=[],i;for(i=start;i<end;i++)options&&options.skip?i%options.skip===0?values.push(i):values.push(undefined):values.push(i);return values}},Ico.BaseGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BaseGraph.prototype,Ico.Base),Helpers.extend(Ico.BaseGraph.prototype,{initialize:function(element,data,options){options=options||{},this.element=element.length?element[0]:element,this.data_sets=this.buildDataSets(data,options),this.flat_data=this.flatten(data),this.data_size=this.longestDataSetLength(),this.plottedCoords=[];if(options&&options.colour){options.colours={};for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(options.colours[key]=options.colour)}this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),plot_padding:10,font_size:10,show_horizontal_labels:!0,show_vertical_labels:!0,background_colour:getStyle(element,"backgroundColor")||"#ffffff",label_colour:"#666",markers:!1,marker_size:5,meanline:!1,grid:!1,grid_colour:"#ccc",y_padding_top:20,draw:!0,bar_labels:!1},Helpers.extend(this.options,this.chartDefaults()||{}),Helpers.extend(this.options,options),this.font_options={font:this.options.font_size+'px "Arial"',stroke:"none",fill:"#000"},this.normaliser=new Ico.Normaliser(this.flat_data,this.normaliserOptions()),this.label_step=options.label_step||this.normaliser.step,this.range=this.normaliser.range,this.start_value=options.start_value||this.normaliser.start_value,this.x_padding_left=10+this.paddingLeftOffset(),this.x_padding_right=20,this.x_padding=this.x_padding_left+this.x_padding_right,this.y_padding_top=this.options.y_padding_top,this.y_padding_bottom=20+this.paddingBottomOffset(),this.y_padding=this.y_padding_top+this.y_padding_bottom,this.graph_width=this.options.width-this.x_padding,this.graph_height=this.options.height-this.y_padding,this.step=this.calculateStep(),this.grid_step=this.step,this.options.labels?this.grouped||(this.grid_step=this.graph_width/this.options.labels.length,this.snap_to_grid=!0):this.options.labels=this.makeRange(1,this.data_size+1),this.options.bar_labels&&(this.range+=this.normaliser.step),options.label_count?this.y_label_count=options.label_count:(this.y_label_count=Math.ceil(this.range/this.label_step),this.normaliser.min+this.y_label_count*this.normaliser.step<this.normaliser.max&&(this.y_label_count+=1)),this.value_labels=this.makeValueLabels(this.y_label_count),this.top_value=this.value_labels[this.value_labels.length-1],this.grid_start_offset=-1,this.options.draw&&(typeof this.options.colours=="undefined"&&(this.options.colours=this.makeRandomColours()),this.paper=Raphael(this.element,this.options.width,this.options.height),this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.options.meanline===!0&&(this.options.meanline={"stroke-width":"2px",stroke:"#BBBBBB"}),this.setChartSpecificOptions(),this.lastPoint={x:0,y:0},this.draw())},buildDataSets:function(data,options){return typeof data.length!="undefined"?{one:data}:data},normaliserOptions:function(){return{}},chartDefaults:function(){return{}},drawPlot:function(index,pathString,x,y,colour){},calculateStep:function(){},makeRandomColours:function(){var colours;if(this.grouped){colours=[];for(var i=0;i<this.group_size;i++)colours.push(Raphael.hsb2rgb(Math.random(),1,.75).hex)}else{colours={};for(var key in this.data_sets)colours.hasOwnProperty(key)||(colours[key]=Raphael.hsb2rgb(Math.random(),1,.75).hex)}return colours},longestDataSetLength:function(){if(this.grouped)return this.flat_data.length;var length=0;for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(length=this.data_sets[key].length>length?this.data_sets[key].length:length);return length},roundValue:function(value,length){var multiplier=Math.pow(10,length);return value*=multiplier,value=Math.round(value)/multiplier,value},roundValues:function(data,length){var roundedData=[],i;for(i=0;i<data.length;i++)roundedData.push(this.roundValue(data[i],length));return roundedData},longestLabel:function(values){var labels=Array.prototype.slice.call(values||this.options.labels,0);return labels.length?labels.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length:0},paddingLeftOffset:function(){var data=this.roundValues(this.flat_data,2),longest_label_length=0;return longest_label_length=data.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length,longest_label_length=longest_label_length>2?longest_label_length-1:longest_label_length,10+longest_label_length*this.options.font_size},paddingBottomOffset:function(){return this.options.font_size},normalise:function(value){var total=this.start_value===0?this.top_value:this.range;return value/total*this.graph_height},draw:function(){this.options.grid&&this.drawGrid(),this.options.meanline&&this.drawMeanLine(this.normaliseData(this.flat_data)),this.drawAxis(),this.options.show_vertical_labels&&this.drawVerticalLabels(),this.options.show_horizontal_labels&&this.drawHorizontalLabels();if(this.grouped)this.drawLines(key,null,this.normaliseData(this.flat_data));else for(var key in this.data_sets)if(this.data_sets.hasOwnProperty(key)){var data=this.data_sets[key];this.drawLines(key,this.options.colours[key],this.normaliseData(data))}this.start_value!==0&&this.drawFocusHint()},drawGrid:function(){var pathString="",i,y;if(this.options.show_vertical_labels){y=this.graph_height+this.y_padding_top;for(i=0;i<this.y_label_count;i++)y-=this.graph_height/this.y_label_count,pathString+="M"+this.x_padding_left+","+y,pathString+="L"+(this.x_padding_left+this.graph_width)+","+y}if(this.options.show_horizontal_labels){var x=this.x_padding_left+this.options.plot_padding+this.grid_start_offset,x_labels=this.grouped?this.flat_data.length:this.options.labels.length,i,step=this.grid_step||this.step;for(i=0;i<x_labels;i++)pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height),x+=step;x=x-this.options.plot_padding-1,pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height)}this.paper.path(pathString).attr({stroke:this.options.grid_colour,"stroke-width":"1px"})},drawLines:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y;for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&this.options.colours&&(colour=this.options.colours[i%this.group_size]),this.plottedCoords.push([x+this.bar_padding,y]),pathString=this.drawPlot(i,pathString,x,y,colour);this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.options.stroke_width}),this.options.bar_labels&&this.drawBarMarkers(),this.options.line&&this.additionalLine(label,colour,this.normaliseData(this.options.line))},additionalLine:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y,step,lineWidth=3;this.grouped&&(step=this.step*(this.group_size-1));for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&(x+=step*i+this.roundValue(step/2,0)),x+=lineWidth,pathString=Ico.LineGraph.prototype.drawPlot.apply(this,[i,pathString,this.roundValue(x,0),y,colour]);this.paper.path(pathString).attr({stroke:"#ff0000","stroke-width":lineWidth+"px"})},calculateCoords:function(data){var x=this.x_padding_left+this.options.plot_padding-this.step,y_offset=this.graph_height+this.y_padding_top+this.normalise(this.start_value),y=0,coords=[],i;for(i=0;i<data.length;i++)y=y_offset-data[i],x+=this.step,coords.push([x,y]);return coords},drawFocusHint:function(){var length=5,x=this.x_padding_left+length/2-1,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y-length),pathString+="M"+x+","+(y-length),pathString+="L"+(x-length)+","+(y-length*2),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawMeanLine:function(data){var offset=Helpers.sum(data)/data.length,pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom-offset),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom-offset),this.paper.path(pathString).attr(this.options.meanline)},drawAxis:function(){var pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom),pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.x_padding_left-1)+","+this.y_padding_top,this.paper.path(pathString).attr({stroke:this.options.label_colour})},makeValueLabels:function(steps){var step=this.label_step,label=this.start_value,labels=[];for(var i=0;i<steps;i++)label=this.roundValue(label+step,2),labels.push(label);return labels},drawMarkers:function(labels,direction,step,start_offset,font_offsets,extra_font_options){function x_offset(value){return value*direction[0]}function y_offset(value){return value*direction[1]}var x=this.x_padding_left-1+x_offset(start_offset),y=this.options.height-this.y_padding_bottom+y_offset(start_offset),pathString="",i,font_options={};Helpers.extend(font_options,this.font_options),Helpers.extend(font_options,extra_font_options||{});for(i=0;i<labels.length;i++)pathString+="M"+x+","+y,typeof labels[i]!="undefined"&&(labels[i]+"").length>0&&(pathString+="L"+(x+y_offset(5))+","+(y+x_offset(5)),this.paper.text(x+font_offsets[0],y-font_offsets[1],labels[i]).attr(font_options).toFront()),x+=x_offset(step),y+=y_offset(step);this.paper.path(pathString).attr({stroke:this.options.label_colour})},drawVerticalLabels:function(){var y_step=this.graph_height/this.y_label_count;this.drawMarkers(this.value_labels,[0,-1],y_step,y_step,[-8,-2],{"text-anchor":"end"})},drawHorizontalLabels:function(){var step=this.snap_to_grid?this.grid_step:this.step;this.drawMarkers(this.options.labels,[1,0],step,this.options.plot_padding,[0,(this.options.font_size+7)*-1])}}),Ico.BarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.BarGraph.prototype,{buildDataSets:function(data,options){if(typeof data.length!="undefined"){if(typeof data[0].length!="undefined"){this.grouped=!0,this.group_size=data[0].length;var o={},k,i=0;for(k in options.labels)k=options.labels[k],o[k]=data[i],i++;return o}return{one:data}}return data},chartDefaults:function(){return{plot_padding:0}},normaliserOptions:function(){return this.options.line?{start_value:0,max:Helpers.max([Helpers.max(this.options.line),Helpers.max(this.flat_data)])}:{start_value:0}},setChartSpecificOptions:function(){this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarWidth(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_width/this.data_size),this.options.plot_padding=this.bar_width/2-this.bar_padding/2,this.step=this.calculateStep(),this.grid_start_offset=this.bar_padding-1,this.start_y=this.options.height-this.y_padding_bottom},calculateBarWidth:function(){var width=this.graph_width/this.data_size-this.bar_padding;return!this.grouped,this.options.max_bar_size&&width>this.options.max_bar_size&&(width=this.options.max_bar_size,this.bar_padding=this.graph_width/this.data_size),width},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2-this.bar_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){return x+=this.bar_padding,pathString+="M"+x+","+this.start_y,pathString+="L"+x+","+y,this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"}),pathString="",x+=this.step,pathString+="M"+x+","+this.start_y,pathString},drawHorizontalLabels:function(){var x_start=this.bar_padding+this.options.plot_padding,step=this.step;this.grouped&&(step*=this.group_size,x_start=(this.bar_width*this.group_size+this.bar_padding*this.group_size)/2,x_start=this.roundValue(x_start,0)),this.drawMarkers(this.options.labels,[1,0],step,x_start,[0,(this.options.font_size+7)*-1])},drawBarMarkers:function(){if(this.plottedCoords.length===0)return;var i,length=this.flat_data.length,x,y,label,font_options={};Helpers.extend(font_options,this.font_options),font_options["text-anchor"]="center";for(i=0;i<length;i++)label=this.roundValue(this.flat_data[i],2).toString(),x=this.plottedCoords[i][0],y=this.roundValue(this.plottedCoords[i][1],0),this.paper.text(x,y-this.options.font_size,label).attr(font_options).toFront()}}),Ico.HorizontalBarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.HorizontalBarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.HorizontalBarGraph.prototype,{setChartSpecificOptions:function(){this.y_padding_top=0,this.x_padding_left=20+this.longestLabel()*(this.options.font_size/2),this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarHeight(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_height/this.data_size),this.options.plot_padding=0,this.step=this.calculateStep()},normalise:function(value){var offset=this.x_padding_left;return value/this.range*(this.graph_width-offset)},calculateBarHeight:function(){var height=this.graph_height/this.data_size-this.bar_padding;return this.options.max_bar_size&&height>this.options.max_bar_size&&(height=this.options.max_bar_size,this.bar_padding=this.graph_height/this.data_size),height},calculateStep:function(){return(this.options.height-this.y_padding_bottom)/validStepDivider(this.data_size)},drawLines:function(label,colour,data){var x=this.x_padding_left+this.options.plot_padding*2,y=this.options.height-this.y_padding_bottom-this.step/2,pathString="M"+x+","+y,i;for(i=0;i<data.length;i++)pathString+="L"+(x+data[i]-this.normalise(this.start_value))+","+y,y-=this.step,pathString+="M"+x+","+y;this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"})},drawFocusHint:function(){var length=5,x=this.x_padding_left+this.step*2,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y+length),pathString+="M"+(x-length)+","+y,pathString+="L"+(x-length*2)+","+(y+length),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawVerticalLabels:function(){var y_start=this.step/2-this.options.plot_padding*2;this.drawMarkers(this.options.labels,[0,-1],this.step,y_start,[-8,this.options.font_size/8],{"text-anchor":"end"})},drawHorizontalLabels:function(){var x_step=this.graph_width/this.y_label_count,x_labels=this.makeValueLabels(this.y_label_count);this.drawMarkers(x_labels,[1,0],x_step,x_step,[0,(this.options.font_size+7)*-1])}}),Ico.LineGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.LineGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.LineGraph.prototype,{normalise:function(value){var total=this.start_value===0?this.top_value:this.top_value-this.start_value;return value/total*this.graph_height},chartDefaults:function(){return{plot_padding:10,stroke_width:"3px"}},setChartSpecificOptions:function(){var longestLabel=this.longestLabel(this.value_labels);this.x_padding_left=30+longestLabel*(this.options.font_size/2),typeof this.options.curve_amount=="undefined"&&(this.options.curve_amount=10)},normaliserOptions:function(){return{start_value:this.options.start_value}},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){var w=this.options.curve_amount;if(this.options.markers==="circle"){var circle=this.paper.circle(x,y,this.options.marker_size);circle.attr({"stroke-width":"1px",stroke:this.options.background_colour,fill:colour})}return index===0?(this.lastPoint={x:x,y:y},pathString+"M"+x+","+y):(w?pathString+=["C",this.lastPoint.x+w,this.lastPoint.y,x-w,y,x,y]:pathString+="L"+x+","+y,this.lastPoint={x:x,y:y},pathString)}}),Ico.SparkLine=function(){this.initialize.apply(this,arguments)},Ico.SparkLine.prototype={initialize:function(element,data,options){this.element=element,this.data=data,this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),highlight:!1,background_colour:getStyle(element,"backgroundColor")||"#ffffff",colour:"#036"},Helpers.extend(this.options,options||{}),this.step=this.calculateStep(),this.paper=Raphael(this.element,this.options.width,this.options.height),this.options.acceptable_range?this.background=this.paper.rect(0,this.options.height-this.normalise(this.options.acceptable_range[1]),this.options.width,this.options.height-this.normalise(this.options.acceptable_range[0])):this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.draw()},calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},normalise:function(value){return this.options.height/Helpers.max(this.data)*value},draw:function(){var data=this.normaliseData(this.data);this.drawLines("",this.options.colour,data),this.options.highlight&&this.showHighlight(data)},drawLines:function(label,colour,data){var pathString="",x=0,values=data.slice(1),i=0;pathString="M0,"+(this.options.height-data[0]);for(i=1;i<data.length;i++)x+=this.step,pathString+="L"+x+","+Ico.round(this.options.height-data[i],2);this.paper.path(pathString).attr({stroke:colour}),this.lastPoint={x:0,y:this.options.height-data[0]}},showHighlight:function(data){var size=2,x=this.options.width-size,i=this.options.highlight.index||data.length-1,y=data[i]+Math.round(size/2);typeof this.options.highlight.index!="undefined"&&(x=this.step*this.options.highlight.index);var circle=this.paper.circle(x,this.options.height-y,size);circle.attr({stroke:!1,fill:this.options.highlight.colour})}},Helpers.extend(Ico.SparkLine.prototype,Ico.Base),Ico.SparkBar=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.SparkBar.prototype,Ico.SparkLine.prototype),Helpers.extend(Ico.SparkBar.prototype,{calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},drawLines:function(label,colour,data){var width=this.step>2?this.step-1:this.step,x=width,pathString="",i=0;for(i=0;i<data.length;i++)pathString+="M"+x+","+(this.options.height-data[i]),pathString+="L"+x+","+this.options.height,x+=this.step;this.paper.path(pathString).attr({stroke:colour,"stroke-width":width})}}),global.Ico=Ico,typeof exports!="undefined"&&(module.exports=Ico)})(typeof window=="undefined"?this:window);
+ */(function(global){var Ico={VERSION:"0.3.9",round:function(num,dec){var result=Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);return result}};function validStepDivider(value){return value>1?value-1:1}function getStyle(el,styleProp){if(typeof window=="undefined")return;var style;return el.currentStyle?style=el.currentStyle[styleProp]:window.getComputedStyle&&(style=document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp)),style&&style.length===0&&(style=null),style}var Helpers={};Helpers.sum=function(a){var i,sum;for(i=0,sum=0;i<a.length;sum+=a[i++]);return sum},typeof Array.prototype.max=="undefined"?Helpers.max=function(a){return Math.max.apply({},a)}:Helpers.max=function(a){return a.max()},typeof Array.prototype.min=="undefined"?Helpers.min=function(a){return Math.min.apply({},a)}:Helpers.min=function(a){return a.min()},Helpers.mean=function(a){return Helpers.sum(a)/a.length},Helpers.variance=function(a){var mean=Helpers.mean(a),variance=0;for(var i=0;i<a.length;i++)variance+=Math.pow(a[i]-mean,2);return variance/(a.length-1)},Helpers.standard_deviation=function(a){return Math.sqrt(Helpers.variance(a))},typeof Object.extend=="undefined"?Helpers.extend=function(destination,source){for(var property in source)source.hasOwnProperty(property)&&(destination[property]=source[property]);return destination}:Helpers.extend=Object.extend,Object.keys?Helpers.keys=Object.keys:Helpers.keys=function(o){if(o!==Object(o))throw new TypeError("Object.keys called on non-object");var ret=[],p;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&ret.push(p);return ret},Ico.Normaliser=function(data,options){this.options={start_value:null},typeof options!="undefined"&&(this.options=options),this.min=Helpers.min(data),this.max=this.options.max||Helpers.max(data),this.standard_deviation=Helpers.standard_deviation(data),this.range=0,this.step=this.labelStep(this.max-this.min),this.start_value=this.calculateStart(),this.process()},Ico.Normaliser.prototype={calculateStart:function(){var min=typeof this.options.start_value!="undefined"&&this.min>=0?this.options.start_value:this.min,start_value=this.round(min,1);return this.min>0&&start_value>this.min?0:this.min===this.max?0:start_value},round:function(value,offset){offset=offset||1;var roundedValue=value;if(this.standard_deviation>.1){var multiplier=Math.pow(10,-offset);roundedValue=Math.round(value*multiplier)/multiplier;if(roundedValue>this.min)return this.round(value-this.step)}return roundedValue},process:function(){this.range=this.max-this.start_value,this.step=this.labelStep(this.range)},labelStep:function(value){return Math.pow(10,Math.round(Math.log(value)/Math.LN10)-1)}},Ico.Base={normaliseData:function(data){var values=[],i=0;for(i=0;i<data.length;i++)values.push(this.normalise(data[i]));return values},flatten:function(data){var flat_data=[];if(typeof data.length=="undefined"){if(typeof data!="object")return[];for(var key in data)data.hasOwnProperty(key)&&(flat_data=flat_data.concat(this.flatten(data[key])))}for(var i=0;i<data.length;i++)typeof data[i].length=="number"?flat_data=flat_data.concat(this.flatten(data[i])):flat_data.push(data[i]);return flat_data},makeRange:function(start,end,options){var values=[],i;for(i=start;i<end;i++)options&&options.skip?i%options.skip===0?values.push(i):values.push(undefined):values.push(i);return values}},Ico.BaseGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BaseGraph.prototype,Ico.Base),Helpers.extend(Ico.BaseGraph.prototype,{initialize:function(element,data,options){options=options||{},this.element=element.length?element[0]:element,this.data_sets=this.buildDataSets(data,options),this.flat_data=this.flatten(data),this.data_size=this.longestDataSetLength(),this.plottedCoords=[];if(options&&options.colour){options.colours={};for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(options.colours[key]=options.colour)}this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),plot_padding:10,font_size:10,show_horizontal_labels:!0,show_vertical_labels:!0,background_colour:getStyle(element,"backgroundColor")||"#ffffff",label_colour:"#666",markers:!1,marker_size:5,meanline:!1,grid:!1,grid_colour:"#ccc",y_padding_top:20,draw:!0,bar_labels:!1},Helpers.extend(this.options,this.chartDefaults()||{}),Helpers.extend(this.options,options),this.font_options={font:this.options.font_size+'px "Arial"',stroke:"none",fill:"#000"},this.normaliser=new Ico.Normaliser(this.flat_data,this.normaliserOptions()),this.label_step=options.label_step||this.normaliser.step,this.range=this.normaliser.range,this.start_value=options.start_value||this.normaliser.start_value,this.x_padding_left=10+this.paddingLeftOffset(),this.x_padding_right=20,this.x_padding=this.x_padding_left+this.x_padding_right,this.y_padding_top=this.options.y_padding_top,this.y_padding_bottom=20+this.paddingBottomOffset(),this.y_padding=this.y_padding_top+this.y_padding_bottom,this.graph_width=this.options.width-this.x_padding,this.graph_height=this.options.height-this.y_padding,this.step=this.calculateStep(),this.grid_step=this.step,this.options.labels?this.grouped||(this.grid_step=this.graph_width/this.options.labels.length,this.snap_to_grid=!0):this.options.labels=this.makeRange(1,this.data_size+1),this.options.bar_labels&&(this.range+=this.normaliser.step),options.label_count?this.y_label_count=options.label_count:this.range===0?(this.y_label_count=1,this.label_step=1):(this.y_label_count=Math.ceil(this.range/this.label_step),this.normaliser.min+this.y_label_count*this.normaliser.step<this.normaliser.max&&(this.y_label_count+=1)),this.value_labels=this.makeValueLabels(this.y_label_count),this.top_value=this.value_labels[this.value_labels.length-1],this.grid_start_offset=-1,this.options.draw&&(typeof this.options.colours=="undefined"&&(this.options.colours=this.makeRandomColours()),this.paper=Raphael(this.element,this.options.width,this.options.height),this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.options.meanline===!0&&(this.options.meanline={"stroke-width":"2px",stroke:"#BBBBBB"}),this.setChartSpecificOptions(),this.lastPoint={x:0,y:0},this.draw())},buildDataSets:function(data,options){return typeof data.length!="undefined"?{one:data}:data},normaliserOptions:function(){return{}},chartDefaults:function(){return{}},drawPlot:function(index,pathString,x,y,colour){},calculateStep:function(){},makeRandomColours:function(){var colours;if(this.grouped){colours=[];for(var i=0;i<this.group_size;i++)colours.push(Raphael.hsb2rgb(Math.random(),1,.75).hex)}else{colours={};for(var key in this.data_sets)colours.hasOwnProperty(key)||(colours[key]=Raphael.hsb2rgb(Math.random(),1,.75).hex)}return colours},longestDataSetLength:function(){if(this.grouped)return this.flat_data.length;var length=0;for(var key in this.data_sets)this.data_sets.hasOwnProperty(key)&&(length=this.data_sets[key].length>length?this.data_sets[key].length:length);return length},roundValue:function(value,length){var multiplier=Math.pow(10,length);return value*=multiplier,value=Math.round(value)/multiplier,value},roundValues:function(data,length){var roundedData=[],i;for(i=0;i<data.length;i++)roundedData.push(this.roundValue(data[i],length));return roundedData},longestLabel:function(values){var labels=Array.prototype.slice.call(values||this.options.labels,0);return labels.length?labels.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length:0},paddingLeftOffset:function(){var data=this.roundValues(this.flat_data,2),longest_label_length=0;return longest_label_length=data.sort(function(a,b){return a.toString().length<b.toString().length})[0].toString().length,longest_label_length=longest_label_length>2?longest_label_length-1:longest_label_length,10+longest_label_length*this.options.font_size},paddingBottomOffset:function(){return this.options.font_size},normalise:function(value){if(value===0)return 0;var total=this.start_value===0?this.top_value:this.range;return value/total*this.graph_height},draw:function(){this.options.grid&&this.drawGrid(),this.options.meanline&&this.drawMeanLine(this.normaliseData(this.flat_data)),this.drawAxis(),this.options.show_vertical_labels&&this.drawVerticalLabels(),this.options.show_horizontal_labels&&this.drawHorizontalLabels();if(this.grouped)this.drawLines(key,null,this.normaliseData(this.flat_data));else for(var key in this.data_sets)if(this.data_sets.hasOwnProperty(key)){var data=this.data_sets[key];this.drawLines(key,this.options.colours[key],this.normaliseData(data))}this.start_value!==0&&this.drawFocusHint()},drawGrid:function(){var pathString="",i,y;if(this.options.show_vertical_labels){y=this.graph_height+this.y_padding_top;for(i=0;i<this.y_label_count;i++)y-=this.graph_height/this.y_label_count,pathString+="M"+this.x_padding_left+","+y,pathString+="L"+(this.x_padding_left+this.graph_width)+","+y}if(this.options.show_horizontal_labels){var x=this.x_padding_left+this.options.plot_padding+this.grid_start_offset,x_labels=this.grouped?this.flat_data.length:this.options.labels.length,i,step=this.grid_step||this.step;for(i=0;i<x_labels;i++)pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height),x+=step;x=x-this.options.plot_padding-1,pathString+="M"+x+","+this.y_padding_top,pathString+="L"+x+","+(this.y_padding_top+this.graph_height)}this.paper.path(pathString).attr({stroke:this.options.grid_colour,"stroke-width":"1px"})},drawLines:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y;for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&this.options.colours&&(colour=this.options.colours[i%this.group_size]),this.plottedCoords.push([x+this.bar_padding,y]),pathString=this.drawPlot(i,pathString,x,y,colour);this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.options.stroke_width}),this.options.bar_labels&&this.drawBarMarkers(),this.options.line&&this.additionalLine(label,colour,this.normaliseData(this.options.line))},additionalLine:function(label,colour,data){var coords=this.calculateCoords(data),pathString="",i,x,y,step,lineWidth=3;this.grouped&&(step=this.step*(this.group_size-1));for(i=0;i<coords.length;i++)x=coords[i][0]||0,y=coords[i][1]||0,this.grouped&&(x+=step*i+this.roundValue(step/2,0)),x+=lineWidth,pathString=Ico.LineGraph.prototype.drawPlot.apply(this,[i,pathString,this.roundValue(x,0),y,colour]);this.paper.path(pathString).attr({stroke:"#ff0000","stroke-width":lineWidth+"px"})},calculateCoords:function(data){var x=this.x_padding_left+this.options.plot_padding-this.step,y_offset=this.graph_height+this.y_padding_top+this.normalise(this.start_value),y=0,coords=[],i;for(i=0;i<data.length;i++)y=y_offset-data[i],x+=this.step,coords.push([x,y]);return coords},drawFocusHint:function(){var length=5,x=this.x_padding_left+length/2-1,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y-length),pathString+="M"+x+","+(y-length),pathString+="L"+(x-length)+","+(y-length*2),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawMeanLine:function(data){var offset=Helpers.sum(data)/data.length,pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom-offset),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom-offset),this.paper.path(pathString).attr(this.options.meanline)},drawAxis:function(){var pathString="";pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.graph_width+this.x_padding_left)+","+(this.options.height-this.y_padding_bottom),pathString+="M"+(this.x_padding_left-1)+","+(this.options.height-this.y_padding_bottom),pathString+="L"+(this.x_padding_left-1)+","+this.y_padding_top,this.paper.path(pathString).attr({stroke:this.options.label_colour})},makeValueLabels:function(steps){var step=this.label_step,label=this.start_value,labels=[];for(var i=0;i<steps;i++)label=this.roundValue(label+step,2),labels.push(label);return labels},drawMarkers:function(labels,direction,step,start_offset,font_offsets,extra_font_options){function x_offset(value){return value*direction[0]}function y_offset(value){return value*direction[1]}var x=this.x_padding_left-1+x_offset(start_offset),y=this.options.height-this.y_padding_bottom+y_offset(start_offset),pathString="",i,font_options={};Helpers.extend(font_options,this.font_options),Helpers.extend(font_options,extra_font_options||{});for(i=0;i<labels.length;i++)pathString+="M"+x+","+y,typeof labels[i]!="undefined"&&(labels[i]+"").length>0&&(pathString+="L"+(x+y_offset(5))+","+(y+x_offset(5)),this.paper.text(x+font_offsets[0],y-font_offsets[1],labels[i]).attr(font_options).toFront()),x+=x_offset(step),y+=y_offset(step);this.paper.path(pathString).attr({stroke:this.options.label_colour})},drawVerticalLabels:function(){var y_step=this.graph_height/this.y_label_count;this.drawMarkers(this.value_labels,[0,-1],y_step,y_step,[-8,-2],{"text-anchor":"end"})},drawHorizontalLabels:function(){var step=this.snap_to_grid?this.grid_step:this.step;this.drawMarkers(this.options.labels,[1,0],step,this.options.plot_padding,[0,(this.options.font_size+7)*-1])}}),Ico.BarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.BarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.BarGraph.prototype,{buildDataSets:function(data,options){if(typeof data.length!="undefined"){if(typeof data[0].length!="undefined"){this.grouped=!0,this.group_size=data[0].length;var o={},k,i=0;for(k in options.labels)k=options.labels[k],o[k]=data[i],i++;return o}return{one:data}}return data},chartDefaults:function(){return{plot_padding:0}},normaliserOptions:function(){return this.options.line?{start_value:0,max:Helpers.max([Helpers.max(this.options.line),Helpers.max(this.flat_data)])}:{start_value:0}},setChartSpecificOptions:function(){this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarWidth(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_width/this.data_size),this.options.plot_padding=this.bar_width/2-this.bar_padding/2,this.step=this.calculateStep(),this.grid_start_offset=this.bar_padding-1,this.start_y=this.options.height-this.y_padding_bottom},calculateBarWidth:function(){var width=this.graph_width/this.data_size-this.bar_padding;return!this.grouped,this.options.max_bar_size&&width>this.options.max_bar_size&&(width=this.options.max_bar_size,this.bar_padding=this.graph_width/this.data_size),width},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2-this.bar_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){return x+=this.bar_padding,pathString+="M"+x+","+this.start_y,pathString+="L"+x+","+y,this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"}),pathString="",x+=this.step,pathString+="M"+x+","+this.start_y,pathString},drawHorizontalLabels:function(){var x_start=this.bar_padding+this.options.plot_padding,step=this.step;this.grouped&&(step*=this.group_size,x_start=(this.bar_width*this.group_size+this.bar_padding*this.group_size)/2,x_start=this.roundValue(x_start,0)),this.drawMarkers(this.options.labels,[1,0],step,x_start,[0,(this.options.font_size+7)*-1])},drawBarMarkers:function(){if(this.plottedCoords.length===0)return;var i,length=this.flat_data.length,x,y,label,font_options={};Helpers.extend(font_options,this.font_options),font_options["text-anchor"]="center";for(i=0;i<length;i++)label=this.roundValue(this.flat_data[i],2).toString(),x=this.plottedCoords[i][0],y=this.roundValue(this.plottedCoords[i][1],0),this.paper.text(x,y-this.options.font_size,label).attr(font_options).toFront()}}),Ico.HorizontalBarGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.HorizontalBarGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.HorizontalBarGraph.prototype,{setChartSpecificOptions:function(){this.y_padding_top=0,this.x_padding_left=20+this.longestLabel()*(this.options.font_size/2),this.bar_padding=this.options.bar_padding||5,this.bar_width=this.options.bar_size||this.calculateBarHeight(),this.options.bar_size&&!this.options.bar_padding&&(this.bar_padding=this.graph_height/this.data_size),this.options.plot_padding=0,this.step=this.calculateStep()},normalise:function(value){var offset=this.x_padding_left;return value/this.range*(this.graph_width-offset)},calculateBarHeight:function(){var height=this.graph_height/this.data_size-this.bar_padding;return this.options.max_bar_size&&height>this.options.max_bar_size&&(height=this.options.max_bar_size,this.bar_padding=this.graph_height/this.data_size),height},calculateStep:function(){return(this.options.height-this.y_padding_bottom)/validStepDivider(this.data_size)},drawLines:function(label,colour,data){var x=this.x_padding_left+this.options.plot_padding*2,y=this.options.height-this.y_padding_bottom-this.step/2,pathString="M"+x+","+y,i;for(i=0;i<data.length;i++)pathString+="L"+(x+data[i]-this.normalise(this.start_value))+","+y,y-=this.step,pathString+="M"+x+","+y;this.paper.path(pathString).attr({stroke:colour,"stroke-width":this.bar_width+"px"})},drawFocusHint:function(){var length=5,x=this.x_padding_left+this.step*2,y=this.options.height-this.y_padding_bottom,pathString="";pathString+="M"+x+","+y,pathString+="L"+(x-length)+","+(y+length),pathString+="M"+(x-length)+","+y,pathString+="L"+(x-length*2)+","+(y+length),this.paper.path(pathString).attr({stroke:this.options.label_colour,"stroke-width":2})},drawVerticalLabels:function(){var y_start=this.step/2-this.options.plot_padding*2;this.drawMarkers(this.options.labels,[0,-1],this.step,y_start,[-8,this.options.font_size/8],{"text-anchor":"end"})},drawHorizontalLabels:function(){var x_step=this.graph_width/this.y_label_count,x_labels=this.makeValueLabels(this.y_label_count);this.drawMarkers(x_labels,[1,0],x_step,x_step,[0,(this.options.font_size+7)*-1])}}),Ico.LineGraph=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.LineGraph.prototype,Ico.BaseGraph.prototype),Helpers.extend(Ico.LineGraph.prototype,{normalise:function(value){if(value===0)return 0;var total=this.start_value===0?this.top_value:this.top_value-this.start_value;return value/total*this.graph_height},chartDefaults:function(){return{plot_padding:10,stroke_width:"3px"}},setChartSpecificOptions:function(){var longestLabel=this.longestLabel(this.value_labels);this.x_padding_left=30+longestLabel*(this.options.font_size/2),typeof this.options.curve_amount=="undefined"&&(this.options.curve_amount=10)},normaliserOptions:function(){return{start_value:this.options.start_value}},calculateStep:function(){return(this.graph_width-this.options.plot_padding*2)/validStepDivider(this.data_size)},drawPlot:function(index,pathString,x,y,colour){var w=this.options.curve_amount;if(this.options.markers==="circle"){var circle=this.paper.circle(x,y,this.options.marker_size);circle.attr({"stroke-width":"1px",stroke:this.options.background_colour,fill:colour})}return index===0?(this.lastPoint={x:x,y:y},pathString+"M"+x+","+y):(w?pathString+=["C",this.lastPoint.x+w,this.lastPoint.y,x-w,y,x,y]:pathString+="L"+x+","+y,this.lastPoint={x:x,y:y},pathString)}}),Ico.SparkLine=function(){this.initialize.apply(this,arguments)},Ico.SparkLine.prototype={initialize:function(element,data,options){this.element=element,this.data=data,this.options={width:parseInt(getStyle(element,"width"),10),height:parseInt(getStyle(element,"height"),10),highlight:!1,background_colour:getStyle(element,"backgroundColor")||"#ffffff",colour:"#036"},Helpers.extend(this.options,options||{}),this.step=this.calculateStep(),this.paper=Raphael(this.element,this.options.width,this.options.height),this.options.acceptable_range?this.background=this.paper.rect(0,this.options.height-this.normalise(this.options.acceptable_range[1]),this.options.width,this.options.height-this.normalise(this.options.acceptable_range[0])):this.background=this.paper.rect(0,0,this.options.width,this.options.height),this.background.attr({fill:this.options.background_colour,stroke:"none"}),this.draw()},calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},normalise:function(value){return this.options.height/Helpers.max(this.data)*value},draw:function(){var data=this.normaliseData(this.data);this.drawLines("",this.options.colour,data),this.options.highlight&&this.showHighlight(data)},drawLines:function(label,colour,data){var pathString="",x=0,values=data.slice(1),i=0;pathString="M0,"+(this.options.height-data[0]);for(i=1;i<data.length;i++)x+=this.step,pathString+="L"+x+","+Ico.round(this.options.height-data[i],2);this.paper.path(pathString).attr({stroke:colour}),this.lastPoint={x:0,y:this.options.height-data[0]}},showHighlight:function(data){var size=2,x=this.options.width-size,i=this.options.highlight.index||data.length-1,y=data[i]+Math.round(size/2);typeof this.options.highlight.index!="undefined"&&(x=this.step*this.options.highlight.index);var circle=this.paper.circle(x,this.options.height-y,size);circle.attr({stroke:!1,fill:this.options.highlight.colour})}},Helpers.extend(Ico.SparkLine.prototype,Ico.Base),Ico.SparkBar=function(){this.initialize.apply(this,arguments)},Helpers.extend(Ico.SparkBar.prototype,Ico.SparkLine.prototype),Helpers.extend(Ico.SparkBar.prototype,{calculateStep:function(){return this.options.width/validStepDivider(this.data.length)},drawLines:function(label,colour,data){var width=this.step>2?this.step-1:this.step,x=width,pathString="",i=0;for(i=0;i<data.length;i++)pathString+="M"+x+","+(this.options.height-data[i]),pathString+="L"+x+","+this.options.height,x+=this.step;this.paper.path(pathString).attr({stroke:colour,"stroke-width":width})}}),global.Ico=Ico,typeof exports!="undefined"&&(module.exports=Ico)})(typeof window=="undefined"?this:window);
View
18 src/graphs/base.js
@@ -104,11 +104,17 @@ Helpers.extend(Ico.BaseGraph.prototype, {
if (options.label_count) {
this.y_label_count = options.label_count;
} else {
- this.y_label_count = Math.ceil(this.range / this.label_step);
- if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
- this.y_label_count += 1;
+ if (this.range === 0) {
+ this.y_label_count = 1;
+ this.label_step = 1;
+ } else {
+ this.y_label_count = Math.ceil(this.range / this.label_step);
+ if ((this.normaliser.min + (this.y_label_count * this.normaliser.step)) < this.normaliser.max) {
+ this.y_label_count += 1;
+ }
}
}
+
this.value_labels = this.makeValueLabels(this.y_label_count);
this.top_value = this.value_labels[this.value_labels.length - 1];
@@ -232,6 +238,10 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.range;
return ((value / total) * (this.graph_height));
},
@@ -449,7 +459,7 @@ Helpers.extend(Ico.BaseGraph.prototype, {
},
drawVerticalLabels: function() {
- var y_step = this.graph_height / this.y_label_count;
+ var y_step = this.graph_height / this.y_label_count;
this.drawMarkers(this.value_labels, [0, -1], y_step, y_step, [-8, -2], { 'text-anchor': 'end' });
},
View
4 src/graphs/line.js
@@ -10,6 +10,10 @@ Ico.LineGraph = function() { this.initialize.apply(this, arguments); };
Helpers.extend(Ico.LineGraph.prototype, Ico.BaseGraph.prototype);
Helpers.extend(Ico.LineGraph.prototype, {
normalise: function(value) {
+ if (value === 0) {
+ return 0;
+ }
+
var total = this.start_value === 0 ? this.top_value : this.top_value - this.start_value;
return ((value / total) * (this.graph_height));
},
View
6 test/browser/normalisation.test.js
@@ -1,5 +1,11 @@
module('Normalisation');
+test('test_0s', function() {
+ var normaliser = new Ico.Normaliser([0, 0, 0, 0, 0]);
+ equal(0, normaliser.step);
+ equal(0, normaliser.start_value);
+});
+
test('test_0_to_1', function() {
var normaliser = new Ico.Normaliser([0.1, 0.5, 0.9, 1.0]);
equal(0.1, normaliser.step);
Please sign in to comment.
Something went wrong with that request. Please try again.