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,51 +1,1526 @@
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.Waterfall=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 tmp=RG.SVG.propertyNameAlias({object:this,name:name,value:value});name=tmp.name;value=tmp.value;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
- {var tmp=RG.SVG.propertyNameAlias({object:this,name:name});name=tmp.name;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='waterfall';this.coords=[];this.colorsParsed=false;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,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:['black','red','blue'],colorsSequential:false,colorsStroke:'#aaa',colorsConnector:null,total:true,hmargin:5,linewidth:1,yaxis:true,yaxisTickmarks:true,yaxisTickmarksLength:5,yaxisColor:'black',yaxisScale:true,yaxisLabels:null,yaxisLabelsOffsetx:0,yaxisLabelsOffsety:0,yaxisLabelsCount:5,yaxisScaleUnitsPre:'',yaxisScaleUnitsPost:'',yaxisScaleStrict:false,yaxisScaleDecimals:0,yaxisScalePoint:'.',yaxisScaleThousand:',',yaxisScaleRound:false,yaxisScaleMax:null,yaxisScaleMin:0,yaxisScaleFormatter:null,yaxisLabelsColor:null,yaxisLabelsBold:null,yaxisLabelsItalic:null,yaxisLabelsFont:null,yaxisLabelsSize:null,xaxis:true,xaxisTickmarks:true,xaxisTickmarksLength:5,xaxisLabels:null,xaxisLabelsFont:null,xaxisLabelsSize:null,xaxisLabelsColor:null,xaxisLabelsBold:null,xaxisLabelsItalic:null,xaxisLabelsPosition:'section',xaxisLabelsPositionEdgeTickmarksCount:null,xaxisColor:'black',xaxisLabelsOffsetx:0,xaxisLabelsOffsety:0,labelsAbove:false,labelsAboveFont:null,labelsAboveSize:null,labelsAboveBold:null,labelsAboveItalic:null,labelsAboveColor:null,labelsAboveBackground:'rgba(255,255,255,0.5)',labelsAboveBackgroundPadding:2,labelsAboveUnitsPre:null,labelsAboveUnitsPost:null,labelsAbovePoint:null,labelsAboveThousand:null,labelsAboveFormatter:null,labelsAboveDecimals:null,labelsAboveOffsetx:0,labelsAboveOffsety:0,labelsAboveHalign:'center',labelsAboveValign:'bottom',labelsAboveSpecific:null,labelsAboveLastFont:null,labelsAboveLastBold:null,labelsAboveLastItalic:null,labelsAboveLastSize:null,labelsAboveLastColor:null,labelsAboveLastBackground:null,labelsAboveLastBackgroundPadding:null,textColor:'black',textFont:'Arial, Verdana, sans-serif',textSize:12,textBold:false,textItalic:false,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:null,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,key:null,keyColors:null,keyOffsetx:0,keyOffsety:0,keyLabelsOffsetx:0,keyLabelsOffsety:-1,keyLabelsFont:null,keyLabelsSize:null,keyLabelsColor:null,keyLabelsBold:null,keyLabelsItalic: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'));RG.SVG.createDefs(this);this.coords=[];this.graphWidth=this.width-prop.marginLeft-prop.marginRight;this.graphHeight=this.height-prop.marginTop-prop.marginBottom;RG.SVG.resetColorsToOriginalValues({object:this});this.parseColors();if(prop.total){var sum=RG.SVG.arraySum(this.data);this.data.push(sum);if(prop.xaxisLabels&&prop.xaxisLabels.length===(this.data.length-1)){prop.xaxisLabels.push('');}}
10
- for(var i=0,max=0,runningTotal=0;i<this.data.length-(prop.total?1:0);++i){runningTotal+=this.data[i]
11
- max=ma.max(ma.abs(max),ma.abs(runningTotal));}
12
- if(typeof prop.yaxisScaleMax==='number'){max=prop.yaxisScaleMax;}
13
- if(prop.yaxisScaleMin==='mirror'||prop.yaxisScaleMin==='middle'||prop.yaxisScaleMin==='center'){var mirrorScale=true;prop.yaxisScaleMin=0;}
14
- 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});}
15
- this.max=this.scale.max;this.min=this.scale.min;prop.yaxisScaleMax=this.scale.max;prop.yaxisScaleMin=this.scale.min;RG.SVG.drawBackground(this);RG.SVG.drawXAxis(this);RG.SVG.drawYAxis(this);this.drawBars();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?');}
16
- RG.SVG.attribution(this);RG.SVG.fireCustomEvent(this,'ondraw');return this;};this.drawBars=function()
17
- {this.graphWidth=this.width-prop.marginLeft-prop.marginRight;this.graphHeight=this.height-prop.marginTop-prop.marginBottom;var innerWidth=(this.graphWidth/this.data.length)-(2*prop.hmargin),outerWidth=(this.graphWidth/this.data.length);var y=this.getYCoord(0),total=0;for(var i=0;i<(this.data.length);++i){var prevValue=this.data[i-1],nextValue=this.data[i+1],currentValue=this.data[i],prevTotal=total;total+=parseFloat(this.data[i])||0;var height=ma.abs((this.data[i]/(this.scale.max-this.scale.min))*this.graphHeight);if(RG.SVG.isNull(prevValue)){if(currentValue>0){y=this.getYCoord(prevTotal)-height;}else{y=this.getYCoord(prevTotal);}}else{if(i==0&&this.data[i]>0){y=y-height;}else if(this.data[i]>0&&this.data[i-1]>0){y=y-height;}else if(this.data[i]>0&&this.data[i-1]<0){y=y+prevHeight-height;}else if(this.data[i]<0&&this.data[i-1]>0){}else if(this.data[i]<0&&this.data[i-1]<0){y=y+prevHeight;}}
18
- var fill=this.data[i]>0?prop.colors[0]:prop.colors[1];if(prop.colorsSequential){fill=prop.colors[i];}
19
- if(prop.total){if(i===(this.data.length-1)&&this.data[this.data.length-1]>=0){y=this.getYCoord(0)-height;if(!prop.colorsSequential){fill=prop.colors[2];}}else if(i===(this.data.length-1)&&this.data[this.data.length-1]<0){y=this.getYCoord(0);if(!prop.colorsSequential){fill=prop.colors[2];}}}
20
- var x=prop.marginLeft+(outerWidth*i)+prop.hmargin;if(this.data[i]===null||typeof this.data[i]==='undefined'){var axisY=this.getYCoord(0);if(prevValue<0){y=prevY+prevHeight;}else{y=prevY;}
21
- height=this.getYCoord(0)-this.getYCoord(total);if(!prop.colorsSequential){fill=prop.colors[3]||prop.colors[2];}
22
- if(height<0){y+=height;height*=-1;}}
23
- var rect=RG.SVG.create({svg:this.svg,type:'rect',parent:this.svg.all,attr:{x:x,y:y,width:innerWidth,height:height,stroke:prop.colorsStroke,fill:fill,'stroke-width':prop.linewidth,'shape-rendering':'crispEdges','data-index':i,'data-original-x':x,'data-original-y':y,'data-original-width':innerWidth,'data-original-height':height,'data-original-stroke':prop.colorsStroke,'data-original-fill':fill,'data-value':String(this.data[i])}});this.coords.push({object:this,element:rect,x:x,y:y,width:innerWidth,height:height});if(!RG.SVG.isNull(prop.tooltips)&&prop.tooltips[i]){var obj=this;(function(idx)
24
- {rect.addEventListener(prop.tooltipsEvent.replace(/^on/,''),function(e)
25
- {obj.removeHighlight();RG.SVG.tooltip({object:obj,index:idx,text:prop.tooltips[idx],event:e});obj.highlight(e.target);},false);rect.addEventListener('mousemove',function(e)
26
- {e.target.style.cursor='pointer'},false);})(i);}
27
- var prevX=x,prevY=y,prevWidth=innerWidth,prevHeight=height,prevValue=this.data[i];}
28
- for(var i=0;i<this.coords.length;++i){if(this.coords[i+1]&&this.coords[i+1].element){var x1=Number(this.coords[i].element.getAttribute('x'))+Number(this.coords[i].element.getAttribute('width')),y1=parseInt(this.coords[i].element.getAttribute('y'))+(this.data[i]>0?0:parseInt(this.coords[i].element.getAttribute('height'))),x2=x1+(2*prop.hmargin),y2=parseInt(this.coords[i].element.getAttribute('y'))+(this.data[i]>0?0:parseInt(this.coords[i].element.getAttribute('height')));if(this.coords[i].element.getAttribute('data-value')==='null'){y1=parseFloat(this.coords[i].element.getAttribute('y'));y2=parseFloat(y1);}
29
- var line=RG.SVG.create({svg:this.svg,type:'line',parent:this.svg.all,attr:{x1:x1,y1:y1+0.5,x2:x2,y2:y2+0.5,stroke:prop.colorsConnector||prop.colorsStroke,'stroke-width':prop.linewidth,'data-index':i,'data-original-x1':x1,'data-original-y1':y1+0.5,'data-original-x2':x2,'data-original-y2':y2+0.5}});}}};this.getYCoord=function(value)
30
- {var prop=this.properties;if(value>this.scale.max){return null;}
31
- var y,xaxispos=prop.xaxispos;if(value<this.scale.min){return null;}
32
- 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)
33
- {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,type:'rect',parent:this.svg.all,attr:{stroke:prop.highlightStroke,fill:prop.highlightFill,x:x,y:y,width:width,height:height,'stroke-width':prop.highlightLinewidth},style:{pointerEvents:'none'}});RG.SVG.REG.set('highlight',highlight);};this.parseColors=function()
34
- {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)}}
35
- var colors=prop.colors;if(colors){for(var i=0;i<colors.length;++i){colors[i]=RG.SVG.parseColorLinear({object:this,color:colors[i]});}}
36
- 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()
37
- {if(prop.labelsAbove){var total=0;for(var i=0;i<this.coords.length;++i){var num=this.data[i],total=total+num;if(typeof num==='number'||RG.SVG.isNull(num)){if(RG.SVG.isNull(num)){num=total;}
38
- 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[i]==='string'||typeof prop.labelsAboveSpecific[i]==='number')){str=prop.labelsAboveSpecific[i];}else if(prop.labelsAboveSpecific&&prop.labelsAboveSpecific.length&&typeof prop.labelsAboveSpecific[i]!=='string'&&typeof prop.labelsAboveSpecific[i]!=='number'){continue;}
39
- var x=parseFloat(this.coords[i].element.getAttribute('x'))+parseFloat(this.coords[i].element.getAttribute('width')/2)+prop.labelsAboveOffsetx;if(this.data[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';}
40
- if(i===(this.coords.length-1)){var font=prop.labelsAboveLastFont||prop.labelsAboveFont||prop.textFont,color=prop.labelsAboveLastColor||prop.labelsAboveColor||prop.textColor,background=prop.labelsAboveLastBackground||prop.labelsAboveBackground||null,padding=(typeof prop.labelsAboveLastBackgroundPadding==='number'?prop.labelsAboveLastBackgroundPadding:prop.labelsAboveBackgroundPadding)||0;if(typeof prop.labelsAboveLastSize==='number'){var size=prop.labelsAboveLastSize;}else if(typeof prop.labelsAboveSize==='number'){var size=prop.labelsAboveSize;}else{var size=prop.textBold;}
41
- if(typeof prop.labelsAboveLastBold==='boolean'){var bold=prop.labelsAboveLastBold;}else if(typeof prop.labelsAboveBold==='boolean'){var bold=prop.labelsAboveBold;}else{var bold=prop.textBold;}
42
- if(typeof prop.labelsAboveLastItalic==='boolean'){var italic=prop.labelsAboveLastItalic;}else if(typeof prop.labelsAboveItalic==='boolean'){var italic=prop.labelsAboveItalic;}else{var italic=prop.textItalic;}}else{var font=prop.labelsAboveFont||prop.textFont,size=typeof prop.labelsAboveSize==='number'?prop.labelsAboveSize:prop.textSize,color=prop.labelsAboveColor||prop.textColor,background=prop.labelsAboveBackground||null,padding=prop.labelsAboveBackgroundPadding||0;if(typeof prop.labelsAboveBold==='boolean'){var bold=prop.labelsAboveBold;}else{var bold=prop.textBold;}
43
- if(typeof prop.labelsAboveItalic==='boolean'){var italic=prop.labelsAboveItalic;}else{var italic=prop.textItalic;}}
44
- RG.SVG.text({object:this,parent:this.svg.all,tag:'labels.above',text:str,x:x,y:y,halign:prop.labelsAboveHalign,valign:valign,font:font,size:size,bold:bold,italic:italic,color:color,background:background,padding:padding});}}}};this.on=function(type,func)
45
- {if(type.substr(0,2)!=='on'){type='on'+type;}
46
- RG.SVG.addCustomEventListener(this,type,func);return this;};this.exec=function(func)
47
- {func(this);return this;};this.removeHighlight=function()
48
- {var highlight=RG.SVG.REG.get('highlight');if(highlight&&highlight.parentNode){highlight.parentNode.removeChild(highlight);}
49
- RG.SVG.REG.set('highlight',null);};this.grow=function()
50
- {var opt=arguments[0]||{},frames=opt.frames||30,frame=0,obj=this,data=[],height=null,seq=0;return this;};this.wave=function()
51
- {return this;};for(i in conf.options){if(typeof i==='string'){this.set(i,conf.options[i]);}}};return this;})(window,document);
12
+
13
+ RGraph = window.RGraph || {isrgraph:true,isRGraph: true,rgraph:true};
14
+ RGraph.SVG = RGraph.SVG || {};
15
+
16
+ // Module pattern
17
+ (function (win, doc, undefined)
18
+ {
19
+ RGraph.SVG.Waterfall = function (conf)
20
+ {
21
+ //
22
+ // A setter that the constructor uses (at the end)
23
+ // to set all of the properties
24
+ //
25
+ // @param string name The name of the property to set
26
+ // @param string value The value to set the property to
27
+ //
28
+ this.set = function (name, value)
29
+ {
30
+ // BC
31
+ if (name === 'colorsConnector') {
32
+ name = 'colorsConnectors';
33
+ }
34
+
35
+ if (arguments.length === 1 && typeof name === 'object') {
36
+ for (i in arguments[0]) {
37
+ if (typeof i === 'string') {
38
+
39
+ name = ret.name;
40
+ value = ret.value;
41
+
42
+ this.set(name, value);
43
+ }
44
+ }
45
+ } else {
46
+ var ret = RGraph.SVG.commonSetter({
47
+ object: this,
48
+ name: name,
49
+ value: value
50
+ });
51
+
52
+ name = ret.name;
53
+ value = ret.value;
54
+
55
+ this.properties[name] = value;
56
+
57
+ // If setting the colors, update the originalColors
58
+ // property too
59
+ if (name === 'colors') {
60
+ this.originalColors = RGraph.SVG.arrayClone(value);
61
+ this.colorsParsed = false;
62
+ }
63
+ }
64
+
65
+ return this;
66
+ };
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+ //
76
+ // A getter.
77
+ //
78
+ // @param name string The name of the property to get
79
+ //
80
+ this.get = function (name)
81
+ {
82
+ return this.properties[name];
83
+ };
84
+
85
+
86
+
87
+
88
+
89
+ // Convert strings to numbers
90
+ conf.data = RGraph.SVG.stringsToNumbers(conf.data);
91
+
92
+
93
+
94
+ this.id = conf.id;
95
+ this.uid = RGraph.SVG.createUID();
96
+ this.container = document.getElementById(this.id);
97
+ this.layers = {}; // MUST be before the SVG tag is created!
98
+ this.svg = RGraph.SVG.createSVG({object: this,container: this.container});
99
+ this.isRGraph = true;
100
+ this.isrgraph = true;
101
+ this.rgraph = true;
102
+ this.data = conf.data;
103
+ this.type = 'waterfall';
104
+ this.coords = [];
105
+ this.colorsParsed = false;
106
+ this.originalColors = {};
107
+ this.gradientCounter = 1;
108
+ this.totalColumns = [];
109
+ this.firstDraw = true; // After the first draw this will be false
110
+
111
+
112
+
113
+
114
+
115
+ // Add this object to the ObjectRegistry
116
+ RGraph.SVG.OR.add(this);
117
+
118
+ this.container.style.display = 'inline-block';
119
+
120
+ //
121
+ // Note the indexes of total columns
122
+ //
123
+ for (var i=0; i<this.data.length; ++i) {
124
+ if (RGraph.SVG.isNull(this.data[i])) {
125
+ this.totalColumns[i] = true;
126
+ }
127
+ }
128
+
129
+ this.properties =
130
+ {
131
+ marginLeft: 35,
132
+ marginRight: 35,
133
+ marginTop: 35,
134
+ marginBottom: 35,
135
+ marginInner: 5,
136
+
137
+ backgroundColor: null,
138
+ backgroundImage: null,
139
+ backgroundImageAspect: 'none',
140
+ backgroundImageStretch: true,
141
+ backgroundImageOpacity: null,
142
+ backgroundImageX: null,
143
+ backgroundImageY: null,
144
+ backgroundImageW: null,
145
+ backgroundImageH: null,
146
+ backgroundGrid: true,
147
+ backgroundGridColor: '#ddd',
148
+ backgroundGridLinewidth: 1,
149
+ backgroundGridHlines: true,
150
+ backgroundGridHlinesCount: null,
151
+ backgroundGridVlines: true,
152
+ backgroundGridVlinesCount: null,
153
+ backgroundGridBorder: true,
154
+ backgroundGridDashed: false,
155
+ backgroundGridDotted: false,
156
+ backgroundGridDashArray: null,
157
+
158
+ // 20 colors. If you need more you need to set the colors property
159
+ colors: ['black', 'red', 'blue'],
160
+ colorsSequential: false,
161
+ colorsStroke: '#aaa',
162
+ colorsConnectors: '#666',
163
+
164
+ total: true,
165
+ linewidth: 1,
166
+
167
+ yaxis: true,
168
+ yaxisTickmarks: true,
169
+ yaxisTickmarksLength: 5,
170
+ yaxisColor: 'black',
171
+ yaxisScale: true,
172
+ yaxisLabels: null,
173
+ yaxisLabelsOffsetx: 0,
174
+ yaxisLabelsOffsety: 0,
175
+ yaxisLabelsCount: 5,
176
+ yaxisScaleUnitsPre: '',
177
+ yaxisScaleUnitsPost: '',
178
+ yaxisScaleStrict: false,
179
+ yaxisScaleDecimals: 0,
180
+ yaxisScalePoint: '.',
181
+ yaxisScaleThousand: ',',
182
+ yaxisScaleRound: false,
183
+ yaxisScaleMax: null,
184
+ yaxisScaleMin: 0,
185
+ yaxisScaleFormatter: null,
186
+ yaxisLabelsColor: null,
187
+ yaxisLabelsBold: null,
188
+ yaxisLabelsItalic: null,
189
+ yaxisLabelsFont: null,
190
+ yaxisLabelsSize: null,
191
+ yaxisTitle: '',
192
+ yaxisTitleBold: null,
193
+ yaxisTitleSize: null,
194
+ yaxisTitleFont: null,
195
+ yaxisTitleColor: null,
196
+ yaxisTitleItalic: null,
197
+ yaxisTitleOffsetx: 0,
198
+ yaxisTitleOffsety: 0,
199
+ yaxisTitleX: null,
200
+ yaxisTitleY: null,
201
+ yaxisTitleHalign: null,
202
+ yaxisTitleValign: null,
203
+
204
+ xaxis: true,
205
+ xaxisTickmarks: true,
206
+ xaxisTickmarksLength: 5,
207
+ xaxisLabels: null,
208
+ xaxisLabelsFont: null,
209
+ xaxisLabelsSize: null,
210
+ xaxisLabelsColor: null,
211
+ xaxisLabelsBold: null,
212
+ xaxisLabelsItalic: null,
213
+ xaxisLabelsPosition: 'section',
214
+ xaxisLabelsPositionEdgeTickmarksCount: null,
215
+ xaxisLabelsFormattedDecimals: 0,
216
+ xaxisLabelsFormattedPoint: '.',
217
+ xaxisLabelsFormattedThousand: ',',
218
+ xaxisLabelsFormattedUnitsPre: '',
219
+ xaxisLabelsFormattedUnitsPost: '',
220
+ xaxisColor: 'black',
221
+ xaxisLabelsOffsetx: 0,
222
+ xaxisLabelsOffsety: 0,
223
+ xaxisTitle: '',
224
+ xaxisTitleBold: null,
225
+ xaxisTitleSize: null,
226
+ xaxisTitleFont: null,
227
+ xaxisTitleColor: null,
228
+ xaxisTitleItalic: null,
229
+ xaxisTitleOffsetx: 0,
230
+ xaxisTitleOffsety: 0,
231
+ xaxisTitleX: null,
232
+ xaxisTitleY: null,
233
+ xaxisTitleHalign: null,
234
+ xaxisTitleValign: null,
235
+
236
+ labelsAbove: false,
237
+ labelsAboveFont: null,
238
+ labelsAboveSize: null,
239
+ labelsAboveBold: null,
240
+ labelsAboveItalic: null,
241
+ labelsAboveColor: null,
242
+ labelsAboveBackground: 'rgba(255,255,255,0.5)',
243
+ labelsAboveBackgroundPadding: 2,
244
+ labelsAboveUnitsPre: null,
245
+ labelsAboveUnitsPost: null,
246
+ labelsAbovePoint: null,
247
+ labelsAboveThousand: null,
248
+ labelsAboveFormatter: null,
249
+ labelsAboveDecimals: null,
250
+ labelsAboveOffsetx: 0,
251
+ labelsAboveOffsety: 0,
252
+ labelsAboveHalign: 'center',
253
+ labelsAboveValign: 'bottom',
254
+ labelsAboveSpecific: null,
255
+ labelsAboveLastFont: null,
256
+ labelsAboveLastBold: null,
257
+ labelsAboveLastItalic: null,
258
+ labelsAboveLastSize: null,
259
+ labelsAboveLastColor: null,
260
+ labelsAboveLastBackground: null,
261
+ labelsAboveLastBackgroundPadding: null,
262
+
263
+ textColor: 'black',
264
+ textFont: 'Arial, Verdana, sans-serif',
265
+ textSize: 12,
266
+ textBold: false,
267
+ textItalic: false,
268
+ text: null,
269
+
270
+
271
+ tooltips: null,
272
+ tooltipsOverride: null,
273
+ tooltipsEffect: 'fade',
274
+ tooltipsCssClass: 'RGraph_tooltip',
275
+ tooltipsCss: null,
276
+ tooltipsEvent: 'click',
277
+ tooltipsFormattedThousand: ',',
278
+ tooltipsFormattedPoint: '.',
279
+ tooltipsFormattedDecimals: 0,
280
+ tooltipsFormattedUnitsPre: '',
281
+ tooltipsFormattedUnitsPost: '',
282
+ tooltipsFormattedKeyColors: null,
283
+ tooltipsFormattedKeyColorsShape: 'square',
284
+ tooltipsFormattedKeyLabels: [],
285
+ tooltipsFormattedTableHeaders: null,
286
+ tooltipsFormattedTableData: null,
287
+ tooltipsPointer: true,
288
+ tooltipsPointerOffsetx: 0,
289
+ tooltipsPointerOffsety: 0,
290
+ tooltipsPositionStatic: true,
291
+
292
+ highlightStroke: 'rgba(0,0,0,0)',
293
+ highlightFill: 'rgba(255,255,255,0.7)',
294
+ highlightLinewidth: 1,
295
+
296
+ title: '',
297
+ titleX: null,
298
+ titleY: null,
299
+ titleHalign: 'center',
300
+ titleValign: null,
301
+ titleSize: null,
302
+ titleColor: null,
303
+ titleFont: null,
304
+ titleBold: null,
305
+ titleItalic: null,
306
+
307
+ titleSubtitle: null,
308
+ titleSubtitleSize: null,
309
+ titleSubtitleColor: '#aaa',
310
+ titleSubtitleFont: null,
311
+ titleSubtitleBold: null,
312
+ titleSubtitleItalic: null,
313
+
314
+ //shadow: false,
315
+ //shadowOffsetx: 2,
316
+ //shadowOffsety: 2,
317
+ //shadowBlur: 2,
318
+ //shadowColor: 'rgba(0,0,0,0.25)',
319
+
320
+ key: null,
321
+ keyColors: null,
322
+ keyOffsetx: 0,
323
+ keyOffsety: 0,
324
+ keyLabelsOffsetx: 0,
325
+ keyLabelsOffsety: -1,
326
+ keyLabelsFont: null,
327
+ keyLabelsSize: null,
328
+ keyLabelsColor: null,
329
+ keyLabelsBold: null,
330
+ keyLabelsItalic: null
331
+ };
332
+
333
+
334
+
335
+
336
+ //
337
+ // Copy the global object properties to this instance
338
+ //
339
+ RGraph.SVG.getGlobals(this);
340
+
341
+
342
+
343
+
344
+
345
+ //
346
+ // "Decorate" the object with the generic effects if the effects library has been included
347
+ //
348
+ if (RGraph.SVG.FX && typeof RGraph.SVG.FX.decorate === 'function') {
349
+ RGraph.SVG.FX.decorate(this);
350
+ }
351
+
352
+
353
+
354
+
355
+
356
+ // Add the responsive function to the object
357
+ this.responsive = RGraph.SVG.responsive;
358
+
359
+
360
+
361
+
362
+ var properties = this.properties;
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+ //
372
+ // The draw method draws the Bar chart
373
+ //
374
+ this.draw = function ()
375
+ {
376
+ // Fire the beforedraw event
377
+ RGraph.SVG.fireCustomEvent(this, 'onbeforedraw');
378
+
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
+
388
+
389
+
390
+
391
+
392
+
393
+ //
394
+ // If the xaxisLabels option is a string then turn it
395
+ // into an array.
396
+ //
397
+ if (properties.xaxisLabels && properties.xaxisLabels.length) {
398
+ if (typeof properties.xaxisLabels === 'string') {
399
+ properties.xaxisLabels = RGraph.SVG.arrayPad({
400
+ array: [],
401
+ length: this.data.length + (properties.total ? 1 : 0),
402
+ value: properties.xaxisLabels
403
+ });
404
+ }
405
+
406
+ //
407
+ // Label substitution
408
+ //
409
+ for (var i=0; i<properties.xaxisLabels.length; ++i) {
410
+ properties.xaxisLabels[i] = RGraph.SVG.labelSubstitution({
411
+ object: this,
412
+ text: properties.xaxisLabels[i],
413
+ index: i,
414
+ value: this.data[i],
415
+ decimals: properties.xaxisLabelsFormattedDecimals || 0,
416
+ unitsPre: properties.xaxisLabelsFormattedUnitsPre || '',
417
+ unitsPost: properties.xaxisLabelsFormattedUnitsPost || '',
418
+ thousand: properties.xaxisLabelsFormattedThousand || ',',
419
+ point: properties.xaxisLabelsFormattedPoint || '.'
420
+ });
421
+ }
422
+ }
423
+
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+ // Create the defs tag if necessary
432
+ RGraph.SVG.createDefs(this);
433
+
434
+
435
+
436
+
437
+ this.coords = []; // Reset this so it doesn't grow
438
+ this.graphWidth = this.width - properties.marginLeft - properties.marginRight;
439
+ this.graphHeight = this.height - properties.marginTop - properties.marginBottom;
440
+
441
+
442
+
443
+ // Parse the colors for gradients
444
+ RGraph.SVG.resetColorsToOriginalValues({object:this});
445
+ this.parseColors();
446
+
447
+
448
+
449
+
450
+ // Work out the sum of the data and add it to the data
451
+ if (properties.total && !this.totalAdded) {
452
+
453
+ this.totalAdded = true;
454
+
455
+ var sum = RGraph.SVG.arraySum(this.data);
456
+
457
+ // Now append the sum to the data
458
+ this.data.push(sum);
459
+
460
+ // May need to append something to the labels array if properties.total
461
+ // is enabled, so that the labels line up
462
+
463
+ if (properties.xaxisLabels && properties.xaxisLabels.length === (this.data.length - 1)) {
464
+ properties.xaxisLabels.push('');
465
+ }
466
+ }
467
+
468
+
469
+
470
+
471
+ for (var i=0,max=0,runningTotal=0; i<this.data.length - (properties.total ? 1 : 0); ++i) {
472
+ runningTotal += this.data[i]
473
+ max = Math.max(Math.abs(max), Math.abs(runningTotal));
474
+ }
475
+
476
+ // A custom, user-specified maximum value
477
+ if (typeof properties.yaxisScaleMax === 'number') {
478
+ max = properties.yaxisScaleMax;
479
+ }
480
+
481
+ // Set the ymin to zero if it's set mirror
482
+ if (properties.yaxisScaleMin === 'mirror' || properties.yaxisScaleMin === 'middle' || properties.yaxisScaleMin === 'center') {
483
+ var mirrorScale = true;
484
+ properties.yaxisScaleMin = 0;
485
+ }
486
+
487
+
488
+ //
489
+ // Generate an appropiate scale
490
+ //
491
+ this.scale = RGraph.SVG.getScale({
492
+ object: this,
493
+ numlabels: properties.yaxisLabelsCount,
494
+ unitsPre: properties.yaxisScaleUnitsPre,
495
+ unitsPost: properties.yaxisScaleUnitsPost,
496
+ max: max,
497
+ min: properties.yaxisScaleMin,
498
+ point: properties.yaxisScalePoint,
499
+ round: properties.yaxisScaleRound,
500
+ thousand: properties.yaxisScaleThousand,
501
+ decimals: properties.yaxisScaleDecimals,
502
+ strict: typeof properties.yaxisScaleMax === 'number',
503
+ formatter: properties.yaxisScaleFormatter
504
+ });
505
+
506
+
507
+
508
+ //
509
+ // Get the scale a second time if the ymin should be mirored
510
+ //
511
+ // Set the ymin to zero if it's set mirror
512
+ if (mirrorScale) {
513
+ this.scale = RGraph.SVG.getScale({
514
+ object: this,
515
+ numlabels: properties.yaxisLabelsCount,
516
+ unitsPre: properties.yaxisScaleUnitsPre,
517
+ unitsPost: properties.yaxisScaleUnitsPost,
518
+ max: this.scale.max,
519
+ min: this.scale.max * -1,
520
+ point: properties.yaxisScalePoint,
521
+ round: false,
522
+ thousand: properties.yaxisScaleThousand,
523
+ decimals: properties.yaxisScaleDecimals,
524
+ strict: typeof properties.yaxisScaleMax === 'number',
525
+ formatter: properties.yaxisScaleFormatter
526
+ });
527
+ }
528
+
529
+ // Now the scale has been generated adopt its max value
530
+ this.max = this.scale.max;
531
+ this.min = this.scale.min;
532
+ properties.yaxisScaleMax = this.scale.max;
533
+ properties.yaxisScaleMin = this.scale.min;
534
+
535
+
536
+
537
+
538
+ // Draw the background first
539
+ RGraph.SVG.drawBackground(this);
540
+
541
+
542
+
543
+ // Draw the axes BEFORE the bars
544
+ RGraph.SVG.drawXAxis(this);
545
+ RGraph.SVG.drawYAxis(this);
546
+
547
+
548
+ // Draw the bars
549
+ this.drawBars();
550
+
551
+
552
+ // Draw the labelsAbove labels
553
+ this.drawLabelsAbove();
554
+
555
+
556
+
557
+
558
+
559
+
560
+
561
+
562
+
563
+
564
+ // Draw the key
565
+ if (typeof properties.key !== null && RGraph.SVG.drawKey) {
566
+ RGraph.SVG.drawKey(this);
567
+ } else if (!RGraph.SVG.isNull(properties.key)) {
568
+ alert('The drawKey() function does not exist - have you forgotten to include the key library?');
569
+ }
570
+
571
+
572
+
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+
581
+ // Add the event listener that clears the highlight rect if
582
+ // there is any. Must be MOUSEDOWN (ie before the click event)
583
+ //var obj = this;
584
+ //document.body.addEventListener('mousedown', function (e)
585
+ //{
586
+ // //RGraph.SVG.removeHighlight(obj);
587
+ //
588
+ //}, false);
589
+
590
+
591
+
592
+
593
+
594
+
595
+
596
+
597
+ //
598
+ // Allow the addition of custom text via the
599
+ // text: property.
600
+ //
601
+ RGraph.SVG.addCustomText(this);
602
+
603
+
604
+
605
+
606
+
607
+
608
+
609
+
610
+
611
+
612
+
613
+
614
+ //
615
+ // Fire the onfirstdraw event
616
+ //
617
+ if (this.firstDraw) {
618
+ this.firstDraw = false;
619
+ RGraph.SVG.fireCustomEvent(this, 'onfirstdraw');
620
+ }
621
+
622
+
623
+
624
+
625
+ // Fire the draw event
626
+ RGraph.SVG.fireCustomEvent(this, 'ondraw');
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+ //
635
+ // Install any inline responsive configuration. This
636
+ // should be last in the draw function - even after
637
+ // the draw events.
638
+ //
639
+ RGraph.SVG.installInlineResponsive(this);
640
+
641
+
642
+
643
+
644
+
645
+
646
+
647
+
648
+
649
+
650
+
651
+
652
+ return this;
653
+ };
654
+
655
+
656
+
657
+
658
+
659
+
660
+
661
+
662
+ //
663
+ // New create() shortcut function
664
+ // For example:
665
+ // this.create('rect,x:0,y:0,width:100,height:100'[,parent]);
666
+ //
667
+ // @param str string The tag definition to parse and create
668
+ // @param object The (optional) parent element
669
+ // @return object The new tag
670
+ //
671
+ this.create = function (str)
672
+ {
673
+ var def = RGraph.SVG.create.parseStr(this, str);
674
+ def.svg = this.svg;
675
+
676
+ // By default the parent is the SVG tag - but if
677
+ // requested then change it to the tag that has
678
+ // been given
679
+ if (arguments[1]) {
680
+ def.parent = arguments[1];
681
+ }
682
+
683
+ return RGraph.SVG.create(def);
684
+ };
685
+
686
+
687
+
688
+
689
+
690
+
691
+
692
+
693
+ //
694
+ // Draws the bars
695
+ //
696
+ this.drawBars = function ()
697
+ {
698
+ this.graphWidth = this.width - properties.marginLeft - properties.marginRight;
699
+ this.graphHeight = this.height - properties.marginTop - properties.marginBottom;
700
+
701
+ // The width of the bars
702
+ var innerWidth = (this.graphWidth / this.data.length) - (2 * properties.marginInner),
703
+ outerWidth = (this.graphWidth / this.data.length);
704
+
705
+
706
+ // The starting Y coordinate
707
+ var y = this.getYCoord(0),
708
+ total = 0;
709
+
710
+
711
+
712
+ // Loop thru the data drawing the bars
713
+ for (var i=0; i<(this.data.length); ++i) {
714
+
715
+ var prevValue = this.data[i - 1],
716
+ nextValue = this.data[i + 1],
717
+ currentValue = this.data[i],
718
+ prevTotal = total;
719
+
720
+ total += parseFloat(this.data[i]) || 0;
721
+
722
+ // Figure out the height
723
+ var height = Math.abs((this.data[i] / (this.scale.max - this.scale.min) ) * this.graphHeight);
724
+
725
+
726
+
727
+
728
+
729
+
730
+
731
+
732
+
733
+
734
+ // Work out the starting coord
735
+ if (RGraph.SVG.isNull(prevValue)) {
736
+
737
+ if (currentValue > 0) {
738
+ y = this.getYCoord(prevTotal) - height;
739
+ } else {
740
+ y = this.getYCoord(prevTotal);
741
+ }
742
+
743
+ } else {
744
+ if (i == 0 && this.data[i] > 0) {
745
+ y = y - height;
746
+
747
+ } else if (this.data[i] > 0 && this.data[i - 1] > 0) {
748
+ y = y - height;
749
+
750
+ } else if (this.data[i] > 0 && this.data[i - 1] < 0) {
751
+ y = y + prevHeight - height;
752
+
753
+ } else if (this.data[i] < 0 && this.data[i - 1] > 0) {
754
+ // Nada
755
+
756
+ } else if (this.data[i] < 0 && this.data[i - 1] < 0) {
757
+ y = y + prevHeight;
758
+ }
759
+ }
760
+
761
+ //
762
+ // Determine the color
763
+ //
764
+ var fill = this.data[i] > 0 ? properties.colors[0] : properties.colors[1];
765
+
766
+ if (properties.colorsSequential) {
767
+ fill = properties.colors[i];
768
+ }
769
+
770
+
771
+
772
+
773
+
774
+ // The last (the total) value if required
775
+ if (properties.total) {
776
+ if (i === (this.data.length - 1) && this.data[this.data.length - 1] >= 0) {
777
+
778
+ y = this.getYCoord(0) - height;
779
+
780
+ if (!properties.colorsSequential) {
781
+ fill = properties.colors[2];
782
+ }
783
+ } else if (i === (this.data.length - 1) && this.data[this.data.length - 1] < 0) {
784
+ y = this.getYCoord(0);
785
+
786
+ if (!properties.colorsSequential) {
787
+ fill = properties.colors[2];
788
+ }
789
+ }
790
+ }
791
+
792
+
793
+
794
+
795
+
796
+ // Calculate the X coordinate
797
+ var x = properties.marginLeft + (outerWidth * i) + properties.marginInner;
798
+
799
+
800
+
801
+
802
+
803
+ // This handles an intermediate total
804
+ if (this.data[i] === null || typeof this.data[i] === 'undefined') {
805
+
806
+ var axisY = this.getYCoord(0);
807
+
808
+ if (prevValue < 0) {
809
+ y = prevY + prevHeight;
810
+ } else {
811
+ y = prevY;
812
+ }
813
+
814
+ height = this.getYCoord(0) - this.getYCoord(total);
815
+
816
+ // Do this if not sequential colors
817
+ if (!properties.colorsSequential) {
818
+ fill = properties.colors[3] || properties.colors[2];
819
+ }
820
+
821
+ if (height < 0) {
822
+ y += height;
823
+ height *= -1;
824
+ }
825
+ }
826
+
827
+
828
+
829
+ //
830
+ // Set a shadow if requested
831
+ //
832
+ if (properties.shadow) {
833
+ RGraph.SVG.setShadow({
834
+ object: this,
835
+ offsetx: properties.shadowOffsetx,
836
+ offsety: properties.shadowOffsety,
837
+ blur: properties.shadowBlur,
838
+ color: properties.shadowColor,
839
+ id: 'dropShadow'
840
+ });
841
+ }
842
+
843
+
844
+ // Create the rect object
845
+ var rect = RGraph.SVG.create({
846
+ svg: this.svg,
847
+ type: 'rect',
848
+ parent: this.svg.all,
849
+ attr: {
850
+ x: x,
851
+ y: y,
852
+ width: innerWidth,
853
+ height: height,
854
+ stroke: properties.colorsStroke,
855
+ fill: fill,
856
+ 'stroke-width': properties.linewidth,
857
+ 'shape-rendering': 'crispEdges',
858
+ 'data-index': i,
859
+ 'data-original-x': x,
860
+ 'data-original-y': y,
861
+ 'data-original-width': innerWidth,
862
+ 'data-original-height': height,
863
+ 'data-original-stroke': properties.colorsStroke,
864
+ 'data-original-fill': fill,
865
+ 'data-value': String(this.data[i]),
866
+ filter: properties.shadow ? 'url(#dropShadow)' : '',
867
+ }
868
+ });
869
+
870
+ // Store the coordinates
871
+ this.coords.push({
872
+ object: this,
873
+ element: rect,
874
+ x: x,
875
+ y: y,
876
+ width: innerWidth,
877
+ height: height
878
+ });
879
+
880
+
881
+
882
+
883
+
884
+
885
+
886
+
887
+ // Add the tooltips
888
+ if (!RGraph.SVG.isNull(properties.tooltips) && (properties.tooltips[i] || typeof properties.tooltips === 'string') ) {
889
+
890
+ var obj = this;
891
+
892
+ //
893
+ // Add tooltip event listeners
894
+ //
895
+ (function (idx)
896
+ {
897
+ rect.addEventListener(properties.tooltipsEvent.replace(/^on/, ''), function (e)
898
+ {
899
+ obj.removeHighlight();
900
+
901
+ // Show the tooltip
902
+ RGraph.SVG.tooltip({
903
+ object: obj,
904
+ index: idx,
905
+ group: 0,
906
+ sequentialIndex: idx,
907
+ text: typeof properties.tooltips === 'string' ? properties.tooltips : properties.tooltips[idx],
908
+ event: e
909
+ });
910
+
911
+ // Highlight the rect that has been clicked on
912
+ obj.highlight(e.target);
913
+ }, false);
914
+
915
+ rect.addEventListener('mousemove', function (e)
916
+ {
917
+ e.target.style.cursor = 'pointer'
918
+ }, false);
919
+ })(i);
920
+ }
921
+
922
+
923
+
924
+
925
+
926
+
927
+
928
+
929
+
930
+
931
+ // Store these for the next iteration of the loop
932
+ var prevX = x,
933
+ prevY = y,
934
+ prevWidth = innerWidth,
935
+ prevHeight = height,
936
+ prevValue = this.data[i];
937
+ }
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+
949
+
950
+
951
+
952
+
953
+
954
+
955
+
956
+
957
+
958
+ // Now draw the connecting lines
959
+ for (var i=0; i<this.coords.length; ++i) {
960
+
961
+ if (this.coords[i+1] && this.coords[i+1].element) {
962
+
963
+ var x1 = Number(this.coords[i].element.getAttribute('x')) + Number(this.coords[i].element.getAttribute('width')),
964
+ y1 = parseInt(this.coords[i].element.getAttribute('y')) + (this.data[i] > 0 ? 0 : parseInt(this.coords[i].element.getAttribute('height')) ),
965
+ x2 = x1 + (2 * properties.marginInner),
966
+ y2 = parseInt(this.coords[i].element.getAttribute('y')) + (this.data[i] > 0 ? 0 : parseInt(this.coords[i].element.getAttribute('height')) );
967
+
968
+ // Handle total columns
969
+ if(this.coords[i].element.getAttribute('data-value') === 'null') {
970
+ if (i === (this.data.length - 1) ) {
971
+ y1 = parseFloat(this.coords[i].element.getAttribute('y'));
972
+ y2 = parseFloat(y1);
973
+ }
974
+
975
+ if (this.totalColumns[i]) {
976
+ // Calculate the total thus far
977
+ for (var k=0,total=0; k<i; ++k) {
978
+ total += this.data[k];
979
+ }
980
+
981
+ if (total > 0 && this.data[i-1] > 0) {
982
+ y1 = Number(this.coords[i-1].element.getAttribute('y'));
983
+ y2 = y1;
984
+ } else if (total > 0 && this.data[i-1] < 0) {
985
+ y1 = Number(this.coords[i-1].element.getAttribute('y')) + Number(this.coords[i-1].element.getAttribute('height'));
986
+ y2 = y1;
987
+ }
988
+ }
989
+ }
990
+
991
+
992
+ var line = RGraph.SVG.create({
993
+ svg: this.svg,
994
+ type: 'line',
995
+ parent: this.svg.all,
996
+ attr: {
997
+ x1: x1,
998
+ y1: y1 + 0.5,
999
+ x2: x2,
1000
+ y2: y2 + 0.5,
1001
+ stroke: properties.colorsConnectors || properties.colorsStroke,
1002
+ 'stroke-width': properties.linewidth,
1003
+ 'data-index': i,
1004
+ 'data-original-x1': x1,
1005
+ 'data-original-y1': y1 + 0.5,
1006
+ 'data-original-x2': x2,
1007
+ 'data-original-y2': y2 + 0.5
1008
+ }
1009
+ });
1010
+
1011
+ }
1012
+ }
1013
+ };
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+ //
1023
+ // This function can be used to retrieve the relevant Y coordinate for a
1024
+ // particular value.
1025
+ //
1026
+ // @param int value The value to get the Y coordinate for
1027
+ //
1028
+ this.getYCoord = function (value)
1029
+ {
1030
+ if (value > this.scale.max) {
1031
+ return null;
1032
+ }
1033
+
1034
+ var y, xaxispos = properties.xaxispos;
1035
+
1036
+ if (value < this.scale.min) {
1037
+ return null;
1038
+ }
1039
+
1040
+ y = ((value - this.scale.min) / (this.scale.max - this.scale.min));
1041
+ y *= (this.height - properties.marginTop - properties.marginBottom);
1042
+
1043
+ y = this.height - properties.marginBottom - y;
1044
+
1045
+ return y;
1046
+ };
1047
+
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+
1054
+
1055
+ //
1056
+ // This function can be used to highlight a bar on the chart
1057
+ //
1058
+ // @param object rect The rectangle to highlight
1059
+ //
1060
+ this.highlight = function (rect)
1061
+ {
1062
+ var x = parseFloat(rect.getAttribute('x')) - 0.5,
1063
+ y = parseFloat(rect.getAttribute('y')) - 0.5,
1064
+ width = parseFloat(rect.getAttribute('width')) + 1,
1065
+ height = parseFloat(rect.getAttribute('height')) + 1;
1066
+
1067
+ var highlight = RGraph.SVG.create({
1068
+ svg: this.svg,
1069
+ type: 'rect',
1070
+ parent: this.svg.all,
1071
+ attr: {
1072
+ stroke: properties.highlightStroke,
1073
+ fill: properties.highlightFill,
1074
+ x: x,
1075
+ y: y,
1076
+ width: width,
1077
+ height: height,
1078
+ 'stroke-width': properties.highlightLinewidth
1079
+ },
1080
+ style: {
1081
+ pointerEvents: 'none'
1082
+ }
1083
+ });
1084
+
1085
+
1086
+ // Store the highlight rect in the rebistry so
1087
+ // it can be cleared later
1088
+ RGraph.SVG.REG.set('highlight', highlight);
1089
+ };
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+
1097
+
1098
+ //
1099
+ // This allows for easy specification of gradients
1100
+ //
1101
+ this.parseColors = function ()
1102
+ {
1103
+ // Save the original colors so that they can be restored when
1104
+ // the canvas is cleared
1105
+ if (!Object.keys(this.originalColors).length) {
1106
+ this.originalColors = {
1107
+ colors: RGraph.SVG.arrayClone(properties.colors),
1108
+ backgroundGridColor: RGraph.SVG.arrayClone(properties.backgroundGridColor),
1109
+ highlightFill: RGraph.SVG.arrayClone(properties.highlightFill),
1110
+ backgroundColor: RGraph.SVG.arrayClone(properties.backgroundColor)
1111
+ }
1112
+ }
1113
+
1114
+
1115
+ // colors
1116
+ var colors = properties.colors;
1117
+
1118
+ if (colors) {
1119
+ for (var i=0; i<colors.length; ++i) {
1120
+ colors[i] = RGraph.SVG.parseColorLinear({
1121
+ object: this,
1122
+ color: colors[i]
1123
+ });
1124
+ }
1125
+ }
1126
+
1127
+ properties.backgroundGridColor = RGraph.SVG.parseColorLinear({object: this, color: properties.backgroundGridColor});
1128
+ properties.highlightFill = RGraph.SVG.parseColorLinear({object: this, color: properties.highlightFill});
1129
+ properties.backgroundColor = RGraph.SVG.parseColorLinear({object: this, color: properties.backgroundColor});
1130
+ };
1131
+
1132
+
1133
+
1134
+
1135
+
1136
+
1137
+
1138
+
1139
+ //
1140
+ // Draws the labelsAbove
1141
+ //
1142
+ this.drawLabelsAbove = function ()
1143
+ {
1144
+ // Go through the above labels
1145
+ if (properties.labelsAbove) {
1146
+
1147
+ var total = 0;
1148
+
1149
+ for (var i=0; i<this.coords.length; ++i) {
1150
+
1151
+ var num = this.data[i],
1152
+ total = total + num;
1153
+
1154
+ if (typeof num === 'number' || RGraph.SVG.isNull(num)) {
1155
+
1156
+ if (RGraph.SVG.isNull(num)) {
1157
+ num = total;
1158
+ }
1159
+
1160
+ var str = RGraph.SVG.numberFormat({
1161
+ object: this,
1162
+ num: num.toFixed(properties.labelsAboveDecimals),
1163
+ prepend: typeof properties.labelsAboveUnitsPre === 'string' ? properties.labelsAboveUnitsPre : null,
1164
+ append: typeof properties.labelsAboveUnitsPost === 'string' ? properties.labelsAboveUnitsPost : null,
1165
+ point: typeof properties.labelsAbovePoint === 'string' ? properties.labelsAbovePoint : null,
1166
+ thousand: typeof properties.labelsAboveThousand === 'string' ? properties.labelsAboveThousand : null,
1167
+ formatter: typeof properties.labelsAboveFormatter === 'function' ? properties.labelsAboveFormatter : null
1168
+ });
1169
+
1170
+ // Facilitate labelsAboveSpecific
1171
+ if (properties.labelsAboveSpecific && properties.labelsAboveSpecific.length && (typeof properties.labelsAboveSpecific[i] === 'string' || typeof properties.labelsAboveSpecific[i] === 'number') ) {
1172
+ str = properties.labelsAboveSpecific[i];
1173
+ } else if ( properties.labelsAboveSpecific && properties.labelsAboveSpecific.length && typeof properties.labelsAboveSpecific[i] !== 'string' && typeof properties.labelsAboveSpecific[i] !== 'number') {
1174
+ continue;
1175
+ }
1176
+
1177
+ var x = parseFloat(this.coords[i].element.getAttribute('x')) + parseFloat(this.coords[i].element.getAttribute('width') / 2) + properties.labelsAboveOffsetx;
1178
+
1179
+ if (this.data[i] >= 0) {
1180
+ var y = parseFloat(this.coords[i].element.getAttribute('y')) - 7 + properties.labelsAboveOffsety;
1181
+ var valign = properties.labelsAboveValign;
1182
+ } else {
1183
+ var y = parseFloat(this.coords[i].element.getAttribute('y')) + parseFloat(this.coords[i].element.getAttribute('height')) + 7 - properties.labelsAboveOffsety;
1184
+ var valign = properties.labelsAboveValign === 'top' ? 'bottom' : 'top';
1185
+ }
1186
+
1187
+
1188
+
1189
+
1190
+
1191
+
1192
+
1193
+
1194
+
1195
+ // Formatting options for the labels
1196
+ //
1197
+ // NB The last label can have different formatting
1198
+ if (properties.total && i === (this.coords.length - 1) ) {
1199
+
1200
+ var background = properties.labelsAboveLastBackground || properties.labelsAboveBackground || null;
1201
+ var padding = (typeof properties.labelsAboveLastBackgroundPadding === 'number' ? properties.labelsAboveLastBackgroundPadding : properties.labelsAboveBackgroundPadding) || 0;
1202
+ var textConf = {};
1203
+
1204
+ // font and color
1205
+ textConf.font = properties.labelsAboveLastFont
1206
+ || properties.labelsAboveFont
1207
+ || properties.textFont;
1208
+
1209
+ textConf.color = properties.labelsAboveLastColor
1210
+ || properties.labelsAboveColor
1211
+ || properties.textColor;
1212
+
1213
+ // Size
1214
+ if (typeof properties.labelsAboveLastSize === 'number') {
1215
+ textConf.size = properties.labelsAboveLastSize;
1216
+ } else if (typeof properties.labelsAboveSize === 'number') {
1217
+ textConf.size = properties.labelsAboveSize;
1218
+ } else {
1219
+ textConf.size = properties.textSize;
1220
+ }
1221
+
1222
+ // Bold
1223
+ if (typeof properties.labelsAboveLastBold === 'boolean') {
1224
+ textConf.bold = properties.labelsAboveLastBold;
1225
+ } else if (typeof properties.labelsAboveBold === 'boolean') {
1226
+ textConf.bold = properties.labelsAboveBold;
1227
+ } else {
1228
+ textConf.bold = properties.textBold;
1229
+ }
1230
+
1231
+ // Italic
1232
+ if (typeof properties.labelsAboveLastItalic === 'boolean') {
1233
+ textConf.italic = properties.labelsAboveLastItalic;
1234
+ } else if (typeof properties.labelsAboveItalic === 'boolean') {
1235
+ textConf.italic = properties.labelsAboveItalic;
1236
+ } else {
1237
+ textConf.italic = properties.textItalic;
1238
+ }
1239
+
1240
+ } else {
1241
+
1242
+ var background = properties.labelsAboveBackground || null,
1243
+ padding = properties.labelsAboveBackgroundPadding || 0;
1244
+
1245
+ // Get the text configuration
1246
+ var textConf = RGraph.SVG.getTextConf({
1247
+ object: this,
1248
+ prefix: 'labelsAbove'
1249
+ });
1250
+ }
1251
+
1252
+
1253
+
1254
+
1255
+
1256
+ RGraph.SVG.text({
1257
+ object: this,
1258
+ parent: this.svg.all,
1259
+ tag: 'labels.above',
1260
+
1261
+ text: str,
1262
+
1263
+ x: x,
1264
+ y: y,
1265
+
1266
+ halign: properties.labelsAboveHalign,
1267
+ valign: valign,
1268
+
1269
+ font: textConf.font,
1270
+ size: textConf.size,
1271
+ bold: textConf.bold,
1272
+ italic: textConf.italic,
1273
+ color: textConf.color,
1274
+
1275
+ background: background,
1276
+ padding: padding
1277
+ });
1278
+ }
1279
+ }
1280
+ }
1281
+ };
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+ //
1291
+ // Using a function to add events makes it easier to facilitate method
1292
+ // chaining
1293
+ //
1294
+ // @param string type The type of even to add
1295
+ // @param function func
1296
+ //
1297
+ this.on = function (type, func)
1298
+ {
1299
+ if (type.substr(0,2) !== 'on') {
1300
+ type = 'on' + type;
1301
+ }
1302
+
1303
+ RGraph.SVG.addCustomEventListener(this, type, func);
1304
+
1305
+ return this;
1306
+ };
1307
+
1308
+
1309
+
1310
+
1311
+
1312
+
1313
+
1314
+
1315
+ //
1316
+ // Used in chaining. Runs a function there and then - not waiting for
1317
+ // the events to fire (eg the onbeforedraw event)
1318
+ //
1319
+ // @param function func The function to execute
1320
+ //
1321
+ this.exec = function (func)
1322
+ {
1323
+ func(this);
1324
+
1325
+ return this;
1326
+ };
1327
+
1328
+
1329
+
1330
+
1331
+
1332
+
1333
+
1334
+
1335
+ //
1336
+ // Remove highlight from the chart (tooltips)
1337
+ //
1338
+ this.removeHighlight = function ()
1339
+ {
1340
+ RGraph.SVG.removeHighlight();
1341
+ };
1342
+
1343
+
1344
+
1345
+
1346
+
1347
+
1348
+
1349
+
1350
+ //
1351
+ // A worker function that handles Bar chart specific tooltip substitutions
1352
+ //
1353
+ this.tooltipSubstitutions = function (opt)
1354
+ {
1355
+ return {
1356
+ index: opt.index,
1357
+ dataset: 0,
1358
+ sequentialIndex: opt.index,
1359
+ value: this.data[opt.index],
1360
+ values: [this.data[opt.index]]
1361
+ };
1362
+ };
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+
1371
+ //
1372
+ // A worker function that returns the correct color/label/value
1373
+ //
1374
+ // @param object specific The indexes that are applicable
1375
+ // @param number index The appropriate index
1376
+ //
1377
+ this.tooltipsFormattedCustom = function (specific, index)
1378
+ {
1379
+ var color, label, value;
1380
+
1381
+ //
1382
+ // Check for null values (ie subtotals) and calculate the subtotal if required
1383
+ //
1384
+
1385
+ // Determine the correct color to use
1386
+ var colors = properties.colors;
1387
+
1388
+ if ( properties.tooltipsFormattedKeyColors
1389
+ && properties.tooltipsFormattedKeyColors[0]
1390
+ && properties.tooltipsFormattedKeyColors[1]
1391
+ && properties.tooltipsFormattedKeyColors[2]) {
1392
+
1393
+ colors = properties.tooltipsFormattedKeyColors;
1394
+ //} else {
1395
+ // colors = properties.colors;
1396
+ }
1397
+
1398
+ color = colors[0];
1399
+
1400
+ // Change the color for negative bars
1401
+ if (specific.value < 0) {
1402
+ color = colors[1];
1403
+ }
1404
+
1405
+ // Change the color for the last bar
1406
+ if ( (specific.index + 1) === this.data.length || RGraph.SVG.isNull(this.data[specific.index])) {
1407
+ color = colors[2];
1408
+ }
1409
+
1410
+
1411
+
1412
+
1413
+ // Figure out the correct label
1414
+ if (properties.tooltipsFormattedKeyLabels && typeof properties.tooltipsFormattedKeyLabels === 'object') {
1415
+
1416
+ var isLast = specific.index === (this.data.length - 1);
1417
+ var isNull = RGraph.SVG.isNull(this.data[specific.index]);
1418
+ var isPositive = specific.value > 0;
1419
+ var isNegative = specific.value < 0;
1420
+
1421
+ if (isLast) {
1422
+ label = typeof properties.tooltipsFormattedKeyLabels[2] === 'string' ? properties.tooltipsFormattedKeyLabels[2] : '';
1423
+ } else if (!isLast && isNull) {
1424
+ label = typeof properties.tooltipsFormattedKeyLabels[3] === 'string' ? properties.tooltipsFormattedKeyLabels[3] : '';
1425
+ } else if (typeof properties.tooltipsFormattedKeyLabels[0] === 'string' && isPositive && !isLast) {
1426
+ label = properties.tooltipsFormattedKeyLabels[0];
1427
+ } else if (typeof properties.tooltipsFormattedKeyLabels[1] === 'string' && isNegative) {
1428
+ label = properties.tooltipsFormattedKeyLabels[1];
1429
+ } else if (typeof properties.tooltipsFormattedKeyLabels[2] === 'string' && isLast) {
1430
+ label = properties.tooltipsFormattedKeyLabels[2];
1431
+ }
1432
+ }
1433
+
1434
+
1435
+
1436
+
1437
+
1438
+ //
1439
+ // Calculate the subtotal for null values which are
1440
+ // within the dataset
1441
+ //
1442
+ if (RGraph.SVG.isNull(this.data[specific.index])) {
1443
+
1444
+ // Calculate the total thus far
1445
+ for (var i=0,value=0; i<=specific.index; ++i) {
1446
+ value += this.data[i];
1447
+ }
1448
+ }
1449
+
1450
+ return {
1451
+ label: label,
1452
+ color: color,
1453
+ value: value
1454
+ };
1455
+ };
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+
1464
+ //
1465
+ // This allows for static tooltip positioning
1466
+ //
1467
+ this.positionTooltipStatic = function (args)
1468
+ {
1469
+ var obj = args.object,
1470
+ e = args.event,
1471
+ tooltip = args.tooltip,
1472
+ index = args.index,
1473
+ svgXY = RGraph.SVG.getSVGXY(obj.svg),
1474
+ coords = this.coords[args.index];
1475
+
1476
+ // Position the tooltip in the X direction
1477
+ args.tooltip.style.left = (
1478
+ svgXY[0] // The X coordinate of the SVG tag
1479
+ + coords.x // The X coordinate of the bar on the chart
1480
+ - (tooltip.offsetWidth / 2) // Subtract half of the tooltip width
1481
+ + (coords.width / 2) // Add half of the bar width
1482
+ ) + 'px';
1483
+
1484
+ args.tooltip.style.top = (
1485
+ svgXY[1] // The Y coordinate of the SVG tag
1486
+ + coords.y // The Y coordinate of the bar on the chart
1487
+ - tooltip.offsetHeight // The height of the tooltip
1488
+ - 10 // An arbitrary amount
1489
+ ) + 'px';
1490
+
1491
+
1492
+
1493
+ // If the top of the tooltip is off the top of the page
1494
+ // then move the tooltip down
1495
+ if(parseFloat(args.tooltip.style.top) < 0) {
1496
+ args.tooltip.style.top = (
1497
+ svgXY[1] // The Y coordinate of the SVG tag
1498
+ + coords.y // The Y coordinate of the bar on the chart
1499
+ + (coords.height / 2) // Add half the height of the bar
1500
+ - tooltip.offsetHeight // The height of the tooltip
1501
+ - 10 // An arbitrary amount
1502
+ ) + 'px';
1503
+ }
1504
+ };
1505
+
1506
+
1507
+
1508
+
1509
+
1510
+
1511
+
1512
+
1513
+ //
1514
+ // Set the options that the user has provided
1515
+ //
1516
+ for (i in conf.options) {
1517
+ if (typeof i === 'string') {
1518
+ this.set(i, conf.options[i]);
1519
+ }
1520
+ }
1521
+ };
1522
+
1523
+ return this;
1524
+
1525
+ // End module pattern
1526
+ })(window, document);