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,57 +1,1278 @@
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.Funnel=function(conf)
3
- {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var id=conf.id
4
- var canvas=document.getElementById(id);var data=conf.data;var parseConfObjectForOptions=true;}else{var id=conf;var canvas=document.getElementById(id);var data=arguments[1];}
5
- this.id=id;this.canvas=canvas;this.context=this.canvas.getContext?this.canvas.getContext("2d",{alpha:(typeof id==='object'&&id.alpha===false)?false:true}):null;this.canvas.__object__=this;this.type='funnel';this.coords=[];this.isRGraph=true;this.uid=RGraph.CreateUID();this.canvas.uid=this.canvas.uid?this.canvas.uid:RGraph.CreateUID();this.coordsText=[];this.original_colors=[];this.firstDraw=true;this.propertyNameAliases={};if(!this.canvas){alert('[FUNNEL] No canvas support');return;}
6
- this.properties={'chart.colors.stroke':'rgba(0,0,0,0)','chart.colors':['Gradient(white:red)','Gradient(white:green)','Gradient(white:gray)','Gradient(white:blue)','Gradient(white:black)','Gradient(white:gray)','Gradient(white:pink)','Gradient(white:blue)','Gradient(white:yellow)','Gradient(white:green)','Gradient(white:red)'],'chart.margin.left':25,'chart.margin.right':25,'chart.margin.top':25,'chart.margin.bottom':25,'chart.labels':null,'chart.labels.font':null,'chart.labels.size':null,'chart.labels.color':null,'chart.labels.bold':null,'chart.labels.italic':null,'chart.labels.sticks':false,'chart.labels.x':null,'chart.title':'','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.italic':null,'chart.title.bold':null,'chart.title.font':null,'chart.title.size':null,'chart.title.color':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.text.size':12,'chart.text.color':'black','chart.text.font':'Arial, Verdana, sans-serif','chart.text.bold':false,'chart.text.italic':false,'chart.text.halign':'left','chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':false,'chart.contextmenu':null,'chart.shadow':false,'chart.shadow.color':'#666','chart.shadow.blur':3,'chart.shadow.offsetx':3,'chart.shadow.offsety':3,'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.margin.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':'black','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.font':null,'chart.key.labels.size':null,'chart.key.labels.color':null,'chart.key.labels.bold':null,'chart.key.labels.italic':null,'chart.key.labels.offsetx':0,'chart.key.labels.offsety':0,'chart.tooltips.highlight':true,'chart.tooltips':null,'chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.event':'onclick','chart.highlight.stroke':'rgba(0,0,0,0)','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.annotatable':false,'chart.annotatable.color':'black','chart.resizable':false,'chart.resizable.handle.background':null,'chart.events.click':null,'chart.events.mousemove':null,'chart.clearto':'rgba(0,0,0,0)'}
7
- for(var i=0;i<data.length;++i){data[i]=parseFloat(data[i]);}
8
- this.data=data;for(var i=0;i<data.length;++i){this['$'+i]={};}
9
- if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
10
- var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
11
- if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
12
- this.set=this.Set=function(name)
13
- {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
14
- if(name.substr(0,6)!='chart.'){name='chart.'+name;}
15
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
16
- prop[name]=value;return this;};this.get=this.Get=function(name)
17
- {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
18
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
19
- return prop[name.toLowerCase()];};this.draw=this.Draw=function()
20
- {RG.fireCustomEvent(this,'onbeforedraw');if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
21
- 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=[];RG.drawTitle(this,prop['chart.title'],this.marginTop,null,typeof prop['chart.title.size']==='number'?prop['chart.title.size']:prop['chart.text.size']);this.drawFunnel();if(prop['chart.contextmenu']){RG.showContext(this);}
22
- this.drawLabels();if(prop['chart.resizable']){RG.allowResizing(this);}
23
- RG.InstallEventListeners(this);if(this.firstDraw){this.firstDraw=false;RG.fireCustomEvent(this,'onfirstdraw');this.firstDrawFunc();}
24
- RG.FireCustomEvent(this,'ondraw');return this;};this.exec=function(func)
25
- {func(this);return this;};this.drawFunnel=this.DrawFunnel=function()
26
- {var width=ca.width-this.marginLeft-this.marginRight;var height=ca.height-this.marginTop-this.marginBottom;var max=RG.arrayMax(this.data);var accheight=this.marginTop;if(prop['chart.shadow']){co.shadowColor=prop['chart.shadow.color'];co.shadowBlur=prop['chart.shadow.blur'];co.shadowOffsetX=prop['chart.shadow.offsetx'];co.shadowOffsetY=prop['chart.shadow.offsety'];}
27
- for(i=0,len=this.data.length;i<len;++i){var firstvalue=this.data[0];var firstwidth=(firstvalue/max)*width;var curvalue=this.data[i];var curwidth=(curvalue/max)*width;var curheight=height/(this.data.length-1);var halfCurWidth=(curwidth/2);var nextvalue=this.data[i+1];var nextwidth=this.data[i+1]?(nextvalue/max)*width:null;var halfNextWidth=(nextwidth/2);var center=this.marginLeft+(firstwidth/2);var x1=center-halfCurWidth;var y1=accheight;var x2=center+halfCurWidth;var y2=accheight;var x3=center+halfNextWidth;var y3=accheight+curheight;var x4=center-halfNextWidth;var y4=accheight+curheight;if(nextwidth&&i<this.data.length-1){co.beginPath();co.strokeStyle=prop['chart.colors.stroke'];co.fillStyle=prop['chart.colors'][i];co.moveTo(x1,y1);co.lineTo(x2,y2);co.lineTo(x3,y3);co.lineTo(x4,y4);co.closePath();this.coords.push([x1,y1,x2,y2,x3,y3,x4,y4]);}
28
- if(!prop['chart.shadow']){co.stroke();}
29
- co.fill();accheight+=curheight;}
30
- if(prop['chart.shadow']){RG.noShadow(this);for(i=0;i<this.coords.length;++i){co.strokeStyle=prop['chart.colors.stroke'];co.fillStyle=prop['chart.colors'][i];co.beginPath();co.moveTo(this.coords[i][0],this.coords[i][1]);co.lineTo(this.coords[i][2],this.coords[i][3]);co.lineTo(this.coords[i][4],this.coords[i][5]);co.lineTo(this.coords[i][6],this.coords[i][7]);co.closePath();co.stroke();co.fill();}}
31
- if(prop['chart.key']&&prop['chart.key'].length){RG.drawKey(this,prop['chart.key'],prop['chart.colors']);}};this.drawLabels=this.DrawLabels=function()
32
- {if(prop['chart.labels']&&prop['chart.labels'].length>0){var font=prop['chart.text.font'];var size=prop['chart.text.size'];var color=prop['chart.text.color'];var labels=prop['chart.labels'];var halign=prop['chart.text.halign']=='left'?'left':'center';var textConf=RG.getTextConf({object:this,prefix:'chart.labels'});if(typeof prop['chart.labels.x']=='number'){var x=prop['chart.labels.x'];}else{var x=halign=='left'?(this.marginLeft-15):((ca.width-this.marginLeft-this.marginRight)/2)+this.marginLeft;}
33
- for(var j=0;j<this.coords.length;++j){co.beginPath();co.strokeStyle='black';co.fillStyle=color;RG.noShadow(this);var label=labels[j]||'';RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:x,y:this.coords[j][1],text:label,valign:'center',halign:halign,bounding:true,boundingFill:'rgba(255,255,255,0.7)',boundingStroke:'rgba(0,0,0,0)',tag:'labels'});if(prop['chart.labels.sticks']&&labels[j]){co.font=size+'pt '+font;var labelWidth=co.measureText(label).width;co.beginPath();co.strokeStyle='gray';co.moveTo(x+labelWidth+10,ma.round(this.coords[j][1]));co.lineTo(this.coords[j][0]-10,ma.round(this.coords[j][1]));co.stroke();}}
34
- var lastLabel=labels[j];if(lastLabel){RG.text2(this,{font:textConf.font,size:textConf.size,color:textConf.color,bold:textConf.bold,italic:textConf.italic,x:x,y:this.coords[j-1][5],text:lastLabel,valign:'center',halign:halign,bounding:true,boundingFill:'rgba(255,255,255,0.7)',boundingStroke:'rgba(0,0,0,0)',tag:'labels'});if(prop['chart.labels.sticks']){co.font=size+'pt '+font;var labelWidth=co.measureText(lastLabel).width;co.beginPath();co.strokeStyle='gray';co.moveTo(x+labelWidth+10,Math.round(this.coords[j-1][7]));co.lineTo(this.coords[j-1][6]-10,Math.round(this.coords[j-1][7]));co.stroke();}}}};this.getShape=this.getSegment=function(e)
35
- {var coords=this.coords;var mouseCoords=RG.getMouseXY(e);var x=mouseCoords[0];var y=mouseCoords[1];for(i=0,len=coords.length;i<len;++i){var segment=coords[i]
36
- co.beginPath();co.moveTo(segment[0],segment[1]);co.lineTo(segment[2],segment[3]);co.lineTo(segment[4],segment[5]);co.lineTo(segment[6],segment[7]);co.lineTo(segment[8],segment[9]);if(co.isPointInPath(x,y)){var tooltip=RGraph.parseTooltipText(prop['chart.tooltips'],i);return{0:this,1:coords,2:i,'object':this,'coords':segment,'index':i,'tooltip':tooltip};}}
37
- return null;};this.highlight=this.Highlight=function(shape)
38
- {if(prop['chart.tooltips.highlight']){if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);return;}
39
- var coords=shape['coords'];pa2(co,'b m % % l % % l % % l % % c s % f %',coords[0],coords[1],coords[2],coords[3],coords[4],coords[5],coords[6],coords[7],prop['chart.highlight.stroke'],prop['chart.highlight.fill']);}};this.getObjectByXY=function(e)
40
- {var mouseXY=RGraph.getMouseXY(e);if(mouseXY[0]>prop['chart.margin.left']&&mouseXY[0]<(ca.width-prop['chart.margin.right'])&&mouseXY[1]>prop['chart.margin.top']&&mouseXY[1]<(ca.height-prop['chart.margin.bottom'])){return this;}};this.parseColors=function()
41
- {if(this.original_colors.length===0){this.original_colors['chart.colors']=RG.array_clone(prop['chart.colors']);this.original_colors['chart.key.colors']=RG.array_clone(prop['chart.key.colors']);this.original_colors['chart.highlight.fill']=RG.array_clone(prop['chart.highlight.fill']);this.original_colors['chart.highlight.stroke']=RG.array_clone(prop['chart.highlight.stroke']);this.original_colors['chart.colors.stroke']=RG.array_clone(prop['chart.colors.stroke']);}
42
- var colors=prop['chart.colors'];for(var i=0;i<colors.length;++i){colors[i]=this.parseSingleColorForHorizontalGradient(colors[i]);}
43
- var keyColors=prop['chart.key.colors'];if(keyColors){for(var i=0;i<keyColors.length;++i){keyColors[i]=this.parseSingleColorForHorizontalGradient(keyColors[i]);}}
44
- prop['chart.colors.stroke']=this.parseSingleColorForVerticalGradient(prop['chart.colors.stroke']);prop['chart.highlight.stroke']=this.parseSingleColorForHorizontalGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForHorizontalGradient(prop['chart.highlight.fill']);};this.reset=function()
45
- {};this.parseSingleColorForHorizontalGradient=function(color)
46
- {if(!color||typeof(color)!='string'){return color;}
47
- if(color.match(/^gradient\((.*)\)$/i)){if(color.match(/^gradient\(({.*})\)$/i)){return RGraph.parseJSONGradient({object:this,def:RegExp.$1});}
48
- var parts=RegExp.$1.split(':');var grad=co.createLinearGradient(prop['chart.margin.left'],0,ca.width-prop['chart.margin.right'],0);var diff=1/(parts.length-1);grad.addColorStop(0,RGraph.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
49
- return grad?grad:color;};this.parseSingleColorForVerticalGradient=function(color)
50
- {if(!color||typeof(color)!='string'){return color;}
51
- if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');var grad=co.createLinearGradient(0,prop['chart.margin.top'],0,ca.height-prop['chart.margin.bottom']);var diff=1/(parts.length-1);grad.addColorStop(0,RGraph.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
52
- return grad?grad:color;};this.interactiveKeyHighlight=function(index)
53
- {var coords=this.coords[index];if(coords&&coords.length==8){var pre_linewidth=co.lineWidth;co.lineWidth=2;co.strokeStyle=prop['chart.key.interactive.highlight.chart.stroke'];co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.beginPath();co.moveTo(coords[0],coords[1]);co.lineTo(coords[2],coords[3]);co.lineTo(coords[4],coords[5]);co.lineTo(coords[6],coords[7]);co.closePath();co.fill();co.stroke();co.lineWidth=pre_linewidth;}};this.on=function(type,func)
54
- {if(type.substr(0,2)!=='on'){type='on'+type;}
55
- if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
56
- return this;};this.firstDrawFunc=function()
57
- {};RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};
12
+ RGraph = window.RGraph || {isrgraph:true,isRGraph:true,rgraph:true};
13
+
14
+ //
15
+ // The bar chart constructor
16
+ //
17
+ RGraph.Funnel = function (conf)
18
+ {
19
+ var id = conf.id;
20
+ var canvas = document.getElementById(id);
21
+ var data = conf.data;
22
+
23
+ this.id = id;
24
+ this.canvas = canvas;
25
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
26
+ this.canvas.__object__ = this;
27
+ this.type = 'funnel';
28
+ this.coords = [];
29
+ this.isRGraph = true;
30
+ this.isrgraph = true;
31
+ this.rgraph = true;
32
+ this.uid = RGraph.createUID();
33
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.createUID();
34
+ this.coordsText = [];
35
+ this.original_colors = [];
36
+ this.firstDraw = true; // After the first draw this will be false
37
+
38
+ // Check for support
39
+ if (!this.canvas) {
40
+ alert('[FUNNEL] No canvas support');
41
+ return;
42
+ }
43
+
44
+ //
45
+ // The funnel charts properties
46
+ //
47
+ this.properties =
48
+ {
49
+ colorsStroke: 'rgba(0,0,0,0)',
50
+ colors: ['red','green','gray','black','pink','orange','blue','yellow','green','red'],
51
+
52
+ marginLeft: 35,
53
+ marginRight: 35,
54
+ marginTop: 35,
55
+ marginBottom: 35,
56
+
57
+ labels: null,
58
+ labelsFont: null,
59
+ labelsSize: null,
60
+ labelsColor: null,
61
+ labelsBold: null,
62
+ labelsItalic: null,
63
+ labelsSticks: false,
64
+ labelsX: null,
65
+ labelsPosition: 'edge',
66
+ labelsOffsetx: 0,
67
+ labelsOffsety: 0,
68
+ labelsBackground: 'rgba(255,255,255,0.7)',
69
+ labelsFormattedDecimals: 0,
70
+ labelsFormattedPoint: '.',
71
+ labelsFormattedThousand: ',',
72
+ labelsFormattedUnitsPre: '',
73
+ labelsFormattedUnitsPost: '',
74
+
75
+ title: '',
76
+ titleItalic: null,
77
+ titleBold: null,
78
+ titleFont: null,
79
+ titleSize: null,
80
+ titleColor: null,
81
+ titleX: null,
82
+ titleY: null,
83
+ titleHalign: null,
84
+ titleValign: null,
85
+ titleOffsetx: 0,
86
+ titleOffsety: 0,
87
+ titleSubtitle: '',
88
+ titleSubtitleSize: null,
89
+ titleSubtitleColor: '#aaa',
90
+ titleSubtitleFont: null,
91
+ titleSubtitleBold: null,
92
+ titleSubtitleItalic: null,
93
+ titleSubtitleOffsetx: 0,
94
+ titleSubtitleOffsety: 0,
95
+
96
+ textSize: 12,
97
+ textColor: 'black',
98
+ textFont: 'Arial, Verdana, sans-serif',
99
+ textBold: false,
100
+ textItalic: false,
101
+ textHalign: 'left',
102
+ textAccessible: false,
103
+ textAccessibleOverflow: 'visible',
104
+ textAccessiblePointerevents: false,
105
+ text: null,
106
+
107
+ contextmenu: null,
108
+
109
+ shadow: false,
110
+ shadowColor: '#666',
111
+ shadowBlur: 3,
112
+ shadowOffsetx: 3,
113
+ shadowOffsety: 3,
114
+
115
+ key: null,
116
+ keyBackground: 'white',
117
+ keyPosition: 'graph',
118
+ keyHalign: 'right',
119
+ keyShadow: false,
120
+ keyShadowColor: '#666',
121
+ keyShadowBlur: 3,
122
+ keyShadowOffsetx: 2,
123
+ keyShadowOffsety: 2,
124
+ keyPositionMarginBoxed: false,
125
+ keyPositionMarginHSpace: 0,
126
+ keyPositionX: null,
127
+ keyPositionY: null,
128
+ keyColorShape: 'square',
129
+ keyRounded: true,
130
+ keyLinewidth: 1,
131
+ keyColors: null,
132
+ keyInteractive: false,
133
+ keyInteractiveHighlightChartStroke: 'black',
134
+ keyInteractiveHighlightChartFill: 'rgba(255,255,255,0.7)',
135
+ keyInteractiveHighlightLabel: 'rgba(255,0,0,0.2)',
136
+ keyLabelsFont: null,
137
+ keyLabelsSize: null,
138
+ keyLabelsColor: null,
139
+ keyLabelsBold: null,
140
+ keyLabelsItalic: null,
141
+ keyLabelsOffsetx: 0,
142
+ keyLabelsOffsety: 0,
143
+ keyFormattedDecimals: 0,
144
+ keyFormattedPoint: '.',
145
+ keyFormattedThousand: ',',
146
+ keyFormattedUnitsPre: '',
147
+ keyFormattedUnitsPost: '',
148
+ keyFormattedValueSpecific: null,
149
+ keyFormattedItemsCount: null,
150
+
151
+ tooltipsHighlight: true,
152
+ tooltips: null,
153
+ tooltipsEffect: 'slide',
154
+ tooltipsCssClass: 'RGraph_tooltip',
155
+ tooltipsCss: null,
156
+ tooltipsEvent: 'onclick',
157
+ tooltipsFormattedThousand: ',',
158
+ tooltipsFormattedPoint: '.',
159
+ tooltipsFormattedDecimals: 0,
160
+ tooltipsFormattedUnitsPre: '',
161
+ tooltipsFormattedUnitsPost: '',
162
+ tooltipsFormattedKeyColors: null,
163
+ tooltipsFormattedKeyColorsShape: 'square',
164
+ tooltipsFormattedKeyLabels: [],
165
+ tooltipsFormattedListType: 'ul',
166
+ tooltipsFormattedListItems: null,
167
+ tooltipsFormattedTableHeaders: null,
168
+ tooltipsFormattedTableData: null,
169
+ tooltipsPointer: true,
170
+ tooltipsPointerOffsetx: 0,
171
+ tooltipsPointerOffsety: 0,
172
+ tooltipsPositionStatic: true,
173
+ tooltipsHotspotIgnore: null,
174
+
175
+ highlightStroke: 'rgba(0,0,0,0)',
176
+ highlightFill: 'rgba(255,255,255,0.7)',
177
+
178
+ annotatable: false,
179
+ annotatableColor: 'black',
180
+
181
+ resizable: false,
182
+ resizableHandleBackground: null,
183
+
184
+ clearto: 'rgba(0,0,0,0)'
185
+ }
186
+
187
+
188
+ // If the data is a string split it up
189
+ data = RGraph.stringsToNumbers(data);
190
+ this.data = data;
191
+
192
+
193
+ //
194
+ // Create the dollar objects so that functions can be added to them
195
+ //
196
+ for (var i=0; i<data.length; ++i) {
197
+ this['$' + i] = {};
198
+ }
199
+
200
+
201
+
202
+
203
+ // Easy access to properties and the path function
204
+ var properties = this.properties;
205
+ this.path = RGraph.pathObjectFunction;
206
+
207
+
208
+
209
+ //
210
+ // "Decorate" the object with the generic effects if the effects library has been included
211
+ //
212
+ if (RGraph.Effects && typeof RGraph.Effects.decorate === 'function') {
213
+ RGraph.Effects.decorate(this);
214
+ }
215
+
216
+
217
+
218
+ // Add the responsive method. This method resides in the common file.
219
+ this.responsive = RGraph.responsive;
220
+
221
+
222
+
223
+
224
+ //
225
+ // A setter
226
+ //
227
+ // @param name string The name of the property to set
228
+ // @param value mixed The value of the property
229
+ //
230
+ this.set = function (name)
231
+ {
232
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
233
+
234
+ // the number of arguments is only one and it's an
235
+ // object - parse it for configuration data and return.
236
+ if (arguments.length === 1 && typeof arguments[0] === 'object') {
237
+ for (i in arguments[0]) {
238
+ if (typeof i === 'string') {
239
+ this.set(i, arguments[0][i]);
240
+ }
241
+ }
242
+
243
+ return this;
244
+ }
245
+
246
+ properties[name] = value;
247
+
248
+ return this;
249
+ };
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+ //
259
+ // A getter
260
+ //
261
+ // @param name string The name of the property to get
262
+ //
263
+ this.get = function (name)
264
+ {
265
+ return properties[name];
266
+ };
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275
+ //
276
+ // The function you call to draw the bar chart
277
+ //
278
+ this.draw = function ()
279
+ {
280
+ // Fire the onbeforedraw event
281
+ RGraph.fireCustomEvent(this, 'onbeforedraw');
282
+
283
+
284
+
285
+
286
+ // Translate half a pixel for antialiasing purposes - but only if it hasn't been
287
+ // done already
288
+ //
289
+ // MUST be the first thing done!
290
+ //
291
+ if (!this.canvas.__rgraph_aa_translated__) {
292
+ this.context.translate(0.5,0.5);
293
+
294
+ this.canvas.__rgraph_aa_translated__ = true;
295
+ }
296
+
297
+
298
+ //
299
+ // Parse the colors. This allows for simple gradient syntax
300
+ //
301
+ if (!this.colorsParsed) {
302
+ this.parseColors();
303
+
304
+ // Don't want to do this again
305
+ this.colorsParsed = true;
306
+ }
307
+
308
+
309
+
310
+ //
311
+ // Make the margins easy ro access
312
+ //
313
+ this.marginLeft = properties.marginLeft;
314
+ this.marginRight = properties.marginRight;
315
+ this.marginTop = properties.marginTop;
316
+ this.marginBottom = properties.marginBottom;
317
+
318
+ // This stops the coords array from growing
319
+ this.coords = [];
320
+
321
+ //
322
+ // Stop this growing uncntrollably
323
+ //
324
+ this.coordsText = [];
325
+
326
+ // Draw the title using the new drawTitle() function
327
+ RGraph.drawTitle(this);
328
+
329
+ this.drawFunnel();
330
+
331
+
332
+ //
333
+ // Setup the context menu if required
334
+ //
335
+ if (properties.contextmenu) {
336
+ RGraph.showContext(this);
337
+ }
338
+
339
+
340
+
341
+ //
342
+ // Draw the labels on the chart
343
+ //
344
+ this.drawLabels();
345
+
346
+
347
+
348
+
349
+ //
350
+ // Add custom text thats specified
351
+ //
352
+ RGraph.addCustomText(this);
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+ //
362
+ // This installs the event listeners
363
+ //
364
+ RGraph.installEventListeners(this);
365
+
366
+
367
+
368
+
369
+ //
370
+ // Fire the onfirstdraw event
371
+ //
372
+ if (this.firstDraw) {
373
+ this.firstDraw = false;
374
+ RGraph.fireCustomEvent(this, 'onfirstdraw');
375
+ this.firstDrawFunc();
376
+ }
377
+
378
+
379
+
380
+
381
+ //
382
+ // Fire the RGraph draw event
383
+ //
384
+ RGraph.fireCustomEvent(this, 'ondraw');
385
+
386
+
387
+
388
+
389
+
390
+
391
+
392
+
393
+
394
+ //
395
+ // Install any inline responsive configuration. This
396
+ // should be last in the draw function - even after
397
+ // the draw events.
398
+ //
399
+ RGraph.installInlineResponsive(this);
400
+
401
+
402
+
403
+
404
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+ return this;
413
+ };
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+ //
423
+ // Used in chaining. Runs a function there and then - not waiting for
424
+ // the events to fire (eg the onbeforedraw event)
425
+ //
426
+ // @param function func The function to execute
427
+ //
428
+ this.exec = function (func)
429
+ {
430
+ func(this);
431
+
432
+ return this;
433
+ };
434
+
435
+
436
+
437
+
438
+
439
+
440
+
441
+
442
+ //
443
+ // This function actually draws the chart
444
+ //
445
+ this.drawFunnel = function ()
446
+ {
447
+ var width = this.canvas.width - this.marginLeft - this.marginRight;
448
+ var height = this.canvas.height - this.marginTop - this.marginBottom;
449
+ var max = RGraph.arrayMax(this.data);
450
+ var accheight = this.marginTop;
451
+
452
+
453
+ //
454
+ // Loop through each segment to draw
455
+ //
456
+
457
+ // Set a shadow if it's been requested
458
+ if (properties.shadow) {
459
+ this.context.shadowColor = properties.shadowColor;
460
+ this.context.shadowBlur = properties.shadowBlur;
461
+ this.context.shadowOffsetX = properties.shadowOffsetx;
462
+ this.context.shadowOffsetY = properties.shadowOffsety;
463
+ }
464
+
465
+ this.context.strokeStyle = '#0000';
466
+
467
+ for (i=0,len=this.data.length; i<len; ++i) {
468
+
469
+ var firstvalue = this.data[0];
470
+ var firstwidth = (firstvalue / max) * width;
471
+ var curvalue = this.data[i];
472
+ var curwidth = (curvalue / max) * width;
473
+ var curheight = height / (this.data.length - 1);
474
+ var halfCurWidth = (curwidth / 2);
475
+ var nextvalue = this.data[i + 1];
476
+ var nextwidth = this.data[i + 1] ? (nextvalue / max) * width : null;
477
+ var halfNextWidth = (nextwidth / 2);
478
+ var center = this.marginLeft + (firstwidth / 2);
479
+
480
+ var x1 = center - halfCurWidth;
481
+ var y1 = accheight;
482
+ var x2 = center + halfCurWidth;
483
+ var y2 = accheight;
484
+ var x3 = center + halfNextWidth;
485
+ var y3 = accheight + curheight;
486
+ var x4 = center - halfNextWidth;
487
+ var y4 = accheight + curheight;
488
+
489
+ if (nextwidth && i < this.data.length - 1) {
490
+
491
+ this.context.beginPath();
492
+
493
+ this.context.fillStyle = properties.colors[i];
494
+ this.context.strokeStyle = '#0000';
495
+
496
+ this.context.moveTo(x1, y1);
497
+ this.context.lineTo(x2, y2);
498
+ this.context.lineTo(x3, y3);
499
+ this.context.lineTo(x4, y4);
500
+
501
+
502
+ //
503
+ // Store the coordinates
504
+ //
505
+ this.coords.push([x1, y1, x2, y2, x3, y3, x4, y4]);
506
+ }
507
+
508
+
509
+ // The redrawing if the shadow is on will do the stroke
510
+ if (!properties.shadow) {
511
+ this.context.stroke();
512
+ }
513
+
514
+ this.context.fill();
515
+
516
+ accheight += curheight;
517
+ }
518
+
519
+ //
520
+ // If the shadow is enabled, redraw every segment, in
521
+ // order to allow for shadows going upwards
522
+ //
523
+ if (properties.shadow) {
524
+
525
+ RGraph.noShadow(this);
526
+
527
+ for (i=0; i<this.coords.length; ++i) {
528
+
529
+ this.context.strokeStyle = properties.colors[i];
530
+ this.context.fillStyle = properties.colors[i];
531
+
532
+ this.context.beginPath();
533
+ this.context.moveTo(this.coords[i][0], this.coords[i][1]);
534
+ this.context.lineTo(this.coords[i][2], this.coords[i][3]);
535
+ this.context.lineTo(this.coords[i][4], this.coords[i][5]);
536
+ this.context.lineTo(this.coords[i][6], this.coords[i][7]);
537
+ this.context.closePath();
538
+
539
+ this.context.stroke();
540
+ this.context.fill();
541
+ }
542
+ }
543
+
544
+ //
545
+ // Lastly, draw the key if necessary
546
+ //
547
+ if (properties.key && properties.key.length) {
548
+ RGraph.drawKey(this, properties.key, properties.colors);
549
+ }
550
+ };
551
+
552
+
553
+
554
+
555
+
556
+
557
+
558
+
559
+ //
560
+ // Draws the labels
561
+ //
562
+ this.drawLabels = function ()
563
+ {
564
+ if (properties.labels && properties.labels.length) {
565
+ //
566
+ // If the xaxisLabels option is a string then turn it
567
+ // into an array.
568
+ //
569
+ if (typeof properties.labels === 'string') {
570
+ properties.labels = RGraph.arrayPad({
571
+ array: [],
572
+ length: this.coords.length + 1,
573
+ value: properties.labels
574
+ });
575
+ }
576
+
577
+ //
578
+ // Label substitution
579
+ //
580
+ for (var i=0; i<properties.labels.length; ++i) {
581
+ properties.labels[i] = RGraph.labelSubstitution({
582
+ object: this,
583
+ text: properties.labels[i],
584
+ index: i,
585
+ value: this.data[i],
586
+ decimals: properties.labelsFormattedDecimals || 0,
587
+ unitsPre: properties.labelsFormattedUnitsPre || '',
588
+ unitsPost: properties.labelsFormattedUnitsPost || '',
589
+ thousand: properties.labelsFormattedThousand || ',',
590
+ point: properties.labelsFormattedPoint || '.'
591
+ });
592
+ }
593
+ }
594
+
595
+
596
+
597
+
598
+
599
+
600
+ //
601
+ // Draws the labels
602
+ //
603
+ if (!RGraph.isNull(properties.labels) && typeof properties.labels === 'object' && properties.labels.length > 0) {
604
+
605
+ var font = properties.textFont,
606
+ size = properties.textSize,
607
+ color = properties.textColor,
608
+ labels = properties.labels,
609
+ halign = properties.textHalign === 'left' ? 'left' : 'center';
610
+
611
+ // Get the text configuration
612
+ var textConf = RGraph.getTextConf({
613
+ object: this,
614
+ prefix: 'labels'
615
+ });
616
+
617
+ // Determine the X coordinate
618
+ if (typeof properties.labelsX == 'number') {
619
+ var x = properties.labelsX;
620
+ } else {
621
+ var x = halign == 'left' ? (this.marginLeft - 15) : ((this.canvas.width - this.marginLeft - this.marginRight) / 2) + this.marginLeft;
622
+ }
623
+
624
+ // Loop through the labels drawing them on the canvas.
625
+ // All but the last label
626
+ for (var j=0; j<this.coords.length; ++j) { // MUST be "j"
627
+
628
+ this.context.beginPath();
629
+
630
+ // Set the color back to black
631
+ this.path('ss black fs %', color);
632
+
633
+ // Turn off any shadow
634
+ RGraph.noShadow(this);
635
+
636
+ // Calculate the Y coordinate
637
+ if (properties.labelsPosition === 'section') {
638
+ var y = this.coords[j][1] + ((this.coords[j][5] - this.coords[j][3]) / 2);
639
+ } else {
640
+ var y = this.coords[j][1];
641
+ }
642
+
643
+ var ret = RGraph.text({
644
+
645
+ object: this,
646
+
647
+ font: textConf.font,
648
+ size: textConf.size,
649
+ color: textConf.color,
650
+ bold: textConf.bold,
651
+ italic: textConf.italic,
652
+
653
+ x: x + properties.labelsOffsetx,
654
+ y: y + properties.labelsOffsety,
655
+
656
+ text: labels[j] || '',
657
+ valign: 'center',
658
+ halign: halign,
659
+ bounding: true,
660
+ boundingFill: properties.labelsBackground,
661
+ boundingStroke: 'rgba(0,0,0,0)',
662
+ tag: 'labels',
663
+ cssClass: RGraph.getLabelsCSSClassName({
664
+ object: this,
665
+ name: 'labelsClass',
666
+ index: j
667
+ })
668
+ });
669
+
670
+
671
+
672
+
673
+
674
+
675
+
676
+ if (properties.labelsSticks && labels[j]) {
677
+ //
678
+ // Measure the text
679
+ //
680
+ this.context.font = textConf.size + 'pt ' + font;
681
+ var labelWidth = this.context.measureText(labels[j]).width;
682
+
683
+
684
+ //
685
+ // Draw the horizontal indicator line
686
+ //
687
+ this.path(
688
+ 'b m % % l % % s gray',
689
+ x + labelWidth + 10,
690
+ y,
691
+ (properties.labelsPosition === 'section' ? this.coords[j][0] + ((this.coords[j][6] - this.coords[j][0]) / 2) : this.coords[j][0]) - 10,
692
+ y
693
+ );
694
+ }
695
+ }
696
+
697
+ // This draws the last label if defined
698
+ var lastLabel = labels[j];
699
+
700
+ if (lastLabel && properties.labelsPosition === 'edge') {
701
+
702
+ RGraph.text({
703
+
704
+ object: this,
705
+
706
+ font: textConf.font,
707
+ size: textConf.size,
708
+ color: textConf.color,
709
+ bold: textConf.bold,
710
+ italic: textConf.italic,
711
+
712
+ x: x + properties.labelsOffsetx,
713
+ y: this.coords[j - 1][5] + properties.labelsOffsety,
714
+
715
+ text: lastLabel,
716
+
717
+ valign: 'center',
718
+ halign: halign,
719
+
720
+ bounding: true,
721
+ boundingFill: 'rgba(255,255,255,0.7)',
722
+ boundingStroke: 'rgba(0,0,0,0)',
723
+ tag: 'labels',
724
+ cssClass: RGraph.getLabelsCSSClassName({
725
+ object: this,
726
+ name: 'labelsClass',
727
+ index: j
728
+ })
729
+ });
730
+
731
+ if (properties.labelsSticks) {
732
+
733
+ // Measure the text
734
+ this.context.font = textConf.size + 'pt ' + font;
735
+ var labelWidth = this.context.measureText(lastLabel).width;
736
+
737
+ // Draw the horizontal indicator line
738
+ this.path(
739
+ 'b m % % l % % s gray',
740
+ x + labelWidth + 10, Math.round(this.coords[j - 1][7]),
741
+ this.coords[j - 1][6] - 10, Math.round(this.coords[j - 1][7])
742
+ );
743
+ }
744
+ }
745
+ }
746
+ };
747
+
748
+
749
+
750
+
751
+
752
+
753
+
754
+
755
+ //
756
+ // Gets the appropriate segment that has been highlighted
757
+ //
758
+ this.getShape = function (e)
759
+ {
760
+ var coords = this.coords;
761
+ var mouseCoords = RGraph.getMouseXY(e);
762
+ var x = mouseCoords[0];
763
+ var y = mouseCoords[1];
764
+
765
+ for (i=0,len=coords.length; i<len; ++i) {
766
+
767
+ var segment = coords[i]
768
+
769
+ if (RGraph.tooltipsHotspotIgnore(this, i)) {
770
+ continue;
771
+ }
772
+
773
+ // Path testing
774
+ this.path(
775
+ 'b m % % l % % l % % l % % l % %',
776
+ segment[0], segment[1],
777
+ segment[2], segment[3],
778
+ segment[4], segment[5],
779
+ segment[6], segment[7],
780
+ segment[8], segment[9]
781
+ );
782
+
783
+
784
+ if (this.context.isPointInPath(x, y)) {
785
+
786
+ if (RGraph.parseTooltipText && properties.tooltips) {
787
+ var tooltip = RGraph.parseTooltipText(properties.tooltips, i);
788
+ }
789
+
790
+ return {
791
+ object: this,
792
+ coords: segment,
793
+ dataset: 0,
794
+ index: i,
795
+ sequentialIndex: i,
796
+ label: properties.labels && typeof properties.labels[i] === 'string' ? properties.labels[i] : null,
797
+ tooltip: typeof tooltip === 'string' ? tooltip : null
798
+ };
799
+ }
800
+ }
801
+
802
+ return null;
803
+ };
804
+
805
+
806
+
807
+
808
+
809
+
810
+
811
+
812
+ //
813
+ // Each object type has its own Highlight() function which highlights the appropriate shape
814
+ //
815
+ // @param object shape The shape to highlight
816
+ //
817
+ this.highlight = function (shape)
818
+ {
819
+ if (properties.tooltipsHighlight) {
820
+
821
+ if (typeof properties.highlightStyle === 'function') {
822
+ (properties.highlightStyle)(shape);
823
+ return;
824
+ }
825
+
826
+ if (typeof properties.highlightStyle === 'string' && properties.highlightStyle === 'invert') {
827
+ for (var i=0; i<this.coords.length; ++i) {
828
+ if (i !== shape.sequentialIndex) {
829
+
830
+ var coords = this.coords[i];
831
+
832
+ this.path(
833
+ 'b m % % l % % l % % l % % c s % f %',
834
+ coords[0] - 0.5, coords[1] - 0.5,
835
+ coords[2] + 0.5, coords[3] - 0.5,
836
+ coords[4] + 0.5, coords[5] + 0.5,
837
+ coords[6] - 0.5, coords[7] + 0.5,
838
+ properties.highlightStroke,
839
+ properties.highlightFill
840
+ );
841
+ }
842
+ }
843
+
844
+ return;
845
+ }
846
+
847
+
848
+
849
+ var coords = shape.coords;
850
+
851
+ this.path(
852
+ 'b m % % l % % l % % l % % c s % f %',
853
+ coords[0] - 0.5, coords[1] - 0.5,
854
+ coords[2] + 0.5, coords[3] - 0.5,
855
+ coords[4] + 0.5, coords[5] + 0.5,
856
+ coords[6] - 0.5, coords[7] + 0.5,
857
+ properties.highlightStroke,
858
+ properties.highlightFill
859
+ );
860
+ }
861
+ };
862
+
863
+
864
+
865
+
866
+
867
+
868
+
869
+
870
+ //
871
+ // The getObjectByXY() worker method. Don't call this call:
872
+ //
873
+ // RGraph.ObjectRegistry.getObjectByXY(e)
874
+ //
875
+ // @param object e The event object
876
+ //
877
+ this.getObjectByXY = function (e)
878
+ {
879
+ var mouseXY = RGraph.getMouseXY(e);
880
+
881
+ if (
882
+ mouseXY[0] > properties.marginLeft
883
+ && mouseXY[0] < (this.canvas.width - properties.marginRight)
884
+ && mouseXY[1] > properties.marginTop
885
+ && mouseXY[1] < (this.canvas.height - properties.marginBottom)
886
+ ) {
887
+
888
+ return this;
889
+ }
890
+ };
891
+
892
+
893
+
894
+
895
+
896
+
897
+
898
+
899
+ //
900
+ // This allows for easy specification of gradients
901
+ //
902
+ this.parseColors = function ()
903
+ {
904
+ // Save the original colors so that they can be restored when the canvas is reset
905
+ if (this.original_colors.length === 0) {
906
+ this.original_colors.colors = RGraph.arrayClone(properties.colors);
907
+ this.original_colors.keyColors = RGraph.arrayClone(properties.keyColors);
908
+ this.original_colors.highlightFill = RGraph.arrayClone(properties.highlightFill);
909
+ this.original_colors.highlightStroke = RGraph.arrayClone(properties.highlightStroke);
910
+ this.original_colors.colorsStroke = RGraph.arrayClone(properties.colorsStroke);
911
+ }
912
+
913
+ var colors = properties.colors;
914
+
915
+ for (var i=0; i<colors.length; ++i) {
916
+ colors[i] = this.parseSingleColorForHorizontalGradient(colors[i]);
917
+ }
918
+
919
+ var keyColors = properties.keyColors;
920
+ if (keyColors) {
921
+ for (var i=0; i<keyColors.length; ++i) {
922
+ keyColors[i] = this.parseSingleColorForHorizontalGradient(keyColors[i]);
923
+ }
924
+ }
925
+
926
+
927
+ properties.colorsStroke = this.parseSingleColorForVerticalGradient(properties.colorsStroke);
928
+ properties.highlightStroke = this.parseSingleColorForHorizontalGradient(properties.highlightStroke);
929
+ properties.highlightFill = this.parseSingleColorForHorizontalGradient(properties.highlightFill);
930
+ };
931
+
932
+
933
+
934
+
935
+
936
+
937
+
938
+
939
+ //
940
+ // Use this function to reset the object to the post-constructor state. Eg reset colors if
941
+ // need be etc
942
+ //
943
+ this.reset = function ()
944
+ {
945
+ };
946
+
947
+
948
+
949
+
950
+
951
+
952
+
953
+
954
+ //
955
+ // This parses a single color value
956
+ //
957
+ this.parseSingleColorForHorizontalGradient = function (color)
958
+ {
959
+ if (!color || typeof color != 'string') {
960
+ return color;
961
+ }
962
+
963
+ if (color.match(/^gradient\((.*)\)$/i)) {
964
+
965
+ // Allow for JSON gradients
966
+ if (color.match(/^gradient\(({.*})\)$/i)) {
967
+ return RGraph.parseJSONGradient({object: this, def: RegExp.$1});
968
+ }
969
+
970
+ var parts = RegExp.$1.split(':');
971
+
972
+ // Create the gradient
973
+ var grad = this.context.createLinearGradient(properties.marginLeft,0,this.canvas.width - properties.marginRight,0);
974
+
975
+ var diff = 1 / (parts.length - 1);
976
+
977
+ grad.addColorStop(0, RGraph.trim(parts[0]));
978
+
979
+ for (var j=1; j<parts.length; ++j) {
980
+ grad.addColorStop(j * diff, RGraph.trim(parts[j]));
981
+ }
982
+ }
983
+
984
+ return grad ? grad : color;
985
+ };
986
+
987
+
988
+
989
+
990
+
991
+
992
+
993
+
994
+ //
995
+ // This parses a single color value
996
+ //
997
+ this.parseSingleColorForVerticalGradient = function (color)
998
+ {
999
+ if (!color || typeof color != 'string') {
1000
+ return color;
1001
+ }
1002
+
1003
+ if (color.match(/^gradient\((.*)\)$/i)) {
1004
+
1005
+ var parts = RegExp.$1.split(':');
1006
+
1007
+ // Create the gradient
1008
+ var grad = this.context.createLinearGradient(0, properties.marginTop,0,this.canvas.height - properties.marginBottom);
1009
+
1010
+ var diff = 1 / (parts.length - 1);
1011
+
1012
+ grad.addColorStop(0, RGraph.trim(parts[0]));
1013
+
1014
+ for (var j=1; j<parts.length; ++j) {
1015
+ grad.addColorStop(j * diff, RGraph.trim(parts[j]));
1016
+ }
1017
+ }
1018
+
1019
+ return grad ? grad : color;
1020
+ };
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+ //
1030
+ // This function handles highlighting an entire data-series for the interactive
1031
+ // key
1032
+ //
1033
+ // @param int index The index of the data series to be highlighted
1034
+ //
1035
+ this.interactiveKeyHighlight = function (index)
1036
+ {
1037
+ var coords = this.coords[index];
1038
+
1039
+ if (coords && coords.length == 8) {
1040
+ var pre_linewidth = this.context.lineWidth;
1041
+
1042
+ this.context.lineWidth = 2;
1043
+ this.context.strokeStyle = properties.keyInteractiveHighlightChartStroke;
1044
+ this.context.fillStyle = properties.keyInteractiveHighlightChartFill;
1045
+
1046
+ this.context.beginPath();
1047
+ this.context.moveTo(coords[0] - 0.5, coords[1] - 0.5);
1048
+ this.context.lineTo(coords[2] + 0.5, coords[3] - 0.5);
1049
+ this.context.lineTo(coords[4] + 0.5, coords[5] + 0.5);
1050
+ this.context.lineTo(coords[6] - 0.5, coords[7] + 0.5);
1051
+ this.context.closePath();
1052
+ this.context.fill();
1053
+ this.context.stroke();
1054
+
1055
+ // Reset the linewidth
1056
+ this.context.lineWidth = pre_linewidth;
1057
+ }
1058
+ };
1059
+
1060
+
1061
+
1062
+
1063
+
1064
+
1065
+
1066
+
1067
+ //
1068
+ // Using a function to add events makes it easier to facilitate method chaining
1069
+ //
1070
+ // @param string type The type of even to add
1071
+ // @param function func
1072
+ //
1073
+ this.on = function (type, func)
1074
+ {
1075
+ if (type.substr(0,2) !== 'on') {
1076
+ type = 'on' + type;
1077
+ }
1078
+
1079
+ if (typeof this[type] !== 'function') {
1080
+ this[type] = func;
1081
+ } else {
1082
+ RGraph.addCustomEventListener(this, type, func);
1083
+ }
1084
+
1085
+ return this;
1086
+ };
1087
+
1088
+
1089
+
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+ //
1096
+ // This function runs once only
1097
+ // (put at the end of the file (before any effects))
1098
+ //
1099
+ this.firstDrawFunc = function ()
1100
+ {
1101
+ };
1102
+
1103
+
1104
+
1105
+
1106
+
1107
+
1108
+
1109
+
1110
+ //
1111
+ // A worker function that handles Bar chart specific tooltip substitutions
1112
+ //
1113
+ this.tooltipSubstitutions = function (opt)
1114
+ {
1115
+ return {
1116
+ index: opt.index,
1117
+ dataset: 0,
1118
+ sequentialIndex: opt.index,
1119
+ value: this.data[opt.index],
1120
+ values: [this.data[opt.index]]
1121
+ };
1122
+ };
1123
+
1124
+
1125
+
1126
+
1127
+
1128
+
1129
+
1130
+
1131
+ //
1132
+ // A worker function that returns the correct color/label/value
1133
+ //
1134
+ // @param object specific The indexes that are applicable
1135
+ // @param number index The appropriate index
1136
+ //
1137
+ this.tooltipsFormattedCustom = function (specific, index)
1138
+ {
1139
+ var color = properties.colors[specific.index];
1140
+ var label = RGraph.isString(properties.tooltipsFormattedKeyLabels[specific.index]) ? properties.tooltipsFormattedKeyLabels[specific.index] : '';
1141
+
1142
+ if ( !RGraph.isNull(properties.tooltipsFormattedKeyColors)
1143
+ && typeof properties.tooltipsFormattedKeyColors === 'object'
1144
+ && typeof properties.tooltipsFormattedKeyColors[specific.index] === 'string')
1145
+ {
1146
+
1147
+ color = properties.tooltipsFormattedKeyColors[specific.index];
1148
+ }
1149
+
1150
+ return {
1151
+ label: label,
1152
+ color: color
1153
+ };
1154
+ };
1155
+
1156
+
1157
+
1158
+
1159
+
1160
+
1161
+
1162
+
1163
+ //
1164
+ // This allows for static tooltip positioning
1165
+ //
1166
+ this.positionTooltipStatic = function (args)
1167
+ {
1168
+ var obj = args.object,
1169
+ e = args.event,
1170
+ tooltip = args.tooltip,
1171
+ index = args.index,
1172
+ canvasXY = RGraph.getCanvasXY(obj.canvas)
1173
+ coords = this.coords[args.index];
1174
+
1175
+ // Position the tooltip in the X direction
1176
+ args.tooltip.style.left = (
1177
+ canvasXY[0] // The X coordinate of the canvas
1178
+ + (((coords[2] - coords[0]) / 2) + coords[0]) // The X coordinate of the bar on the chart
1179
+ - (tooltip.offsetWidth / 2) // Subtract half of the tooltip width
1180
+ + obj.properties.tooltipsOffsetx // Add any user defined offset
1181
+ ) + 'px';
1182
+
1183
+ args.tooltip.style.top = (
1184
+ canvasXY[1] // The Y coordinate of the canvas
1185
+ + coords[1] // The Y coordinate of the bar on the chart
1186
+ //+ ((coords[5] - coords[1]) / 2) // Add half of the height of the segment
1187
+ - tooltip.offsetHeight // The height of the tooltip
1188
+ + obj.properties.tooltipsOffsety // Add any user defined offset
1189
+ - 10 // An arbitrary amount
1190
+ ) + 'px';
1191
+
1192
+
1193
+
1194
+ // If the top of the tooltip is off the top of the page
1195
+ // then move the tooltip down
1196
+ if(parseFloat(args.tooltip.style.top) < 0) {
1197
+ args.tooltip.style.top = parseFloat(args.tooltip.style.top) + 20 + 'px';
1198
+ }
1199
+ };
1200
+
1201
+
1202
+
1203
+
1204
+
1205
+
1206
+
1207
+
1208
+ //
1209
+ // This returns the relevant value for the formatted key
1210
+ // macro %{value}. THIS VALUE SHOULD NOT BE FORMATTED.
1211
+ //
1212
+ // @param number index The index in the dataset to get
1213
+ // the value for
1214
+ //
1215
+ this.getKeyValue = function (index)
1216
+ {
1217
+ return RGraph.isArray(this.properties.keyFormattedValueSpecific) && RGraph.isNumber(this.properties.keyFormattedValueSpecific[index])
1218
+ ? this.properties.keyFormattedValueSpecific[index]
1219
+ : this.data[index];
1220
+ };
1221
+
1222
+
1223
+
1224
+
1225
+
1226
+
1227
+
1228
+
1229
+ //
1230
+ // Returns how many data-points there should be when a string
1231
+ // based key property has been specified. For example, this:
1232
+ //
1233
+ // key: '%{property:_labels[%{index}]} %{value_formatted}'
1234
+ //
1235
+ // ...depending on how many bits of data ther is might get
1236
+ // turned into this:
1237
+ //
1238
+ // key: [
1239
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1240
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1241
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1242
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1243
+ // '%{property:_labels[%{index}]} %{value_formatted}',
1244
+ // ]
1245
+ //
1246
+ // ... ie in that case there would be 4 data-points so the
1247
+ // template is repeated 4 times.
1248
+ //
1249
+ this.getKeyNumDatapoints = function ()
1250
+ {
1251
+ return this.data.length - 1;
1252
+ };
1253
+
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+ //
1262
+ // Always now regsiter the object
1263
+ //
1264
+ RGraph.register(this);
1265
+
1266
+
1267
+
1268
+
1269
+
1270
+
1271
+
1272
+
1273
+ //
1274
+ // This is the 'end' of the constructor so if the first argument
1275
+ // contains configuration data - handle that.
1276
+ //
1277
+ RGraph.parseObjectStyleConfig(this, conf.options);
1278
+ };