/*
 +-------------------------------------------------------------------+
 |                   H T M L - G R A P H S   (v4.4)                  |
 |                                                                   |
 | Copyright Gerd Tentler               www.gerd-tentler.de/tools    |
 | Created: Sep. 17, 2002               Last modified: Nov. 17, 2007 |
 +-------------------------------------------------------------------+
 | This program may be used and hosted free of charge by anyone for  |
 | personal purpose as long as this copyright notice remains intact. |
 |                                                                   |
 | Obtain permission before selling the code for this program or     |
 | hosting this software on a commercial website or redistributing   |
 | this software over the Internet or in any other medium. In all    |
 | cases copyright must remain intact.                               |
 +-------------------------------------------------------------------+

======================================================================================================
 Example:

   graph = new BAR_GRAPH("hBar");
   graph.values = new Array(234, 125, 289, 147, 190);
   document.write(graph.create());

 Returns HTML code
------------------------------------------------------------------------------------------------------
 This script was tested with the following systems and browsers:

 - Windows XP: IE 6, NN 7, Opera 7 + 9, Firefox 2
 - Mac OS X:   IE 5, Safari 1

 If you use another browser or system, this script may not work for you - sorry.
======================================================================================================
*/

function BAR_GRAPH(type){this.type='hBar';if(type)this.type=type;this.values;this.graphBGColor='';this.graphBorder='';this.graphPadding=0;this.titles;this.titleColor='black';this.titleBGColor='#C0E0FF';this.titleBorder='2px groove white';this.titleFont='Arial, Helvetica';this.titleSize=12;this.titleAlign='center';this.titlePadding=2;this.labels;this.labelColor='black';this.labelBGColor='#C0E0FF';this.labelBorder='2px groove white';this.labelFont='Arial, Helvetica';this.labelSize=12;this.labelAlign='center';this.labelSpace=0;this.barWidth=20;this.barLength=1.0;this.barColors;this.barBGColor;this.barBorder='2px outset white';this.barLevelColors;this.showValues=0;this.absValuesColor='black';this.absValuesBGColor='#C0E0FF';this.absValuesBorder='2px groove white';this.absValuesFont='Arial, Helvetica';this.absValuesSize=12;this.absValuesPrefix='';this.absValuesSuffix='';this.percValuesColor='black';this.percValuesFont='Arial, Helvetica';this.percValuesSize=12;this.percValuesDecimals=0;this.charts=1;this.legend;this.legendColor='black';this.legendBGColor='#F0F0F0';this.legendBorder='2px groove white';this.legendFont='Arial, Helvetica';this.legendSize=12;this.debug=false;this.colors=new Array('#0000FF','#FF0000','#00E000','#A0A0FF','#FFA0A0','#00A000');this.err_type='ERROR: Type must be "hBar", "vBar", "pBar", or "fader"';this.cssGRAPH='';this.cssBAR='';this.cssBARBG='';this.cssTITLE='';this.cssLABEL='';this.cssLABELBG='';this.cssLEGEND='';this.cssLEGENDBG='';this.cssABSVALUES='';this.cssPERCVALUES='';this.set_styles=function(){if(this.graphBGColor)this.cssGRAPH+='background-color:'+this.graphBGColor+';';if(this.graphBorder)this.cssGRAPH+='border:'+this.graphBorder+';';if(this.barBorder)this.cssBAR+='border:'+this.barBorder+';';if(this.barBGColor)this.cssBARBG+='background-color:'+this.barBGColor+';';if(this.titleColor)this.cssTITLE+='color:'+this.titleColor+';';if(this.titleBGColor)this.cssTITLE+='background-color:'+this.titleBGColor+';';if(this.titleBorder)this.cssTITLE+='border:'+this.titleBorder+';';if(this.titleFont)this.cssTITLE+='font-family:'+this.titleFont+';';if(this.titleAlign)this.cssTITLE+='text-align:'+this.titleAlign+';';if(this.titleSize)this.cssTITLE+='font-size:'+this.titleSize+'px;';if(this.titleBGColor)this.cssTITLE+='background-color:'+this.titleBGColor+';';if(this.titlePadding)this.cssTITLE+='padding:'+this.titlePadding+'px;';if(this.labelColor)this.cssLABEL+='color:'+this.labelColor+';';if(this.labelBGColor)this.cssLABEL+='background-color:'+this.labelBGColor+';';if(this.labelBorder)this.cssLABEL+='border:'+this.labelBorder+';';if(this.labelFont)this.cssLABEL+='font-family:'+this.labelFont+';';if(this.labelAlign)this.cssLABEL+='text-align:'+this.labelAlign+';';if(this.labelSize)this.cssLABEL+='font-size:'+this.labelSize+'px;';if(this.labelBGColor)this.cssLABELBG+='background-color:'+this.labelBGColor+';';if(this.legendColor)this.cssLEGEND+='color:'+this.legendColor+';';if(this.legendFont)this.cssLEGEND+='font-family:'+this.legendFont+';';if(this.legendSize)this.cssLEGEND+='font-size:'+this.legendSize+'px;';if(this.legendBGColor)this.cssLEGENDBG+='background-color:'+this.legendBGColor+';';if(this.legendBorder)this.cssLEGENDBG+='border:'+this.legendBorder+';';if(this.absValuesColor)this.cssABSVALUES+='color:'+this.absValuesColor+';';if(this.absValuesBGColor)this.cssABSVALUES+='background-color:'+this.absValuesBGColor+';';if(this.absValuesBorder)this.cssABSVALUES+='border:'+this.absValuesBorder+';';if(this.absValuesFont)this.cssABSVALUES+='font-family:'+this.absValuesFont+';';if(this.absValuesSize)this.cssABSVALUES+='font-size:'+this.absValuesSize+'px;';if(this.percValuesColor)this.cssPERCVALUES+='color:'+this.percValuesColor+';';if(this.percValuesFont)this.cssPERCVALUES+='font-family:'+this.percValuesFont+';';if(this.percValuesSize)this.cssPERCVALUES+='font-size:'+this.percValuesSize+'px;';}
this.level_color=function(value,color){if(this.barLevelColors){for(var i=0;i<this.barLevelColors.length;i+=2){if(i+1<this.barLevelColors.length){if((this.barLevelColors[i]>0&&value>=this.barLevelColors[i])||(this.barLevelColors[i]<0&&value<=this.barLevelColors[i])){color=this.barLevelColors[i+1];}}}}
return color;}
this.build_bar=function(value,width,height,color){var title=this.absValuesPrefix+value+this.absValuesSuffix;var bg=(color.search(/\.(jpg|jpeg|jpe|gif|png)$/i)!=-1)?'background':'bgcolor';var bar='<table border=0 cellspacing=0 cellpadding=0><tr>';bar+='<td style="'+this.cssBAR+'" '+bg+'="'+color+'"';bar+=((value!='')?' title="'+title+'">':'>');bar+='<div style="width:'+width+'px; height:'+height+'px;';bar+=' line-height:1px; font-size:1px;"></div>';bar+='</td></tr></table>';return bar;}
this.build_fader=function(value,width,height,x,color){var fader='<table border=0 cellspacing=0 cellpadding=0><tr>';x-=Math.round(width/2);if(x>0)fader+='<td width='+x+'></td>';fader+='<td>'+this.build_bar(value,width,height,color)+'</td>';fader+='</tr></table>';return fader;}
this.build_value=function(val,max_dec,sum,align){val=_number_format(val,max_dec);if(sum)sum=_number_format(sum,max_dec);var value='<td style="'+this.cssABSVALUES+'"';if(align)value+=' align='+align;value+=' nowrap>';value+='&nbsp;'+this.absValuesPrefix+val+this.absValuesSuffix;if(sum)value+=' / '+this.absValuesPrefix+sum+this.absValuesSuffix;value+='&nbsp;</td>';return value;}
this.build_legend=function(barColors){var legend='<table border=0 cellspacing=0 cellpadding=0><tr>';legend+='<td style="'+this.cssLEGENDBG+'">';legend+='<table border=0 cellspacing=4 cellpadding=0>';var l=(typeof(this.legend)=='string')?this.legend.split(','):this.legend;for(var i=0;i<barColors.length;i++){legend+='<tr>';legend+='<td>'+this.build_bar('',this.barWidth,this.barWidth,barColors[i])+'</td>';legend+='<td style="'+this.cssLEGEND+'" nowrap>'+_trim(l[i])+'</td>';legend+='</tr>';}
legend+='</table></td></tr></table>';return legend;}
this.build_hTitle=function(titleLabel,titleValue,titleBar){var title='<tr>';title+='<td style="'+this.cssTITLE+'">'+titleLabel+'</td>';if(titleValue!='')title+='<td style="'+this.cssTITLE+'">'+titleValue+'</td>';title+='<td style="'+this.cssTITLE+'">'+titleBar+'</td>';title+='</tr>';return title;}
this.create_hBar=function(value,percent,mPerc,mPerc_neg,max_neg,mul,valSpace,bColor,border,spacer,spacer_neg){var bar='<table border=0 cellspacing=0 cellpadding=0 height=100%><tr>';if(percent<0){percent*=-1;bar+='<td style="'+this.cssLABELBG+'" height='+this.barWidth+' width='+Math.round((mPerc_neg-percent)*mul+valSpace)+' align=right nowrap>';if(this.showValues<2)bar+='<span style="'+this.cssPERCVALUES+'">'+_number_format(percent,this.percValuesDecimals)+'%</span>';bar+='&nbsp;</td><td style="'+this.cssLABELBG+'">';bar+=this.build_bar(value,Math.round(percent*mul),this.barWidth,bColor);bar+='</td><td width='+spacer+'></td>';}
else{if(max_neg){bar+='<td style="'+this.cssLABELBG+'" width='+spacer_neg+'>';bar+='<table border=0 cellspacing=0 cellpadding=0><tr><td></td></tr></table></td>';}
if(percent){bar+='<td>';bar+=this.build_bar(value,Math.round(percent*mul),this.barWidth,bColor);bar+='</td>';}
else bar+='<td><img width=1 height='+(this.barWidth+(border*2))+'></td>';bar+='<td style="'+this.cssPERCVALUES+'" width='+Math.round((mPerc-percent)*mul+valSpace)+' align=left nowrap>';if(this.showValues<2)bar+='&nbsp;'+_number_format(percent,this.percValuesDecimals)+'%';bar+='&nbsp;</td>';}
bar+='</tr></table>';return bar;}
this.create_vBar=function(value,percent,mPerc,mPerc_neg,max_neg,mul,valSpace,bColor,border,spacer,spacer_neg){var bar='<table border=0 cellspacing=0 cellpadding=0 width=100%><tr align=center>';if(percent<0){percent*=-1;bar+='<td height='+spacer+'></td></tr><tr align=center valign=top><td style="'+this.cssLABELBG+'">';bar+=this.build_bar(value,this.barWidth,Math.round(percent*mul),bColor);bar+='</td></tr><tr align=center valign=top>';bar+='<td style="'+this.cssLABELBG+'" height='+Math.round((mPerc_neg-percent)*mul+valSpace)+' nowrap>';bar+=(this.showValues<2)?'<span style="'+this.cssPERCVALUES+'">'+_number_format(percent,this.percValuesDecimals)+'%</span>':'&nbsp;';bar+='</td>';}
else{bar+='<td style="'+this.cssPERCVALUES+'" valign=bottom height='+Math.round((mPerc-percent)*mul+valSpace)+' nowrap>';if(this.showValues<2)bar+=_number_format(percent,this.percValuesDecimals)+'%';bar+='</td>';if(percent){bar+='</tr><tr align=center valign=bottom><td>';bar+=this.build_bar(value,this.barWidth,Math.round(percent*mul),bColor);bar+='</td>';}
else bar+='</tr><tr><td><img width='+(this.barWidth+(border*2))+' height=1></td>';if(max_neg){bar+='</tr><tr><td style="'+this.cssLABELBG+'" height='+spacer_neg+'>';bar+='<table border=0 cellspacing=0 cellpadding=0><tr><td></td></tr></table></td>';}}
bar+='</tr></table>';return bar;}
this.create=function(){this.type=this.type.toLowerCase();var d=(typeof(this.values)=='string')?this.values.split(','):this.values;if(this.titles)var t=(typeof(this.titles)=='string')?this.titles.split(','):this.titles;else var t=new Array();if(this.labels)var r=(typeof(this.labels)=='string')?this.labels.split(','):this.labels;else var r=new Array();var label='';var graph='';var bColor='';var percent=0;var value=0;var rowspan=0;var colspan=0;if(this.barColors)var drc=(typeof(this.barColors)=='string')?this.barColors.split(','):this.barColors;else var drc=new Array();var drv,val=new Array();var bc=new Array();if(this.barLength<0.1)this.barLength=0.1;else if(this.barLength>2.9)this.barLength=2.9;var bars=(d.length>r.length)?d.length:r.length;if(this.type=='pbar'||this.type=='fader'){if(!this.barBGColor)this.barBGColor=this.labelBGColor;if(this.labelBGColor==this.barBGColor&&t.length==0){this.labelBGColor='';this.labelBorder='';}}
this.set_styles();graph+='<table border=0 cellspacing=0 cellpadding='+this.graphPadding+'><tr>';graph+='<td'+(this.cssGRAPH?' style="'+this.cssGRAPH+'"':'')+'>';if(this.legend&&this.type!='pbar'&&this.type!='fader')
graph+='<table border=0 cellspacing=0 cellpadding=0><tr valign=top><td>';if(this.charts>1){divide=Math.ceil(bars/this.charts);graph+='<table border=0 cellspacing=0 cellpadding=6><tr valign=top><td>';}
else divide=0;var sum=max=max_neg=max_dec=ccnt=lcnt=chart=0;val[chart]=new Array();for(var i=0;i<bars;i++){if(divide&&i&&!(i%divide)){lcnt=0;chart++;val[chart]=new Array();}
if(typeof(d[i])=='string')drv=d[i].split(';');else{drv=new Array();drv[0]=d[i];}
val[chart][lcnt]=new Array();for(var j=v=0;j<drv.length;j++){val[chart][lcnt][j]=v=drv[j]?parseFloat(drv[j]):0;if(v>max)max=v;else if(v<max_neg)max_neg=v;if(v<0)v*=-1;sum+=v;v=v.toString();if(v.indexOf('.')!=-1){v=v.substr(v.indexOf('.')+1);dec=v.length;if(dec>max_dec)max_dec=dec;}
if(!bc[j]){if(ccnt>=this.colors.length)ccnt=0;bc[j]=(!drc[j]||drc[j].length<3)?this.colors[ccnt++]:_trim(drc[j]);}}
lcnt++;}
var border=parseInt(this.barBorder);var mPerc=sum?Math.round(max*100/sum):0;if(this.type=='pbar'||this.type=='fader')var mul=2;else var mul=mPerc?100/mPerc:1;mul*=this.barLength;if(this.showValues<2){if(this.type=='hbar')
valSpace=(this.percValuesDecimals*(this.percValuesSize/1.6))+(this.percValuesSize*3.2);else valSpace=this.percValuesSize*1.2;}
else valSpace=this.percValuesSize;var spacer=maxSize=Math.round(mPerc*mul+valSpace+border*2);if(max_neg){var mPerc_neg=sum?Math.round(-max_neg*100/sum):0;var spacer_neg=Math.round(mPerc_neg*mul+valSpace+border*2);maxSize+=spacer_neg;}
var titleLabel=titleValue=titleBar='';if(t.length>0){titleLabel=(t[0]=='')?'&nbsp;':t[0];if(this.showValues==1||this.showValues==2){titleValue=(t[1]=='')?'&nbsp;':t[1];titleBar=(t[2]=='')?'&nbsp;':t[2];}
else titleBar=(t[1]=='')?'&nbsp;':t[1];}
for(chart=lcnt=0;chart<val.length;chart++){graph+='<table border=0 cellspacing=2 cellpadding=0>';if(this.type=='hbar'){if(t.length>0)graph+=this.build_hTitle(titleLabel,titleValue,titleBar);for(i=0;i<val[chart].length;i++,lcnt++){label=(lcnt<r.length)?_trim(r[lcnt]):lcnt+1;rowspan=val[chart][i].length;graph+='<tr><td style="'+this.cssLABEL+'"'+((rowspan>1)?' rowspan='+rowspan:'')+'>';graph+='&nbsp;'+label+'&nbsp;</td>';for(j=0;j<val[chart][i].length;j++){percent=sum?val[chart][i][j]*100/sum:0;value=_number_format(val[chart][i][j],max_dec);bColor=this.level_color(val[chart][i][j],bc[j]);if(this.showValues==1||this.showValues==2)
graph+=this.build_value(val[chart][i][j],max_dec,0,'right');graph+='<td'+(this.cssBARBG?' style="'+this.cssBARBG+'"':'')+' height=100% width='+maxSize+'>';graph+=this.create_hBar(value,percent,mPerc,mPerc_neg,max_neg,mul,valSpace,bColor,border,spacer,spacer_neg);graph+='</td></tr>';if(j<val[chart][i].length-1)graph+='<tr>';}
if(this.labelSpace&&i<val[chart].length-1)graph+='<tr><td colspan=3 height='+this.labelSpace+'></td></tr>';}}
else if(this.type=='vbar'){graph+='<tr align=center valign=bottom>';if(titleBar!=''){titleBar=titleBar.replace(/-/g,'-<br>');graph+='<td style="'+this.cssTITLE+'" valign=middle>'+titleBar+'</td>';}
for(i=0;i<val[chart].length;i++){for(j=0;j<val[chart][i].length;j++){percent=sum?val[chart][i][j]*100/sum:0;value=_number_format(val[chart][i][j],max_dec);bColor=this.level_color(val[chart][i][j],bc[j]);graph+='<td'+(this.cssBARBG?' style="'+this.cssBARBG+'"':'')+'>';graph+=this.create_vBar(value,percent,mPerc,mPerc_neg,max_neg,mul,valSpace,bColor,border,spacer,spacer_neg);graph+='</td>';}
if(this.labelSpace)graph+='<td width='+this.labelSpace+'></td>';}
if(this.showValues==1||this.showValues==2){graph+='</tr><tr align=center>';if(titleValue!='')graph+='<td style="'+this.cssTITLE+'">'+titleValue+'</td>';for(i=0;i<val[chart].length;i++){for(j=0;j<val[chart][i].length;j++){graph+=this.build_value(val[chart][i][j],max_dec);}
if(this.labelSpace)graph+='<td width='+this.labelSpace+'></td>';}}
graph+='</tr><tr>';if(titleLabel!='')graph+='<td style="'+this.cssTITLE+'">'+titleLabel+'</td>';for(i=0;i<val[chart].length;i++,lcnt++){label=(lcnt<r.length)?_trim(r[lcnt]):lcnt+1;colspan=val[chart][i].length;graph+='<td style="'+this.cssLABEL+'"'+((colspan>1)?' colspan='+colspan:'')+'>';graph+='&nbsp;'+label+'&nbsp;</td>';if(this.labelSpace)graph+='<td width='+this.labelSpace+'></td>';}
graph+='</tr>';}
else if(this.type=='pbar'||this.type=='fader'){if(t.length>0)graph+=this.build_hTitle(titleLabel,titleValue,titleBar);for(i=0;i<val[chart].length;i++,lcnt++){label=(lcnt<r.length)?_trim(r[lcnt]):'';graph+='<tr>';if(label){graph+='<td style="'+this.cssLABEL+'">';graph+='&nbsp;'+label+'&nbsp;</td>';}
sum=val[chart][i][1]?val[chart][i][1]:0;percent=sum?val[chart][i][0]*100/sum:0;value=_number_format(val[chart][i][0],max_dec);if(this.showValues==1||this.showValues==2)
graph+=this.build_value(val[chart][i][0],max_dec,sum,'right');graph+='<td'+(this.cssBARBG?' style="'+this.cssBARBG+'"':'')+'>';this.barColors=drc[i]?_trim(drc[i]):this.colors[0];bColor=this.level_color(val[chart][i][0],this.barColors);graph+='<table border=0 cellspacing=0 cellpadding=0><tr><td>';if(this.type=='fader')graph+=this.build_fader(value,Math.round(this.barWidth/2),this.barWidth,Math.round(percent*mul),bColor);else graph+=this.build_bar(value,Math.round(percent*mul),this.barWidth,bColor);graph+='</td><td width='+Math.round((100-percent)*mul)+'></td>';graph+='</tr></table></td>';if(this.showValues<2)graph+='<td style="'+this.cssPERCVALUES+'" nowrap>&nbsp;'+_number_format(percent,this.percValuesDecimals)+'%</td>';graph+='</tr>';if(this.labelSpace&&i<val[chart].length-1)graph+='<td colspan=3 height='+this.labelSpace+'></td>';}}
else graph+='<tr><td>'+this.err_type+'</td></tr>';graph+='</table>';if(chart<this.charts-1&&val[chart+1].length){graph+='</td>';if(this.type=='vbar')graph+='</tr><tr valign=top>';graph+='<td>';}}
if(this.charts>1)graph+='</td></tr></table>';if(this.legend&&this.type!='pbar'&&this.type!='fader'){graph+='</td><td width=10>&nbsp;</td><td>';graph+=this.build_legend(bc);graph+='</td></tr></table>';}
if(this.debug){graph+='<br>sum='+sum+' max='+max+' max_neg='+max_neg+' max_dec='+max_dec;graph+=' mPerc='+mPerc+' mPerc_neg='+mPerc_neg+' mul='+mul+' valSpace='+valSpace;}
graph+='</td></tr></table>';return graph;}}
function _number_format(val,dec){if(dec){if(val<0){var neg=true;val*=-1;}
else var neg=false;var v=(Math.round(val*Math.pow(10,dec))).toString();if(v.length<=dec)for(var i=0;i<dec-v.length+1;i++)v='0'+v;v=v.substr(0,v.length-dec)+'.'+v.substr(v.length-dec);if(v.substr(0,1)=='.')v='0'+v;if(neg)v='-'+v;}
else v=Math.round(val);return v;}
function _trim(str){return str.replace(/^\s+|\s+$/,'');}