rgraph-rails 5.00 → 6.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/publish-geml.yaml +46 -0
  3. data/.gitignore +1 -0
  4. data/README.md +4 -5
  5. data/lib/rgraph-rails/version.rb +1 -1
  6. data/rgraph-rails.gemspec +4 -4
  7. data/vendor/assets/javascripts/RGraph.activity.js +1691 -0
  8. data/vendor/assets/javascripts/RGraph.bar.js +4253 -236
  9. data/vendor/assets/javascripts/RGraph.bipolar.js +3958 -162
  10. data/vendor/assets/javascripts/RGraph.common.annotate.js +414 -35
  11. data/vendor/assets/javascripts/RGraph.common.context.js +635 -30
  12. data/vendor/assets/javascripts/RGraph.common.core.js +10485 -419
  13. data/vendor/assets/javascripts/RGraph.common.csv.js +508 -27
  14. data/vendor/assets/javascripts/RGraph.common.dynamic.js +1693 -90
  15. data/vendor/assets/javascripts/RGraph.common.effects.js +1629 -89
  16. data/vendor/assets/javascripts/RGraph.common.key.js +1003 -53
  17. data/vendor/assets/javascripts/RGraph.common.moment.js +5670 -0
  18. data/vendor/assets/javascripts/RGraph.common.sheets.js +541 -31
  19. data/vendor/assets/javascripts/RGraph.common.sheets.php +351 -0
  20. data/vendor/assets/javascripts/RGraph.common.starburst.js +382 -0
  21. data/vendor/assets/javascripts/RGraph.common.table.js +386 -0
  22. data/vendor/assets/javascripts/RGraph.common.tooltips.js +1433 -32
  23. data/vendor/assets/javascripts/RGraph.drawing.background.js +660 -35
  24. data/vendor/assets/javascripts/RGraph.drawing.circle.js +618 -34
  25. data/vendor/assets/javascripts/RGraph.drawing.image.js +857 -52
  26. data/vendor/assets/javascripts/RGraph.drawing.line.js +712 -0
  27. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +760 -38
  28. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +740 -37
  29. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +573 -36
  30. data/vendor/assets/javascripts/RGraph.drawing.poly.js +667 -36
  31. data/vendor/assets/javascripts/RGraph.drawing.rect.js +638 -34
  32. data/vendor/assets/javascripts/RGraph.drawing.text.js +672 -37
  33. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +653 -52
  34. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +714 -51
  35. data/vendor/assets/javascripts/RGraph.fuel.js +1149 -59
  36. data/vendor/assets/javascripts/RGraph.funnel.js +1277 -56
  37. data/vendor/assets/javascripts/RGraph.gantt.js +1646 -82
  38. data/vendor/assets/javascripts/RGraph.gauge.js +1773 -89
  39. data/vendor/assets/javascripts/RGraph.hbar.js +3869 -159
  40. data/vendor/assets/javascripts/RGraph.horseshoe.js +970 -0
  41. data/vendor/assets/javascripts/RGraph.hprogress.js +1829 -81
  42. data/vendor/assets/javascripts/RGraph.line.js +5293 -244
  43. data/vendor/assets/javascripts/RGraph.meter.js +1570 -77
  44. data/vendor/assets/javascripts/RGraph.modaldialog.js +300 -19
  45. data/vendor/assets/javascripts/RGraph.odo.js +1553 -68
  46. data/vendor/assets/javascripts/RGraph.pie.js +3273 -129
  47. data/vendor/assets/javascripts/RGraph.radar.js +2333 -108
  48. data/vendor/assets/javascripts/RGraph.rose.js +2685 -114
  49. data/vendor/assets/javascripts/RGraph.rscatter.js +1920 -80
  50. data/vendor/assets/javascripts/RGraph.scatter.js +4215 -171
  51. data/vendor/assets/javascripts/RGraph.segmented.js +1006 -0
  52. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1980 -59
  53. data/vendor/assets/javascripts/RGraph.svg.activity.js +1696 -0
  54. data/vendor/assets/javascripts/RGraph.svg.bar.js +2575 -77
  55. data/vendor/assets/javascripts/RGraph.svg.bipolar.js +3533 -106
  56. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +240 -21
  57. data/vendor/assets/javascripts/RGraph.svg.common.core.js +7105 -299
  58. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +408 -28
  59. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +1291 -68
  60. data/vendor/assets/javascripts/RGraph.svg.common.key.js +451 -20
  61. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +543 -31
  62. data/vendor/assets/javascripts/RGraph.svg.common.table.js +391 -0
  63. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +1072 -23
  64. data/vendor/assets/javascripts/RGraph.svg.funnel.js +1151 -32
  65. data/vendor/assets/javascripts/RGraph.svg.gauge.js +1429 -34
  66. data/vendor/assets/javascripts/RGraph.svg.hbar.js +2692 -65
  67. data/vendor/assets/javascripts/RGraph.svg.horseshoe.js +969 -0
  68. data/vendor/assets/javascripts/RGraph.svg.line.js +2855 -86
  69. data/vendor/assets/javascripts/RGraph.svg.pie.js +1630 -58
  70. data/vendor/assets/javascripts/RGraph.svg.radar.js +1772 -58
  71. data/vendor/assets/javascripts/RGraph.svg.rose.js +2419 -83
  72. data/vendor/assets/javascripts/RGraph.svg.scatter.js +2280 -65
  73. data/vendor/assets/javascripts/RGraph.svg.segmented.js +930 -0
  74. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +1612 -29
  75. data/vendor/assets/javascripts/RGraph.svg.waterfall.js +1525 -50
  76. data/vendor/assets/javascripts/RGraph.thermometer.js +1411 -64
  77. data/vendor/assets/javascripts/RGraph.vprogress.js +1915 -81
  78. data/vendor/assets/javascripts/RGraph.waterfall.js +1896 -89
  79. data/vendor/assets/javascripts/financial-data.js +1067 -0
  80. metadata +37 -16
  81. data/.travis.yml +0 -11
  82. data/vendor/assets/javascripts/RGraph.common.deprecated.js +0 -35
  83. data/vendor/assets/javascripts/RGraph.common.resizing.js +0 -38
  84. data/vendor/assets/javascripts/RGraph.common.zoom.js +0 -15
  85. data/vendor/assets/javascripts/RGraph.cornergauge.js +0 -71
@@ -1,78 +1,2576 @@
1
+ 'version:2023-09-16 (6.14)';
2
+ //
3
+ // o--------------------------------------------------------------------------------o
4
+ // | This file is part of the RGraph package - you can learn more at: |
5
+ // | |
6
+ // | https://www.rgraph.net |
7
+ // | |
8
+ // | RGraph is licensed under the Open Source MIT license. That means that it's |
9
+ // | totally free to use and there are no restrictions on what you can do with it! |
10
+ // o--------------------------------------------------------------------------------o
1
11
 
2
- RGraph=window.RGraph||{isRGraph:true};RGraph.SVG=RGraph.SVG||{};(function(win,doc,undefined)
3
- {var RG=RGraph,ua=navigator.userAgent,ma=Math,win=window,doc=document;RG.SVG.Bar=function(conf)
4
- {this.set=function(name,value)
5
- {if(arguments.length===1&&typeof name==='object'){for(i in arguments[0]){if(typeof i==='string'){name=ret.name;value=ret.value;this.set(name,value);}}}else{var ret=RG.SVG.commonSetter({object:this,name:name,value:value});name=ret.name;value=ret.value;this.properties[name]=value;if(name==='colors'){this.originalColors=RG.SVG.arrayClone(value);this.colorsParsed=false;}}
6
- return this;};this.get=function(name)
7
- {return this.properties[name];};this.id=conf.id;this.uid=RG.SVG.createUID();this.container=document.getElementById(this.id);this.layers={};this.svg=RG.SVG.createSVG({object:this,container:this.container});this.isRGraph=true;this.data=conf.data;this.type='bar';this.coords=[];this.coords2=[];this.stackedBackfaces=[];this.originalColors={};this.gradientCounter=1;this.propertyNameAliases={};RG.SVG.OR.add(this);this.container.style.display='inline-block';this.properties={marginLeft:35,marginRight:35,marginTop:35,marginBottom:35,variant:null,variant3dOffsetx:10,variant3dOffsety:5,backgroundColor:null,backgroundImage:null,backgroundImageAspect:'none',backgroundImageStretch:true,backgroundImageOpacity:null,backgroundImageX:null,backgroundImageY:null,backgroundImageW:null,backgroundImageH:null,backgroundGrid:true,backgroundGridColor:'#ddd',backgroundGridLinewidth:1,backgroundGridHlines:true,backgroundGridHlinesCount:null,backgroundGridVlines:true,backgroundGridVlinesCount:null,backgroundGridBorder:true,backgroundGridDashed:false,backgroundGridDotted:false,backgroundGridDashArray:null,colors:['red','#0f0','#00f','#ff0','#0ff','#0f0','pink','orange','gray','black','red','#0f0','#00f','#ff0','#0ff','#0f0','pink','orange','gray','black'],colorsSequential:false,colorsStroke:'rgba(0,0,0,0)',errorbars:null,hmargin:3,hmarginGrouped:2,hmarginLeft:0,hmarginRight:0,yaxis:true,yaxisTickmarks:true,yaxisTickmarksLength:3,yaxisColor:'black',yaxisScale:true,yaxisLabels:null,yaxisLabelsFont:null,yaxisLabelsSize:null,yaxisLabelsColor:null,yaxisLabelsBold:null,yaxisLabelsItalic:null,yaxisLabelsOffsetx:0,yaxisLabelsOffsety:0,yaxisLabelsCount:5,yaxisScaleUnitsPre:'',yaxisScaleUnitsPost:'',yaxisScaleStrict:false,yaxisScaleDecimals:0,yaxisScalePoint:'.',yaxisScaleThousand:',',yaxisScaleRound:false,yaxisScaleMax:null,yaxisScaleMin:0,yaxisScaleFormatter:null,xaxis:true,xaxisTickmarks:true,xaxisTickmarksLength:5,xaxisLabels:null,xaxisLabelsFont:null,xaxisLabelsSize:null,xaxisLabelsColor:null,xaxisLabelsBold:null,xaxisLabelsItalic:null,xaxisLabelsPosition:'section',xaxisLabelsPositionSectionTickmarksCount:null,xaxisLabelsOffsetx:0,xaxisLabelsOffsety:0,xaxisColor:'black',labelsAbove:false,labelsAboveFont:null,labelsAboveSize:null,labelsAboveBold:null,labelsAboveItalic:null,labelsAboveColor:null,labelsAboveBackground:null,labelsAboveBackgroundPadding:0,labelsAboveUnitsPre:null,labelsAboveUnitsPost:null,labelsAbovePoint:null,labelsAboveThousand:null,labelsAboveFormatter:null,labelsAboveDecimals:null,labelsAboveOffsetx:0,labelsAboveOffsety:0,labelsAboveHalign:'center',labelsAboveValign:'bottom',labelsAboveSpecific:null,textColor:'black',textFont:'Arial, Verdana, sans-serif',textSize:12,textBold:false,textItalic:false,linewidth:1,grouping:'grouped',tooltips:null,tooltipsOverride:null,tooltipsEffect:'fade',tooltipsCssClass:'RGraph_tooltip',tooltipsEvent:'click',highlightStroke:'rgba(0,0,0,0)',highlightFill:'rgba(255,255,255,0.7)',highlightLinewidth:1,title:'',titleX:null,titleY:null,titleHalign:'center',titleValign:null,titleSize:null,titleColor:null,titleFont:null,titleBold:null,titleItalic:null,titleSubtitle:null,titleSubtitleX:null,titleSubtitleY:null,titleSubtitleHalign:'center',titleSubtitleValign:null,titleSubtitleSize:null,titleSubtitleColor:'#aaa',titleSubtitleFont:null,titleSubtitleBold:null,titleSubtitleItalic:null,shadow:false,shadowOffsetx:2,shadowOffsety:2,shadowBlur:2,shadowOpacity:0.25,errorbars:null,errorbarsColor:'black',errorbarsLinewidth:1,errorbarsCapwidth:10,key:null,keyColors:null,keyOffsetx:0,keyOffsety:0,keyLabelsOffsetx:0,keyLabelsOffsety:-1,keyLabelsColor:null,keyLabelsSize:null,keyLabelsBold:null,keyLabelsItalic:null,keyLabelsFont:null};RG.SVG.getGlobals(this);if(RG.SVG.FX&&typeof RG.SVG.FX.decorate==='function'){RG.SVG.FX.decorate(this);}
8
- var prop=this.properties;this.draw=function()
9
- {RG.SVG.fireCustomEvent(this,'onbeforedraw');this.width=Number(this.svg.getAttribute('width'));this.height=Number(this.svg.getAttribute('height'));if(prop.variant!=='3d'){prop.variant3dOffsetx=0;prop.variant3dOffsety=0;}else{this.svg.all.setAttribute('transform','skewY(5)');}
10
- RG.SVG.createDefs(this);this.coords=[];this.coords2=[];this.graphWidth=this.width-prop.marginLeft-prop.marginRight;this.graphHeight=this.height-prop.marginTop-prop.marginBottom;this.data_seq=RG.SVG.arrayLinearize(this.data);if(prop.errorbars){for(var i=0;i<this.data_seq.length;++i){if(typeof prop.errorbars[i]==='undefined'||RG.SVG.isNull(prop.errorbars[i])){prop.errorbars[i]={max:null,min:null};}else if(typeof prop.errorbars[i]==='number'){prop.errorbars[i]={min:prop.errorbars[i],max:prop.errorbars[i]};}else if(typeof prop.errorbars[i]==='object'&&typeof prop.errorbars[i].max==='undefined'){prop.errorbars[i].max=null;}else if(typeof prop.errorbars[i]==='object'&&typeof prop.errorbars[i].min==='undefined'){prop.errorbars[i].min=null;}}}
11
- RG.SVG.resetColorsToOriginalValues({object:this});this.parseColors();var values=[];for(var i=0,max=0;i<this.data.length;++i){if(prop.errorbars&&typeof prop.errorbars[i]==='number'){var errorbar=prop.errorbars[i];}else if(prop.errorbars&&typeof prop.errorbars[i]==='object'&&typeof prop.errorbars[i].max==='number'){var errorbar=prop.errorbars[i].max;}else{var errorbar=0;}
12
- if(typeof this.data[i]==='number'){values.push(this.data[i]+errorbar);}else if(RG.SVG.isArray(this.data[i])&&prop.grouping==='grouped'){values.push(RG.SVG.arrayMax(this.data[i])+errorbar);}else if(RG.SVG.isArray(this.data[i])&&prop.grouping==='stacked'){values.push(RG.SVG.arraySum(this.data[i])+errorbar);}}
13
- var max=RG.SVG.arrayMax(values);if(typeof prop.yaxisScaleMax==='number'){max=prop.yaxisScaleMax;}
14
- if(prop.yaxisScaleMin==='mirror'||prop.yaxisScaleMin==='middle'||prop.yaxisScaleMin==='center'){this.mirrorScale=true;var mirrorScale=true;prop.yaxisScaleMin=0;}
15
- this.scale=RG.SVG.getScale({object:this,numlabels:prop.yaxisLabelsCount,unitsPre:prop.yaxisScaleUnitsPre,unitsPost:prop.yaxisScaleUnitsPost,max:max,min:prop.yaxisScaleMin,point:prop.yaxisScalePoint,round:prop.yaxisScaleRound,thousand:prop.yaxisScaleThousand,decimals:prop.yaxisScaleDecimals,strict:typeof prop.yaxisScaleMax==='number',formatter:prop.yaxisScaleFormatter});if(mirrorScale){this.scale=RG.SVG.getScale({object:this,numlabels:prop.yaxisLabelsCount,unitsPre:prop.yaxisScaleUnitsPre,unitsPost:prop.yaxisScaleUnitsPost,max:this.scale.max,min:this.scale.max* -1,point:prop.yaxisScalePoint,round:false,thousand:prop.yaxisScaleThousand,decimals:prop.yaxisScaleDecimals,strict:typeof prop.yaxisScaleMax==='number',formatter:prop.yaxisScaleFormatter});}
16
- this.max=this.scale.max;this.min=this.scale.min;RG.SVG.drawBackground(this);if(prop.variant==='3d'){RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(prop.marginLeft,prop.marginTop,prop.marginLeft+prop.variant3dOffsetx,prop.marginTop-prop.variant3dOffsety,prop.marginLeft+prop.variant3dOffsetx,this.height-prop.marginBottom-prop.variant3dOffsety,prop.marginLeft,this.height-prop.marginBottom,prop.marginLeft,prop.marginTop),fill:'#ddd',stroke:'#ccc'}});this.threed_xaxis_group=RG.SVG.create({svg:this.svg,type:'g',parent:this.svg.all,attr:{className:'rgraph_3d_bar_xaxis_negative'}});RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'path',attr:{d:'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(prop.marginLeft,this.getYCoord(0),prop.marginLeft+prop.variant3dOffsetx,this.getYCoord(0)-prop.variant3dOffsety,this.width-prop.marginRight+prop.variant3dOffsetx,this.getYCoord(0)-prop.variant3dOffsety,this.width-prop.marginRight,this.getYCoord(0),prop.marginLeft,this.getYCoord(0)),fill:'#ddd',stroke:'#ccc'}});}
17
- this.drawBars();RG.SVG.drawXAxis(this);RG.SVG.drawYAxis(this);this.drawLabelsAbove();if(typeof prop.key!==null&&RG.SVG.drawKey){RG.SVG.drawKey(this);}else if(!RGraph.SVG.isNull(prop.key)){alert('The drawKey() function does not exist - have you forgotten to include the key library?');}
18
- RG.SVG.fireCustomEvent(this,'ondraw');return this;};this.drawBars=function()
19
- {var y=this.getYCoord(0);if(prop.shadow){RG.SVG.setShadow({object:this,offsetx:prop.shadowOffsetx,offsety:prop.shadowOffsety,blur:prop.shadowBlur,opacity:prop.shadowOpacity,id:'dropShadow'});}
20
- for(var i=0,sequentialIndex=0;i<this.data.length;++i,++sequentialIndex){if(typeof this.data[i]==='number'){var outerSegment=(this.graphWidth-prop.hmarginLeft-prop.hmarginRight)/this.data.length,height=(ma.abs(this.data[i])-ma.abs(this.scale.min))/(ma.abs(this.scale.max)-ma.abs(this.scale.min))*this.graphHeight,width=((this.graphWidth-prop.hmarginLeft-prop.hmarginRight)/this.data.length)-prop.hmargin-prop.hmargin,x=prop.marginLeft+prop.hmargin+prop.hmarginLeft+(outerSegment*i);if(this.scale.min>=0&&this.scale.max>0){y=this.getYCoord(this.scale.min)-height;}else if(this.scale.min<0&&this.scale.max>0){height=(ma.abs(this.data[i])/(this.scale.max-this.scale.min))*this.graphHeight;y=this.getYCoord(0)-height;if(this.data[i]<0){y=this.getYCoord(0);}}else if(this.scale.min<0&&this.scale.max<0){height=(ma.abs(this.data[i])-ma.abs(this.scale.max))/(ma.abs(this.scale.min)-ma.abs(this.scale.max))*this.graphHeight;y=prop.marginTop;}
21
- var rect=RG.SVG.create({svg:this.svg,type:'rect',parent:prop.variant==='3d'&&this.data[i]<0?this.threed_xaxis_group:this.svg.all,attr:{stroke:prop.colorsStroke,fill:prop.colorsSequential?(prop.colors[sequentialIndex]?prop.colors[sequentialIndex]:prop.colors[prop.colors.length-1]):prop.colors[0],x:x,y:y,width:width<0?0:width,height:height,'stroke-width':prop.linewidth,'data-original-x':x,'data-original-y':y,'data-original-width':width,'data-original-height':height,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[i]:'','data-index':i,'data-sequential-index':sequentialIndex,'data-value':this.data[i],filter:prop.shadow?'url(#dropShadow)':''}});this.drawErrorbar({object:this,element:rect,index:i,value:this.data[i],type:'normal'});this.coords.push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(!this.coords2[0]){this.coords2[0]=[];}
22
- this.coords2[0].push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(prop.variant==='3d'){this.drawTop3dFace({rect:rect,value:this.data[i]});this.drawSide3dFace({rect:rect,value:this.data[i]});}
23
- if(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips[sequentialIndex]){var obj=this;(function(idx,seq)
24
- {rect.addEventListener(prop.tooltipsEvent.replace(/^on/,''),function(e)
25
- {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:idx,group:null,sequentialIndex:seq,text:prop.tooltips[seq],event:e});obj.highlight(e.target);},false);rect.addEventListener('mousemove',function(e)
26
- {e.target.style.cursor='pointer'},false);})(i,sequentialIndex);}}else if(RG.SVG.isArray(this.data[i])&&prop.grouping==='grouped'){var outerSegment=((this.graphWidth-prop.hmarginLeft-prop.hmarginRight)/this.data.length),innerSegment=outerSegment-(2*prop.hmargin);for(var j=0;j<this.data[i].length;++j,++sequentialIndex){var width=((innerSegment-((this.data[i].length-1)*prop.hmarginGrouped))/this.data[i].length),x=(outerSegment*i)+prop.hmargin+prop.marginLeft+prop.hmarginLeft+(j*width)+((j-1)*prop.hmarginGrouped);x=prop.marginLeft+prop.hmarginLeft+(outerSegment*i)+(width*j)+prop.hmargin+(j*prop.hmarginGrouped);if(this.scale.min===0&&this.scale.max>this.scale.min){var height=((this.data[i][j]-this.scale.min)/(this.scale.max-this.scale.min))*this.graphHeight,y=this.getYCoord(0)-height;}else if(this.scale.max<=0&&this.scale.min<this.scale.max){var height=((this.data[i][j]-this.scale.max)/(this.scale.max-this.scale.min))*this.graphHeight,y=this.getYCoord(this.scale.max);height=ma.abs(height);}else if(this.scale.max>0&&this.scale.min<0){var height=(ma.abs(this.data[i][j])/(this.scale.max-this.scale.min))*this.graphHeight,y=this.data[i][j]<0?this.getYCoord(0):this.getYCoord(this.data[i][j]);}else if(this.scale.min>0&&this.scale.max>this.scale.min){var height=(ma.abs(this.data[i][j]-this.scale.min)/(this.scale.max-this.scale.min))*this.graphHeight,y=this.getYCoord(this.scale.min)-height;}
27
- var rect=RG.SVG.create({svg:this.svg,parent:prop.variant==='3d'&&this.data[i][j]<0?this.threed_xaxis_group:this.svg.all,type:'rect',attr:{stroke:prop['strokestyle'],fill:(prop.colorsSequential&&prop.colors[sequentialIndex])?prop.colors[sequentialIndex]:prop.colors[j],x:x,y:y,width:width,height:height,'stroke-width':prop.linewidth,'data-original-x':x,'data-original-y':y,'data-original-width':width,'data-original-height':height,'data-index':i,'data-subindex':j,'data-sequential-index':sequentialIndex,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[sequentialIndex]:'','data-value':this.data[i][j],filter:prop.shadow?'url(#dropShadow)':''}});this.drawErrorbar({object:this,element:rect,index:sequentialIndex,value:this.data[i][j],type:'grouped'});this.coords.push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(!this.coords2[i]){this.coords2[i]=[];}
28
- this.coords2[i].push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(prop.variant==='3d'){this.drawTop3dFace({rect:rect,value:this.data[i][j]});this.drawSide3dFace({rect:rect,value:this.data[i][j]});}
29
- if(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips[sequentialIndex]){var obj=this;(function(idx,seq)
30
- {obj.removeHighlight();var indexes=RG.SVG.sequentialIndexToGrouped(seq,obj.data);rect.addEventListener(prop.tooltipsEvent.replace(/^on/,''),function(e)
31
- {RG.SVG.tooltip({object:obj,group:idx,index:indexes[1],sequentialIndex:seq,text:prop.tooltips[seq],event:e});obj.highlight(e.target);},false);rect.addEventListener('mousemove',function(e)
32
- {e.target.style.cursor='pointer'},false);})(i,sequentialIndex);}}
33
- --sequentialIndex;}else if(RG.SVG.isArray(this.data[i])&&prop.grouping==='stacked'){var section=((this.graphWidth-prop.hmarginLeft-prop.hmarginRight)/this.data.length);var y=this.getYCoord(0);for(var j=0;j<this.data[i].length;++j,++sequentialIndex){var height=(this.data[i][j]/(this.max-this.min))*this.graphHeight,width=section-(2*prop.hmargin),x=prop.marginLeft+prop.hmarginLeft+(i*section)+prop.hmargin,y=y-height;if(j===0&&prop.shadow){var fullHeight=(RG.SVG.arraySum(this.data[i])/(this.max-this.min))*this.graphHeight;var rect=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'rect',attr:{fill:'white',x:x,y:this.height-prop.marginBottom-fullHeight,width:width,height:fullHeight,'stroke-width':0,'data-index':i,filter:'url(#dropShadow)'}});this.stackedBackfaces[i]=rect;}
34
- var rect=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'rect',attr:{stroke:prop['strokestyle'],fill:prop.colorsSequential?(prop.colors[sequentialIndex]?prop.colors[sequentialIndex]:prop.colors[prop.colors.length-1]):prop.colors[j],x:x,y:y,width:width,height:height,'stroke-width':prop.linewidth,'data-original-x':x,'data-original-y':y,'data-original-width':width,'data-original-height':height,'data-index':i,'data-subindex':j,'data-sequential-index':sequentialIndex,'data-tooltip':(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips.length)?prop.tooltips[sequentialIndex]:'','data-value':this.data[i][j]}});if(j===(this.data[i].length-1)){this.drawErrorbar({object:this,element:rect,index:i,value:this.data[i][j],type:'stacked'});}
35
- this.coords.push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(!this.coords2[i]){this.coords2[i]=[];}
36
- this.coords2[i].push({object:this,element:rect,x:parseFloat(rect.getAttribute('x')),y:parseFloat(rect.getAttribute('y')),width:parseFloat(rect.getAttribute('width')),height:parseFloat(rect.getAttribute('height'))});if(prop.variant==='3d'){this.drawTop3dFace({rect:rect,value:this.data[i][j]});this.drawSide3dFace({rect:rect,value:this.data[i][j]});}
37
- if(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips[sequentialIndex]){var obj=this;(function(idx,seq)
38
- {rect.addEventListener(prop.tooltipsEvent.replace(/^on/,''),function(e)
39
- {obj.removeHighlight();var indexes=RG.SVG.sequentialIndexToGrouped(seq,obj.data);RG.SVG.tooltip({object:obj,index:indexes[1],group:idx,sequentialIndex:seq,text:prop.tooltips[seq],event:e});obj.highlight(e.target);},false);rect.addEventListener('mousemove',function(e)
40
- {e.target.style.cursor='pointer';},false);})(i,sequentialIndex);}}
41
- --sequentialIndex;}}};this.getYCoord=function(value)
42
- {if(value>this.scale.max){return null;}
43
- var y,xaxispos=prop.xaxispos;if(value<this.scale.min){return null;}
44
- y=((value-this.scale.min)/(this.scale.max-this.scale.min));y*=(this.height-prop.marginTop-prop.marginBottom);y=this.height-prop.marginBottom-y;return y;};this.highlight=function(rect)
45
- {var x=rect.getAttribute('x'),y=rect.getAttribute('y'),width=rect.getAttribute('width'),height=rect.getAttribute('height');var highlight=RG.SVG.create({svg:this.svg,parent:this.svg.all,type:'rect',attr:{stroke:prop.highlightStroke,fill:prop.highlightFill,x:x,y:y,width:width,height:height,'stroke-width':prop.highlightLinewidth},style:{pointerEvents:'none'}});if(prop.tooltipsEvent==='mousemove'){}
46
- RG.SVG.REG.set('highlight',highlight);};this.parseColors=function()
47
- {if(!Object.keys(this.originalColors).length){this.originalColors={colors:RG.SVG.arrayClone(prop.colors),backgroundGridColor:RG.SVG.arrayClone(prop.backgroundGridColor),highlightFill:RG.SVG.arrayClone(prop.highlightFill),backgroundColor:RG.SVG.arrayClone(prop.backgroundColor)}}
48
- var colors=prop.colors;if(colors){for(var i=0;i<colors.length;++i){colors[i]=RG.SVG.parseColorLinear({object:this,color:colors[i]});}}
49
- prop.backgroundGridColor=RG.SVG.parseColorLinear({object:this,color:prop.backgroundGridColor});prop.highlightFill=RG.SVG.parseColorLinear({object:this,color:prop.highlightFill});prop.backgroundColor=RG.SVG.parseColorLinear({object:this,color:prop.backgroundColor});};this.drawLabelsAbove=function()
50
- {if(prop.labelsAbove){var data_seq=RG.SVG.arrayLinearize(this.data),seq=0,stacked_total=0;;for(var i=0;i<this.coords.length;++i,seq++){var num=typeof this.data[i]==='number'?this.data[i]:data_seq[seq];if(prop.grouping==='stacked'){var indexes=RG.SVG.sequentialIndexToGrouped(i,this.data);var group=indexes[0];var datapiece=indexes[1];if(datapiece!==(this.data[group].length-1)){continue;}else{num=RG.SVG.arraySum(this.data[group]);}}
51
- var str=RG.SVG.numberFormat({object:this,num:num.toFixed(prop.labelsAboveDecimals),prepend:typeof prop.labelsAboveUnitsPre==='string'?prop.labelsAboveUnitsPre:null,append:typeof prop.labelsAboveUnitsPost==='string'?prop.labelsAboveUnitsPost:null,point:typeof prop.labelsAbovePoint==='string'?prop.labelsAbovePoint:null,thousand:typeof prop.labelsAboveThousand==='string'?prop.labelsAboveThousand:null,formatter:typeof prop.labelsAboveFormatter==='function'?prop.labelsAboveFormatter:null});if(prop.labelsAboveSpecific&&prop.labelsAboveSpecific.length&&(typeof prop.labelsAboveSpecific[seq]==='string'||typeof prop.labelsAboveSpecific[seq]==='number')){str=prop.labelsAboveSpecific[seq];}else if(prop.labelsAboveSpecific&&prop.labelsAboveSpecific.length&&typeof prop.labelsAboveSpecific[seq]!=='string'&&typeof prop.labelsAboveSpecific[seq]!=='number'){continue;}
52
- var x=parseFloat(this.coords[i].element.getAttribute('x'))+parseFloat(this.coords[i].element.getAttribute('width')/2)+prop.labelsAboveOffsetx;if(data_seq[i]>=0){var y=parseFloat(this.coords[i].element.getAttribute('y'))-7+prop.labelsAboveOffsety;var valign=prop.labelsAboveValign;}else{var y=parseFloat(this.coords[i].element.getAttribute('y'))+parseFloat(this.coords[i].element.getAttribute('height'))+7-prop.labelsAboveOffsety;var valign=prop.labelsAboveValign==='top'?'bottom':'top';}
53
- RG.SVG.text({object:this,parent:this.svg.all,text:str,x:x,y:y,halign:prop.labelsAboveHalign,valign:valign,tag:'labels.above',font:prop.labelsAboveFont||prop.textFont,size:prop.labelsAboveSize||prop.textSize,bold:prop.labelsAboveBold||prop.textBold,italic:prop.labelsAboveItalic||prop.textItalic,color:prop.labelsAboveColor||prop.textColor,background:prop.labelsAboveBackground||null,padding:prop.labelsAboveBackgroundPadding||0});}}};this.on=function(type,func)
54
- {if(type.substr(0,2)!=='on'){type='on'+type;}
55
- RG.SVG.addCustomEventListener(this,type,func);return this;};this.exec=function(func)
56
- {func(this);return this;};this.removeHighlight=function()
57
- {var highlight=RG.SVG.REG.get('highlight');if(highlight&&highlight.parentNode){highlight.parentNode.removeChild(highlight);}
58
- RG.SVG.REG.set('highlight',null);};this.drawTop3dFace=function(opt)
59
- {var rect=opt.rect,arr=[parseInt(rect.getAttribute('fill')),'rgba(255,255,255,0.7)'],x=parseInt(rect.getAttribute('x')),y=parseInt(rect.getAttribute('y')),w=parseInt(rect.getAttribute('width')),h=parseInt(rect.getAttribute('height')),value=parseFloat(rect.getAttribute('data-value'));rect.rgraph_3d_top_face=[];for(var i=0;i<2;++i){var color=(i===0?rect.getAttribute('fill'):'rgba(255,255,255,0.7)');var face=RG.SVG.create({svg:this.svg,type:'path',parent:prop.variant==='3d'&&opt.value<0?this.threed_xaxis_group:this.svg.all,attr:{stroke:prop.colorsStroke,fill:color,'stroke-width':prop.linewidth,d:'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(x,y,x+prop.variant3dOffsetx,y-prop.variant3dOffsety,x+w+prop.variant3dOffsetx,y-prop.variant3dOffsety,x+w,y)}});rect.rgraph_3d_top_face[i]=face}};this.drawSide3dFace=function(opt)
60
- {var rect=opt.rect,arr=[parseInt(rect.getAttribute('fill')),'rgba(0,0,0,0.3)'],x=parseInt(rect.getAttribute('x')),y=parseInt(rect.getAttribute('y')),w=parseInt(rect.getAttribute('width')),h=parseInt(rect.getAttribute('height'));rect.rgraph_3d_side_face=[];for(var i=0;i<2;++i){var color=(i===0?rect.getAttribute('fill'):'rgba(0,0,0,0.3)');var face=RG.SVG.create({svg:this.svg,type:'path',parent:prop.variant==='3d'&&opt.value<0?this.threed_xaxis_group:this.svg.all,attr:{stroke:prop.colorsStroke,fill:color,'stroke-width':prop.linewidth,d:'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(x+w,y,x+w+prop.variant3dOffsetx,y-prop.variant3dOffsety,x+w+prop.variant3dOffsetx,y+h-prop.variant3dOffsety,x+w,y+h)}});rect.rgraph_3d_side_face[i]=face}};this.drawErrorbar=function(opt)
61
- {var prop=this.properties,index=opt.index,datapoint=opt.value,linewidth=RG.SVG.getErrorbarsLinewidth({object:this,index:index}),color=RG.SVG.getErrorbarsColor({object:this,index:index}),capwidth=RG.SVG.getErrorbarsCapWidth({object:this,index:index}),element=opt.element,type=opt.type;var max=RG.SVG.getErrorbarsMaxValue({object:this,index:index});var min=RG.SVG.getErrorbarsMinValue({object:this,index:index});if(!max&&!min){return;}
62
- if(type==='stacked'){datapoint=RG.SVG.arraySum(this.data[index]);}
63
- if(datapoint>=0){var x1=parseFloat(element.getAttribute('x'))+(parseFloat(element.getAttribute('width'))/2);var errorbarLine=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:x1,y1:parseFloat(element.getAttribute('y')),x2:x1,y2:this.getYCoord(parseFloat(datapoint+max)),stroke:color,'stroke-width':linewidth}});var errorbarCap=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:parseFloat(errorbarLine.getAttribute('x1'))-(capwidth/2),y1:errorbarLine.getAttribute('y2'),x2:parseFloat(errorbarLine.getAttribute('x1'))+(capwidth/2),y2:errorbarLine.getAttribute('y2'),stroke:color,'stroke-width':linewidth}});if(typeof min==='number'){var errorbarLine=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:x1,y1:parseFloat(element.getAttribute('y')),x2:x1,y2:this.getYCoord(parseFloat(datapoint-min)),stroke:color,'stroke-width':linewidth}});var errorbarCap=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:parseFloat(errorbarLine.getAttribute('x1'))-(capwidth/2),y1:errorbarLine.getAttribute('y2'),x2:parseFloat(errorbarLine.getAttribute('x1'))+(capwidth/2),y2:errorbarLine.getAttribute('y2'),stroke:color,'stroke-width':linewidth}});}}else if(datapoint<0){var x1=parseFloat(element.getAttribute('x'))+(parseFloat(element.getAttribute('width'))/2),y1=parseFloat(element.getAttribute('y'))+parseFloat(element.getAttribute('height')),y2=this.getYCoord(parseFloat(datapoint-ma.abs(max)))
64
- var errorbarLine=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:x1,y1:y1,x2:x1,y2:y2,stroke:color,'stroke-width':linewidth}});var errorbarCap=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:parseFloat(errorbarLine.getAttribute('x1'))-(capwidth/2),y1:errorbarLine.getAttribute('y2'),x2:parseFloat(errorbarLine.getAttribute('x1'))+(capwidth/2),y2:errorbarLine.getAttribute('y2'),stroke:color,'stroke-width':linewidth}});if(typeof min==='number'){var x1=parseFloat(element.getAttribute('x'))+(parseFloat(element.getAttribute('width'))/2);var errorbarLine=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:x1,y1:this.getYCoord(parseFloat(datapoint+min)),x2:x1,y2:this.getYCoord(parseFloat(datapoint)),stroke:color,'stroke-width':linewidth}});var errorbarCap=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:parseFloat(errorbarLine.getAttribute('x1'))-(capwidth/2),y1:errorbarLine.getAttribute('y1'),x2:parseFloat(errorbarLine.getAttribute('x1'))+(capwidth/2),y2:errorbarLine.getAttribute('y1'),stroke:color,'stroke-width':linewidth}});}}};this.grow=function()
65
- {var opt=arguments[0]||{},frames=opt.frames||30,frame=0,obj=this,data=[],height=null,seq=0;data=RG.SVG.arrayClone(this.data);this.draw();var iterate=function()
66
- {for(var i=0,seq=0,len=obj.coords.length;i<len;++i,++seq){var multiplier=(frame/frames)*RG.SVG.FX.getEasingMultiplier(frames,frame)*RG.SVG.FX.getEasingMultiplier(frames,frame);if(typeof data[i]==='number'){height=ma.abs(obj.getYCoord(data[i])-obj.getYCoord(0));obj.data[i]=data[i]*multiplier;height=multiplier*height;obj.coords[seq].element.setAttribute('height',height);obj.coords[seq].element.setAttribute('y',data[i]<0?obj.getYCoord(0):obj.getYCoord(0)-height);if(prop.variant==='3d'){if(obj.coords[i].element.rgraph_3d_side_face[0].parentNode)obj.coords[i].element.rgraph_3d_side_face[0].parentNode.removeChild(obj.coords[i].element.rgraph_3d_side_face[0]);if(obj.coords[i].element.rgraph_3d_side_face[1].parentNode)obj.coords[i].element.rgraph_3d_side_face[1].parentNode.removeChild(obj.coords[i].element.rgraph_3d_side_face[1]);if(obj.coords[i].element.rgraph_3d_top_face[0].parentNode)obj.coords[i].element.rgraph_3d_top_face[0].parentNode.removeChild(obj.coords[i].element.rgraph_3d_top_face[0]);if(obj.coords[i].element.rgraph_3d_top_face[1].parentNode)obj.coords[i].element.rgraph_3d_top_face[1].parentNode.removeChild(obj.coords[i].element.rgraph_3d_top_face[1]);obj.drawSide3dFace({rect:obj.coords[i].element});if(prop.grouping==='grouped'){obj.drawTop3dFace({rect:obj.coords[i].element});}
67
- if(obj.coords[i].element.parentNode){var parent=obj.coords[i].element.parentNode;var node=parent.removeChild(obj.coords[i].element);parent.appendChild(node);}}}else if(typeof data[i]==='object'){var accumulativeHeight=0;for(var j=0,len2=data[i].length;j<len2;++j,++seq){height=ma.abs(obj.getYCoord(data[i][j])-obj.getYCoord(0));height=multiplier*height;obj.data[i][j]=data[i][j]*multiplier;height=ma.round(height);obj.coords[seq].element.setAttribute('height',height);obj.coords[seq].element.setAttribute('y',data[i][j]<0?(obj.getYCoord(0)+accumulativeHeight):(obj.getYCoord(0)-height-accumulativeHeight));if(prop.variant==='3d'){if(obj.coords[seq].element.rgraph_3d_side_face[0].parentNode)obj.coords[seq].element.rgraph_3d_side_face[0].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_side_face[0]);if(obj.coords[seq].element.rgraph_3d_side_face[1].parentNode)obj.coords[seq].element.rgraph_3d_side_face[1].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_side_face[1]);if(obj.coords[seq].element.rgraph_3d_top_face[0].parentNode)obj.coords[seq].element.rgraph_3d_top_face[0].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_top_face[0]);if(obj.coords[seq].element.rgraph_3d_top_face[1].parentNode)obj.coords[seq].element.rgraph_3d_top_face[1].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_top_face[1]);obj.drawSide3dFace({rect:obj.coords[seq].element});obj.drawTop3dFace({rect:obj.coords[seq].element});if(obj.coords[seq].element.parentNode){var parent=obj.coords[seq].element.parentNode;var node=parent.removeChild(obj.coords[seq].element);parent.appendChild(node);}}
68
- accumulativeHeight+=(prop.grouping==='stacked'?height:0);}
69
- if(obj.stackedBackfaces[i]){obj.stackedBackfaces[i].setAttribute('height',accumulativeHeight);obj.stackedBackfaces[i].setAttribute('y',obj.height-prop.marginBottom-accumulativeHeight);}
70
- --seq;}}
71
- if(frame++<frames){RG.SVG.FX.update(iterate);}else if(opt.callback){(opt.callback)(obj);}};iterate();return this;};this.wave=function()
72
- {this.draw();var obj=this,opt=arguments[0]||{};opt.frames=opt.frames||60;opt.startFrames=[];opt.counters=[];var framesperbar=opt.frames/3,frame=-1,callback=opt.callback||function(){};for(var i=0,len=this.coords.length;i<len;i+=1){opt.startFrames[i]=((opt.frames/2)/(obj.coords.length-1))*i;opt.counters[i]=0;this.coords[i].element.setAttribute('height',0);if(this.coords[i].element.rgraph_3d_side_face){var parent=this.coords[i].element.rgraph_3d_side_face[0].parentNode;parent.removeChild(this.coords[i].element.rgraph_3d_side_face[0]);parent.removeChild(this.coords[i].element.rgraph_3d_side_face[1]);parent.removeChild(this.coords[i].element.rgraph_3d_top_face[0]);parent.removeChild(this.coords[i].element.rgraph_3d_top_face[1]);}}
73
- function iterator()
74
- {++frame;for(var i=0,len=obj.coords.length;i<len;i+=1){if(frame>opt.startFrames[i]){var originalHeight=obj.coords[i].element.getAttribute('data-original-height'),height,value=parseFloat(obj.coords[i].element.getAttribute('data-value'));var height=ma.min(((frame-opt.startFrames[i])/framesperbar)*originalHeight,originalHeight);obj.coords[i].element.setAttribute('height',height<0?0:height);obj.coords[i].element.setAttribute('y',value>=0?obj.getYCoord(0)-height:obj.getYCoord(0));if(prop.variant==='3d'){var parent=obj.coords[i].element.rgraph_3d_side_face[0].parentNode;if(parent)parent.removeChild(obj.coords[i].element.rgraph_3d_side_face[0]);if(parent)parent.removeChild(obj.coords[i].element.rgraph_3d_side_face[1]);var parent=obj.coords[i].element.rgraph_3d_top_face[0].parentNode;if(parent)parent.removeChild(obj.coords[i].element.rgraph_3d_top_face[0]);if(parent)parent.removeChild(obj.coords[i].element.rgraph_3d_top_face[1]);if(obj.coords[i].element.parentNode){var parent=obj.coords[i].element.parentNode;var node=parent.removeChild(obj.coords[i].element);parent.appendChild(node);}}
75
- if(prop.grouping==='stacked'){var seq=obj.coords[i].element.getAttribute('data-sequential-index');var indexes=RG.SVG.sequentialIndexToGrouped(seq,obj.data);if(indexes[1]>0){obj.coords[i].element.setAttribute('y',parseInt(obj.coords[i-1].element.getAttribute('y'))-height);}}
76
- if(prop.variant==='3d'){obj.drawSide3dFace({rect:obj.coords[i].element,value:obj.coords[i].element.getAttribute('data-value')});if(prop.grouping==='grouped'||(prop.grouping==='stacked'&&(indexes[1]+1)===obj.data[indexes[0]].length)){obj.drawTop3dFace({rect:obj.coords[i].element,value:obj.coords[i].element.getAttribute('data-value')});}}}}
77
- if(frame>=opt.frames){callback(obj);}else{RG.SVG.FX.update(iterator);}}
78
- iterator();return this;};for(i in conf.options){if(typeof i==='string'){this.set(i,conf.options[i]);}}};return this;})(window,document);
12
+ RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
13
+ RGraph.SVG = RGraph.SVG || {};
14
+
15
+ // Module pattern
16
+ (function (win, doc, undefined)
17
+ {
18
+ RGraph.SVG.Bar = function (conf)
19
+ {
20
+ //
21
+ // A setter that the constructor uses (at the end)
22
+ // to set all of the properties
23
+ //
24
+ // @param string name The name of the property to set
25
+ // @param string value The value to set the property to
26
+ //
27
+ this.set = function (name, value)
28
+ {
29
+ if (arguments.length === 1 && typeof name === 'object') {
30
+ for (i in arguments[0]) {
31
+ if (typeof i === 'string') {
32
+
33
+ name = ret.name;
34
+ value = ret.value;
35
+
36
+ this.set(name, value);
37
+ }
38
+ }
39
+ } else {
40
+
41
+ var ret = RGraph.SVG.commonSetter({
42
+ object: this,
43
+ name: name,
44
+ value: value
45
+ });
46
+
47
+ name = ret.name;
48
+ value = ret.value;
49
+
50
+ this.properties[name] = value;
51
+
52
+ // If setting the colors, update the originalColors
53
+ // property too
54
+ if (name === 'colors') {
55
+ this.originalColors = RGraph.SVG.arrayClone(value);
56
+ this.colorsParsed = false;
57
+ }
58
+ }
59
+
60
+ return this;
61
+ };
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+ //
71
+ // A getter.
72
+ //
73
+ // @param name string The name of the property to get
74
+ //
75
+ this.get = function (name)
76
+ {
77
+ return this.properties[name];
78
+ };
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+ this.id = conf.id;
88
+ this.uid = RGraph.SVG.createUID();
89
+ this.container = document.getElementById(this.id);
90
+ this.layers = {}; // MUST be before the SVG tag is created!
91
+ this.svg = RGraph.SVG.createSVG({object: this,container: this.container});
92
+ this.isRGraph = true;
93
+ this.isrgraph = true;
94
+ this.rgraph = true;
95
+ this.data = conf.data;
96
+ this.type = 'bar';
97
+ this.coords = [];
98
+ this.coords2 = [];
99
+ this.stackedBackfaces = [];
100
+ this.originalColors = {};
101
+ this.gradientCounter = 1;
102
+ this.firstDraw = true; // After the first draw this will be false
103
+
104
+
105
+
106
+ // Convert strings to numbers
107
+ this.data = RGraph.SVG.stringsToNumbers(this.data);
108
+
109
+
110
+
111
+
112
+ // Add this object to the ObjectRegistry
113
+ RGraph.SVG.OR.add(this);
114
+
115
+ this.container.style.display = 'inline-block';
116
+
117
+ this.properties =
118
+ {
119
+ marginLeft: 35,
120
+ marginRight: 35,
121
+ marginTop: 35,
122
+ marginBottom: 35,
123
+
124
+ variant: null,
125
+ variant3dOffsetx: 10,
126
+ variant3dOffsety: 5,
127
+
128
+ backgroundColor: null,
129
+ backgroundImage: null,
130
+ backgroundImageAspect: 'none',
131
+ backgroundImageStretch: true,
132
+ backgroundImageOpacity: null,
133
+ backgroundImageX: null,
134
+ backgroundImageY: null,
135
+ backgroundImageW: null,
136
+ backgroundImageH: null,
137
+ backgroundGrid: true,
138
+ backgroundGridColor: '#ddd',
139
+ backgroundGridLinewidth: 1,
140
+ backgroundGridHlines: true,
141
+ backgroundGridHlinesCount: null,
142
+ backgroundGridVlines: true,
143
+ backgroundGridVlinesCount: null,
144
+ backgroundGridBorder: true,
145
+ backgroundGridDashed: false,
146
+ backgroundGridDotted: false,
147
+ backgroundGridDashArray: null,
148
+
149
+ // 20 colors. If you need more you need to set the colors property
150
+ colors: [
151
+ 'red', '#0f0', '#00f', '#ff0', '#0ff', '#0f0','pink','orange','gray','black',
152
+ 'red', '#0f0', '#00f', '#ff0', '#0ff', '#0f0','pink','orange','gray','black'
153
+ ],
154
+ colorsSequential: false,
155
+ colorsStroke: 'rgba(0,0,0,0)',
156
+
157
+ errorbars: null,
158
+
159
+ marginInner: 3,
160
+ marginInnerGrouped: 2,
161
+ marginInnerLeft: 0,
162
+ marginInnerRight: 0,
163
+
164
+ yaxis: true,
165
+ yaxisTickmarks: true,
166
+ yaxisTickmarksLength: 3,
167
+ yaxisColor: 'black',
168
+ yaxisScale: true,
169
+ yaxisLabels: null,
170
+ yaxisLabelsFont: null,
171
+ yaxisLabelsSize: null,
172
+ yaxisLabelsColor: null,
173
+ yaxisLabelsBold: null,
174
+ yaxisLabelsItalic: null,
175
+ yaxisLabelsOffsetx: 0,
176
+ yaxisLabelsOffsety: 0,
177
+ yaxisLabelsCount: 5,
178
+ yaxisScaleUnitsPre: '',
179
+ yaxisScaleUnitsPost: '',
180
+ yaxisScaleStrict: false,
181
+ yaxisScaleDecimals: 0,
182
+ yaxisScalePoint: '.',
183
+ yaxisScaleThousand: ',',
184
+ yaxisScaleRound: false,
185
+ yaxisScaleMax: null,
186
+ yaxisScaleMin: 0,
187
+ yaxisScaleFormatter: null,
188
+ yaxisTitle: '',
189
+ yaxisTitleBold: null,
190
+ yaxisTitleSize: null,
191
+ yaxisTitleFont: null,
192
+ yaxisTitleColor: null,
193
+ yaxisTitleItalic: null,
194
+ yaxisTitleOffsetx: 0,
195
+ yaxisTitleOffsety: 0,
196
+ yaxisTitleX: null,
197
+ yaxisTitleY: null,
198
+ yaxisTitleHalign: null,
199
+ yaxisTitleValign: null,
200
+
201
+ xaxis: true,
202
+ xaxisTickmarks: true,
203
+ xaxisTickmarksLength: 5,
204
+ xaxisLabels: null,
205
+ xaxisLabelsFont: null,
206
+ xaxisLabelsSize: null,
207
+ xaxisLabelsColor: null,
208
+ xaxisLabelsBold: null,
209
+ xaxisLabelsItalic: null,
210
+ xaxisLabelsPosition: 'section',
211
+ xaxisLabelsPositionSectionTickmarksCount: null,
212
+ xaxisLabelsOffsetx: 0,
213
+ xaxisLabelsOffsety: 0,
214
+ xaxisLabelsFormattedDecimals: 0,
215
+ xaxisLabelsFormattedPoint: '.',
216
+ xaxisLabelsFormattedThousand: ',',
217
+ xaxisLabelsFormattedUnitsPre: '',
218
+ xaxisLabelsFormattedUnitsPost: '',
219
+ xaxisColor: 'black',
220
+ xaxisTitle: '',
221
+ xaxisTitleBold: null,
222
+ xaxisTitleSize: null,
223
+ xaxisTitleFont: null,
224
+ xaxisTitleColor: null,
225
+ xaxisTitleItalic: null,
226
+ xaxisTitleOffsetx: 0,
227
+ xaxisTitleOffsety: 0,
228
+ xaxisTitleX: null,
229
+ xaxisTitleY: null,
230
+ xaxisTitleHalign: null,
231
+ xaxisTitleValign: null,
232
+
233
+ labelsAbove: false,
234
+ labelsAboveFont: null,
235
+ labelsAboveSize: null,
236
+ labelsAboveBold: null,
237
+ labelsAboveItalic: null,
238
+ labelsAboveColor: null,
239
+ labelsAboveBackground: null,
240
+ labelsAboveBackgroundPadding: 0,
241
+ labelsAboveUnitsPre: null,
242
+ labelsAboveUnitsPost: null,
243
+ labelsAbovePoint: null,
244
+ labelsAboveThousand: null,
245
+ labelsAboveFormatter: null,
246
+ labelsAboveDecimals: null,
247
+ labelsAboveOffsetx: 0,
248
+ labelsAboveOffsety: 0,
249
+ labelsAboveHalign: 'center',
250
+ labelsAboveValign: 'bottom',
251
+ labelsAboveSpecific: null,
252
+
253
+ textColor: 'black',
254
+ textFont: 'Arial, Verdana, sans-serif',
255
+ textSize: 12,
256
+ textBold: false,
257
+ textItalic: false,
258
+ text: null,
259
+
260
+ linewidth: 1,
261
+ grouping: 'grouped',
262
+
263
+ tooltips: null,
264
+ tooltipsOverride: null,
265
+ tooltipsEffect: 'fade',
266
+ tooltipsCssClass: 'RGraph_tooltip',
267
+ tooltipsCss: null,
268
+ tooltipsEvent: 'click',
269
+ tooltipsFormattedThousand: ',',
270
+ tooltipsFormattedPoint: '.',
271
+ tooltipsFormattedDecimals: 0,
272
+ tooltipsFormattedUnitsPre: '',
273
+ tooltipsFormattedUnitsPost: '',
274
+ tooltipsFormattedKeyColors: null,
275
+ tooltipsFormattedKeyColorsShape: 'square',
276
+ tooltipsFormattedKeyLabels: [],
277
+ tooltipsFormattedTableHeaders: null,
278
+ tooltipsFormattedTableData: null,
279
+ tooltipsPointer: true,
280
+ tooltipsPointerOffsetx: 0,
281
+ tooltipsPointerOffsety: 0,
282
+ tooltipsPositionStatic: true,
283
+
284
+ highlightStroke: 'rgba(0,0,0,0)',
285
+ highlightFill: 'rgba(255,255,255,0.7)',
286
+ highlightLinewidth: 1,
287
+
288
+ title: '',
289
+ titleX: null,
290
+ titleY: null,
291
+ titleHalign: 'center',
292
+ //titleValign: null,
293
+ titleSize: null,
294
+ titleColor: null,
295
+ titleFont: null,
296
+ titleBold: null,
297
+ titleItalic: null,
298
+
299
+ titleSubtitle: null,
300
+ titleSubtitleSize: null,
301
+ titleSubtitleColor: '#aaa',
302
+ titleSubtitleFont: null,
303
+ titleSubtitleBold: null,
304
+ titleSubtitleItalic: null,
305
+
306
+ shadow: false,
307
+ shadowOffsetx: 2,
308
+ shadowOffsety: 2,
309
+ shadowBlur: 2,
310
+ shadowColor: 'rgba(0,0,0,0.25)',
311
+
312
+ errorbars: null,
313
+ errorbarsColor: 'black',
314
+ errorbarsLinewidth: 1,
315
+ errorbarsCapwidth: 10,
316
+
317
+ key: null,
318
+ keyColors: null,
319
+ keyOffsetx: 0,
320
+ keyOffsety: 0,
321
+ keyLabelsOffsetx: 0,
322
+ keyLabelsOffsety: -1,
323
+ keyLabelsColor: null,
324
+ keyLabelsSize: null,
325
+ keyLabelsBold: null,
326
+ keyLabelsItalic: null,
327
+ keyLabelsFont: null
328
+ };
329
+
330
+
331
+
332
+
333
+ //
334
+ // Copy the global object properties to this instance
335
+ //
336
+ RGraph.SVG.getGlobals(this);
337
+
338
+
339
+
340
+
341
+
342
+ //
343
+ // "Decorate" the object with the generic effects if the effects library has been included
344
+ //
345
+ if (RGraph.SVG.FX && typeof RGraph.SVG.FX.decorate === 'function') {
346
+ RGraph.SVG.FX.decorate(this);
347
+ }
348
+
349
+
350
+
351
+
352
+
353
+ // Add the responsive function to the object
354
+ this.responsive = RGraph.SVG.responsive;
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+ // A shortcut
363
+ var properties = this.properties;
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+ //
373
+ // The draw method draws the Bar chart
374
+ //
375
+ this.draw = function ()
376
+ {
377
+ // Fire the beforedraw event
378
+ RGraph.SVG.fireCustomEvent(this, 'onbeforedraw');
379
+
380
+
381
+ // Should the first thing that's done inthe.draw() function
382
+ // except for the onbeforedraw event
383
+ this.width = Number(this.svg.getAttribute('width'));
384
+ this.height = Number(this.svg.getAttribute('height'));
385
+
386
+
387
+ // Zero these if the 3D effect is not wanted
388
+ if (properties.variant !== '3d') {
389
+ properties.variant3dOffsetx = 0;
390
+ properties.variant3dOffsety = 0;
391
+
392
+ } else {
393
+
394
+ // Set the skew transform on the all group if necessary
395
+ this.svg.all.setAttribute('transform', 'skewY(5)');
396
+ }
397
+
398
+
399
+
400
+ // Create the defs tag if necessary
401
+ RGraph.SVG.createDefs(this);
402
+
403
+
404
+
405
+
406
+
407
+
408
+
409
+ // Reset the coords array
410
+ this.coords = [];
411
+ this.coords2 = [];
412
+
413
+
414
+ this.graphWidth = this.width - properties.marginLeft - properties.marginRight;
415
+ this.graphHeight = this.height - properties.marginTop - properties.marginBottom;
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+ // Make the data sequential first
432
+ this.data_seq = RGraph.SVG.arrayLinearize(this.data);
433
+
434
+ // This allows the errorbars to be a variety of formats and convert
435
+ // them all into an array of objects which have the min and max
436
+ // properties set
437
+ if (properties.errorbars) {
438
+ // Go through the error bars and convert numbers to objects
439
+ for (var i=0; i<this.data_seq.length; ++i) {
440
+
441
+ if (typeof properties.errorbars[i] === 'undefined' || RGraph.SVG.isNull(properties.errorbars[i]) ) {
442
+ properties.errorbars[i] = {max: null, min: null};
443
+
444
+ } else if (typeof properties.errorbars[i] === 'number') {
445
+ properties.errorbars[i] = {
446
+ min: properties.errorbars[i],
447
+ max: properties.errorbars[i]
448
+ };
449
+
450
+ // Max is undefined
451
+ } else if (typeof properties.errorbars[i] === 'object' && typeof properties.errorbars[i].max === 'undefined') {
452
+ properties.errorbars[i].max = null;
453
+
454
+ // Min is not defined
455
+ } else if (typeof properties.errorbars[i] === 'object' && typeof properties.errorbars[i].min === 'undefined') {
456
+ properties.errorbars[i].min = null;
457
+ }
458
+ }
459
+ }
460
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470
+ //
471
+ // Parse the colors. This allows for simple gradient syntax
472
+ //
473
+
474
+ // Parse the colors for gradients
475
+ RGraph.SVG.resetColorsToOriginalValues({object:this});
476
+ this.parseColors();
477
+
478
+
479
+
480
+
481
+ // Go through the data and work out the maximum value
482
+ // This now also accounts for errorbars
483
+ var values = [];
484
+
485
+ for (var i=0,max=0; i<this.data.length; ++i) {
486
+
487
+ // Errorbars affect the max value
488
+ if (properties.errorbars && typeof properties.errorbars[i] === 'number') {
489
+ var errorbar = properties.errorbars[i];
490
+ } else if (properties.errorbars && typeof properties.errorbars[i] === 'object' && typeof properties.errorbars[i].max === 'number') {
491
+ var errorbar = properties.errorbars[i].max;
492
+ } else {
493
+ var errorbar = 0;
494
+ }
495
+
496
+
497
+ if (typeof this.data[i] === 'number') {
498
+ values.push(this.data[i] + errorbar);
499
+
500
+ } else if (RGraph.SVG.isArray(this.data[i]) && properties.grouping === 'grouped') {
501
+ values.push(RGraph.SVG.arrayMax(this.data[i]) + errorbar);
502
+
503
+ } else if (RGraph.SVG.isArray(this.data[i]) && properties.grouping === 'stacked') {
504
+ values.push(RGraph.SVG.arraySum(this.data[i]) + errorbar);
505
+ }
506
+ }
507
+ var max = RGraph.SVG.arrayMax(values);
508
+
509
+ // A custom, user-specified maximum value
510
+ if (typeof properties.yaxisScaleMax === 'number') {
511
+ max = properties.yaxisScaleMax;
512
+ }
513
+
514
+ // Set the ymin to zero if it's set mirror
515
+ if (properties.yaxisScaleMin === 'mirror' || properties.yaxisScaleMin === 'middle' || properties.yaxisScaleMin === 'center') {
516
+ this.mirrorScale = true;
517
+ var mirrorScale = true;
518
+ properties.yaxisScaleMin = 0;
519
+ }
520
+
521
+
522
+ //
523
+ // Generate an appropiate scale
524
+ //
525
+ this.scale = RGraph.SVG.getScale({
526
+ object: this,
527
+ numlabels: properties.yaxisLabelsCount,
528
+ unitsPre: properties.yaxisScaleUnitsPre,
529
+ unitsPost: properties.yaxisScaleUnitsPost,
530
+ max: max,
531
+ min: properties.yaxisScaleMin,
532
+ point: properties.yaxisScalePoint,
533
+ round: properties.yaxisScaleRound,
534
+ thousand: properties.yaxisScaleThousand,
535
+ decimals: properties.yaxisScaleDecimals,
536
+ strict: typeof properties.yaxisScaleMax === 'number',
537
+ formatter: properties.yaxisScaleFormatter
538
+ });
539
+
540
+
541
+
542
+ //
543
+ // Get the scale a second time if the ymin should be mirored
544
+ //
545
+ // Set the ymin to zero if it's set mirror
546
+ if (mirrorScale) {
547
+ this.scale = RGraph.SVG.getScale({
548
+ object: this,
549
+ numlabels: properties.yaxisLabelsCount,
550
+ unitsPre: properties.yaxisScaleUnitsPre,
551
+ unitsPost: properties.yaxisScaleUnitsPost,
552
+ max: this.scale.max,
553
+ min: this.scale.max * -1,
554
+ point: properties.yaxisScalePoint,
555
+ round: false,
556
+ thousand: properties.yaxisScaleThousand,
557
+ decimals: properties.yaxisScaleDecimals,
558
+ strict: typeof properties.yaxisScaleMax === 'number',
559
+ formatter: properties.yaxisScaleFormatter
560
+ });
561
+ }
562
+
563
+ // Now the scale has been generated adopt its max value
564
+ this.max = this.scale.max;
565
+ this.min = this.scale.min;
566
+
567
+ // Commenting these two lines out allows the data to change and
568
+ // subsequently a new max can be generated to accommodate the
569
+ // new data
570
+ //properties.yaxisScaleMax = this.scale.max;
571
+ //properties.yaxisScaleMin = this.scale.min;
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+ // Draw the background first
598
+ RGraph.SVG.drawBackground(this);
599
+
600
+
601
+
602
+ // Draw the threeD axes here so everything else is drawn on top of
603
+ // it, but after the scale generation
604
+ if (properties.variant === '3d') {
605
+
606
+
607
+
608
+
609
+ // Draw the 3D Y axis
610
+ RGraph.SVG.create({
611
+ svg: this.svg,
612
+ parent: this.svg.all,
613
+ type: 'path',
614
+ attr: {
615
+ d: 'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(
616
+ properties.marginLeft,
617
+ properties.marginTop,
618
+
619
+ properties.marginLeft + properties.variant3dOffsetx,
620
+ properties.marginTop - properties.variant3dOffsety,
621
+
622
+ properties.marginLeft + properties.variant3dOffsetx,
623
+ this.height - properties.marginBottom - properties.variant3dOffsety,
624
+
625
+ properties.marginLeft,
626
+ this.height - properties.marginBottom,
627
+
628
+ properties.marginLeft,
629
+ properties.marginTop
630
+ ),
631
+ fill: '#ddd',
632
+ stroke: '#ccc'
633
+ }
634
+ });
635
+
636
+
637
+
638
+
639
+ // Add the group that the negative bars are added to. This makes them
640
+ // appear below the axes
641
+ this.threed_xaxis_group = RGraph.SVG.create({
642
+ svg: this.svg,
643
+ type: 'g',
644
+ parent: this.svg.all,
645
+ attr: {
646
+ className: 'rgraph_3d_bar_xaxis_negative'
647
+ }
648
+ });
649
+
650
+
651
+
652
+ // Draw the 3D X axis
653
+ RGraph.SVG.create({
654
+ svg: this.svg,
655
+ parent: this.svg.all,
656
+ type: 'path',
657
+ attr: {
658
+ d: 'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(
659
+ properties.marginLeft,
660
+ this.getYCoord(0),
661
+
662
+ properties.marginLeft + properties.variant3dOffsetx,
663
+ this.getYCoord(0) - properties.variant3dOffsety,
664
+
665
+ this.width - properties.marginRight + properties.variant3dOffsetx,
666
+ this.getYCoord(0) - properties.variant3dOffsety,
667
+
668
+ this.width - properties.marginRight,
669
+ this.getYCoord(0),
670
+
671
+ properties.marginLeft,
672
+ this.getYCoord(0)
673
+ ),
674
+ fill: '#ddd',
675
+ stroke: '#ccc'
676
+ }
677
+ });
678
+ }
679
+
680
+
681
+
682
+
683
+
684
+
685
+ // Draw the bars
686
+ this.drawBars();
687
+
688
+
689
+
690
+
691
+ //
692
+ // If the xaxisLabels option is a string then turn it
693
+ // into an array.
694
+ //
695
+ if (properties.xaxisLabels && properties.xaxisLabels.length) {
696
+ if (typeof properties.xaxisLabels === 'string') {
697
+ properties.xaxisLabels = RGraph.SVG.arrayPad({
698
+ array: [],
699
+ length: this.data.length,
700
+ value: properties.xaxisLabels
701
+ });
702
+ }
703
+
704
+ // Label substitution
705
+ //
706
+ for (var i=0; i<properties.xaxisLabels.length; ++i) {
707
+ properties.xaxisLabels[i] = RGraph.SVG.labelSubstitution({
708
+ object: this,
709
+ text: properties.xaxisLabels[i],
710
+ index: i,
711
+ value: this.data[i],
712
+ decimals: properties.xaxisLabelsFormattedDecimals || 0,
713
+ unitsPre: properties.xaxisLabelsFormattedUnitsPre || '',
714
+ unitsPost: properties.xaxisLabelsFormattedUnitsPost || '',
715
+ thousand: properties.xaxisLabelsFormattedThousand || ',',
716
+ point: properties.xaxisLabelsFormattedPoint || '.'
717
+ });
718
+ }
719
+ }
720
+
721
+
722
+
723
+
724
+ // Draw the axes over the bars
725
+ RGraph.SVG.drawXAxis(this);
726
+ RGraph.SVG.drawYAxis(this);
727
+
728
+
729
+ // Draw the labelsAbove labels
730
+ this.drawLabelsAbove();
731
+
732
+
733
+
734
+
735
+
736
+ // Draw the key
737
+ if (typeof properties.key !== null && RGraph.SVG.drawKey) {
738
+ RGraph.SVG.drawKey(this);
739
+ } else if (!RGraph.SVG.isNull(properties.key)) {
740
+ alert('The drawKey() function does not exist - have you forgotten to include the key library?');
741
+ }
742
+
743
+
744
+
745
+
746
+
747
+
748
+
749
+
750
+
751
+ // Add the event listener that clears the highlight rect if
752
+ // there is any. Must be MOUSEDOWN (ie before the click event)
753
+ //var obj = this;
754
+ //document.body.addEventListener('mousedown', function (e)
755
+ //{
756
+ // //RGraph.SVG.removeHighlight(obj);
757
+ //
758
+ //}, false);
759
+
760
+
761
+
762
+
763
+
764
+
765
+
766
+
767
+ //
768
+ // Allow the addition of custom text via the
769
+ // text: property.
770
+ //
771
+ RGraph.SVG.addCustomText(this);
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+ // Draw any custom lines that have been defined
785
+ RGraph.SVG.drawHorizontalLines(this);
786
+
787
+
788
+
789
+
790
+
791
+
792
+
793
+
794
+
795
+
796
+
797
+ //
798
+ // Fire the onfirstdraw event
799
+ //
800
+ if (this.firstDraw) {
801
+ this.firstDraw = false;
802
+ RGraph.SVG.fireCustomEvent(this, 'onfirstdraw');
803
+ }
804
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+ // Fire the draw event
812
+ RGraph.SVG.fireCustomEvent(this, 'ondraw');
813
+
814
+
815
+
816
+
817
+
818
+
819
+
820
+
821
+ //
822
+ // Install any inline responsive configuration. This
823
+ // should be last in the draw function - even after
824
+ // the draw events.
825
+ //
826
+ RGraph.SVG.installInlineResponsive(this);
827
+
828
+
829
+
830
+
831
+
832
+
833
+
834
+
835
+
836
+
837
+
838
+
839
+ return this;
840
+ };
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+ //
850
+ // New create() shortcut function
851
+ // For example:
852
+ // this.create('rect,x:0,y:0,width:100,height:100'[,parent]);
853
+ //
854
+ // @param str string The tag definition to parse and create
855
+ // @param object The (optional) parent element
856
+ // @return object The new tag
857
+ //
858
+ this.create = function (str)
859
+ {
860
+ var def = RGraph.SVG.create.parseStr(this, str);
861
+ def.svg = this.svg;
862
+
863
+ // By default the parent is the SVG tag - but if
864
+ // requested then change it to the tag that has
865
+ // been given
866
+ if (arguments[1]) {
867
+ def.parent = arguments[1];
868
+ }
869
+
870
+ return RGraph.SVG.create(def);
871
+ };
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+ //
881
+ // Draws the bars
882
+ //
883
+ this.drawBars = function ()
884
+ {
885
+ var y = this.getYCoord(0);
886
+
887
+ if (properties.shadow) {
888
+ RGraph.SVG.setShadow({
889
+ object: this,
890
+ offsetx: properties.shadowOffsetx,
891
+ offsety: properties.shadowOffsety,
892
+ blur: properties.shadowBlur,
893
+ color: properties.shadowColor,
894
+ id: 'dropShadow'
895
+ });
896
+ }
897
+
898
+ // Go through the bars
899
+ for (var i=0,sequentialIndex=0; i<this.data.length; ++i,++sequentialIndex) {
900
+
901
+ //
902
+ // REGULAR BARS
903
+ //
904
+ if (typeof this.data[i] === 'number') {
905
+
906
+ var outerSegment = (this.graphWidth - properties.marginInnerLeft - properties.marginInnerRight) / this.data.length,
907
+ height = (Math.abs(this.data[i]) - Math.abs(this.scale.min)) / (Math.abs(this.scale.max) - Math.abs(this.scale.min)) * this.graphHeight,
908
+ width = ( (this.graphWidth - properties.marginInnerLeft - properties.marginInnerRight) / this.data.length) - properties.marginInner - properties.marginInner,
909
+ x = properties.marginLeft + properties.marginInner + properties.marginInnerLeft + (outerSegment * i);
910
+
911
+ // Work out the height and the Y coord of the Bar
912
+ if (this.scale.min >= 0 && this.scale.max > 0) {
913
+ y = this.getYCoord(this.scale.min) - height;
914
+
915
+ } else if (this.scale.min < 0 && this.scale.max > 0) {
916
+ height = (Math.abs(this.data[i]) / (this.scale.max - this.scale.min)) * this.graphHeight;
917
+ y = this.getYCoord(0) - height;
918
+
919
+ if (this.data[i] < 0) {
920
+ y = this.getYCoord(0);
921
+ }
922
+ } else if (this.scale.min < 0 && this.scale.max < 0) {
923
+ height = (Math.abs(this.data[i]) - Math.abs(this.scale.max)) / (Math.abs(this.scale.min) - Math.abs(this.scale.max)) * this.graphHeight;
924
+ y = properties.marginTop;
925
+ }
926
+
927
+
928
+
929
+
930
+
931
+
932
+
933
+
934
+
935
+ var rect = RGraph.SVG.create({
936
+ svg: this.svg,
937
+ type: 'rect',
938
+ parent: properties.variant === '3d' && this.data[i] < 0 ? this.threed_xaxis_group : this.svg.all,
939
+ attr: {
940
+ stroke: properties.colorsStroke,
941
+ fill: properties.colorsSequential ? (properties.colors[sequentialIndex] ? properties.colors[sequentialIndex] : properties.colors[properties.colors.length - 1]) : properties.colors[0],
942
+ x: x,
943
+ y: y,
944
+ width: width < 0 ? 0 : width,
945
+ height: height,
946
+ 'stroke-width': properties.linewidth,
947
+ 'data-original-x': x,
948
+ 'data-original-y': y,
949
+ 'data-original-width': width,
950
+ 'data-original-height': height,
951
+ 'data-tooltip': (!RGraph.SVG.isNull(properties.tooltips) && properties.tooltips.length) ? properties.tooltips[i] : '',
952
+ 'data-index': i,
953
+ 'data-sequential-index': sequentialIndex,
954
+ 'data-value': this.data[i],
955
+ filter: properties.shadow ? 'url(#dropShadow)' : ''
956
+ }
957
+ });
958
+
959
+
960
+
961
+
962
+
963
+
964
+
965
+
966
+
967
+ // Draw the errorbar if required
968
+ this.drawErrorbar({
969
+ object: this,
970
+ element: rect,
971
+ index: i,
972
+ value: this.data[i],
973
+ type: 'normal'
974
+ });
975
+
976
+
977
+
978
+
979
+
980
+ this.coords.push({
981
+ object: this,
982
+ element: rect,
983
+ x: parseFloat(rect.getAttribute('x')),
984
+ y: parseFloat(rect.getAttribute('y')),
985
+ width: parseFloat(rect.getAttribute('width')),
986
+ height: parseFloat(rect.getAttribute('height'))
987
+ });
988
+
989
+ if (!this.coords2[0]) {
990
+ this.coords2[0] = [];
991
+ }
992
+
993
+ this.coords2[0].push({
994
+ object: this,
995
+ element: rect,
996
+ x: parseFloat(rect.getAttribute('x')),
997
+ y: parseFloat(rect.getAttribute('y')),
998
+ width: parseFloat(rect.getAttribute('width')),
999
+ height: parseFloat(rect.getAttribute('height'))
1000
+ });
1001
+
1002
+
1003
+
1004
+ //
1005
+ // Add the 3D faces if required
1006
+ //
1007
+ if (properties.variant === '3d') {
1008
+ this.drawTop3dFace({rect: rect, value: this.data[i]});
1009
+ this.drawSide3dFace({rect: rect, value: this.data[i]});
1010
+ }
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+ // Add the tooltip data- attribute
1017
+ if ( !RGraph.SVG.isNull(properties.tooltips)
1018
+ && (!RGraph.SVG.isNull(properties.tooltips[sequentialIndex]) || typeof properties.tooltips === 'string')
1019
+ ) {
1020
+
1021
+ var obj = this;
1022
+
1023
+ //
1024
+ // Add tooltip event listeners
1025
+ //
1026
+ (function (idx, seq)
1027
+ {
1028
+ rect.addEventListener(properties.tooltipsEvent.replace(/^on/, ''), function (e)
1029
+ {
1030
+ obj.removeHighlight();
1031
+
1032
+ // Show the tooltip
1033
+ RGraph.SVG.tooltip({
1034
+ object: obj,
1035
+ index: idx,
1036
+ group: null,
1037
+ sequentialIndex: seq,
1038
+ text: typeof properties.tooltips === 'string' ? properties.tooltips : properties.tooltips[seq],
1039
+ event: e
1040
+ });
1041
+
1042
+ // Highlight the rect that has been clicked on
1043
+ obj.highlight(e.target);
1044
+ }, false);
1045
+
1046
+ rect.addEventListener('mousemove', function (e)
1047
+ {
1048
+ e.target.style.cursor = 'pointer'
1049
+ }, false);
1050
+ })(i, sequentialIndex);
1051
+ }
1052
+
1053
+
1054
+
1055
+
1056
+
1057
+ //
1058
+ // GROUPED BARS
1059
+ //
1060
+ } else if (RGraph.SVG.isArray(this.data[i]) && properties.grouping === 'grouped') {
1061
+
1062
+ var outerSegment = ( (this.graphWidth - properties.marginInnerLeft - properties.marginInnerRight) / this.data.length),
1063
+ innerSegment = outerSegment - (2 * properties.marginInner);
1064
+
1065
+ // Loop through the group
1066
+ for (var j=0; j<this.data[i].length; ++j,++sequentialIndex) {
1067
+
1068
+ var width = ( (innerSegment - ((this.data[i].length - 1) * properties.marginInnerGrouped)) / this.data[i].length),
1069
+ x = (outerSegment * i) + properties.marginInner + properties.marginLeft + properties.marginInnerLeft + (j * width) + ((j - 1) * properties.marginInnerGrouped);
1070
+
1071
+ x = properties.marginLeft + properties.marginInnerLeft + (outerSegment * i) + (width * j) + properties.marginInner + (j * properties.marginInnerGrouped);
1072
+
1073
+
1074
+
1075
+
1076
+
1077
+
1078
+
1079
+
1080
+
1081
+
1082
+
1083
+
1084
+
1085
+
1086
+
1087
+ // Calculate the height
1088
+ // eg 0 -> 10
1089
+ if (this.scale.min === 0 && this.scale.max > this.scale.min) {
1090
+ var height = ((this.data[i][j] - this.scale.min) / (this.scale.max - this.scale.min)) * this.graphHeight,
1091
+ y = this.getYCoord(0) - height;
1092
+
1093
+ // eg -5 -> -15
1094
+ } else if (this.scale.max <= 0 && this.scale.min < this.scale.max) {
1095
+ var height = ((this.data[i][j] - this.scale.max) / (this.scale.max - this.scale.min)) * this.graphHeight,
1096
+ y = this.getYCoord(this.scale.max);
1097
+
1098
+ height = Math.abs(height);
1099
+
1100
+ // eg 10 -> -10
1101
+ } else if (this.scale.max > 0 && this.scale.min < 0) {
1102
+
1103
+ var height = (Math.abs(this.data[i][j]) / (this.scale.max - this.scale.min)) * this.graphHeight,
1104
+ y = this.data[i][j] < 0 ? this.getYCoord(0) : this.getYCoord(this.data[i][j]);
1105
+
1106
+ // eg 5 -> 10
1107
+ } else if (this.scale.min > 0 && this.scale.max > this.scale.min) {
1108
+ var height = (Math.abs(this.data[i][j] - this.scale.min) / (this.scale.max - this.scale.min)) * this.graphHeight,
1109
+ y = this.getYCoord(this.scale.min) - height;
1110
+ }
1111
+
1112
+
1113
+
1114
+
1115
+
1116
+
1117
+
1118
+ // Add the rect tag
1119
+ var rect = RGraph.SVG.create({
1120
+ svg: this.svg,
1121
+ parent: properties.variant === '3d' && this.data[i][j] < 0 ? this.threed_xaxis_group : this.svg.all,
1122
+ type: 'rect',
1123
+ attr: {
1124
+ stroke: properties.colorsStroke,
1125
+ fill: (properties.colorsSequential && properties.colors[sequentialIndex]) ? properties.colors[sequentialIndex] : properties.colors[j],
1126
+ x: x,
1127
+ y: y,
1128
+ width: width,
1129
+ height: height,
1130
+ 'stroke-width': properties.linewidth,
1131
+ 'data-original-x': x,
1132
+ 'data-original-y': y,
1133
+ 'data-original-width': width,
1134
+ 'data-original-height': height,
1135
+ 'data-index': i,
1136
+ 'data-subindex': j,
1137
+ 'data-sequential-index': sequentialIndex,
1138
+ 'data-tooltip': (!RGraph.SVG.isNull(properties.tooltips) && properties.tooltips.length) ? properties.tooltips[sequentialIndex] : '',
1139
+ 'data-value': this.data[i][j],
1140
+ filter: properties.shadow ? 'url(#dropShadow)' : ''
1141
+ }
1142
+ });
1143
+
1144
+
1145
+
1146
+
1147
+
1148
+
1149
+
1150
+
1151
+
1152
+
1153
+ // Draw the errorbar if required
1154
+ this.drawErrorbar({
1155
+ object: this,
1156
+ element: rect,
1157
+ index: sequentialIndex,
1158
+ value: this.data[i][j],
1159
+ type: 'grouped'
1160
+ });
1161
+
1162
+
1163
+
1164
+
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+ this.coords.push({
1172
+ object: this,
1173
+ element: rect,
1174
+ x: parseFloat(rect.getAttribute('x')),
1175
+ y: parseFloat(rect.getAttribute('y')),
1176
+ width: parseFloat(rect.getAttribute('width')),
1177
+ height: parseFloat(rect.getAttribute('height'))
1178
+ });
1179
+
1180
+ if (!this.coords2[i]) {
1181
+ this.coords2[i] = [];
1182
+ }
1183
+
1184
+ this.coords2[i].push({
1185
+ object: this,
1186
+ element: rect,
1187
+ x: parseFloat(rect.getAttribute('x')),
1188
+ y: parseFloat(rect.getAttribute('y')),
1189
+ width: parseFloat(rect.getAttribute('width')),
1190
+ height: parseFloat(rect.getAttribute('height'))
1191
+ });
1192
+
1193
+
1194
+
1195
+
1196
+ //
1197
+ // Add the 3D faces if required
1198
+ //
1199
+ if (properties.variant === '3d') {
1200
+ this.drawTop3dFace({rect: rect, value: this.data[i][j]});
1201
+ this.drawSide3dFace({rect: rect, value: this.data[i][j]});
1202
+ }
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+
1209
+
1210
+ // Add the tooltip data- attribute
1211
+ if ( !RGraph.SVG.isNull(properties.tooltips)
1212
+ && (properties.tooltips[sequentialIndex] || typeof properties.tooltips === 'string')
1213
+ ) {
1214
+
1215
+ var obj = this;
1216
+
1217
+
1218
+ //
1219
+ // Add tooltip event listeners
1220
+ //
1221
+ (function (idx, seq)
1222
+ {
1223
+ obj.removeHighlight();
1224
+
1225
+ var indexes = RGraph.SVG.sequentialIndexToGrouped(seq, obj.data);
1226
+
1227
+ rect.addEventListener(properties.tooltipsEvent.replace(/^on/, ''), function (e)
1228
+ {
1229
+ // Show the tooltip
1230
+ RGraph.SVG.tooltip({
1231
+ object: obj,
1232
+ group: idx,
1233
+ index: indexes[1],
1234
+ sequentialIndex: seq,
1235
+ text: typeof properties.tooltips === 'string' ? properties.tooltips : properties.tooltips[seq],
1236
+ event: e
1237
+ });
1238
+
1239
+ // Highlight the rect that has been clicked on
1240
+ obj.highlight(e.target);
1241
+
1242
+ }, false);
1243
+
1244
+ rect.addEventListener('mousemove', function (e)
1245
+ {
1246
+ e.target.style.cursor = 'pointer'
1247
+ }, false);
1248
+ })(i, sequentialIndex);
1249
+ }
1250
+ }
1251
+
1252
+ --sequentialIndex;
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1262
+
1263
+ //
1264
+ // STACKED CHARTS
1265
+ //
1266
+ } else if (RGraph.SVG.isArray(this.data[i]) && properties.grouping === 'stacked') {
1267
+
1268
+ var section = ( (this.graphWidth - properties.marginInnerLeft - properties.marginInnerRight) / this.data.length);
1269
+
1270
+
1271
+ // Intialise the Y coordinate to the bottom gutter
1272
+ var y = this.getYCoord(0);
1273
+
1274
+
1275
+
1276
+ // Loop through the stack
1277
+ for (var j=0; j<this.data[i].length; ++j,++sequentialIndex) {
1278
+
1279
+ var height = (this.data[i][j] / (this.max - this.min)) * this.graphHeight,
1280
+ width = section - (2 * properties.marginInner),
1281
+ x = properties.marginLeft + properties.marginInnerLeft + (i * section) + properties.marginInner,
1282
+ y = y - height;
1283
+
1284
+ // If this is the first iteration of the loop and a shadow
1285
+ // is requested draw a rect here to create it.
1286
+ if (j === 0 && properties.shadow) {
1287
+
1288
+ var fullHeight = (RGraph.SVG.arraySum(this.data[i]) / (this.max - this.min)) * this.graphHeight;
1289
+
1290
+ var rect = RGraph.SVG.create({
1291
+ svg: this.svg,
1292
+ parent: this.svg.all,
1293
+ type: 'rect',
1294
+ attr: {
1295
+ fill: 'white',
1296
+ x: x,
1297
+ y: this.height - properties.marginBottom - fullHeight,
1298
+ width: width,
1299
+ height: fullHeight,
1300
+ 'stroke-width': 0,
1301
+ 'data-index': i,
1302
+ filter: 'url(#dropShadow)'
1303
+ }
1304
+ });
1305
+
1306
+ this.stackedBackfaces[i] = rect;
1307
+ }
1308
+
1309
+
1310
+
1311
+ // Create the visible bar
1312
+ var rect = RGraph.SVG.create({
1313
+ svg: this.svg,
1314
+ parent: this.svg.all,
1315
+ type: 'rect',
1316
+ attr: {
1317
+ stroke: properties.colorsStroke,
1318
+ fill: properties.colorsSequential ? (properties.colors[sequentialIndex] ? properties.colors[sequentialIndex] : properties.colors[properties.colors.length - 1]) : properties.colors[j],
1319
+ x: x,
1320
+ y: y,
1321
+ width: width,
1322
+ height: height,
1323
+ 'stroke-width': properties.linewidth,
1324
+ 'data-original-x': x,
1325
+ 'data-original-y': y,
1326
+ 'data-original-width': width,
1327
+ 'data-original-height': height,
1328
+ 'data-index': i,
1329
+ 'data-subindex': j,
1330
+ 'data-sequential-index': sequentialIndex,
1331
+ 'data-tooltip': (!RGraph.SVG.isNull(properties.tooltips) && properties.tooltips.length) ? properties.tooltips[sequentialIndex] : '',
1332
+ 'data-value': this.data[i][j]
1333
+ }
1334
+ });
1335
+
1336
+
1337
+
1338
+
1339
+
1340
+
1341
+
1342
+ // Draw the errorbar if required
1343
+ if (j === (this.data[i].length - 1)) {
1344
+
1345
+ this.drawErrorbar({
1346
+ object: this,
1347
+ element: rect,
1348
+ index: i,
1349
+ value: this.data[i][j],
1350
+ type: 'stacked'
1351
+ });
1352
+ }
1353
+
1354
+
1355
+
1356
+
1357
+
1358
+
1359
+
1360
+
1361
+
1362
+ this.coords.push({
1363
+ object: this,
1364
+ element: rect,
1365
+ x: parseFloat(rect.getAttribute('x')),
1366
+ y: parseFloat(rect.getAttribute('y')),
1367
+ width: parseFloat(rect.getAttribute('width')),
1368
+ height: parseFloat(rect.getAttribute('height'))
1369
+ });
1370
+
1371
+ if (!this.coords2[i]) {
1372
+ this.coords2[i] = [];
1373
+ }
1374
+
1375
+ this.coords2[i].push({
1376
+ object: this,
1377
+ element: rect,
1378
+ x: parseFloat(rect.getAttribute('x')),
1379
+ y: parseFloat(rect.getAttribute('y')),
1380
+ width: parseFloat(rect.getAttribute('width')),
1381
+ height: parseFloat(rect.getAttribute('height'))
1382
+ });
1383
+
1384
+
1385
+
1386
+
1387
+
1388
+
1389
+ //
1390
+ // Add the 3D faces if required
1391
+ //
1392
+ if (properties.variant === '3d') {
1393
+ this.drawTop3dFace({rect: rect, value: this.data[i][j]});
1394
+ this.drawSide3dFace({rect: rect, value: this.data[i][j]});
1395
+ }
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+
1404
+ // Add the tooltip data- attribute
1405
+ if ( !RGraph.SVG.isNull(properties.tooltips)
1406
+ && (properties.tooltips[sequentialIndex] || typeof properties.tooltips === 'string')
1407
+ ) {
1408
+
1409
+ var obj = this;
1410
+
1411
+
1412
+ //
1413
+ // Add tooltip event listeners
1414
+ //
1415
+ (function (idx, seq)
1416
+ {
1417
+ rect.addEventListener(properties.tooltipsEvent.replace(/^on/, ''), function (e)
1418
+ {
1419
+ obj.removeHighlight();
1420
+
1421
+ var indexes = RGraph.SVG.sequentialIndexToGrouped(seq, obj.data);
1422
+
1423
+ // Show the tooltip
1424
+ RGraph.SVG.tooltip({
1425
+ object: obj,
1426
+ index: indexes[1],
1427
+ group: idx,
1428
+ sequentialIndex: seq,
1429
+ text: typeof properties.tooltips === 'string' ? properties.tooltips : properties.tooltips[seq],
1430
+ event: e
1431
+ });
1432
+
1433
+ // Highlight the rect that has been clicked on
1434
+ obj.highlight(e.target);
1435
+ }, false);
1436
+
1437
+ rect.addEventListener('mousemove', function (e)
1438
+ {
1439
+ e.target.style.cursor = 'pointer';
1440
+ }, false);
1441
+ })(i, sequentialIndex);
1442
+ }
1443
+ }
1444
+
1445
+ --sequentialIndex;
1446
+ }
1447
+ }
1448
+ };
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+ //
1458
+ // This function can be used to retrieve the relevant Y coordinate for a
1459
+ // particular value.
1460
+ //
1461
+ // @param int value The value to get the Y coordinate for
1462
+ //
1463
+ this.getYCoord = function (value)
1464
+ {
1465
+ if (value > this.scale.max) {
1466
+ return null;
1467
+ }
1468
+
1469
+ var y, xaxispos = properties.xaxispos;
1470
+
1471
+ if (value < this.scale.min) {
1472
+ return null;
1473
+ }
1474
+
1475
+ y = ((value - this.scale.min) / (this.scale.max - this.scale.min));
1476
+
1477
+ y *= (this.height - properties.marginTop - properties.marginBottom);
1478
+
1479
+ y = this.height - properties.marginBottom - y;
1480
+
1481
+ return y;
1482
+ };
1483
+
1484
+
1485
+
1486
+
1487
+
1488
+
1489
+
1490
+
1491
+ //
1492
+ // This function can be used to highlight a bar on the chart
1493
+ //
1494
+ // @param object rect The rectangle to highlight
1495
+ //
1496
+ this.highlight = function (rect)
1497
+ {
1498
+ var x = parseFloat(rect.getAttribute('x')) - 0.5,
1499
+ y = parseFloat(rect.getAttribute('y')) - 0.5,
1500
+ width = parseFloat(rect.getAttribute('width')) + 1,
1501
+ height = parseFloat(rect.getAttribute('height')) + 1;
1502
+
1503
+ var highlight = RGraph.SVG.create({
1504
+ svg: this.svg,
1505
+ parent: this.svg.all,
1506
+ type: 'rect',
1507
+ attr: {
1508
+ stroke: properties.highlightStroke,
1509
+ fill: properties.highlightFill,
1510
+ x: x,
1511
+ y: y,
1512
+ width: width,
1513
+ height: height,
1514
+ 'stroke-width': properties.highlightLinewidth
1515
+ },
1516
+ style: {
1517
+ pointerEvents: 'none'
1518
+ }
1519
+ });
1520
+
1521
+
1522
+ if (properties.tooltipsEvent === 'mousemove') {
1523
+
1524
+ //var obj = this;
1525
+
1526
+ //highlight.addEventListener('mouseout', function (e)
1527
+ //{
1528
+ // obj.removeHighlight();
1529
+ // RGraph.SVG.hideTooltip();
1530
+ // RGraph.SVG.REG.set('highlight', null);
1531
+ //}, false);
1532
+ }
1533
+
1534
+
1535
+ // Store the highlight rect in the rebistry so
1536
+ // it can be cleared later
1537
+ RGraph.SVG.REG.set('highlight', highlight);
1538
+ };
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+
1547
+ //
1548
+ // This allows for easy specification of gradients
1549
+ //
1550
+ this.parseColors = function ()
1551
+ {
1552
+ // Save the original colors so that they can be restored when
1553
+ // the canvas is cleared
1554
+ if (!Object.keys(this.originalColors).length) {
1555
+ this.originalColors = {
1556
+ colors: RGraph.SVG.arrayClone(properties.colors),
1557
+ backgroundGridColor: RGraph.SVG.arrayClone(properties.backgroundGridColor),
1558
+ highlightFill: RGraph.SVG.arrayClone(properties.highlightFill),
1559
+ backgroundColor: RGraph.SVG.arrayClone(properties.backgroundColor)
1560
+ }
1561
+ }
1562
+
1563
+
1564
+ // colors
1565
+ var colors = properties.colors;
1566
+
1567
+ if (colors) {
1568
+ for (var i=0; i<colors.length; ++i) {
1569
+
1570
+ colors[i] = RGraph.SVG.parseColorLinear({
1571
+ object: this,
1572
+ color: colors[i]
1573
+ });
1574
+ }
1575
+ }
1576
+
1577
+ properties.backgroundGridColor = RGraph.SVG.parseColorLinear({object: this, color: properties.backgroundGridColor});
1578
+ properties.highlightFill = RGraph.SVG.parseColorLinear({object: this, color: properties.highlightFill});
1579
+ properties.backgroundColor = RGraph.SVG.parseColorLinear({object: this, color: properties.backgroundColor});
1580
+ };
1581
+
1582
+
1583
+
1584
+
1585
+
1586
+
1587
+
1588
+
1589
+ //
1590
+ // Draws the labelsAbove
1591
+ //
1592
+ this.drawLabelsAbove = function ()
1593
+ {
1594
+ // Go through the above labels
1595
+ if (properties.labelsAbove) {
1596
+
1597
+ var data_seq = RGraph.SVG.arrayLinearize(this.data),
1598
+ seq = 0,
1599
+ stacked_total = 0;;
1600
+
1601
+ for (var i=0; i<this.coords.length; ++i,seq++) {
1602
+
1603
+ var num = typeof this.data[i] === 'number' ? this.data[i] : data_seq[seq] ;
1604
+
1605
+
1606
+
1607
+
1608
+
1609
+ // If this is a stacked chart then only dothe label
1610
+ // if it's the top segment
1611
+ if (properties.grouping === 'stacked') {
1612
+
1613
+ var indexes = RGraph.SVG.sequentialIndexToGrouped(i, this.data);
1614
+ var group = indexes[0];
1615
+ var datapiece = indexes[1];
1616
+
1617
+ if (datapiece !== (this.data[group].length - 1) ) {
1618
+ continue;
1619
+ } else {
1620
+ num = RGraph.SVG.arraySum(this.data[group]);
1621
+ }
1622
+ }
1623
+
1624
+
1625
+
1626
+
1627
+
1628
+ var str = RGraph.SVG.numberFormat({
1629
+ object: this,
1630
+ num: num.toFixed(properties.labelsAboveDecimals),
1631
+ prepend: typeof properties.labelsAboveUnitsPre === 'string' ? properties.labelsAboveUnitsPre : null,
1632
+ append: typeof properties.labelsAboveUnitsPost === 'string' ? properties.labelsAboveUnitsPost : null,
1633
+ point: typeof properties.labelsAbovePoint === 'string' ? properties.labelsAbovePoint : null,
1634
+ thousand: typeof properties.labelsAboveThousand === 'string' ? properties.labelsAboveThousand : null,
1635
+ formatter: typeof properties.labelsAboveFormatter === 'function' ? properties.labelsAboveFormatter : null
1636
+ });
1637
+
1638
+ // Facilitate labelsAboveSpecific
1639
+ if (properties.labelsAboveSpecific && properties.labelsAboveSpecific.length && (typeof properties.labelsAboveSpecific[seq] === 'string' || typeof properties.labelsAboveSpecific[seq] === 'number') ) {
1640
+ str = properties.labelsAboveSpecific[seq];
1641
+ } else if ( properties.labelsAboveSpecific && properties.labelsAboveSpecific.length && typeof properties.labelsAboveSpecific[seq] !== 'string' && typeof properties.labelsAboveSpecific[seq] !== 'number') {
1642
+ continue;
1643
+ }
1644
+
1645
+ var x = parseFloat(this.coords[i].element.getAttribute('x')) + parseFloat(this.coords[i].element.getAttribute('width') / 2) + properties.labelsAboveOffsetx;
1646
+
1647
+ if (data_seq[i] >= 0) {
1648
+ var y = parseFloat(this.coords[i].element.getAttribute('y')) - 7 + properties.labelsAboveOffsety;
1649
+ var valign = properties.labelsAboveValign;
1650
+ } else {
1651
+ var y = parseFloat(this.coords[i].element.getAttribute('y')) + parseFloat(this.coords[i].element.getAttribute('height')) + 7 - properties.labelsAboveOffsety;
1652
+ var valign = properties.labelsAboveValign === 'top' ? 'bottom' : 'top';
1653
+ }
1654
+
1655
+ var textConf = RGraph.SVG.getTextConf({
1656
+ object: this,
1657
+ prefix: 'labelsAbove'
1658
+ });
1659
+
1660
+ RGraph.SVG.text({
1661
+ object: this,
1662
+ parent: this.svg.all,
1663
+ tag: 'labels.above',
1664
+
1665
+ text: str,
1666
+
1667
+ x: x,
1668
+ y: y,
1669
+
1670
+ halign: properties.labelsAboveHalign,
1671
+ valign: valign,
1672
+
1673
+ font: textConf.font,
1674
+ size: textConf.size,
1675
+ bold: textConf.bold,
1676
+ italic: textConf.italic,
1677
+ color: textConf.color,
1678
+
1679
+ background: properties.labelsAboveBackground || null,
1680
+ padding: properties.labelsAboveBackgroundPadding || 0
1681
+ });
1682
+ }
1683
+ }
1684
+ };
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+
1691
+
1692
+
1693
+ //
1694
+ // Using a function to add events makes it easier to facilitate method
1695
+ // chaining
1696
+ //
1697
+ // @param string type The type of even to add
1698
+ // @param function func
1699
+ //
1700
+ this.on = function (type, func)
1701
+ {
1702
+ if (type.substr(0,2) !== 'on') {
1703
+ type = 'on' + type;
1704
+ }
1705
+
1706
+ RGraph.SVG.addCustomEventListener(this, type, func);
1707
+
1708
+ return this;
1709
+ };
1710
+
1711
+
1712
+
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+ //
1719
+ // Used in chaining. Runs a function there and then - not waiting for
1720
+ // the events to fire (eg the onbeforedraw event)
1721
+ //
1722
+ // @param function func The function to execute
1723
+ //
1724
+ this.exec = function (func)
1725
+ {
1726
+ func(this);
1727
+
1728
+ return this;
1729
+ };
1730
+
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+
1737
+
1738
+ //
1739
+ // Remove highlight from the chart (tooltips)
1740
+ //
1741
+ this.removeHighlight = function ()
1742
+ {
1743
+ //var highlight = RGraph.SVG.REG.get('highlight');
1744
+ //if (highlight && highlight.parentNode) {
1745
+ // highlight.parentNode.removeChild(highlight);
1746
+ //}
1747
+
1748
+ //RGraph.SVG.REG.set('highlight', null);
1749
+
1750
+ RGraph.SVG.removeHighlight();
1751
+ };
1752
+
1753
+
1754
+
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+ //
1761
+ // Draws the top of 3D bars
1762
+ //
1763
+ this.drawTop3dFace = function (opt)
1764
+ {
1765
+ var rect = opt.rect,
1766
+ arr = [parseInt(rect.getAttribute('fill')), 'rgba(255,255,255,0.7)'],
1767
+ x = parseInt(rect.getAttribute('x')),
1768
+ y = parseInt(rect.getAttribute('y')),
1769
+ w = parseInt(rect.getAttribute('width')),
1770
+ h = parseInt(rect.getAttribute('height')),
1771
+ value = parseFloat(rect.getAttribute('data-value'));
1772
+
1773
+
1774
+ rect.rgraph_3d_top_face = [];
1775
+
1776
+
1777
+ for (var i=0; i<2; ++i) {
1778
+
1779
+ var color = (i === 0 ? rect.getAttribute('fill') : 'rgba(255,255,255,0.7)');
1780
+
1781
+ var face = RGraph.SVG.create({
1782
+ svg: this.svg,
1783
+ type: 'path',
1784
+ parent: properties.variant === '3d' && opt.value < 0 ? this.threed_xaxis_group : this.svg.all,
1785
+ attr: {
1786
+ stroke: properties.colorsStroke,
1787
+ fill: color,
1788
+ 'stroke-width': properties.linewidth,
1789
+ d: 'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(
1790
+ x,
1791
+ y,
1792
+
1793
+ x + properties.variant3dOffsetx,
1794
+ y - properties.variant3dOffsety,
1795
+
1796
+ x + w + properties.variant3dOffsetx,
1797
+ y - properties.variant3dOffsety,
1798
+
1799
+ x + w,
1800
+ y
1801
+ )
1802
+ }
1803
+ });
1804
+
1805
+
1806
+
1807
+ // Store a reference to the rect on the front face of the bar
1808
+ rect.rgraph_3d_top_face[i] = face
1809
+ }
1810
+ };
1811
+
1812
+
1813
+
1814
+
1815
+
1816
+
1817
+
1818
+
1819
+ //
1820
+ // Draws the top of 3D bars
1821
+ //
1822
+ this.drawSide3dFace = function (opt)
1823
+ {
1824
+ var rect = opt.rect,
1825
+ arr = [parseInt(rect.getAttribute('fill')), 'rgba(0,0,0,0.3)'],
1826
+ x = parseInt(rect.getAttribute('x')),
1827
+ y = parseInt(rect.getAttribute('y')),
1828
+ w = parseInt(rect.getAttribute('width')),
1829
+ h = parseInt(rect.getAttribute('height'));
1830
+
1831
+ rect.rgraph_3d_side_face = [];
1832
+
1833
+ for (var i=0; i<2; ++i) {
1834
+
1835
+ var color = (i === 0 ? rect.getAttribute('fill') : 'rgba(0,0,0,0.3)');
1836
+
1837
+ var face = RGraph.SVG.create({
1838
+ svg: this.svg,
1839
+ type: 'path',
1840
+ parent: properties.variant === '3d' && opt.value < 0 ? this.threed_xaxis_group : this.svg.all,
1841
+ attr: {
1842
+ stroke: properties.colorsStroke,
1843
+ fill: color,
1844
+ 'stroke-width': properties.linewidth,
1845
+ d: 'M {1} {2} L {3} {4} L {5} {6} L {7} {8}'.format(
1846
+ x + w,
1847
+ y,
1848
+
1849
+ x + w + properties.variant3dOffsetx,
1850
+ y - properties.variant3dOffsety,
1851
+
1852
+ x + w + properties.variant3dOffsetx,
1853
+ y + h - properties.variant3dOffsety,
1854
+
1855
+ x + w,
1856
+ y + h
1857
+ )
1858
+ }
1859
+ });
1860
+
1861
+
1862
+ // Store a reference to the rect on the front face of the bar
1863
+ rect.rgraph_3d_side_face[i] = face
1864
+ }
1865
+ };
1866
+
1867
+
1868
+
1869
+
1870
+
1871
+
1872
+
1873
+
1874
+ // This function is used to draw the errorbar. Its in the common
1875
+ // file because it's used by multiple chart libraries
1876
+ this.drawErrorbar = function (opt)
1877
+ {
1878
+ var index = opt.index,
1879
+ datapoint = opt.value,
1880
+ linewidth = RGraph.SVG.getErrorbarsLinewidth({object: this, index: index}),
1881
+ color = RGraph.SVG.getErrorbarsColor({object: this, index: index}),
1882
+ capwidth = RGraph.SVG.getErrorbarsCapWidth({object: this, index: index}),
1883
+ element = opt.element,
1884
+ type = opt.type;
1885
+
1886
+
1887
+
1888
+ // Get the error bar value
1889
+ var max = RGraph.SVG.getErrorbarsMaxValue({
1890
+ object: this,
1891
+ index: index
1892
+ });
1893
+
1894
+
1895
+
1896
+ // Get the error bar value
1897
+ var min = RGraph.SVG.getErrorbarsMinValue({
1898
+ object: this,
1899
+ index: index
1900
+ });
1901
+
1902
+
1903
+
1904
+
1905
+ if (!max && !min) {
1906
+ return;
1907
+ }
1908
+
1909
+
1910
+ // Accounts for stacked bars
1911
+ if (type === 'stacked') {
1912
+ datapoint = RGraph.SVG.arraySum(this.data[index]);
1913
+ }
1914
+
1915
+
1916
+ if (datapoint >= 0) {
1917
+
1918
+ var x1 = parseFloat(element.getAttribute('x')) + (parseFloat(element.getAttribute('width')) / 2);
1919
+
1920
+ // Draw the UPPER vertical line
1921
+ var errorbarLine = RGraph.SVG.create({
1922
+ svg: this.svg,
1923
+ type: 'line',
1924
+ parent: this.svg.all,
1925
+ attr: {
1926
+ x1: x1,
1927
+ y1: parseFloat(element.getAttribute('y')),
1928
+ x2: x1,
1929
+ y2: this.getYCoord(parseFloat(datapoint + max)),
1930
+ stroke: color,
1931
+ 'stroke-width': linewidth
1932
+ }
1933
+ });
1934
+
1935
+ // Draw the cap to the UPPER line
1936
+ var errorbarCap = RGraph.SVG.create({
1937
+ svg: this.svg,
1938
+ type: 'line',
1939
+ parent: this.svg.all,
1940
+ attr: {
1941
+ x1: parseFloat(errorbarLine.getAttribute('x1')) - (capwidth / 2),
1942
+ y1: errorbarLine.getAttribute('y2'),
1943
+ x2: parseFloat(errorbarLine.getAttribute('x1')) + (capwidth / 2),
1944
+ y2: errorbarLine.getAttribute('y2'),
1945
+ stroke: color,
1946
+ 'stroke-width': linewidth
1947
+ }
1948
+ });
1949
+
1950
+
1951
+
1952
+
1953
+
1954
+
1955
+
1956
+
1957
+
1958
+
1959
+
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+ // Draw the minimum errorbar if necessary
1966
+ if (typeof min === 'number') {
1967
+
1968
+ var errorbarLine = RGraph.SVG.create({
1969
+ svg: this.svg,
1970
+ type: 'line',
1971
+ parent: this.svg.all,
1972
+ attr: {
1973
+ x1: x1,
1974
+ y1: parseFloat(element.getAttribute('y')),
1975
+ x2: x1,
1976
+ y2: this.getYCoord(parseFloat(datapoint - min)),
1977
+ stroke: color,
1978
+ 'stroke-width': linewidth
1979
+ }
1980
+ });
1981
+
1982
+ // Draw the cap to the UPPER line
1983
+ var errorbarCap = RGraph.SVG.create({
1984
+ svg: this.svg,
1985
+ type: 'line',
1986
+ parent: this.svg.all,
1987
+ attr: {
1988
+ x1: parseFloat(errorbarLine.getAttribute('x1')) - (capwidth / 2),
1989
+ y1: errorbarLine.getAttribute('y2'),
1990
+ x2: parseFloat(errorbarLine.getAttribute('x1')) + (capwidth / 2),
1991
+ y2: errorbarLine.getAttribute('y2'),
1992
+ stroke: color,
1993
+ 'stroke-width': linewidth
1994
+ }
1995
+ });
1996
+ }
1997
+
1998
+
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+
2009
+
2010
+
2011
+ } else if (datapoint < 0) {
2012
+
2013
+ var x1 = parseFloat(element.getAttribute('x')) + (parseFloat(element.getAttribute('width')) / 2),
2014
+ y1 = parseFloat(element.getAttribute('y')) + parseFloat(element.getAttribute('height')),
2015
+ y2 = this.getYCoord(parseFloat(datapoint - Math.abs(max) ))
2016
+
2017
+ // Draw the vertical line
2018
+ var errorbarLine = RGraph.SVG.create({
2019
+ svg: this.svg,
2020
+ type: 'line',
2021
+ parent: this.svg.all,
2022
+ attr: {
2023
+ x1: x1,
2024
+ y1: y1,
2025
+ x2: x1,
2026
+ y2: y2,
2027
+ stroke: color,
2028
+ 'stroke-width': linewidth
2029
+ }
2030
+ });
2031
+
2032
+ // Draw the cap to the vertical line
2033
+ var errorbarCap = RGraph.SVG.create({
2034
+ svg: this.svg,
2035
+ type: 'line',
2036
+ parent: this.svg.all,
2037
+ attr: {
2038
+ x1: parseFloat(errorbarLine.getAttribute('x1')) - (capwidth / 2),
2039
+ y1: errorbarLine.getAttribute('y2'),
2040
+ x2: parseFloat(errorbarLine.getAttribute('x1')) + (capwidth / 2),
2041
+ y2: errorbarLine.getAttribute('y2'),
2042
+ stroke: color,
2043
+ 'stroke-width': linewidth
2044
+ }
2045
+ });
2046
+
2047
+
2048
+
2049
+
2050
+
2051
+
2052
+
2053
+
2054
+
2055
+
2056
+
2057
+
2058
+ // Draw the minimum errorbar if necessary
2059
+ if (typeof min === 'number') {
2060
+
2061
+ var x1 = parseFloat(element.getAttribute('x')) + (parseFloat(element.getAttribute('width')) / 2);
2062
+
2063
+ var errorbarLine = RGraph.SVG.create({
2064
+ svg: this.svg,
2065
+ type: 'line',
2066
+ parent: this.svg.all,
2067
+ attr: {
2068
+ x1: x1,
2069
+ y1: this.getYCoord(parseFloat(datapoint + min)),
2070
+ x2: x1,
2071
+ y2: this.getYCoord(parseFloat(datapoint)),
2072
+ stroke: color,
2073
+ 'stroke-width': linewidth
2074
+ }
2075
+ });
2076
+
2077
+ // Draw the cap to the UPPER line
2078
+ var errorbarCap = RGraph.SVG.create({
2079
+ svg: this.svg,
2080
+ type: 'line',
2081
+ parent: this.svg.all,
2082
+ attr: {
2083
+ x1: parseFloat(errorbarLine.getAttribute('x1')) - (capwidth / 2),
2084
+ y1: errorbarLine.getAttribute('y1'),
2085
+ x2: parseFloat(errorbarLine.getAttribute('x1')) + (capwidth / 2),
2086
+ y2: errorbarLine.getAttribute('y1'),
2087
+ stroke: color,
2088
+ 'stroke-width': linewidth
2089
+ }
2090
+ });
2091
+ }
2092
+ }
2093
+ };
2094
+
2095
+
2096
+
2097
+
2098
+
2099
+
2100
+
2101
+
2102
+ //
2103
+ // The Bar chart grow effect
2104
+ //
2105
+ this.grow = function ()
2106
+ {
2107
+ var opt = arguments[0] || {},
2108
+ frames = opt.frames || 30,
2109
+ frame = 0,
2110
+ obj = this,
2111
+ data = [],
2112
+ height = null,
2113
+ seq = 0;
2114
+
2115
+ //
2116
+ // Copy the data
2117
+ //
2118
+ data = RGraph.SVG.arrayClone(this.data);
2119
+
2120
+ this.draw();
2121
+
2122
+ var iterate = function ()
2123
+ {
2124
+
2125
+ for (var i=0,seq=0,len=obj.coords.length; i<len; ++i, ++seq) {
2126
+
2127
+ var multiplier = (frame / frames)
2128
+ // RGraph.SVG.FX.getEasingMultiplier(frames, frame)
2129
+ // RGraph.SVG.FX.getEasingMultiplier(frames, frame);
2130
+
2131
+
2132
+
2133
+
2134
+ // TODO Go through the data and update the value according to
2135
+ // the frame number
2136
+ if (typeof data[i] === 'number') {
2137
+
2138
+ height = Math.abs(obj.getYCoord(data[i]) - obj.getYCoord(0));
2139
+ obj.data[i] = data[i] * multiplier;
2140
+ height = multiplier * height;
2141
+
2142
+ // Set the new height on the rect
2143
+ obj.coords[seq].element.setAttribute(
2144
+ 'height',
2145
+ height
2146
+ );
2147
+
2148
+ // Set the correct Y coord on the object
2149
+ obj.coords[seq].element.setAttribute(
2150
+ 'y',
2151
+ data[i] < 0 ? obj.getYCoord(0) : obj.getYCoord(0) - height
2152
+ );
2153
+
2154
+
2155
+
2156
+ // This upadtes the size of the 3D sides to the bar
2157
+ if (properties.variant === '3d') {
2158
+
2159
+ // Remove the 3D sides to the bar
2160
+ if (obj.coords[i].element.rgraph_3d_side_face[0].parentNode) obj.coords[i].element.rgraph_3d_side_face[0].parentNode.removeChild(obj.coords[i].element.rgraph_3d_side_face[0]);
2161
+ if (obj.coords[i].element.rgraph_3d_side_face[1].parentNode) obj.coords[i].element.rgraph_3d_side_face[1].parentNode.removeChild(obj.coords[i].element.rgraph_3d_side_face[1]);
2162
+
2163
+ if (obj.coords[i].element.rgraph_3d_top_face[0].parentNode) obj.coords[i].element.rgraph_3d_top_face[0].parentNode.removeChild(obj.coords[i].element.rgraph_3d_top_face[0]);
2164
+ if (obj.coords[i].element.rgraph_3d_top_face[1].parentNode) obj.coords[i].element.rgraph_3d_top_face[1].parentNode.removeChild(obj.coords[i].element.rgraph_3d_top_face[1]);
2165
+
2166
+ // Add the 3D sides to the bar (again)
2167
+ obj.drawSide3dFace({rect: obj.coords[i].element});
2168
+
2169
+ // Draw the top side of the 3D bar
2170
+ if (properties.grouping === 'grouped') {
2171
+ obj.drawTop3dFace({rect: obj.coords[i].element });
2172
+ }
2173
+
2174
+ // Now remove and immediately re-add the front face of
2175
+ // the bar - this is so that the front face appears
2176
+ // above the other sides
2177
+ if (obj.coords[i].element.parentNode) {
2178
+ var parent = obj.coords[i].element.parentNode;
2179
+ var node = parent.removeChild(obj.coords[i].element);
2180
+ parent.appendChild(node);
2181
+ }
2182
+ }
2183
+
2184
+
2185
+ } else if (typeof data[i] === 'object') {
2186
+
2187
+ var accumulativeHeight = 0;
2188
+
2189
+ for (var j=0,len2=data[i].length; j<len2; ++j, ++seq) {
2190
+
2191
+ height = Math.abs(obj.getYCoord(data[i][j]) - obj.getYCoord(0));
2192
+ height = multiplier * height;
2193
+ obj.data[i][j] = data[i][j] * multiplier;
2194
+ height = Math.round(height);
2195
+
2196
+ obj.coords[seq].element.setAttribute(
2197
+ 'height',
2198
+ height
2199
+ );
2200
+
2201
+ obj.coords[seq].element.setAttribute(
2202
+ 'y',
2203
+ data[i][j] < 0 ? (obj.getYCoord(0) + accumulativeHeight) : (obj.getYCoord(0) - height - accumulativeHeight)
2204
+ );
2205
+
2206
+
2207
+
2208
+
2209
+
2210
+ // This updates the size of the 3D sides to the bar
2211
+ if (properties.variant === '3d') {
2212
+
2213
+ // Remove the 3D sides to the bar
2214
+ if (obj.coords[seq].element.rgraph_3d_side_face[0].parentNode) obj.coords[seq].element.rgraph_3d_side_face[0].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_side_face[0]);
2215
+ if (obj.coords[seq].element.rgraph_3d_side_face[1].parentNode) obj.coords[seq].element.rgraph_3d_side_face[1].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_side_face[1]);
2216
+
2217
+ if (obj.coords[seq].element.rgraph_3d_top_face[0].parentNode) obj.coords[seq].element.rgraph_3d_top_face[0].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_top_face[0]);
2218
+ if (obj.coords[seq].element.rgraph_3d_top_face[1].parentNode) obj.coords[seq].element.rgraph_3d_top_face[1].parentNode.removeChild(obj.coords[seq].element.rgraph_3d_top_face[1]);
2219
+
2220
+ // Add the 3D sides to the bar (again)
2221
+ obj.drawSide3dFace({rect: obj.coords[seq].element});
2222
+
2223
+ // Draw the top side of the 3D bar
2224
+ // TODO Need to only draw the top face when the bar is either
2225
+ // not stacked or is the last segment in the stack
2226
+ obj.drawTop3dFace({rect: obj.coords[seq].element});
2227
+
2228
+ // Now remove and immediately re-add the front face of
2229
+ // the bar - this is so that the front face appears
2230
+ // above the other sides
2231
+ if (obj.coords[seq].element.parentNode) {
2232
+ var parent = obj.coords[seq].element.parentNode;
2233
+ var node = parent.removeChild(obj.coords[seq].element);
2234
+ parent.appendChild(node);
2235
+ }
2236
+ }
2237
+ accumulativeHeight += (properties.grouping === 'stacked' ? height : 0);
2238
+
2239
+ }
2240
+
2241
+ //
2242
+ // Set the height and Y cooord of the backfaces if necessary
2243
+ //
2244
+ if (obj.stackedBackfaces[i]) {
2245
+ obj.stackedBackfaces[i].setAttribute(
2246
+ 'height',
2247
+ accumulativeHeight
2248
+ );
2249
+
2250
+ obj.stackedBackfaces[i].setAttribute(
2251
+ 'y',
2252
+ obj.height - properties.marginBottom - accumulativeHeight
2253
+ );
2254
+ }
2255
+
2256
+ // Decrease seq by one so that it's not incremented twice
2257
+ --seq;
2258
+ }
2259
+ }
2260
+
2261
+ if (frame++ < frames) {
2262
+ //setTimeout(iterate, frame > 1 ? opt.delay : 200);
2263
+ RGraph.SVG.FX.update(iterate);
2264
+ } else if (opt.callback) {
2265
+ (opt.callback)(obj);
2266
+ }
2267
+ };
2268
+
2269
+ iterate();
2270
+
2271
+ return this;
2272
+ };
2273
+
2274
+
2275
+
2276
+
2277
+
2278
+
2279
+
2280
+
2281
+ //
2282
+ // HBar chart Wave effect.
2283
+ //
2284
+ // @param object OPTIONAL An object map of options. You specify 'frames'
2285
+ // here to give the number of frames in the effect
2286
+ // and also callback to specify a callback function
2287
+ // thats called at the end of the effect
2288
+ //
2289
+ this.wave = function ()
2290
+ {
2291
+ // First draw the chart
2292
+ this.draw();
2293
+
2294
+ var obj = this,
2295
+ opt = arguments[0] || {};
2296
+
2297
+ opt.frames = opt.frames || 60;
2298
+ opt.startFrames = [];
2299
+ opt.counters = [];
2300
+
2301
+ var framesperbar = opt.frames / 3,
2302
+ frame = -1,
2303
+ callback = opt.callback || function () {};
2304
+
2305
+ for (var i=0,len=this.coords.length; i<len; ++i) {
2306
+
2307
+ opt.startFrames[i] = ((opt.frames / 2) / (obj.coords.length - 1)) * i;
2308
+ opt.counters[i] = 0;
2309
+
2310
+ // Now zero the height of the bar (and remove the 3D faces)
2311
+ this.coords[i].element.setAttribute('height', 0);
2312
+
2313
+ if (this.coords[i].element.rgraph_3d_side_face) {
2314
+
2315
+ var parent = this.coords[i].element.rgraph_3d_side_face[0].parentNode;
2316
+
2317
+ parent.removeChild(this.coords[i].element.rgraph_3d_side_face[0]);
2318
+ parent.removeChild(this.coords[i].element.rgraph_3d_side_face[1]);
2319
+
2320
+ parent.removeChild(this.coords[i].element.rgraph_3d_top_face[0]);
2321
+ parent.removeChild(this.coords[i].element.rgraph_3d_top_face[1]);
2322
+ }
2323
+ }
2324
+
2325
+ function iterator ()
2326
+ {
2327
+ ++frame;
2328
+
2329
+ for (var i=0,len=obj.coords.length; i<len; ++i) {
2330
+
2331
+ var el = obj.coords[i].element;
2332
+
2333
+ if (frame > opt.startFrames[i]) {
2334
+
2335
+ var originalHeight = el.getAttribute('data-original-height'),
2336
+ height,
2337
+ value = parseFloat(el.getAttribute('data-value'));
2338
+
2339
+ var height = Math.min(
2340
+ ((frame - opt.startFrames[i]) / framesperbar) * originalHeight,
2341
+ originalHeight
2342
+ );
2343
+
2344
+ el.setAttribute(
2345
+ 'height',
2346
+ height < 0 ? 0 : height
2347
+ );
2348
+
2349
+ el.setAttribute(
2350
+ 'y',
2351
+ value >=0 ? obj.getYCoord(0) - height : obj.getYCoord(0)
2352
+ );
2353
+
2354
+
2355
+
2356
+ // This updates the size of the 3D sides to the bar
2357
+ if (properties.variant === '3d') {
2358
+
2359
+ // Remove the 3D sides to the bar
2360
+ var parent = el.rgraph_3d_side_face[0].parentNode;
2361
+
2362
+ if (parent) parent.removeChild(el.rgraph_3d_side_face[0]);
2363
+ if (parent) parent.removeChild(el.rgraph_3d_side_face[1]);
2364
+
2365
+ var parent = el.rgraph_3d_top_face[0].parentNode;
2366
+ if (parent) parent.removeChild(el.rgraph_3d_top_face[0]);
2367
+ if (parent) parent.removeChild(el.rgraph_3d_top_face[1]);
2368
+
2369
+
2370
+
2371
+ // Now remove and immediately re-add the front face of
2372
+ // the bar - this is so that the front face appears
2373
+ // above the other sides
2374
+ if (el.parentNode) {
2375
+ var parent = el.parentNode;
2376
+ var node = parent.removeChild(el);
2377
+ parent.appendChild(node);
2378
+ }
2379
+ }
2380
+
2381
+
2382
+ if (properties.grouping === 'stacked') {
2383
+
2384
+ var seq = el.getAttribute('data-sequential-index');
2385
+ var indexes = RGraph.SVG.sequentialIndexToGrouped(seq, obj.data);
2386
+
2387
+ if (indexes[1] > 0) {
2388
+ el.setAttribute(
2389
+ 'y',
2390
+ parseFloat(obj.coords[i - 1].element.getAttribute('y')) - height + 1
2391
+ );
2392
+ }
2393
+ }
2394
+
2395
+ if (properties.variant === '3d') {
2396
+ // Add the 3D sides to the bar (again)
2397
+ obj.drawSide3dFace({
2398
+ rect: el,
2399
+ value: el.getAttribute('data-value')
2400
+ });
2401
+
2402
+ // Draw the top side of the 3D bar
2403
+ if (properties.grouping === 'grouped' || (properties.grouping === 'stacked' && (indexes[1] + 1) === obj.data[indexes[0]].length) ) {
2404
+ obj.drawTop3dFace({
2405
+ rect: el,
2406
+ value: el.getAttribute('data-value')
2407
+ });
2408
+ }
2409
+ }
2410
+ }
2411
+ }
2412
+
2413
+
2414
+ if (frame >= opt.frames) {
2415
+ callback(obj);
2416
+ } else {
2417
+ RGraph.SVG.FX.update(iterator);
2418
+ }
2419
+ }
2420
+
2421
+ iterator();
2422
+
2423
+ return this;
2424
+ };
2425
+
2426
+
2427
+
2428
+
2429
+
2430
+
2431
+
2432
+
2433
+ //
2434
+ // A worker function that handles Bar chart specific tooltip substitutions
2435
+ //
2436
+ this.tooltipSubstitutions = function (opt)
2437
+ {
2438
+ var indexes = RGraph.SVG.sequentialIndexToGrouped(opt.index, this.data);
2439
+
2440
+ return {
2441
+ index: indexes[1],
2442
+ dataset: indexes[0],
2443
+ sequentialIndex: opt.index,
2444
+ value: typeof this.data[indexes[0]] === 'number' ? this.data[indexes[0]] : this.data[indexes[0]][indexes[1]],
2445
+ values: typeof this.data[indexes[0]] === 'number' ? [this.data[indexes[0]]] : this.data[indexes[0]]
2446
+ };
2447
+ };
2448
+
2449
+
2450
+
2451
+
2452
+
2453
+
2454
+
2455
+
2456
+ //
2457
+ // A worker function that returns the correct color/label/value
2458
+ //
2459
+ // @param object specific The indexes that are applicable
2460
+ // @param number index The appropriate index
2461
+ //
2462
+ this.tooltipsFormattedCustom = function (specific, index)
2463
+ {
2464
+ if (typeof this.data[0] === 'object') {
2465
+ var label = (!RGraph.SVG.isNull(properties.tooltipsFormattedKeyLabels) && typeof properties.tooltipsFormattedKeyLabels === 'object' && properties.tooltipsFormattedKeyLabels[index])
2466
+ ? properties.tooltipsFormattedKeyLabels[index]
2467
+ : '';
2468
+
2469
+ } else {
2470
+
2471
+ var label = ( !RGraph.SVG.isNull(properties.tooltipsFormattedKeyLabels)
2472
+ && typeof properties.tooltipsFormattedKeyLabels === 'object'
2473
+ && properties.tooltipsFormattedKeyLabels[specific.index])
2474
+ ? properties.tooltipsFormattedKeyLabels[specific.index]
2475
+ : '';
2476
+ }
2477
+
2478
+ return {
2479
+ label: label
2480
+ };
2481
+ };
2482
+
2483
+
2484
+
2485
+
2486
+
2487
+
2488
+
2489
+
2490
+ //
2491
+ // This allows for static tooltip positioning
2492
+ //
2493
+ this.positionTooltipStatic = function (args)
2494
+ {
2495
+ var obj = args.object,
2496
+ e = args.event,
2497
+ tooltip = args.tooltip,
2498
+ index = args.index,
2499
+ svgXY = RGraph.SVG.getSVGXY(obj.svg),
2500
+ coords = this.coords[args.index];
2501
+
2502
+ // Position the tooltip in the X direction
2503
+ args.tooltip.style.left = (
2504
+ svgXY[0] // The X coordinate of the canvas
2505
+ + coords.x // The X coordinate of the bar on the chart
2506
+ - (tooltip.offsetWidth / 2) // Subtract half of the tooltip width
2507
+ + (coords.width / 2) // Add half of the bar width
2508
+ ) + 'px';
2509
+
2510
+
2511
+
2512
+
2513
+ // If the chart is a 3D version the tooltip Y position needs this
2514
+ // adjustment
2515
+ var adjustment = 0;
2516
+
2517
+ if (properties.variant === '3d') {
2518
+ var left = coords.x;
2519
+ var top = coords.y;
2520
+ var angle = 5 / (180 / Math.PI);
2521
+
2522
+ var adjustment = Math.tan(angle) * left;
2523
+ }
2524
+
2525
+
2526
+
2527
+
2528
+ args.tooltip.style.top = (
2529
+ svgXY[1] // The Y coordinate of the canvas
2530
+ + coords.y // The Y coordinate of the bar on the chart
2531
+ - tooltip.offsetHeight // The height of the tooltip
2532
+ - 15 // An arbitrary amount
2533
+ + adjustment // Account for the 3D
2534
+ ) + 'px';
2535
+
2536
+
2537
+ // If the bar is a negative one, add half the height to the Y coord
2538
+ var data_arr = RGraph.SVG.arrayLinearize(this.data);
2539
+
2540
+ if (data_arr[index] < 0) {
2541
+ args.tooltip.style.top =
2542
+ parseFloat(args.tooltip.style.top)
2543
+ + (coords.height / 2)
2544
+ + 'px';
2545
+ }
2546
+
2547
+
2548
+
2549
+ // If the top of the tooltip is off the top of the page
2550
+ // then move the tooltip down
2551
+ if(parseFloat(args.tooltip.style.top) < 0) {
2552
+ args.tooltip.style.top = parseFloat(args.tooltip.style.top) + 20 + 'px';
2553
+ }
2554
+ };
2555
+
2556
+
2557
+
2558
+
2559
+
2560
+
2561
+
2562
+
2563
+ //
2564
+ // Set the options that the user has provided
2565
+ //
2566
+ for (i in conf.options) {
2567
+ if (typeof i === 'string') {
2568
+ this.set(i, conf.options[i]);
2569
+ }
2570
+ }
2571
+ };
2572
+
2573
+ return this;
2574
+
2575
+ // End module pattern
2576
+ })(window, document);