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,90 +1,1897 @@
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.Waterfall=function(conf)
3
- {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var parseConfObjectForOptions=true;}else{var conf={id:conf,data:arguments[1]};}
4
- this.id=conf.id;this.canvas=document.getElementById(this.id);this.context=this.canvas.getContext?this.canvas.getContext("2d"):null;this.canvas.__object__=this;this.type='waterfall';this.max=0;this.data=conf.data;this.isRGraph=true;this.coords=[];this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.colorsParsed=false;this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.propertyNameAliases={};this.properties={'chart.background.bars.count':null,'chart.background.bars.color1':'rgba(0,0,0,0)','chart.background.bars.color2':'rgba(0,0,0,0)','chart.background.grid':true,'chart.background.grid.autofit':true,'chart.background.grid.autofit.align':true,'chart.background.grid.color':'#ddd','chart.background.grid.linewidth':1,'chart.background.grid.hsize':20,'chart.background.grid.vsize':20,'chart.background.grid.vlines':true,'chart.background.grid.hlines':true,'chart.background.grid.border':true,'chart.background.grid.align':true,'chart.background.grid.hlines.count':5,'chart.background.grid.vlines.count':20,'chart.background.image':null,'chart.background.image.stretch':true,'chart.background.image.x':null,'chart.background.image.y':null,'chart.background.image.w':null,'chart.background.image.h':null,'chart.background.image.align':null,'chart.background.hbars':null,'chart.linewidth':1,'chart.axes':true,'chart.axes.linewidth':1,'chart.axes.color':'black','chart.hmargin':5,'chart.colors.stroke':'#666','chart.colors':['green','red','blue'],'chart.colors.sequential':false,'chart.margin.left':35,'chart.margin.right':35,'chart.margin.top':35,'chart.margin.bottom':35,'chart.xaxis':true,'chart.xaxis.position':'bottom','chart.xaxis.tickmarks.count':null,'chart.xaxis.title':'','chart.xaxis.title.pos':null,'chart.xaxis.title.bold':null,'chart.xaxis.title.italic':null,'chart.xaxis.title.size':null,'chart.xaxis.title.font':null,'chart.xaxis.title.color':null,'chart.xaxis.title.x':null,'chart.xaxis.title.y':null,'chart.xaxis.labels':[],'chart.xaxis.labels.bold':null,'chart.xaxis.labels.color':null,'chart.xaxis.labels.font':null,'chart.xaxis.labels.italic':null,'chart.xaxis.labels.size':null,'chart.xaxis.labels.offsetx':0,'chart.xaxis.labels.offsety':0,'chart.yaxis':true,'chart.yaxis.tickmarks.count':10,'chart.yaxis.title':'','chart.yaxis.title.bold':null,'chart.yaxis.title.italic':null,'chart.yaxis.title.size':null,'chart.yaxis.title.font':null,'chart.yaxis.title.color':null,'chart.yaxis.title.pos':null,'chart.yaxis.title.align':'left','chart.yaxis.title.x':null,'chart.yaxis.title.y':null,'chart.yaxis.labels':true,'chart.yaxis.labels.count':5,'chart.yaxis.labels.offsetx':0,'chart.yaxis.labels.offsety':0,'chart.yaxis.labels.font':null,'chart.yaxis.labels.size':null,'chart.yaxis.labels.color':null,'chart.yaxis.labels.bold':null,'chart.yaxis.labels.italic':null,'chart.yaxis.scale.max':null,'chart.yaxis.scale.min':0,'chart.yaxis.scale.units.pre':'','chart.yaxis.scale.units.post':'','chart.yaxis.scale.decimals':0,'chart.yaxis.scale.point':'.','chart.yaxis.scale.thousand':',','chart.yaxis.scale.zerostart':true,'chart.labels.above':false,'chart.labels.above.font':null,'chart.labels.above.size':null,'chart.labels.above.bold':null,'chart.labels.above.italic':null,'chart.labels.above.color':null,'chart.labels.above.offsetx':0,'chart.labels.above.offsety':0,'chart.labels.above.specific':null,'chart.labels.above.decimals':0,'chart.labels.above.units.pre':'','chart.labels.above.units.post':'','chart.labels.above.point':'.','chart.labels.above.thousand':',','chart.labels.above.formatter':null,'chart.labels.above.total.italic':null,'chart.labels.above.total.bold':null,'chart.labels.above.total.size':null,'chart.labels.above.total.font':null,'chart.labels.above.total.color':null,'chart.labels.above.total.decimals':null,'chart.labels.above.total.units.pre':null,'chart.labels.above.total.units.post':null,'chart.labels.above.total.point':null,'chart.labels.above.total.thousand':null,'chart.labels.above.total.formatter':null,'chart.text.color':'black','chart.text.size':12,'chart.text.font':'Arial, Verdana, sans-serif','chart.text.bold':false,'chart.text.italic':false,'chart.text.angle':0,'chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':false,'chart.title':'','chart.title.color':'black','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':null,'chart.title.font':null,'chart.title.size':null,'chart.title.italic':null,'chart.title.color':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.offsetx':3,'chart.shadow.offsety':3,'chart.shadow.blur':3,'chart.tooltips':null,'chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.event':'onclick','chart.tooltips.highlight':true,'chart.tooltips.override':null,'chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.contextmenu':null,'chart.crosshairs':false,'chart.crosshairs.color':'#333','chart.crosshairs.hline':true,'chart.crosshairs.vline':true,'chart.annotatable':false,'chart.annotatable.linewidth':1,'chart.annotatable.color':'black','chart.resizable':false,'chart.resizable.handle.background':null,'chart.total':true,'chart.multiplier.x':1,'chart.multiplier.w':1,'chart.events.click':null,'chart.events.mousemove':null,'chart.key':null,'chart.key.background':'white','chart.key.position':'graph','chart.key.halign':'right','chart.key.shadow':false,'chart.key.shadow.color':'#666','chart.key.shadow.blur':3,'chart.key.shadow.offsetx':2,'chart.key.shadow.offsety':2,'chart.key.position.gutter.boxed':false,'chart.key.position.x':null,'chart.key.position.y':null,'chart.key.color.shape':'square','chart.key.rounded':true,'chart.key.linewidth':1,'chart.key.colors':null,'chart.key.interactive':false,'chart.key.interactive.highlight.chart.stroke':'#000','chart.key.interactive.highlight.chart.fill':'rgba(255,255,255,0.7)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.labels.color':null,'chart.key.labels.font':null,'chart.key.labels.size':null,'chart.key.labels.bold':null,'chart.key.labels.italic':null,'chart.key.labels.offsetx':0,'chart.key.labels.offsety':0,'chart.bar.offsetx':0,'chart.bar.offsety':0,'chart.clearto':'rgba(0,0,0,0)'}
5
- if(!this.canvas){alert('[WATERFALL] No canvas support');return;}
6
- for(var i=0,len=this.data.length;i<=len;++i){this['$'+i]={}
7
- if(typeof this.data[i]==='string'){this.data[i]=parseFloat(this.data[i]);}}
8
- if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
9
- var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
10
- if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
11
- this.set=this.Set=function(name,value)
12
- {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
13
- if(name.substr(0,6)!='chart.'){name='chart.'+name;}
14
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
15
- prop[name.toLowerCase()]=value;return this;};this.get=this.Get=function(name)
16
- {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
17
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
18
- return prop[name.toLowerCase()];};this.draw=this.Draw=function()
19
- {RG.fireCustomEvent(this,'onbeforedraw');if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
20
- RGraph.DrawBackgroundImage(this);this.marginLeft=prop['chart.margin.left'];this.marginRight=prop['chart.margin.right'];this.marginTop=prop['chart.margin.top'];this.marginBottom=prop['chart.margin.bottom'];this.coords=[];this.coordsText=[];this.centery=((ca.height-this.marginTop-this.marginBottom)/2)+this.marginTop;this.max=0;this.grapharea=ca.height-this.marginTop-this.marginBottom;this.graphwidth=ca.width-this.marginLeft-this.marginRight;this.halfTextHeight=prop['chart.text.size']/2;this.max=this.getMax(this.data);var decimals=prop['chart.yaxis.scale.decimals'];this.scale2=RG.getScale2(this,{'scale.max':typeof(prop['chart.yaxis.scale.max'])=='number'?prop['chart.yaxis.scale.max']:this.max,'scale.min':prop['chart.yaxis.scale.min'],'scale.strict':typeof(prop['chart.yaxis.scale.max'])==='number'?true:false,'scale.decimals':Number(decimals),'scale.point':prop['chart.yaxis.scale.point'],'scale.thousand':prop['chart.yaxis.scale.thousand'],'scale.round':prop['chart.yaxis.scale.round'],'scale.units.pre':prop['chart.yaxis.scale.units.pre'],'scale.units.post':prop['chart.yaxis.scale.units.post'],'scale.labels.count':prop['chart.yaxis.labels.count']});this.max=this.scale2.max;this.min=this.scale2.min;RG.drawBars(this)
21
- RG.Background.draw(this);this.DrawAxes();this.Drawbars();this.DrawLabels();if(prop['chart.xaxis.position']==='bottom'&&prop['chart.axes']&&prop['chart.xaxis']&&prop['chart.yaxis.scale.min']===0){co.strokeStyle=prop['chart.axes.color'];co.strokeRect(prop['chart.margin.left'],ca.height-this.marginBottom,ca.width-this.marginLeft-this.marginRight,0);}
22
- if(prop['chart.contextmenu']){RG.ShowContext(this);}
23
- if(prop['chart.resizable']){RG.AllowResizing(this);}
24
- RG.InstallEventListeners(this);if(prop['chart.key']&&prop['chart.key'].length){RG.DrawKey(this,prop['chart.key'],prop['chart.colors']);}
25
- if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
26
- RG.FireCustomEvent(this,'ondraw');return this;};this.drawAxes=this.DrawAxes=function()
27
- {if(!prop['chart.axes']){return;}
28
- co.beginPath();co.strokeStyle=prop['chart.axes.color'];co.lineWidth=prop['chart.axes.linewidth']+0.001;if(prop['chart.yaxis']){co.moveTo(ma.round(this.marginLeft),this.marginTop);co.lineTo(ma.round(this.marginLeft),ca.height-this.marginBottom);}
29
- if(prop['chart.xaxis']){if(prop['chart.xaxis.position']=='center'){co.moveTo(this.marginLeft,ma.round(((ca.height-this.marginTop-this.marginBottom)/2)+this.marginTop));co.lineTo(ca.width-this.marginRight,ma.round(((ca.height-this.marginTop-this.marginBottom)/2)+this.marginTop));}else{var y=ma.floor(this.getYCoord(0));co.moveTo(this.marginLeft,y);co.lineTo(ca.width-this.marginRight,y);}}
30
- var numYTicks=prop['chart.yaxis.tickmarks.count'];if(prop['chart.yaxis']&&prop['chart.yaxis.tickmarks.count']>0){var yTickGap=(ca.height-this.marginTop-this.marginBottom)/numYTicks;for(y=this.marginTop;y<(ca.height-this.marginBottom);y+=yTickGap){if(prop['chart.xaxis.position']=='bottom'||(y!=((ca.height-this.marginTop-this.marginBottom)/2)+this.marginTop)){co.moveTo(this.marginLeft,ma.round(y));co.lineTo(this.marginLeft-3,ma.round(y));}}
31
- if(!prop['chart.xaxis']||prop['chart.xaxis.position']=='center'||prop['chart.yaxis.scale.min']!==0){co.moveTo(this.marginLeft-3,Math.round(ca.height-this.marginBottom));co.lineTo(this.marginLeft,Math.round(ca.height-this.marginBottom));}}
32
- if(prop['chart.xaxis.tickmarks.count']==null){prop['chart.xaxis.tickmarks.count']=this.data.length+(prop['chart.total']?1:0)}
33
- if(prop['chart.xaxis']&&prop['chart.xaxis.tickmarks.count']>0){xTickGap=(ca.width-this.marginLeft-this.marginRight)/prop['chart.xaxis.tickmarks.count'];if(prop['chart.xaxis.position']=='center'){yStart=((ca.height-this.marginBottom-this.marginTop)/2)+this.marginTop-3;yEnd=((ca.height-this.marginBottom-this.marginTop)/2)+this.marginTop+3;}else{yStart=this.getYCoord(0)-(this.scale2.min<0?3:0);yEnd=this.getYCoord(0)+3;}
34
- for(x=this.marginLeft+xTickGap;x<=ca.width-this.marginRight+1;x+=xTickGap){co.moveTo(ma.round(x),yStart);co.lineTo(ma.round(x),yEnd);}
35
- if(!prop['chart.yaxis']){co.moveTo(ma.round(this.marginLeft),yStart);co.lineTo(ma.round(this.marginLeft),yEnd);}}
36
- if(!prop['chart.yaxis']&&prop['chart.xaxis']){co.moveTo(ma.round(this.marginLeft),this.getYCoord(0));co.lineTo(ma.round(this.marginLeft),this.getYCoord(0));}
37
- co.stroke();};this.drawLabels=this.DrawLabels=function()
38
- {var context=co,numYLabels=5,interval=this.grapharea/numYLabels,italic=prop['chart.text.italic'],bold=prop['chart.text.bold'],font=prop['chart.text.font'],size=prop['chart.text.size'],color=prop['chart.text.color'],units_pre=prop['chart.yaxis.scale.units.pre'],units_post=prop['chart.yaxis.scale.units.post'],offsetx=prop['chart.yaxis.labels.offsetx'],offsety=prop['chart.yaxis.labels.offsety'];co.beginPath();co.fillStyle=color;var textConf=RG.getTextConf({object:this,prefix:'chart.yaxis.labels'});if(prop['chart.yaxis.labels']){if(prop['chart.xaxis.position']=='center'){var halfInterval=interval/2;var halfWay=((ca.height-this.marginTop-this.marginBottom)/2)+this.marginTop;for(var i=0,len=this.scale2.labels.length;i<len;++i){RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft-5+offsetx,y:this.marginTop+(((this.grapharea/2)/len)*i)+offsety,text:this.scale2.labels[len-i-1],valign:'center',halign:'right',tag:'scale'});RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft-5+offsetx,y:halfWay+(((this.grapharea/2)/len)*(i+1))+offsety,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
39
- if(prop['chart.yaxis.scale.zerostart']){RG.text2(co,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft-5+offsetx,y:halfWay,text:'0',valign:'center',halign:'right',tag:'scale'});}}else{for(var i=0,len=this.scale2.values.length;i<len;++i){var y=this.getYCoord(this.scale2.values[i])+offsety;RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft-5+offsetx,y:y,text:this.scale2.labels[i],valign:'center',halign:'right',tag:'scale'});}
40
- if(prop['chart.yaxis.scale.zerostart']||prop['chart.yaxis.scale.min']!==0){RG.text2(co,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft-5+offsetx,y:this.getYCoord(prop['chart.yaxis.scale.min']||0),text:RG.numberFormat({object:this,number:String(Number(prop['chart.yaxis.scale.min']||0).toFixed(prop['chart.yaxis.scale.min']===0?0:prop['chart.yaxis.scale.decimals'])),unitspre:prop['chart.yaxis.scale.units.pre'],unitspost:prop['chart.yaxis.scale.units.post']}),valign:'center',halign:'right',tag:'scale'});}}}
41
- if(prop['chart.xaxis.labels'].length>0){interval=(ca.width-this.marginLeft-this.marginRight)/prop['chart.xaxis.labels'].length;var halign='center',valign='top',angle=prop['chart.text.angle'];if(angle){halign='right';angle*=-1;}
42
- var labels=prop['chart.xaxis.labels'],offsetx=prop['chart.xaxis.labels.offsetx'],offsety=prop['chart.xaxis.labels.offsety'];var textConf=RG.getTextConf({object:this,prefix:'chart.xaxis.labels'});for(var i=0,len=labels.length;i<len;i+=1){RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:this.marginLeft+(i*interval)+(interval/2)+offsetx,y:ca.height-this.marginBottom+this.halfTextHeight+offsety,text:labels[i],valign:valign,halign:halign,angle:angle,tag:'labels'});}}
43
- co.stroke();co.fill();if(prop['chart.labels.above']){this.drawLabelsAbove();}};this.drawLabelsAbove=function()
44
- {var data=this.data,unitsPre=prop['chart.labels.above.units.pre'],unitsPost=prop['chart.labels.above.units.post'],decimals=prop['chart.labels.above.decimals'],thousand=prop['chart.labels.above.thousand'],point=prop['chart.labels.above.point'],formatter=prop['chart.labels.above.formatter'];var textConf=RG.getTextConf({object:this,prefix:'chart.labels.above'});for(var i=0;i<this.data.length+(prop['chart.total']?1:0);++i){if(prop['chart.total']&&i===this.data.length){var isTotal=true;}
45
- var value=Number(isTotal?this.total:this.data[i]);if(typeof prop['chart.labels.above.color']==='object'&&prop['chart.labels.above.color']){if(isTotal&&typeof prop['chart.labels.above.color'][2]==='string'){color=prop['chart.labels.above.color'][2];}else if(this.data[i]<0){color=prop['chart.labels.above.color'][1];}else{color=prop['chart.labels.above.color'][0];}}
46
- if(typeof prop['chart.labels.above.total.color']==='object'&&prop['chart.labels.above.total.color']){if(isTotal&&typeof prop['chart.labels.above.total.color'][0]==='string'&&typeof prop['chart.labels.above.total.color'][1]==='string'){if(this.total<0){color=prop['chart.labels.above.total.color'][1];}else{color=prop['chart.labels.above.total.color'][0];}}}
47
- var coords=this.coords[i];var tmpScaleThousand=prop['chart.yaxis.scale.thousand'],tmpScalePoint=prop['chart.yaxis.scale.decimal'];prop['chart.yaxis.scale.thousand']=prop['chart.labels.above.thousand'];prop['chart.yaxis.scale.point']=prop['chart.labels.above.point'];if(formatter){var str=(formatter)({object:this,value:value,index:i});}else{var str=RG.numberFormat({object:this,number:String(value.toFixed(decimals)),unitspre:unitsPre,unitspost:unitsPost,point:point,thousand:thousand});}
48
- if(isTotal||i===this.data.length){if(typeof prop['chart.labels.above.total.font']==='string')textConf.font=prop['chart.labels.above.total.font'];if(typeof prop['chart.labels.above.total.color']==='string')textConf.color=prop['chart.labels.above.total.color'];if(typeof prop['chart.labels.above.total.size']==='number')textConf.size=prop['chart.labels.above.total.size'];if(!RG.isNull(prop['chart.labels.above.total.bold']))textConf.bold=prop['chart.labels.above.total.bold'];if(!RG.isNull(prop['chart.labels.above.total.italic']))textConf.italic=prop['chart.labels.above.total.italic'];if(typeof prop['chart.labels.above.total.units.pre']==='string')unitsPre=prop['chart.labels.above.total.units.pre'];if(typeof prop['chart.labels.above.total.units.post']==='string')unitsPost=prop['chart.labels.above.total.units.post'];if(typeof prop['chart.labels.above.total.decimals']==='number')decimals=prop['chart.labels.above.total.decimals'];if(typeof prop['chart.labels.above.total.formatter']==='function')formatter=prop['chart.labels.above.total.formatter'];if(typeof prop['chart.labels.above.total.thousand']==='string')thousand=prop['chart.labels.above.total.thousand'];if(typeof prop['chart.labels.above.total.point']==='string')point=prop['chart.labels.above.total.point'];if(formatter){var str=(formatter)({object:this,value:value,index:i});}else{str=RG.numberFormat({object:this,number:String(value.toFixed(decimals)),unitspre:unitsPre,unitspost:unitsPost,point:point,thousand:thousand});}
49
- prop['chart.yaxis.scale.thousand']=tmpScaleThousand;prop['chart.yaxis.scale.point']=tmpScalePoint;}
50
- if(typeof prop['chart.labels.above.specific']==='object'&&!RG.isNull(prop['chart.labels.above.specific'])&&(typeof prop['chart.labels.above.specific'][i]==='string'||typeof prop['chart.labels.above.specific'][i]==='number')){str=prop['chart.labels.above.specific'][i];}
51
- RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:coords[0]+(coords[2]/2)+prop['chart.labels.above.offsetx'],y:(isTotal?this.total:this.data[i])>=0?(coords[1]-3-prop['chart.labels.above.offsety']):(coords[1]+coords[3]+3+prop['chart.labels.above.offsety']),text:str,valign:(isTotal?this.total:this.data[i])>=0?'bottom':'top',halign:'center',tag:'labels.above'});}};this.drawbars=this.Drawbars=function()
52
- {var context=co,canvas=ca,hmargin=prop['chart.hmargin'],runningTotal=0;co.lineWidth=prop['chart.linewidth']+0.001;for(var i=0,len=this.data.length,seq=0;i<len;++i,++seq){co.beginPath();co.strokeStyle=prop['chart.colors.stroke'];var x=ma.round(this.marginLeft+hmargin+(((this.graphwidth/(this.data.length+(prop['chart.total']?1:0)))*i)*prop['chart.multiplier.x']));var h=this.getYCoord(0)-this.getYCoord(ma.abs(this.data[i]));if(i===0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(runningTotal)-h;}
53
- y=ma.round(y);var w=((ca.width-this.marginLeft-this.marginRight)/(this.data.length+(prop['chart.total']?1:0)))-(2*prop['chart.hmargin']);w=w*prop['chart.multiplier.w'];if(this.data[i]<0){y+=h;}
54
- co.fillStyle=this.data[i]>=0?prop['chart.colors'][0]:prop['chart.colors'][1];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq];}
55
- if(prop['chart.shadow']){RG.setShadow(this,prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'],prop['chart.shadow.blur']);}else{RG.noShadow(this);}
56
- co.rect(x+prop['chart.bar.offsetx'],ma.floor(y)+prop['chart.bar.offsety'],w,ma.floor(h));this.coords.push([x,y,w,h]);runningTotal+=this.data[i];co.stroke();co.fill();}
57
- this.total=runningTotal;if(prop['chart.total']){h=this.getYCoord(0)-this.getYCoord(ma.abs(runningTotal));if(prop['chart.xaxis.position']=='center'){y=runningTotal>0?this.getYCoord(0)-h:this.getYCoord(0);}else{if(runningTotal>0){y=this.getYCoord(0)-h;}else{y=this.getYCoord(0);}}
58
- x=x+(prop['chart.hmargin']*2)+w;co.fillStyle=prop['chart.colors'][2];if(prop['chart.colors.sequential']){co.fillStyle=prop['chart.colors'][seq]}
59
- pa2(co,'b r % % % % s % f %',x+prop['chart.bar.offsetx'],y+prop['chart.bar.offsety'],w,h,co.strokeStyle,co.fillStyle);var previousCoords=[x,y,w,ma.abs(h)];this.coords.push(previousCoords);}
60
- RG.noShadow(this);co.lineWidth=1;co.strokeStyle='#666';co.beginPath();for(var i=1,len=this.coords.length;i<len;i+=1){var prev=this.coords[i-1],curr=this.coords[i],prevData=this.data[i-1];var y=(prevData>0?prev[1]:prev[1]+prev[3]);co.moveTo(prev[0]+prev[2]+prop['chart.bar.offsetx'],y+prop['chart.bar.offsety']);co.lineTo(curr[0]+prop['chart.bar.offsetx'],(prevData>0?prev[1]:prev[1]+prev[3])+prop['chart.bar.offsety']);}
61
- co.stroke();};this.getShape=this.getBar=function(e)
62
- {for(var i=0,len=this.coords.length;i<len;i++){var mouseXY=RG.getMouseXY(e),mouseX=mouseXY[0],mouseY=mouseXY[1];var left=this.coords[i][0],top=this.coords[i][1],width=this.coords[i][2],height=this.coords[i][3];if(mouseX>=left&&mouseX<=(left+width)&&mouseY>=top&&mouseY<=top+height){var tooltip=RG.parseTooltipText(prop['chart.tooltips'],i);return{0:this,object:this,1:left,x:left,2:top,y:top,3:width,width:width,4:height,height:height,5:i,index:i,tooltip:tooltip};}}
63
- return null;};this.getMax=function(data)
64
- {var runningTotal=0,max=0;for(var i=0,len=data.length;i<len;i+=1){runningTotal+=data[i];max=ma.max(ma.abs(runningTotal),max);}
65
- return ma.abs(max);};this.allowTooltips=this.AllowTooltips=function()
66
- {RG.PreLoadTooltipImages(this);RG.InstallWindowMousedownTooltipListener(this);RG.InstallCanvasMousemoveTooltipListener(this);RG.InstallCanvasMouseupTooltipListener(this);};this.highlight=this.Highlight=function(shape)
67
- {if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Rect(this,shape);}};this.getObjectByXY=function(e)
68
- {var mouseXY=RG.getMouseXY(e);if(mouseXY[0]>this.marginLeft&&mouseXY[0]<(ca.width-this.marginRight)&&mouseXY[1]>this.marginTop&&mouseXY[1]<(ca.height-this.marginBottom)){return this;}};this.getYCoord=function(value)
69
- {if(prop['chart.xaxis.position']=='center'){if(value<(-1*this.max)){return null;}
70
- var coord=(value/this.max)*(this.grapharea/2);return this.marginTop+(this.grapharea/2)-coord;}else{var coord=((value-this.scale2.min)/(this.max-this.scale2.min))*this.grapharea;coord=coord+this.marginBottom;return ca.height-coord;}};this.parseColors=function()
71
- {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.arrayClone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.arrayClone(prop['chart.key.colors']);this.original_colors['chart.crosshairs.color']=RG.arrayClone(prop['chart.crosshairs.color']);this.original_colors['chart.highlight.stroke']=RG.arrayClone(prop['chart.highlight.stroke']);this.original_colors['chart.highlight.fill']=RG.arrayClone(prop['chart.highlight.fill']);this.original_colors['chart.background.bars.color1']=RG.arrayClone(prop['chart.background.bars.color1']);this.original_colors['chart.background.bars.color2']=RG.arrayClone(prop['chart.background.bars.color2']);this.original_colors['chart.background.grid.color']=RG.arrayClone(prop['chart.background.grid.color']);this.original_colors['chart.colors.stroke']=RG.arrayClone(prop['chart.colors.stroke']);this.original_colors['chart.axes.color']=RG.arrayClone(prop['chart.axes.color']);}
72
- var colors=prop['chart.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
73
- var colors=prop['chart.key.colors'];if(colors){for(var i=0,len=colors.length;i<len;++i){colors[i]=this.parseSingleColorForGradient(colors[i]);}}
74
- prop['chart.crosshairs.color']=this.parseSingleColorForGradient(prop['chart.crosshairs.color']);prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.background.bars.color1']=this.parseSingleColorForGradient(prop['chart.background.bars.color1']);prop['chart.background.bars.color2']=this.parseSingleColorForGradient(prop['chart.background.bars.color2']);prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.colors.stroke']=this.parseSingleColorForGradient(prop['chart.colors.stroke']);prop['chart.axes.color']=this.parseSingleColorForGradient(prop['chart.axes.color']);};this.reset=function()
75
- {};this.parseSingleColorForGradient=function(color)
76
- {if(!color||typeof color!='string'){return color;}
77
- if(typeof color==='string'&&color.match(/^gradient\((.*)\)$/i)){if(color.match(/^gradient\(({.*})\)$/i)){return RGraph.parseJSONGradient({object:this,def:RegExp.$1});}
78
- var parts=RegExp.$1.split(':');var grad=co.createLinearGradient(0,ca.height-prop['chart.margin.bottom'],0,prop['chart.margin.top']);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1,len=parts.length;j<len;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
79
- return grad?grad:color;};this.on=function(type,func)
80
- {if(type.substr(0,2)!=='on'){type='on'+type;}
81
- if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
82
- return this;};this.firstDrawFunc=function()
83
- {};this.grow=function()
84
- {var opt=arguments[0]||{};var callback=arguments[1]||function(){};var frames=opt.frames||30;var numFrame=0;var obj=this;var data=RG.array_clone(obj.data);for(var i=0,len=obj.data.length;i<len;++i){obj.data[i]/=frames;}
85
- if(obj.get('chart.yaxis.scale.max')==null){var max=obj.getMax(data);var scale2=RG.getScale2(obj,{'scale.max':max});obj.Set('chart.yaxis.scale.max',scale2.max);}
86
- function iterator()
87
- {for(var i=0;i<obj.data.length;++i){obj.data[i]=data[i]*RG.Effects.getEasingMultiplier(frames,numFrame);}
88
- RG.clear(obj.canvas);RG.redrawCanvas(obj.canvas);if(++numFrame<frames){RGraph.Effects.updateCanvas(iterator);}else{callback(obj);}}
89
- iterator();return this;};RG.register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}
90
- return this;};
12
+ RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
13
+
14
+ //
15
+ // The bar chart constructor
16
+ //
17
+ RGraph.Waterfall = function (conf)
18
+ {
19
+ this.id = conf.id;
20
+ this.canvas = document.getElementById(this.id);
21
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
22
+ this.canvas.__object__ = this;
23
+ this.type = 'waterfall';
24
+ this.max = 0;
25
+ this.data = conf.data;
26
+ this.isRGraph = true;
27
+ this.isrgraph = true;
28
+ this.rgraph = true;
29
+ this.coords = [];
30
+ this.uid = RGraph.createUID();
31
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.createUID();
32
+ this.colorsParsed = false;
33
+ this.coordsText = [];
34
+ this.original_colors = [];
35
+ this.original_data = RGraph.arrayClone(conf.data);
36
+ this.firstDraw = true; // After the first draw this will be false
37
+ this.stopAnimationRequested = false;// Used to control the animations
38
+
39
+
40
+
41
+
42
+
43
+
44
+ // Various config
45
+ this.properties =
46
+ {
47
+ backgroundBarsCount: null,
48
+ backgroundBarsColor1: 'rgba(0,0,0,0)',
49
+ backgroundBarsColor2: 'rgba(0,0,0,0)',
50
+ backgroundGrid: true,
51
+ backgroundGridAutofit: true,
52
+ backgroundGridAutofitAlign: true,
53
+ backgroundGridColor: '#ddd',
54
+ backgroundGridLinewidth: 1,
55
+ backgroundGridHsize: 20,
56
+ backgroundGridVsize: 20,
57
+ backgroundGridVlines: true,
58
+ backgroundGridHlines: true,
59
+ backgroundGridBorder: true,
60
+ backgroundGridAlign: true,
61
+ backgroundGridHlinesCount: 5,
62
+ backgroundGridVlinesCount: 20,
63
+ backgroundImage: null,
64
+ backgroundImageStretch: true,
65
+ backgroundImageX: null,
66
+ backgroundImageY: null,
67
+ backgroundImageW: null,
68
+ backgroundImageH: null,
69
+ backgroundImageAlign: null,
70
+ backgroundHbars: null,
71
+
72
+ linewidth: 1,
73
+
74
+ colorsStroke: '#666',
75
+ colors: ['green','red','blue'],
76
+ colorsSequential: false,
77
+ colorsConnectors: '#666',
78
+
79
+ marginLeft: 35,
80
+ marginRight: 35,
81
+ marginTop: 35,
82
+ marginBottom: 35,
83
+ marginInner: 5,
84
+
85
+ xaxis: true,
86
+ xaxisPosition: 'bottom',
87
+ xaxisLinewidth: 1,
88
+ xaxisColor: 'black',
89
+ xaxisTickmarks: true,
90
+ xaxisTickmarksLength: 3,
91
+ xaxisTickmarksLastLeft: null,
92
+ xaxisTickmarksLastRight: null,
93
+ xaxisTickmarksCount: null,
94
+ xaxisLabels: null,
95
+ xaxisLabelsFormattedDecimals: 0,
96
+ xaxisLabelsFormattedUnitsPre: '',
97
+ xaxisLabelsFormattedUnitsPost: '',
98
+ xaxisLabelsFormattedThousand: ',',
99
+ xaxisLabelsFormattedPoint: '.',
100
+ xaxisLabelsSize: null,
101
+ xaxisLabelsFont: null,
102
+ xaxisLabelsItalic: null,
103
+ xaxisLabelsBold: null,
104
+ xaxisLabelsColor: null,
105
+ xaxisLabelsOffsetx: 0,
106
+ xaxisLabelsOffsety: 0,
107
+ xaxisLabelsHalign: null,
108
+ xaxisLabelsValign: null,
109
+ xaxisLabelsPosition: 'section',
110
+ xaxisLabelsSpecificAlign:'LEFT',
111
+ xaxisPosition: 'bottom',
112
+ xaxisLabelsAngle: 0,
113
+ xaxisTitle: '',
114
+ xaxisTitleBold: null,
115
+ xaxisTitleSize: null,
116
+ xaxisTitleFont: null,
117
+ xaxisTitleColor: null,
118
+ xaxisTitleItalic: null,
119
+ xaxisTitlePos: null,
120
+ xaxisTitleOffsetx: 0,
121
+ xaxisTitleOffsety: 0,
122
+ xaxisTitleX: null,
123
+ xaxisTitleY: null,
124
+ xaxisTitleHalign: 'center',
125
+ xaxisTitleValign: 'top',
126
+
127
+
128
+ yaxis: true,
129
+ yaxisPosition: 'left',
130
+ yaxisLinewidth: 1,
131
+ yaxisColor: 'black',
132
+ yaxisTickmarks: true,
133
+ yaxisTickmarksCount: null,
134
+ yaxisTickmarksLastTop: null,
135
+ yaxisTickmarksLastBottom: null,
136
+ yaxisTickmarksLength: 3,
137
+ yaxisScale: true,
138
+ yaxisScaleMin: 0,
139
+ yaxisScaleMax: null,
140
+ yaxisScaleUnitsPre: '',
141
+ yaxisScaleUnitsPost: '',
142
+ yaxisScaleDecimals: 0,
143
+ yaxisScalePoint: '.',
144
+ yaxisScaleThousand: ',',
145
+ yaxisScaleRound: false,
146
+ yaxisScaleFormatter: null,
147
+ yaxisLabelsSpecific: null,
148
+ yaxisLabelsCount: 5,
149
+ yaxisLabelsOffsetx: 0,
150
+ yaxisLabelsOffsety: 0,
151
+ yaxisLabelsHalign: null,
152
+ yaxisLabelsValign: null,
153
+ yaxisLabelsFont: null,
154
+ yaxisLabelsSize: null,
155
+ yaxisLabelsColor: null,
156
+ yaxisLabelsBold: null,
157
+ yaxisLabelsItalic: null,
158
+ yaxisLabelsPosition: 'edge',
159
+ yaxisTitle: '',
160
+ yaxisTitleBold: null,
161
+ yaxisTitleSize: null,
162
+ yaxisTitleFont: null,
163
+ yaxisTitleColor: null,
164
+ yaxisTitleItalic: null,
165
+ yaxisTitlePos: null,
166
+ yaxisTitleX: null,
167
+ yaxisTitleY: null,
168
+ yaxisTitleOffsetx: 0,
169
+ yaxisTitleOffsety: 0,
170
+ yaxisTitleHalign: null,
171
+ yaxisTitleValign: null,
172
+ yaxisTitleAccessible: null,
173
+
174
+ yaxisTitle: '',
175
+ yaxisTitleBold: null,
176
+ yaxisTitleItalic: null,
177
+ yaxisTitleSize: null,
178
+ yaxisTitleFont: null,
179
+ yaxisTitleColor: null,
180
+ yaxisTitlePos: null,
181
+ yaxisTitleAlign: 'left',
182
+ yaxisTitleX: null,
183
+ yaxisTitleY: null,
184
+ yaxisLabels: true,
185
+ yaxisLabelsCount: 5,
186
+ yaxisLabelsOffsetx: 0,
187
+ yaxisLabelsOffsety: 0,
188
+ yaxisLabelsFont: null,
189
+ yaxisLabelsSize: null,
190
+ yaxisLabelsColor: null,
191
+ yaxisLabelsBold: null,
192
+ yaxisLabelsItalic: null,
193
+ yaxisScaleMax: null,
194
+ yaxisScaleMin: 0,
195
+ yaxisScaleUnitsPre: '',
196
+ yaxisScaleUnitsPost: '',
197
+ yaxisScaleDecimals: 0,
198
+ yaxisScalePoint: '.',
199
+ yaxisScaleThousand: ',',
200
+ yaxisScaleFormatter: null,
201
+
202
+ labelsAbove: false,
203
+ labelsAboveFont: null,
204
+ labelsAboveSize: null,
205
+ labelsAboveBold: null,
206
+ labelsAboveItalic: null,
207
+ labelsAboveColor: null,
208
+ labelsAboveOffsetx: 0,
209
+ labelsAboveOffsety: 0,
210
+ labelsAboveSpecific: null,
211
+ labelsAboveDecimals: 0,
212
+ labelsAboveUnitsPre: '',
213
+ labelsAboveUnitsPost: '',
214
+ labelsAbovePoint: '.',
215
+ labelsAboveThousand: ',',
216
+ labelsAboveFormatter: null,
217
+ labelsAboveTotalItalic: null,
218
+ labelsAboveTotalBold: null,
219
+ labelsAboveTotalSize: null,
220
+ labelsAboveTotalFont: null,
221
+ labelsAboveTotalColor: null,
222
+ labelsAboveTotalDecimals: null,
223
+ labelsAboveTotalUnitsPre: null,
224
+ labelsAboveTotalUnitsPost: null,
225
+ labelsAboveTotalPoint: null,
226
+ labelsAboveTotalThousand: null,
227
+ labelsAboveTotalFormatter: null,
228
+ labelsAboveTotalOffsetx: 0,
229
+ labelsAboveTotalOffsety: 0,
230
+
231
+ textColor: 'black',
232
+ textSize: 12,
233
+ textFont: 'Arial, Verdana, sans-serif',
234
+ textBold: false,
235
+ textItalic: false,
236
+ textAccessible: false,
237
+ textAccessibleOverflow: 'visible',
238
+ textAccessiblePointerevents: false,
239
+ text: null,
240
+
241
+ title: '',
242
+ titleBold: null,
243
+ titleFont: null,
244
+ titleSize: null,
245
+ titleItalic: null,
246
+ titleColor: null,
247
+ titleX: null,
248
+ titleY: null,
249
+ titleHalign: null,
250
+ titleValign: null,
251
+ titleOffsetx: 0,
252
+ titleOffsety: 0,
253
+ titleSubtitle: '',
254
+ titleSubtitleSize: null,
255
+ titleSubtitleColor: '#aaa',
256
+ titleSubtitleFont: null,
257
+ titleSubtitleBold: null,
258
+ titleSubtitleItalic: null,
259
+ titleSubtitleOffsetx: 0,
260
+ titleSubtitleOffsety: 0,
261
+
262
+
263
+
264
+ shadow: false,
265
+ shadowOffsetx: 2,
266
+ shadowOffsety: 2,
267
+ shadowBlur: 2,
268
+ shadowColor: 'rgba(0,0,0,0.25)',
269
+
270
+ tooltips: null,
271
+ tooltipsEffect: 'slide',
272
+ tooltipsCssClass: 'RGraph_tooltip',
273
+ tooltipsCss: null,
274
+ tooltipsEvent: 'onclick',
275
+ tooltipsHighlight: true,
276
+ tooltipsOverride: null,
277
+ tooltipsFormattedThousand: ',',
278
+ tooltipsFormattedPoint: '.',
279
+ tooltipsFormattedDecimals: 0,
280
+ tooltipsFormattedUnitsPre: '',
281
+ tooltipsFormattedUnitsPost: '',
282
+ tooltipsFormattedKeyColors: null,
283
+ tooltipsFormattedKeyColorsShape: 'square',
284
+ tooltipsFormattedKeyLabels: [],
285
+ tooltipsFormattedListType: 'ul',
286
+ tooltipsFormattedListItems: null,
287
+ tooltipsFormattedTableHeaders: null,
288
+ tooltipsFormattedTableData: null,
289
+ tooltipsPointer: true,
290
+ tooltipsPointerOffsetx: 0,
291
+ tooltipsPointerOffsety: 0,
292
+ tooltipsPositionStatic: true,
293
+ tooltipsHotspotIgnore: null,
294
+
295
+ highlightStroke: 'rgba(0,0,0,0)',
296
+ highlightFill: 'rgba(255,255,255,0.7)',
297
+
298
+ contextmenu: null,
299
+
300
+ crosshairs: false,
301
+ crosshairsColor: '#333',
302
+ crosshairsHline: true,
303
+ crosshairsVline: true,
304
+
305
+ annotatable: false,
306
+ annotatableLinewidth: 1,
307
+ annotatableColor: 'black',
308
+
309
+ resizable: false,
310
+ resizableHandleBackground: null,
311
+
312
+ total: true,
313
+
314
+ multiplierX: 1, // Used for animation
315
+ multiplierW: 1, // Used for animation
316
+
317
+ key: null,
318
+ keyBackground: 'white',
319
+ keyPosition: 'graph',
320
+ keyHalign: 'right',
321
+ keyShadow: false,
322
+ keyShadowColor: '#666',
323
+ keyShadowBlur: 3,
324
+ keyShadowOffsetx: 2,
325
+ keyShadowOffsety: 2,
326
+ keyPositionGutterBoxed: false,
327
+ keyPositionX: null,
328
+ keyPositionY: null,
329
+ keyColorShape: 'square',
330
+ keyRounded: true,
331
+ keyLinewidth: 1,
332
+ keyColors: null,
333
+ keyInteractive: false,
334
+ keyInteractiveHighlightChartStroke:'#000',
335
+ keyInteractiveHighlightChartFill: 'rgba(255,255,255,0.7)',
336
+ keyInteractiveHighlightLabel: 'rgba(255,0,0,0.2)',
337
+ keyLabelsColor: null,
338
+ keyLabelsFont: null,
339
+ keyLabelsSize: null,
340
+ keyLabelsBold: null,
341
+ keyLabelsItalic: null,
342
+ keyLabelsOffsetx: 0,
343
+ keyLabelsOffsety: 0,
344
+ keyFormattedDecimals: 0,
345
+ keyFormattedPoint: '.',
346
+ keyFormattedThousand: ',',
347
+ keyFormattedUnitsPre: '',
348
+ keyFormattedUnitsPost: '',
349
+ keyFormattedValueSpecific: null,
350
+ keyFormattedItemsCount: null,
351
+
352
+ barOffsetx: 0, // Used to facilitate multiple dataset Waterfall charts
353
+ barOffsety: 0, // Used to facilitate multiple dataset Waterfall charts
354
+
355
+ clearto: 'rgba(0,0,0,0)'
356
+ }
357
+
358
+ // Check for support
359
+ if (!this.canvas) {
360
+ alert('[WATERFALL] No canvas support');
361
+ return;
362
+ }
363
+
364
+ // Split a string
365
+ this.data = RGraph.stringsToNumbers(this.data);
366
+
367
+
368
+
369
+
370
+ //
371
+ // Create the $ objects
372
+ //
373
+ // 2/5/016: Now also use this loop to go through the dat conerting
374
+ // strings to floats
375
+ //
376
+ for (var i=0,len=this.data.length; i<=len; ++i) {
377
+
378
+ // Create the object for adding event listeners
379
+ this['$' + i] = {}
380
+
381
+ // Ensure that the data point is numeric
382
+ //if (typeof this.data[i] === 'string') {
383
+ // this.data[i] = parseFloat(this.data[i]);
384
+ //}
385
+ }
386
+
387
+
388
+
389
+
390
+ // Easy access to properties and the path function
391
+ var properties = this.properties;
392
+ this.path = RGraph.pathObjectFunction;
393
+
394
+
395
+
396
+ //
397
+ // "Decorate" the object with the generic effects if the effects library has been included
398
+ //
399
+ if (RGraph.Effects && typeof RGraph.Effects.decorate === 'function') {
400
+ RGraph.Effects.decorate(this);
401
+ }
402
+
403
+
404
+
405
+ // Add the responsive method. This method resides in the common file.
406
+ this.responsive = RGraph.responsive;
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+ //
416
+ // A setter
417
+ //
418
+ // @param name string The name of the property to set
419
+ // @param value mixed The value of the property
420
+ //
421
+ this.set = function (name)
422
+ {
423
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
424
+
425
+ // the number of arguments is only one and it's an
426
+ // object - parse it for configuration data and return.
427
+ if (arguments.length === 1 && typeof arguments[0] === 'object') {
428
+ for (i in arguments[0]) {
429
+ if (typeof i === 'string') {
430
+ this.set(i, arguments[0][i]);
431
+ }
432
+ }
433
+
434
+ return this;
435
+ }
436
+
437
+ properties[name] = value;
438
+
439
+ return this;
440
+ };
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+ //
450
+ // A getter
451
+ //
452
+ // @param name string The name of the property to get
453
+ //
454
+ this.get = function (name)
455
+ {
456
+ return properties[name];
457
+ };
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+ //
467
+ // The function you call to draw the bar chart
468
+ //
469
+ this.draw = function ()
470
+ {
471
+ //
472
+ // Fire the onbeforedraw event
473
+ //
474
+ RGraph.fireCustomEvent(this, 'onbeforedraw');
475
+
476
+
477
+ // Translate half a pixel for antialiasing purposes - but only if it hasn't been
478
+ // done already
479
+ //
480
+ // MUST be the first thing done!
481
+ //
482
+ if (!this.canvas.__rgraph_aa_translated__) {
483
+ this.context.translate(0.5,0.5);
484
+
485
+ this.canvas.__rgraph_aa_translated__ = true;
486
+ }
487
+
488
+
489
+ //
490
+ // Parse the colors. This allows for simple gradient syntax
491
+ //
492
+ if (!this.colorsParsed) {
493
+ this.parseColors();
494
+
495
+ // Don't want to do this again
496
+ this.colorsParsed = true;
497
+ }
498
+
499
+
500
+ //
501
+ // Draw the background image
502
+ //
503
+ RGraph.drawBackgroundImage(this);
504
+
505
+
506
+
507
+
508
+
509
+ //
510
+ // If the xaxisLabels option is a string then turn it
511
+ // into an array.
512
+ //
513
+ if (properties.xaxisLabels && properties.xaxisLabels.length) {
514
+
515
+ if (typeof properties.xaxisLabels === 'string') {
516
+ properties.xaxisLabels = RGraph.arrayPad({
517
+ array: [],
518
+ length: this.data.length + (properties.total ? 1 : 0),
519
+ value: properties.xaxisLabels
520
+ });
521
+ }
522
+
523
+ // Label substitution
524
+ //
525
+ for (var i=0; i<properties.xaxisLabels.length; ++i) {
526
+ properties.xaxisLabels[i] = RGraph.labelSubstitution({
527
+ object: this,
528
+ text: properties.xaxisLabels[i],
529
+ index: i,
530
+ value: i === this.data.length ? this.runningTotal() : this.data[i],
531
+ decimals: properties.xaxisLabelsFormattedDecimals || 0,
532
+ unitsPre: properties.xaxisLabelsFormattedUnitsPre || '',
533
+ unitsPost: properties.xaxisLabelsFormattedUnitsPost || '',
534
+ thousand: properties.xaxisLabelsFormattedThousand || ',',
535
+ point: properties.xaxisLabelsFormattedPoint || '.'
536
+ });
537
+ }
538
+ }
539
+
540
+
541
+
542
+
543
+
544
+
545
+ //
546
+ // Make the margins easy ro access
547
+ //
548
+ this.marginLeft = properties.marginLeft;
549
+ this.marginRight = properties.marginRight;
550
+ this.marginTop = properties.marginTop;
551
+ this.marginBottom = properties.marginBottom;
552
+
553
+ //
554
+ // Stop the coords array from growing uncontrollably
555
+ //
556
+ this.coords = [];
557
+
558
+
559
+
560
+ //
561
+ // Stop this growing uncontrollably
562
+ //
563
+ this.coordsText = [];
564
+
565
+
566
+
567
+
568
+ //
569
+ // This gets used a lot
570
+ //
571
+ this.centery = ((this.canvas.height - this.marginTop - this.marginBottom) / 2) + this.marginTop;
572
+
573
+ //
574
+ // Work out a few things. They need to be here because they depend on things you can change after you instantiate the object
575
+ //
576
+ this.max = 0;
577
+ this.grapharea = this.canvas.height - this.marginTop - this.marginBottom;
578
+ this.graphwidth = this.canvas.width - this.marginLeft - this.marginRight;
579
+ this.halfTextHeight = properties.textSize / 2;
580
+
581
+
582
+ //
583
+ // Work out the maximum value
584
+ //
585
+ this.max = this.getMax(this.data);
586
+ var decimals = properties.yaxisScaleDecimals;
587
+
588
+ this.scale2 = RGraph.getScale({object: this, options: {
589
+ 'scale.max': typeof properties.yaxisScaleMax == 'number' ? properties.yaxisScaleMax : this.max,
590
+ 'scale.min': properties.yaxisScaleMin,
591
+ 'scale.strict': typeof properties.yaxisScaleMax === 'number' ? true : false,
592
+ 'scale.decimals': Number(decimals),
593
+ 'scale.point': properties.yaxisScalePoint,
594
+ 'scale.thousand': properties.yaxisScaleThousand,
595
+ 'scale.round': properties.yaxisScaleRound,
596
+ 'scale.units.pre': properties.yaxisScaleUnitsPre,
597
+ 'scale.units.post': properties.yaxisScaleUnitsPost,
598
+ 'scale.labels.count': properties.yaxisLabelsCount,
599
+ 'scale.formatter': properties.yaxisScaleFormatter
600
+ }});
601
+
602
+ this.max = this.scale2.max;
603
+ this.min = this.scale2.min;
604
+
605
+ // Draw the background hbars
606
+ RGraph.drawBars(this)
607
+
608
+ // Progressively Draw the chart
609
+ RGraph.Background.draw(this);
610
+
611
+ this.drawAxes();
612
+ this.drawBars();
613
+ this.drawLabels();
614
+
615
+ //
616
+ // If the X axis is at the bottom AND ymin is 0 - draw the it
617
+ // again so that it appears "on top" of the bars
618
+ //
619
+ //if ( properties.xaxisPosition === 'bottom'
620
+ // && properties.axes
621
+ // && properties.xaxis
622
+ // && properties.yaxisScaleMin === 0) {
623
+
624
+ // this.context.strokeStyle = properties.axesColor;
625
+ // this.context.strokeRect(
626
+ // properties.marginLeft,
627
+ // this.canvas.height - this.marginBottom,
628
+ // this.canvas.width - this.marginLeft - this.marginRight,
629
+ // 0
630
+ // );
631
+ //}
632
+
633
+ //
634
+ // Setup the context menu if required
635
+ //
636
+ if (properties.contextmenu) {
637
+ RGraph.showContext(this);
638
+ }
639
+
640
+
641
+
642
+
643
+ //
644
+ // Add custom text thats specified
645
+ //
646
+ RGraph.addCustomText(this);
647
+
648
+
649
+
650
+
651
+
652
+
653
+
654
+
655
+ //
656
+ // This installs the event listeners
657
+ //
658
+ RGraph.installEventListeners(this);
659
+
660
+
661
+ // Draw a key if necessary
662
+ if (properties.key && properties.key.length) {
663
+ RGraph.drawKey(this, properties.key, properties.colors);
664
+ }
665
+
666
+
667
+ //
668
+ // Fire the onfirstdraw event
669
+ //
670
+ if (this.firstDraw) {
671
+ this.firstDraw = false;
672
+ RGraph.fireCustomEvent(this, 'onfirstdraw');
673
+ this.firstDrawFunc();
674
+ }
675
+
676
+
677
+
678
+
679
+ //
680
+ // Fire the RGraph draw event
681
+ //
682
+ RGraph.fireCustomEvent(this, 'ondraw');
683
+
684
+
685
+
686
+
687
+
688
+
689
+
690
+
691
+
692
+
693
+ //
694
+ // Install any inline responsive configuration. This
695
+ // should be last in the draw function - even after
696
+ // the draw events.
697
+ //
698
+ RGraph.installInlineResponsive(this);
699
+
700
+
701
+
702
+
703
+
704
+
705
+
706
+
707
+
708
+ return this;
709
+ };
710
+
711
+
712
+
713
+
714
+
715
+
716
+
717
+
718
+ //
719
+ // Draws the charts axes
720
+ //
721
+ this.drawAxes = function ()
722
+ {
723
+ //
724
+ // Draw the X axis
725
+ //
726
+ RGraph.drawXAxis(this);
727
+
728
+ //
729
+ // Draw the Y axis
730
+ //
731
+ RGraph.drawYAxis(this);
732
+ };
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+ //
742
+ // Draws the labels for the graph
743
+ //
744
+ this.drawLabels = function ()
745
+ {
746
+ //
747
+ // Draw the labelsAbove labels
748
+ //
749
+ if (properties.labelsAbove) {
750
+ this.drawLabelsAbove();
751
+ }
752
+ };
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+ //
762
+ // This function draws all of the above labels
763
+ //
764
+ this.drawLabelsAbove = function ()
765
+ {
766
+ var data = this.data,
767
+ unitsPre = properties.labelsAboveUnitsPre,
768
+ unitsPost = properties.labelsAboveUnitsPost,
769
+ decimals = properties.labelsAboveDecimals,
770
+ thousand = properties.labelsAboveThousand,
771
+ point = properties.labelsAbovePoint,
772
+ formatter = properties.labelsAboveFormatter;
773
+
774
+ var textConf = RGraph.getTextConf({
775
+ object: this,
776
+ prefix: 'labelsAbove'
777
+ });
778
+
779
+ for (var i=0; i<this.data.length + (properties.total ? 1 : 0); ++i) {
780
+
781
+ // Is this the "total" column
782
+ if (properties.total && i === this.data.length) {
783
+ var isTotal = true;
784
+ }
785
+
786
+ // Get the value
787
+ var value = Number(isTotal ? this.total : this.data[i]);
788
+
789
+ // Determine the color based on whether the value is positive,
790
+ // negative or the total
791
+ if (typeof properties.labelsAboveColor === 'object' && properties.labelsAboveColor) {
792
+ if (isTotal && typeof properties.labelsAboveColor[2] === 'string') {
793
+ color = properties.labelsAboveColor[2];
794
+ } else if (this.data[i] < 0) {
795
+ color = properties.labelsAboveColor[1];
796
+ } else {
797
+ color = properties.labelsAboveColor[0];
798
+ }
799
+ }
800
+
801
+
802
+ // Do the color handling again if this is the last
803
+ // label (and its an object) but using the
804
+ // labelsAboveLastColor property if it's set
805
+ if (typeof properties.labelsAboveTotalColor === 'object' && properties.labelsAboveTotalColor) {
806
+ if ( isTotal
807
+ && typeof properties.labelsAboveTotalColor[0] === 'string'
808
+ && typeof properties.labelsAboveTotalColor[1] === 'string'
809
+ ) {
810
+
811
+ if (this.total < 0) {
812
+ color = properties.labelsAboveTotalColor[1];
813
+ } else {
814
+ color = properties.labelsAboveTotalColor[0];
815
+ }
816
+ }
817
+ }
818
+
819
+ var coords = this.coords[i];
820
+
821
+
822
+
823
+
824
+ // This code is repeated below for the last label. Temporarily
825
+ // set the point and thousand properies because the numberFormat
826
+ // function is dumb. These properties are reset after the last
827
+ // label has been formatted
828
+ var tmpScaleThousand = properties.yaxisScaleThousand,
829
+ tmpScalePoint = properties.yaxisScaleDecimal;
830
+
831
+ properties.yaxisScaleThousand = properties.labelsAboveThousand;
832
+ properties.yaxisScalePoint = properties.labelsAbovePoint;
833
+
834
+ // Custom formatting or use the numberFormat function
835
+ if (formatter) {
836
+ var str = (formatter)({
837
+ object: this,
838
+ value: value,
839
+ index: i
840
+ });
841
+ } else {
842
+ var str = RGraph.numberFormat({
843
+ object: this,
844
+ number: String(value.toFixed(decimals)),
845
+ unitspre: unitsPre,
846
+ unitspost: unitsPost,
847
+ point: point,
848
+ thousand: thousand
849
+ });
850
+ }
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+ // Allow for the styling of the last label
860
+ if (isTotal || i === this.data.length) {
861
+
862
+ if (typeof properties.labelsAboveTotalFont === 'string') textConf.font = properties.labelsAboveTotalFont;
863
+ if (typeof properties.labelsAboveTotalColor === 'string') textConf.color = properties.labelsAboveTotalColor;
864
+ if (typeof properties.labelsAboveTotalSize === 'number') textConf.size = properties.labelsAboveTotalSize;
865
+ if (!RGraph.isNull(properties.labelsAboveTotalBold)) textConf.bold = properties.labelsAboveTotalBold;
866
+ if (!RGraph.isNull(properties.labelsAboveTotalItalic)) textConf.italic = properties.labelsAboveTotalItalic;
867
+ if (typeof properties.labelsAboveTotalUnitsPre === 'string') unitsPre = properties.labelsAboveTotalUnitsPre;
868
+ if (typeof properties.labelsAboveTotalUnitsPost === 'string') unitsPost = properties.labelsAboveTotalUnitsPost;
869
+ if (typeof properties.labelsAboveTotalDecimals === 'number') decimals = properties.labelsAboveTotalDecimals;
870
+ if (typeof properties.labelsAboveTotalFormatter === 'function') formatter = properties.labelsAboveTotalFormatter;
871
+ if (typeof properties.labelsAboveTotalThousand === 'string') thousand = properties.labelsAboveTotalThousand;
872
+ if (typeof properties.labelsAboveTotalPoint === 'string') point = properties.labelsAboveTotalPoint;
873
+
874
+
875
+
876
+
877
+ // Custom formatting or use the numberFormat function
878
+ // This code is repeated just up above
879
+ if (formatter) {
880
+ var str = (formatter)({
881
+ object: this,
882
+ value: value,
883
+ index: i
884
+ });
885
+ } else {
886
+
887
+ str = RGraph.numberFormat({
888
+ object: this,
889
+ number: String(value.toFixed(decimals)),
890
+ unitspre: unitsPre,
891
+ unitspost: unitsPost,
892
+ point: point,
893
+ thousand: thousand
894
+ });
895
+ }
896
+
897
+
898
+
899
+ // These two variables can now be reset to what they were when we
900
+ // started
901
+ properties.yaxisScaleThousand = tmpScaleThousand;
902
+ properties.yaxisScalePoint = tmpScalePoint;
903
+ }
904
+
905
+ // Allow for specific labels
906
+ if ( typeof properties.labelsAboveSpecific === 'object'
907
+ && !RGraph.isNull(properties.labelsAboveSpecific)
908
+ ) {
909
+
910
+ if ( typeof properties.labelsAboveSpecific[i] === 'string' || typeof properties.labelsAboveSpecific[i] === 'number' ) {
911
+ str = properties.labelsAboveSpecific[i];
912
+ } else {
913
+ str = '';
914
+ }
915
+ }
916
+
917
+
918
+ RGraph.text({
919
+
920
+ object: this,
921
+
922
+ font: textConf.font,
923
+ size: textConf.size,
924
+ color: textConf.color,
925
+ bold: textConf.bold,
926
+ italic: textConf.italic,
927
+
928
+ x: coords[0] + (coords[2] / 2) + (isTotal ? properties.labelsAboveTotalOffsetx : properties.labelsAboveOffsetx),
929
+ y: (isTotal ? this.total : this.data[i]) >= 0 ? (coords[1] - 3 + (isTotal ? properties.labelsAboveTotalOffsety : properties.labelsAboveOffsety)) : (coords[1] + coords[3] + 3 + (isTotal ? properties.labelsAboveTotalOffsety : properties.labelsAboveOffsety)),
930
+
931
+ text: str,
932
+ valign: (isTotal ? this.total : this.data[i]) >= 0 ? 'bottom' : 'top',
933
+ halign: 'center',
934
+ tag: 'labels.above'
935
+ });
936
+ }
937
+ };
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+ //
947
+ // Calculates the running total from the data
948
+ //
949
+ // @return The resulting total from the data
950
+ //
951
+ this.runningTotal = function ()
952
+ {
953
+ var runningTotal = 0;
954
+
955
+ for (var i=0; i<this.data.length; ++i) {
956
+ runningTotal += this.data[i];
957
+ }
958
+
959
+ return runningTotal;
960
+ };
961
+
962
+
963
+
964
+
965
+
966
+
967
+
968
+
969
+ //
970
+ // Draws the bars on to the chart
971
+ //
972
+ this.drawBars = function ()
973
+ {
974
+ var context = this.context,
975
+ canvas = this.canvas,
976
+ hmargin = properties.marginInner,
977
+ runningTotal = 0;
978
+
979
+ this.context.lineWidth = properties.linewidth + 0.001;
980
+
981
+ for (var i=0,len=this.data.length,seq=0; i<len; ++i,++seq) {
982
+
983
+ this.context.beginPath();
984
+
985
+ this.context.strokeStyle = properties.colorsStroke;
986
+
987
+ var x = Math.round( this.marginLeft + hmargin + (((this.graphwidth / (this.data.length + (properties.total ? 1 : 0))) * i) * properties.multiplierX));
988
+
989
+ // Must be before the y coord calculation
990
+ var h = this.getYCoord(0) - this.getYCoord(Math.abs(this.data[i]));
991
+
992
+
993
+
994
+ // Work out the Y coordinate
995
+ if (i === 0) {
996
+ y = this.getYCoord(0) - h;
997
+ } else {
998
+ y = this.getYCoord(runningTotal) - h;
999
+ }
1000
+ y = Math.round(y);
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+ var w = ((this.canvas.width - this.marginLeft - this.marginRight) / (this.data.length + (properties.total ? 1 : 0 )) ) - (2 * properties.marginInner);
1007
+ w = w * properties.multiplierW;
1008
+
1009
+
1010
+ // Adjust the coords for negative values
1011
+ if (this.data[i] < 0) {
1012
+ y += h;
1013
+ }
1014
+
1015
+
1016
+ // Allow for sequential colors
1017
+ if (properties.colorsSequential) {
1018
+ this.context.fillStyle = properties.colors[seq];
1019
+ } else {
1020
+ // Color
1021
+ this.context.fillStyle = this.data[i] >= 0 ? properties.colors[0] : properties.colors[1];
1022
+ }
1023
+
1024
+
1025
+ if (properties.shadow) {
1026
+ RGraph.setShadow({
1027
+ object: this,
1028
+ prefix: 'shadow'
1029
+ });
1030
+ } else {
1031
+ RGraph.noShadow(this);
1032
+ }
1033
+
1034
+
1035
+
1036
+ //
1037
+ // Draw the bar, first accounting for negative heights
1038
+ //
1039
+ if (h < 0) {
1040
+ h = Math.abs(h);
1041
+ y = y - h;
1042
+ }
1043
+
1044
+ this.context.rect(
1045
+ x + properties.barOffsetx,
1046
+ Math.floor(y) + properties.barOffsety,
1047
+ w,
1048
+ Math.floor(h)
1049
+ );
1050
+
1051
+ this.coords.push([x, y, w, h]);
1052
+
1053
+
1054
+
1055
+ // The "runnningTotal" is also calculated by the
1056
+ // this.runningTotal() function
1057
+ runningTotal += this.data[i];
1058
+
1059
+ this.context.stroke();
1060
+ this.context.fill();
1061
+ }
1062
+
1063
+ // Store the total
1064
+ this.total = runningTotal;
1065
+
1066
+ if (properties.total) {
1067
+
1068
+ // This is the height of the final bar
1069
+ if (properties.xaxisPosition === 'top') {
1070
+ h = this.getYCoord(Math.abs(runningTotal)) - this.getYCoord(0);
1071
+ } else {
1072
+ h = this.getYCoord(0) - this.getYCoord(Math.abs(runningTotal));
1073
+ }
1074
+
1075
+ // Set the Y (ie the start point) value
1076
+ if (properties.xaxisPosition == 'center') {
1077
+ y = runningTotal > 0 ? this.getYCoord(0) - h : this.getYCoord(0);
1078
+
1079
+ } else if (properties.xaxisPosition == 'top') {
1080
+ y = this.getYCoord(0);
1081
+
1082
+ } else {
1083
+ if (runningTotal > 0) {
1084
+ y = this.getYCoord(0) - h;
1085
+ } else {
1086
+ y = this.getYCoord(0);
1087
+ }
1088
+ }
1089
+
1090
+ // This is the X position of the final bar
1091
+ x = x + (properties.marginInner * 2) + w;
1092
+
1093
+
1094
+ // Allow for sequential colors
1095
+ if (properties.colorsSequential) {
1096
+ this.context.fillStyle = properties.colors[seq]
1097
+ } else {
1098
+ // Final color
1099
+ this.context.fillStyle = properties.colors[2];
1100
+ }
1101
+
1102
+ this.path(
1103
+ 'b r % % % % s % f %',
1104
+ x + properties.barOffsetx, y + properties.barOffsety, w, h,
1105
+ this.context.strokeStyle,this.context.fillStyle
1106
+ );
1107
+
1108
+ // This is set so that the next iteration of the loop will be able to
1109
+ // access THIS iterations coordinates
1110
+ var previousCoords = [x, y, w, Math.abs(h)];
1111
+
1112
+ // Add the coordinates to the coords array (the previousCooords array, at
1113
+ // this point, is actually THIS iterations coords
1114
+ this.coords.push(previousCoords);
1115
+ }
1116
+
1117
+
1118
+
1119
+
1120
+
1121
+ // Turn off the shadow
1122
+ RGraph.noShadow(this);
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+ //
1130
+ // This draws the connecting lines
1131
+ //
1132
+ this.context.lineWidth = 1;
1133
+ this.context.strokeStyle = properties.colorsConnectors;
1134
+
1135
+ this.context.beginPath();
1136
+
1137
+ for (var i=1,len=this.coords.length; i<len; i+=1) {
1138
+
1139
+ var prev = this.coords[i - 1],
1140
+ curr = this.coords[i],
1141
+ prevData = this.data[i-1];
1142
+
1143
+ // CANNOT be a part of the var chain above
1144
+ if (properties.xaxisPosition === 'top') {
1145
+ var y = (prevData > 0 ? prev[1] + prev[3] : prev[1]);
1146
+ } else {
1147
+ var y = (prevData > 0 ? prev[1] : prev[1] + prev[3]);
1148
+ }
1149
+
1150
+
1151
+ this.context.moveTo(
1152
+ prev[0] + prev[2] + properties.barOffsetx,
1153
+ y + properties.barOffsety
1154
+ );
1155
+
1156
+ this.context.lineTo(
1157
+ curr[0] + properties.barOffsetx,
1158
+ y + properties.barOffsety
1159
+ );
1160
+
1161
+ }
1162
+
1163
+ this.context.stroke();
1164
+ };
1165
+
1166
+
1167
+
1168
+
1169
+
1170
+
1171
+
1172
+
1173
+ //
1174
+ // Not used by the class during creating the graph, but is used by event handlers
1175
+ // to get the coordinates (if any) of the selected bar
1176
+ //
1177
+ // @param object e The event object
1178
+ //
1179
+ this.getShape = function (e)
1180
+ {
1181
+ //
1182
+ // Loop through the bars determining if the mouse is over a bar
1183
+ //
1184
+ for (var i=0,len=this.coords.length; i<len; i++) {
1185
+
1186
+ if (RGraph.tooltipsHotspotIgnore(this, i)) {
1187
+ continue;
1188
+ }
1189
+
1190
+ var mouseXY = RGraph.getMouseXY(e),
1191
+ mouseX = mouseXY[0],
1192
+ mouseY = mouseXY[1];
1193
+
1194
+ var left = this.coords[i][0],
1195
+ top = this.coords[i][1],
1196
+ width = this.coords[i][2],
1197
+ height = this.coords[i][3];
1198
+
1199
+ if ( mouseX >= left
1200
+ && mouseX <= (left + width)
1201
+ && mouseY >= top
1202
+ && mouseY <= top + height) {
1203
+
1204
+ var tooltip = RGraph.parseTooltipText ? RGraph.parseTooltipText(properties.tooltips, i) : null;
1205
+
1206
+ return {
1207
+ object: this,
1208
+ x: left,
1209
+ y: top,
1210
+ width: width,
1211
+ height: height,
1212
+ index: 0,
1213
+ dataset: i,
1214
+ sequentialIndex: i,
1215
+ label: properties.xaxisLabels && typeof properties.xaxisLabels[i] === 'string' ? properties.xaxisLabels[i] : null,
1216
+ tooltip: typeof tooltip === 'string' ? tooltip : null
1217
+ };
1218
+ }
1219
+ }
1220
+
1221
+ return null;
1222
+ };
1223
+
1224
+
1225
+
1226
+
1227
+
1228
+
1229
+
1230
+
1231
+ //
1232
+ // The Waterfall is slightly different to Bar/Line charts so has this function to get the max value
1233
+ //
1234
+ this.getMax = function (data)
1235
+ {
1236
+ var runningTotal = 0, max = 0;
1237
+
1238
+ for (var i=0,len=data.length; i<len; i+=1) {
1239
+ runningTotal += data[i];
1240
+
1241
+ max = Math.max(Math.abs(runningTotal), max);
1242
+ }
1243
+
1244
+ return Math.abs(max);
1245
+ };
1246
+
1247
+
1248
+
1249
+
1250
+
1251
+
1252
+
1253
+
1254
+ //
1255
+ // This function facilitates the installation of tooltip event
1256
+ // listeners if tooltips are defined.
1257
+ //
1258
+ this.allowTooltips = function ()
1259
+ {
1260
+ // Preload any tooltip images that are used in the tooltips
1261
+ RGraph.preLoadTooltipImages(this);
1262
+
1263
+
1264
+ //
1265
+ // This installs the window mousedown event listener that lears any
1266
+ // highlight that may be visible.
1267
+ //
1268
+ RGraph.installWindowMousedownTooltipListener(this);
1269
+
1270
+
1271
+ //
1272
+ // This installs the canvas mousemove event listener. This function
1273
+ // controls the pointer shape.
1274
+ //
1275
+ RGraph.installCanvasMousemoveTooltipListener(this);
1276
+
1277
+
1278
+ //
1279
+ // This installs the canvas mouseup event listener. This is the
1280
+ // function that actually shows the appropriate tooltip (if any).
1281
+ //
1282
+ RGraph.installCanvasMouseupTooltipListener(this);
1283
+ };
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+
1292
+ //
1293
+ // Each object type has its own Highlight() function which highlights the appropriate shape
1294
+ //
1295
+ // @param object shape The shape to highlight
1296
+ //
1297
+ this.highlight = function (shape)
1298
+ {
1299
+ if (typeof properties.highlightStyle === 'function') {
1300
+ (properties.highlightStyle)(shape);
1301
+
1302
+ // Highlight all of the rects except this one - essentially an inverted highlight
1303
+ } else if (typeof properties.highlightStyle === 'string' && properties.highlightStyle === 'invert') {
1304
+ for (var i=0; i<this.coords.length; ++i) {
1305
+ if (i !== shape.sequentialIndex) {
1306
+ this.path(
1307
+ 'b r % % % % s % f %',
1308
+ this.coords[i][0] - 0.5, this.coords[i][1] - 0.5, this.coords[i][2] + 1, this.coords[i][3] + 1,
1309
+ properties.highlightStroke,
1310
+ properties.highlightFill
1311
+ );
1312
+ }
1313
+ }
1314
+ } else {
1315
+ RGraph.Highlight.rect(this, shape);
1316
+ }
1317
+ };
1318
+
1319
+
1320
+
1321
+
1322
+
1323
+
1324
+
1325
+
1326
+ //
1327
+ // The getObjectByXY() worker method. Don't call this call:
1328
+ //
1329
+ // RGraph.ObjectRegistry.getObjectByXY(e)
1330
+ //
1331
+ // @param object e The event object
1332
+ //
1333
+ this.getObjectByXY = function (e)
1334
+ {
1335
+ var mouseXY = RGraph.getMouseXY(e);
1336
+
1337
+ if (
1338
+ mouseXY[0] > this.marginLeft
1339
+ && mouseXY[0] < (this.canvas.width - this.marginRight)
1340
+ && mouseXY[1] > this.marginTop
1341
+ && mouseXY[1] < (this.canvas.height - this.marginBottom)
1342
+ ) {
1343
+
1344
+ return this;
1345
+ }
1346
+ };
1347
+
1348
+
1349
+
1350
+
1351
+
1352
+
1353
+
1354
+
1355
+ //
1356
+ // This method returns the appropriate Y coord for the given value
1357
+ //
1358
+ // @param number value The value
1359
+ //
1360
+ this.getYCoord = function (value)
1361
+ {
1362
+ // X axis position in the center
1363
+ if (properties.xaxisPosition == 'center') {
1364
+
1365
+ if (value < (-1 * this.max)) {
1366
+ return null;
1367
+ }
1368
+
1369
+ var coord = (value / this.max) * (this.grapharea / 2);
1370
+ return this.marginTop + (this.grapharea / 2) - coord;
1371
+
1372
+
1373
+
1374
+
1375
+ // X axis position at the top
1376
+ } else if (properties.xaxisPosition == 'top') {
1377
+
1378
+ if (value < 0) return null;
1379
+
1380
+ var coord = (value / this.max) * this.grapharea;
1381
+ return this.marginTop + coord;
1382
+
1383
+
1384
+
1385
+
1386
+
1387
+ } else {
1388
+
1389
+ var coord = ( (value - this.scale2.min) / (this.max - this.scale2.min) ) * this.grapharea;
1390
+ coord = coord + this.marginBottom;
1391
+
1392
+ return this.canvas.height - coord;
1393
+ }
1394
+ };
1395
+
1396
+
1397
+
1398
+
1399
+
1400
+
1401
+
1402
+
1403
+ //
1404
+ // This allows for easy specification of gradients
1405
+ //
1406
+ this.parseColors = function ()
1407
+ {
1408
+ // Save the original colors so that they can be restored when the canvas is reset
1409
+ if (this.original_colors.length === 0) {
1410
+ this.original_colors.colors = RGraph.arrayClone(properties.colors);
1411
+ this.original_colors.keyColors = RGraph.arrayClone(properties.keyColors);
1412
+ this.original_colors.crosshairsColor = RGraph.arrayClone(properties.crosshairsColor);
1413
+ this.original_colors.highlightStroke = RGraph.arrayClone(properties.highlightStroke);
1414
+ this.original_colors.highlightFill = RGraph.arrayClone(properties.highlightFill);
1415
+ this.original_colors.backgroundBarsColor1 = RGraph.arrayClone(properties.backgroundBarsColor1);
1416
+ this.original_colors.backgroundBarsColor2 = RGraph.arrayClone(properties.backgroundBarsColor2);
1417
+ this.original_colors.backgroundGridColor = RGraph.arrayClone(properties.backgroundGridColor);
1418
+ this.original_colors.colorsStroke = RGraph.arrayClone(properties.colorsStroke);
1419
+ this.original_colors.xaxisColor = RGraph.arrayClone(properties.xaxisColor);
1420
+ this.original_colors.yaxisColor = RGraph.arrayClone(properties.yaxisColor);
1421
+ }
1422
+
1423
+
1424
+ // Colors
1425
+ var colors = properties.colors;
1426
+
1427
+ if (colors) {
1428
+ for (var i=0,len=colors.length; i<len; ++i) {
1429
+ colors[i] = this.parseSingleColorForGradient(colors[i]);
1430
+ }
1431
+ }
1432
+
1433
+ // keyColors
1434
+ var colors = properties.keyColors;
1435
+
1436
+ if (colors) {
1437
+ for (var i=0,len=colors.length; i<len; ++i) {
1438
+ colors[i] = this.parseSingleColorForGradient(colors[i]);
1439
+ }
1440
+ }
1441
+
1442
+ properties.crosshairsColor = this.parseSingleColorForGradient(properties.crosshairsColor);
1443
+ properties.highlightStroke = this.parseSingleColorForGradient(properties.highlightStroke);
1444
+ properties.highlightFill = this.parseSingleColorForGradient(properties.highlightFill);
1445
+ properties.backgroundBarsColor1 = this.parseSingleColorForGradient(properties.backgroundBarsColor1);
1446
+ properties.backgroundBarsColor2 = this.parseSingleColorForGradient(properties.backgroundBarsColor2);
1447
+ properties.backgroundGridColor = this.parseSingleColorForGradient(properties.backgroundGridColor);
1448
+ properties.colorsStroke = this.parseSingleColorForGradient(properties.colorsStroke);
1449
+ properties.xaxisColor = this.parseSingleColorForGradient(properties.xaxisColor);
1450
+ properties.yaxisColor = this.parseSingleColorForGradient(properties.yaxisColor);
1451
+ };
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+ //
1461
+ // Use this function to reset the object to the post-constructor state. Eg reset colors if
1462
+ // need be etc
1463
+ //
1464
+ this.reset = function ()
1465
+ {
1466
+ };
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+
1473
+
1474
+
1475
+ //
1476
+ // This parses a single color value
1477
+ //
1478
+ // @param string color The color to parse for gradients
1479
+ //
1480
+ this.parseSingleColorForGradient = function (color)
1481
+ {
1482
+ if (!color || typeof color != 'string') {
1483
+ return color;
1484
+ }
1485
+
1486
+ if (typeof color === 'string' && color.match(/^gradient\((.*)\)$/i)) {
1487
+
1488
+ // Allow for JSON gradients
1489
+ if (color.match(/^gradient\(({.*})\)$/i)) {
1490
+ return RGraph.parseJSONGradient({object: this, def: RegExp.$1});
1491
+ }
1492
+
1493
+ var parts = RegExp.$1.split(':');
1494
+
1495
+ // Create the gradient
1496
+
1497
+ var grad = this.context.createLinearGradient(0,this.canvas.height - properties.marginBottom, 0, properties.marginTop);
1498
+
1499
+ var diff = 1 / (parts.length - 1);
1500
+
1501
+ grad.addColorStop(0, RGraph.trim(parts[0]));
1502
+
1503
+ for (var j=1,len=parts.length; j<len; ++j) {
1504
+ grad.addColorStop(j * diff, RGraph.trim(parts[j]));
1505
+ }
1506
+ }
1507
+
1508
+ return grad ? grad : color;
1509
+ };
1510
+
1511
+
1512
+
1513
+
1514
+
1515
+
1516
+
1517
+
1518
+ //
1519
+ // Using a function to add events makes it easier to facilitate method chaining
1520
+ //
1521
+ // @param string type The type of even to add
1522
+ // @param function func
1523
+ //
1524
+ this.on = function (type, func)
1525
+ {
1526
+ if (type.substr(0,2) !== 'on') {
1527
+ type = 'on' + type;
1528
+ }
1529
+
1530
+ if (typeof this[type] !== 'function') {
1531
+ this[type] = func;
1532
+ } else {
1533
+ RGraph.addCustomEventListener(this, type, func);
1534
+ }
1535
+
1536
+ return this;
1537
+ };
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+ //
1547
+ // Used in chaining. Runs a function there and then - not waiting for
1548
+ // the events to fire (eg the onbeforedraw event)
1549
+ //
1550
+ // @param function func The function to execute
1551
+ //
1552
+ this.exec = function (func)
1553
+ {
1554
+ func(this);
1555
+
1556
+ return this;
1557
+ };
1558
+
1559
+
1560
+
1561
+
1562
+
1563
+
1564
+
1565
+
1566
+ //
1567
+ // This function runs once only
1568
+ // (put at the end of the file (before any effects))
1569
+ //
1570
+ this.firstDrawFunc = function ()
1571
+ {
1572
+ };
1573
+
1574
+
1575
+
1576
+
1577
+
1578
+
1579
+
1580
+
1581
+ //
1582
+ // Waterfall Grow
1583
+ //
1584
+ // @param object Options. You can pass frames here - which should be a number
1585
+ // @param function An optional function which is called when the animation is finished
1586
+ //
1587
+ this.grow = function ()
1588
+ {
1589
+ // Cancel any stop request if one is pending
1590
+ this.cancelStopAnimation();
1591
+
1592
+ var opt = arguments[0] || {},
1593
+ callback = arguments[1] || function () {},
1594
+ frames = opt.frames || 30,
1595
+ numFrame = 0,
1596
+ obj = this,
1597
+ data = RGraph.arrayClone(this.original_data);
1598
+
1599
+ // Reset The data to zeros
1600
+ for (var i=0,len=this.data.length; i<len; ++i) {
1601
+ this.data[i] /= frames;
1602
+ }
1603
+
1604
+ //
1605
+ // Fix the scale
1606
+ //
1607
+ if (this.get('yaxisScaleMax') == null) {
1608
+ var max = this.getMax(data);
1609
+ var scale2 = RGraph.getScale({object: this, options: {'scale.max': max}});
1610
+ this.set('yaxisScaleMax', scale2.max);
1611
+ }
1612
+
1613
+ function iterator ()
1614
+ {
1615
+ if (obj.stopAnimationRequested) {
1616
+
1617
+ // Reset the flag
1618
+ obj.stopAnimationRequested = false;
1619
+
1620
+ return;
1621
+ }
1622
+
1623
+
1624
+
1625
+ for (var i=0; i<obj.data.length; ++i) {
1626
+
1627
+ // This produces a very slight easing effect
1628
+ obj.data[i] = data[i] * RGraph.Effects.getEasingMultiplier(frames, numFrame);
1629
+ }
1630
+
1631
+ RGraph.clear(obj.canvas);
1632
+ RGraph.redrawCanvas(obj.canvas);
1633
+
1634
+ if (++numFrame <= frames) {
1635
+ RGraph.Effects.updateCanvas(iterator);
1636
+ } else {
1637
+ callback(obj);
1638
+ }
1639
+ }
1640
+
1641
+ iterator();
1642
+
1643
+ return this;
1644
+ };
1645
+
1646
+
1647
+
1648
+
1649
+
1650
+
1651
+
1652
+
1653
+ //
1654
+ // Couple of functions that allow you to control the
1655
+ // animation effect
1656
+ //
1657
+ this.stopAnimation = function ()
1658
+ {
1659
+ this.stopAnimationRequested = true;
1660
+ };
1661
+
1662
+ this.cancelStopAnimation = function ()
1663
+ {
1664
+ this.stopAnimationRequested = false;
1665
+ };
1666
+
1667
+
1668
+
1669
+
1670
+
1671
+
1672
+
1673
+
1674
+ //
1675
+ // A worker function that handles Bar chart specific tooltip substitutions
1676
+ //
1677
+ this.tooltipSubstitutions = function (opt)
1678
+ {
1679
+ var value = this.data[opt.index];
1680
+
1681
+ if (opt.index === this.data.length && properties.total) {
1682
+ value = this.total;
1683
+ }
1684
+
1685
+
1686
+ return {
1687
+ index: opt.index,
1688
+ dataset: 0,
1689
+ sequentialIndex: opt.index,
1690
+ value: value,
1691
+ values: [value]
1692
+ };
1693
+ };
1694
+
1695
+
1696
+
1697
+
1698
+
1699
+
1700
+
1701
+
1702
+ //
1703
+ // A worker function that returns the correct color/label/value
1704
+ //
1705
+ // @param object specific The indexes that are applicable
1706
+ // @param number index The appropriate index
1707
+ //
1708
+ this.tooltipsFormattedCustom = function (specific, index)
1709
+ {
1710
+ // Determine the correct color array to use
1711
+ var colors = properties.colors;
1712
+
1713
+ if (properties.tooltipsFormattedKeyColors) {
1714
+ colors = properties.tooltipsFormattedKeyColors;
1715
+ }
1716
+
1717
+ var color = colors[0];
1718
+
1719
+ // Change the color for negative bars
1720
+ if (specific.value < 0) {
1721
+ color = colors[1];
1722
+ }
1723
+
1724
+ // Change the color for the last bar
1725
+ if (specific.index == this.data.length) {
1726
+ color = colors[2];
1727
+ }
1728
+
1729
+ // Figure out the correct label
1730
+ if (typeof properties.tooltipsFormattedKeyLabels === 'object' && typeof properties.tooltipsFormattedKeyLabels[specific.index] === 'string') {
1731
+ var label = properties.tooltipsFormattedKeyLabels[specific.index];
1732
+ } else if (properties.xaxisLabels && typeof properties.xaxisLabels === 'object' && typeof properties.xaxisLabels[specific.index] === 'string') {
1733
+ var label = properties.xaxisLabels[specific.index];
1734
+ }
1735
+
1736
+ return {
1737
+ label: label,
1738
+ color: color
1739
+ };
1740
+ };
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+ //
1750
+ // This allows for static tooltip positioning
1751
+ //
1752
+ this.positionTooltipStatic = function (args)
1753
+ {
1754
+ var obj = args.object,
1755
+ e = args.event,
1756
+ tooltip = args.tooltip,
1757
+ index = args.index,
1758
+ canvasXY = RGraph.getCanvasXY(obj.canvas)
1759
+ coords = this.coords[args.index];
1760
+
1761
+ // Position the tooltip in the X direction
1762
+ args.tooltip.style.left = (
1763
+ canvasXY[0] // The X coordinate of the canvas
1764
+ + coords[0] // The X coordinate of the point on the chart
1765
+ + (coords[2] / 2) // Add half of the width of the bar
1766
+ - (tooltip.offsetWidth / 2) // Subtract half of the tooltip width
1767
+ + obj.properties.tooltipsOffsetx // Add any user defined offset
1768
+ ) + 'px';
1769
+
1770
+ args.tooltip.style.top = (
1771
+ canvasXY[1] // The Y coordinate of the canvas
1772
+ + coords[1] // The Y coordinate of the bar on the chart
1773
+ - tooltip.offsetHeight // The height of the tooltip
1774
+ - 10 // An arbitrary amount
1775
+ + obj.properties.tooltipsOffsety // Add any user defined offset
1776
+ ) + 'px';
1777
+
1778
+ // If the top of the tooltip is off the top of the page
1779
+ // then move the tooltip down
1780
+ if(parseFloat(args.tooltip.style.top) < 0) {
1781
+ args.tooltip.style.top = parseFloat(args.tooltip.style.top) + (coords[3] / 2) + 5 + 'px';
1782
+ }
1783
+ };
1784
+
1785
+
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+ //
1793
+ // This returns the relevant value for the formatted key
1794
+ // macro %{value}. THIS VALUE SHOULD NOT BE FORMATTED.
1795
+ //
1796
+ // @param number index The index in the dataset to get
1797
+ // the value for
1798
+ //
1799
+ this.getKeyValue = function (index)
1800
+ {
1801
+ if ( RGraph.isArray(this.properties.keyFormattedValueSpecific)
1802
+ && RGraph.isNumber(this.properties.keyFormattedValueSpecific[index])) {
1803
+
1804
+ return this.properties.keyFormattedValueSpecific[index];
1805
+
1806
+
1807
+
1808
+
1809
+ } else {
1810
+ // Loop thru the data and sum the up and
1811
+ // down values.
1812
+ for (var i=0,pos=0,neg=0,tot=0; i<this.data.length; ++i) {
1813
+ if (this.data[i] >= 0) {
1814
+ pos += this.data[i];
1815
+ } else {
1816
+ neg -= this.data[i];
1817
+ }
1818
+
1819
+ tot += this.data[i]
1820
+ }
1821
+
1822
+ if (index === 0) {
1823
+ return pos;
1824
+ } else if (index === 1) {
1825
+ return neg;
1826
+ } else {
1827
+ return tot;
1828
+ }
1829
+ }
1830
+ };
1831
+
1832
+
1833
+
1834
+
1835
+
1836
+
1837
+
1838
+
1839
+ //
1840
+ // Returns how many data-points there should be when a string
1841
+ // based key property has been specified. For example, this:
1842
+ //
1843
+ // key: '%{property:_labels[%{index}]} %{value_formatted}'
1844
+ //
1845
+ // ...depending on how many bits of data ther is might get
1846
+ // turned into this:
1847
+ //
1848
+ // key: [
1849
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1850
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1851
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1852
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1853
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1854
+ // ]
1855
+ //
1856
+ // ... ie in that case there would be 4 data-points so the
1857
+ // template is repeated 4 times.
1858
+ //
1859
+ this.getKeyNumDatapoints = function ()
1860
+ {
1861
+ return this.properties.total ? 3 : 2;
1862
+ };
1863
+
1864
+
1865
+
1866
+
1867
+
1868
+
1869
+
1870
+
1871
+ //
1872
+ // Now, because canvases can support multiple charts, canvases must always be registered
1873
+ //
1874
+ RGraph.register(this);
1875
+
1876
+
1877
+
1878
+
1879
+
1880
+
1881
+
1882
+
1883
+ //
1884
+ // This is the 'end' of the constructor so if the first argument
1885
+ // contains configuration data - handle that.
1886
+ //
1887
+ RGraph.parseObjectStyleConfig(this,conf.options);
1888
+
1889
+
1890
+
1891
+
1892
+
1893
+
1894
+
1895
+
1896
+ return this;
1897
+ };