rgraph-rails 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/rgraph-rails/version.rb +1 -1
  4. data/license.txt +4 -16
  5. data/vendor/assets/javascripts/RGraph.bar.js +3734 -241
  6. data/vendor/assets/javascripts/RGraph.bipolar.js +2005 -115
  7. data/vendor/assets/javascripts/RGraph.common.annotate.js +395 -35
  8. data/vendor/assets/javascripts/RGraph.common.context.js +595 -30
  9. data/vendor/assets/javascripts/RGraph.common.core.js +5282 -405
  10. data/vendor/assets/javascripts/RGraph.common.csv.js +276 -19
  11. data/vendor/assets/javascripts/RGraph.common.deprecated.js +450 -35
  12. data/vendor/assets/javascripts/RGraph.common.dynamic.js +1395 -86
  13. data/vendor/assets/javascripts/RGraph.common.effects.js +1545 -90
  14. data/vendor/assets/javascripts/RGraph.common.key.js +753 -54
  15. data/vendor/assets/javascripts/RGraph.common.resizing.js +563 -37
  16. data/vendor/assets/javascripts/RGraph.common.sheets.js +352 -29
  17. data/vendor/assets/javascripts/RGraph.common.tooltips.js +450 -32
  18. data/vendor/assets/javascripts/RGraph.common.zoom.js +219 -14
  19. data/vendor/assets/javascripts/RGraph.drawing.background.js +570 -35
  20. data/vendor/assets/javascripts/RGraph.drawing.circle.js +544 -35
  21. data/vendor/assets/javascripts/RGraph.drawing.image.js +755 -52
  22. data/vendor/assets/javascripts/RGraph.drawing.marker1.js +645 -41
  23. data/vendor/assets/javascripts/RGraph.drawing.marker2.js +633 -37
  24. data/vendor/assets/javascripts/RGraph.drawing.marker3.js +514 -36
  25. data/vendor/assets/javascripts/RGraph.drawing.poly.js +559 -39
  26. data/vendor/assets/javascripts/RGraph.drawing.rect.js +548 -35
  27. data/vendor/assets/javascripts/RGraph.drawing.text.js +664 -36
  28. data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +812 -50
  29. data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +856 -51
  30. data/vendor/assets/javascripts/RGraph.fuel.js +964 -58
  31. data/vendor/assets/javascripts/RGraph.funnel.js +984 -55
  32. data/vendor/assets/javascripts/RGraph.gantt.js +1354 -77
  33. data/vendor/assets/javascripts/RGraph.gauge.js +1421 -87
  34. data/vendor/assets/javascripts/RGraph.hbar.js +2562 -146
  35. data/vendor/assets/javascripts/RGraph.hprogress.js +1401 -80
  36. data/vendor/assets/javascripts/RGraph.line.js +4226 -244
  37. data/vendor/assets/javascripts/RGraph.meter.js +1280 -74
  38. data/vendor/assets/javascripts/RGraph.modaldialog.js +301 -19
  39. data/vendor/assets/javascripts/RGraph.odo.js +1264 -71
  40. data/vendor/assets/javascripts/RGraph.pie.js +2288 -137
  41. data/vendor/assets/javascripts/RGraph.radar.js +1847 -110
  42. data/vendor/assets/javascripts/RGraph.rose.js +1977 -108
  43. data/vendor/assets/javascripts/RGraph.rscatter.js +1432 -80
  44. data/vendor/assets/javascripts/RGraph.scatter.js +3036 -168
  45. data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1120 -60
  46. data/vendor/assets/javascripts/RGraph.svg.bar.js +1067 -0
  47. data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +247 -0
  48. data/vendor/assets/javascripts/RGraph.svg.common.core.js +3363 -0
  49. data/vendor/assets/javascripts/RGraph.svg.common.csv.js +277 -0
  50. data/vendor/assets/javascripts/RGraph.svg.common.fx.js +1304 -0
  51. data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +353 -0
  52. data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +233 -0
  53. data/vendor/assets/javascripts/RGraph.svg.hbar.js +1141 -0
  54. data/vendor/assets/javascripts/RGraph.svg.line.js +1486 -0
  55. data/vendor/assets/javascripts/RGraph.svg.pie.js +781 -0
  56. data/vendor/assets/javascripts/RGraph.svg.radar.js +1326 -0
  57. data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +817 -0
  58. data/vendor/assets/javascripts/RGraph.thermometer.js +1135 -62
  59. data/vendor/assets/javascripts/RGraph.vprogress.js +1470 -83
  60. data/vendor/assets/javascripts/RGraph.waterfall.js +1347 -80
  61. metadata +15 -3
@@ -1,81 +1,1433 @@
1
+ // version: 2017-01-02
2
+ /**
3
+ * o--------------------------------------------------------------------------------o
4
+ * | This file is part of the RGraph package - you can learn more at: |
5
+ * | |
6
+ * | http://www.rgraph.net |
7
+ * | |
8
+ * | RGraph is licensed under the Open Source MIT license. That means that it's |
9
+ * | totally free to use! |
10
+ * o--------------------------------------------------------------------------------o
11
+ */
1
12
 
2
- RGraph=window.RGraph||{isRGraph:true};RGraph.RScatter=RGraph.Rscatter=function(conf)
3
- {if(typeof conf==='object'&&typeof conf.data==='object'&&typeof conf.id==='string'){var parseConfObjectForOptions=true;this.data=new Array(conf.data.length);this.data=RGraph.arrayClone(conf.data);if(typeof conf.data==='object'&&typeof conf.data[0]==='object'&&typeof conf.data[0][0]==='number'){var tmp=RGraph.arrayClone(conf.data);conf.data=new Array();conf.data[0]=RGraph.arrayClone(tmp);this.data=RGraph.arrayClone(conf.data);}}else{var conf={id:conf};conf.data=arguments[1];this.data=[];if(arguments[1][0]&&arguments[1][0][0]&&typeof arguments[1][0][0]=='object'){for(var i=0;i<arguments[1].length;++i){this.data[i]=arguments[1][i];}}else{for(var i=1;i<arguments.length;++i){this.data[i-1]=RGraph.arrayClone(arguments[i]);}}}
4
- this.id=conf.id
5
- this.canvas=document.getElementById(this.id)
6
- this.context=this.canvas.getContext?this.canvas.getContext("2d"):null;this.canvas.__object__=this;this.type='rscatter';this.hasTooltips=false;this.isRGraph=true;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.centerx=0;this.centery=0;this.radius=0;this.max=0;for(var i=0;i<this.data.length;++i){for(var j=0;j<this.data[i].length;++j){if(typeof this.data[i][j][0]==='string'){this.data[i][j][0]=parseFloat(this.data[i][j][0]);}
7
- if(typeof this.data[i][j][1]==='string'){this.data[i][j][1]=parseFloat(this.data[i][j][1]);}}}
8
- this.properties={'chart.background.color':'transparent','chart.background.grid':true,'chart.background.grid.diagonals':true,'chart.background.grid.diagonals.count':null,'chart.background.grid.radials':true,'chart.background.grid.radials.count':null,'chart.background.grid.linewidth':1,'chart.background.grid.color':'#ccc','chart.radius':null,'chart.colors':[],'chart.colors.default':'black','chart.gutter.left':25,'chart.gutter.right':25,'chart.gutter.top':25,'chart.gutter.bottom':25,'chart.title':'','chart.title.background':null,'chart.title.hpos':null,'chart.title.vpos':null,'chart.title.bold':true,'chart.title.font':null,'chart.title.x':null,'chart.title.y':null,'chart.title.halign':null,'chart.title.valign':null,'chart.labels':null,'chart.labels.color':null,'chart.labels.axes':'nsew','chart.labels.axes.background':'rgba(255,255,255,0.8)','chart.labels.count':5,'chart.text.color':'black','chart.text.font':'Segoe UI, Arial, Verdana, sans-serif','chart.text.size':12,'chart.text.accessible':true,'chart.text.accessible.overflow':'visible','chart.text.accessible.pointerevents':true,'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.fill':'rgba(255,0,0,0.9)','chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)','chart.key.text.color':'black','chart.contextmenu':null,'chart.tooltips':null,'chart.tooltips.event':'onmousemove','chart.tooltips.effect':'fade','chart.tooltips.css.class':'RGraph_tooltip','chart.tooltips.highlight':true,'chart.tooltips.hotspot':3,'chart.tooltips.coords.page':false,'chart.annotatable':false,'chart.annotate.color':'black','chart.zoom.factor':1.5,'chart.zoom.fade.in':true,'chart.zoom.fade.out':true,'chart.zoom.hdir':'right','chart.zoom.vdir':'down','chart.zoom.frames':25,'chart.zoom.delay':16.666,'chart.zoom.shadow':true,'chart.zoom.background':true,'chart.zoom.action':'zoom','chart.resizable':false,'chart.resize.handle.background':null,'chart.ymax':null,'chart.ymin':0,'chart.tickmarks':'cross','chart.ticksize':3,'chart.scale.decimals':null,'chart.scale.point':'.','chart.scale.thousand':',','chart.scale.round':false,'chart.scale.zerostart':true,'chart.units.pre':'','chart.units.post':'','chart.events.mousemove':null,'chart.events.click':null,'chart.highlight.stroke':'transparent','chart.highlight.fill':'rgba(255,255,255,0.7)','chart.highlight.point.radius':3,'chart.axes.color':'black','chart.axes.numticks':null,'chart.axes.caps':true,'chart.segment.highlight':false,'chart.segment.highlight.count':null,'chart.segment.highlight.fill':'rgba(0,255,0,0.5)','chart.segment.highlight.stroke':'rgba(0,0,0,0)','chart.line':false,'chart.line.close':false,'chart.line.linewidth':1,'chart.line.colors':['black'],'chart.line.shadow':false,'chart.line.shadow.color':'black','chart.line.shadow.blur':2,'chart.line.shadow.offsetx':3,'chart.line.shadow.offsety':3,'chart.clearto':'rgba(0,0,0,0)'}
9
- for(var i=0,idx=0;i<this.data.length;++i){for(var j=0,len=this.data[i].length;j<len;j+=1,idx+=1){this['$'+idx]={}}}
10
- if(!this.canvas.__rgraph_aa_translated__){this.context.translate(0.5,0.5);this.canvas.__rgraph_aa_translated__=true;}
11
- var RG=RGraph,ca=this.canvas,co=ca.getContext('2d'),prop=this.properties,pa2=RG.path2,win=window,doc=document,ma=Math
12
- if(RG.Effects&&typeof RG.Effects.decorate==='function'){RG.Effects.decorate(this);}
13
- this.set=this.Set=function(name,value)
14
- {var value=typeof arguments[1]==='undefined'?null:arguments[1];if(arguments.length===1&&typeof name==='object'){RG.parseObjectStyleConfig(this,name);return this;}
15
- if(name.substr(0,6)!='chart.'){name='chart.'+name;}
16
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
17
- if(name==='chart.segments.highlight')name='chart.segment.highlight';if(name==='chart.segments.highlight.count')name='chart.segment.highlight.count';if(name==='chart.segments.highlight.fill')name='chart.segment.highlight.fill';if(name==='chart.segments.highlight.stroke')name='chart.segment.highlight.stroke';prop[name.toLowerCase()]=value;return this;};this.get=this.Get=function(name)
18
- {if(name.substr(0,6)!='chart.'){name='chart.'+name;}
19
- while(name.match(/([A-Z])/)){name=name.replace(/([A-Z])/,'.'+RegExp.$1.toLowerCase());}
20
- return prop[name.toLowerCase()];};this.draw=this.Draw=function()
21
- {RG.FireCustomEvent(this,'onbeforedraw');this.gutterLeft=prop['chart.gutter.left'];this.gutterRight=prop['chart.gutter.right'];this.gutterTop=prop['chart.gutter.top'];this.gutterBottom=prop['chart.gutter.bottom'];this.radius=(Math.min(ca.width-this.gutterLeft-this.gutterRight,ca.height-this.gutterTop-this.gutterBottom)/2);this.centerx=((ca.width-this.gutterLeft-this.gutterRight)/2)+this.gutterLeft;this.centery=((ca.height-this.gutterTop-this.gutterBottom)/2)+this.gutterTop;this.coords=[];this.coords2=[];this.coordsText=[];if(typeof(prop['chart.centerx'])=='number')this.centerx=prop['chart.centerx'];if(typeof(prop['chart.centery'])=='number')this.centery=prop['chart.centery'];if(typeof(prop['chart.radius'])=='number')this.radius=prop['chart.radius'];if(!this.colorsParsed){this.parseColors();this.colorsParsed=true;}
22
- var max=prop['chart.ymax'];var min=prop['chart.ymin'];if(typeof(max)=='number'){this.max=max;this.scale2=RG.getScale2(this,{'max':max,'min':min,'strict':true,'scale.decimals':Number(prop['chart.scale.decimals']),'scale.point':prop['chart.scale.point'],'scale.thousand':prop['chart.scale.thousand'],'scale.round':prop['chart.scale.round'],'units.pre':prop['chart.units.pre'],'units.post':prop['chart.units.post'],'ylabels.count':prop['chart.labels.count']});}else{for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){this.max=Math.max(this.max,this.data[i][j][1]);}}
23
- this.min=prop['chart.ymin'];this.scale2=RG.getScale2(this,{'max':this.max,'min':min,'scale.decimals':Number(prop['chart.scale.decimals']),'scale.point':prop['chart.scale.point'],'scale.thousand':prop['chart.scale.thousand'],'scale.round':prop['chart.scale.round'],'units.pre':prop['chart.units.pre'],'units.post':prop['chart.units.post'],'ylabels.count':prop['chart.labels.count']});this.max=this.scale2.max;}
24
- if(prop['chart.key']&&prop['chart.key'].length>0&&prop['chart.key'].length>=3){this.centerx=this.centerx-prop['chart.gutter.right']+5;}
25
- if(typeof(prop['chart.key'])=='object'&&RG.is_array(prop['chart.key'])&&prop['chart.key'][0]){prop['chart.colors']=[];for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){if(typeof this.data[i][j][2]=='string'){prop['chart.colors'].push(this.data[i][j][2]);}}}}
26
- this.Set('chart.tooltips',[]);for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){if(typeof this.data[i][j][3]=='string'){prop['chart.tooltips'].push(this.data[i][j][3]);}}}
27
- co.beginPath();this.DrawBackground();this.DrawRscatter();this.DrawLabels();if(prop['chart.contextmenu']){RG.ShowContext(this);}
28
- if(prop['chart.title']){RG.DrawTitle(this,prop['chart.title'],this.centery-this.radius-10,this.centerx,prop['chart.title.size']?prop['chart.title.size']:prop['chart.text.size']+2);}
29
- if(prop['chart.resizable']){RG.AllowResizing(this);}
30
- RG.InstallEventListeners(this);if(prop['chart.segment.highlight']){RG.allowSegmentHighlight({object:this,count:typeof prop['chart.segment.highlight.count']==='number'?prop['chart.segment.highlight.count']:((prop['chart.background.grid.diagonals.count']?prop['chart.background.grid.diagonals.count']:(prop['chart.labels']?prop['chart.labels'].length:8))),fill:prop['chart.segment.highlight.fill'],stroke:prop['chart.segment.highlight.stroke']});}
31
- if(this.firstDraw){RG.fireCustomEvent(this,'onfirstdraw');this.firstDraw=false;this.firstDrawFunc();}
32
- RG.FireCustomEvent(this,'ondraw');return this;};this.drawBackground=this.DrawBackground=function()
33
- {if(prop['chart.background.color']!='transparent'){pa2(co,['b','a',this.centerx,this.centery,this.radius,0,2*ma.PI,-1,'f',prop['chart.background.color']]);}
34
- var gridEnabled=prop['chart.background.grid'];if(gridEnabled){co.lineWidth=prop['chart.background.grid.linewidth'];if(prop['chart.background.grid.radials']){co.strokeStyle=prop['chart.background.grid.color'];if(RG.isNull(prop['chart.background.grid.radials.count'])){prop['chart.background.grid.radials.count']=prop['chart.labels.count'];}
35
- var r=this.radius/prop['chart.background.grid.radials.count'];for(var i=0,len=this.radius;i<=len;i+=r){co.arc(this.centerx,this.centery,i,0,RG.TWOPI,0);}
36
- co.stroke();}
37
- if(prop['chart.background.grid.diagonals']){co.strokeStyle=prop['chart.background.grid.color'];co.beginPath();var inc=360/((prop['chart.background.grid.diagonals.count']?prop['chart.background.grid.diagonals.count']:(prop['chart.labels']?prop['chart.labels'].length:8)));for(var i=inc;i<360;i+=inc){co.arc(this.centerx,this.centery,this.radius,(i/(180/RG.PI))-RG.HALFPI,((i+0.01)/(180/RG.PI))-RG.HALFPI,0);co.lineTo(this.centerx,this.centery);}
38
- co.stroke();}}
39
- co.lineWidth=1;co.beginPath();co.strokeStyle=prop['chart.axes.color'];co.moveTo(this.centerx-this.radius,Math.round(this.centery));co.lineTo(this.centerx+this.radius,Math.round(this.centery));if(prop['chart.axes.caps']){co.moveTo(ma.round(this.centerx-this.radius),this.centery-5);co.lineTo(ma.round(this.centerx-this.radius),this.centery+5);co.moveTo(ma.round(this.centerx+this.radius),this.centery-5);co.lineTo(ma.round(this.centerx+this.radius),this.centery+5);}
40
- if(!RG.isNull(prop['chart.axes.numticks'])){var numticks=prop['chart.axes.numticks']}else{var numticks=prop['chart.labels.count'];}
41
- var caps=prop['chart.axes.caps'];if(numticks){for(var i=(this.centerx-this.radius);i<(this.centerx+this.radius);i+=(this.radius/numticks)){co.moveTo(ma.round(i),this.centery-3);co.lineTo(ma.round(i),this.centery+3);}
42
- for(var i=(this.centery-this.radius);i<(this.centery+this.radius);i+=(this.radius/numticks)){co.moveTo(this.centerx-3,ma.round(i));co.lineTo(this.centerx+3,ma.round(i));}}
43
- co.moveTo(ma.round(this.centerx),this.centery-this.radius);co.lineTo(ma.round(this.centerx),this.centery+this.radius);if(prop['chart.axes.caps']){co.moveTo(this.centerx-5,ma.round(this.centery-this.radius));co.lineTo(this.centerx+5,ma.round(this.centery-this.radius));co.moveTo(this.centerx-5,ma.round(this.centery+this.radius));co.lineTo(this.centerx+5,ma.round(this.centery+this.radius));}
44
- co.closePath();co.stroke();};this.drawRscatter=this.DrawRscatter=function()
45
- {for(var dataset=0;dataset<this.data.length;dataset+=1){var data=this.data[dataset];this.coords2[dataset]=[];var drawPoints=function(obj)
46
- {for(var i=0;i<data.length;++i){var d1=data[i][0],d2=data[i][1],a=d1/(180/RG.PI),r=((d2-prop['chart.ymin'])/(obj.scale2.max-obj.scale2.min))*obj.radius,x=ma.sin(a)*r,y=ma.cos(a)*r,color=data[i][2]?data[i][2]:prop['chart.colors.default'],tooltip=data[i][3]?data[i][3]:null
47
- if(tooltip&&String(tooltip).length){obj.hasTooltips=true;}
48
- x=x+obj.centerx;y=obj.centery-y;obj.drawTick(x,y,color);obj.coords.push([x,y,color,tooltip]);obj.coords2[dataset].push([x,y,color,tooltip]);}}
49
- drawPoints(this);if(prop['chart.line']){this.drawLine(dataset);}}};this.drawLine=function(idx)
50
- {var opt={dataset:idx,coords:this.coords2[idx],color:prop['chart.line.colors'][idx],shadow:prop['chart.line.shadow'],shadowColor:prop['chart.line.shadow.color'],shadowOffsetX:prop['chart.line.shadow.offsetx'],shadowOffsetY:prop['chart.line.shadow.offsety'],shadowBlur:prop['chart.line.shadow.blur'],linewidth:prop['chart.line.linewidth']};co.beginPath();co.strokeStyle=this.parseSingleColorForGradient(opt.color);co.lineWidth=typeof prop['chart.line.linewidth']==='object'?prop['chart.line.linewidth'][idx]:prop['chart.line.linewidth'];co.lineCap='round';if(opt.shadow){RG.setShadow(this,opt.shadowColor,opt.shadowOffsetX,opt.shadowOffsetY,opt.shadowBlur);}
51
- for(var i=0;i<this.coords2[idx].length;++i){if(i===0){co.moveTo(this.coords2[idx][i][0],this.coords2[idx][i][1]);var startCoords=RG.arrayClone(this.coords2[idx]);}else{co.lineTo(this.coords2[idx][i][0],this.coords2[idx][i][1]);}}
52
- if((typeof prop['chart.line.close']==='boolean'&&prop['chart.line.close'])||(typeof prop['chart.line.close']==='object'&&prop['chart.line.close'][idx])){co.lineTo(this.coords2[idx][0][0],this.coords2[idx][0][1]);}
53
- co.stroke();RG.noShadow(this);};this.drawLabels=this.DrawLabels=function()
54
- {co.lineWidth=1;co.fillStyle='black';co.strokeStyle='black';var key=prop['chart.key'];var r=this.radius;var axesColor=prop['chart.axes.color'];var color=prop['chart.text.color'];var font=prop['chart.text.font'];var size=prop['chart.text.size'];var axes=prop['chart.labels.axes'].toLowerCase();var units_pre=prop['chart.units.pre'];var units_post=prop['chart.units.post'];var decimals=prop['chart.scale.decimals'];var centerx=this.centerx;var centery=this.centery;co.fillStyle=prop['chart.text.color'];if(typeof prop['chart.labels']=='object'&&prop['chart.labels']){this.DrawCircularLabels(co,prop['chart.labels'],font,size,r);}
55
- var offset=10;var centered=false;if(axesColor==='rgba(0,0,0,0)'||axesColor==='rgb(0,0,0)'||axesColor==='transparent'){offset=0;centered=true;}
56
- for(var i=0,len=this.scale2.labels.length;i<len;++i){if(axes.indexOf('n')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-offset,'y':centery-(r*((i+1)/len)),'text':this.scale2.labels[i],'valign':'center','halign':centered?'center':'right',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('s')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-offset,'y':centery+(r*((i+1)/len)),'text':this.scale2.labels[i],'valign':'center','halign':centered?'center':'right',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('e')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx+(r*((i+1)/len)),'y':centery+offset,'text':this.scale2.labels[i],'valign':centered?'center':'top','halign':'center',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});if(axes.indexOf('w')>-1)RG.text2(this,{'tag':'scale','font':font,'size':size,'x':centerx-(r*((i+1)/len)),'y':centery+offset,'text':this.scale2.labels[i],'valign':centered?'center':'top','halign':'center',bounding:true,boundingFill:prop['chart.labels.axes.background'],boundingStroke:'rgba(0,0,0,0)'});}
57
- if(prop['chart.labels.axes'].length>0&&prop['chart.scale.zerostart']){RG.text2(this,{'font':font,'size':size,'x':centerx,'y':centery,'text':RG.numberFormat(this,Number(this.scale2.min).toFixed(this.scale2.decimals),this.scale2.units_pre,this.scale2.units_post),'valign':'center','halign':'center','bounding':true,'boundingFill':prop['chart.labels.axes.background'],'boundingStroke':'rgba(0,0,0,0)','tag':'scale'});}
58
- if(key&&key.length){RG.drawKey(this,key,prop['chart.colors']);}};this.drawCircularLabels=this.DrawCircularLabels=function(context,labels,font_face,font_size,r)
59
- {var r=r+10,color=prop['chart.labels.color'];for(var i=0;i<labels.length;++i){var a=(360/labels.length)*(i+1)-(360/(labels.length*2));var a=a-90+(prop['chart.labels.position']=='edge'?((360/labels.length)/2):0);var x=ma.cos(a/(180/RG.PI))*r;var y=ma.sin(a/(180/RG.PI))*r;RG.Text2(this,{'color':color,'font':font_face,'size':font_size,'x':this.centerx+x,'y':this.centery+y,'text':String(labels[i]),'valign':'center','halign':((this.centerx+x)>this.centerx)?'left':'right','tag':'labels'});}};this.drawTick=this.DrawTick=function(x,y,color)
60
- {var tickmarks=prop['chart.tickmarks'];var ticksize=prop['chart.ticksize'];co.strokeStyle=color;co.fillStyle=color;var prevLinewidth=co.lineWidth;co.lineWidth=1;if(tickmarks=='cross'){co.beginPath();co.moveTo(x+ticksize,y+ticksize);co.lineTo(x-ticksize,y-ticksize);co.stroke();co.beginPath();co.moveTo(x-ticksize,y+ticksize);co.lineTo(x+ticksize,y-ticksize);co.stroke();}else if(tickmarks=='circle'){co.beginPath();co.arc(x,y,ticksize,0,6.2830,false);co.fill();}else if(tickmarks=='square'){co.beginPath();co.fillRect(x-ticksize,y-ticksize,2*ticksize,2*ticksize);co.fill();}else if(tickmarks=='diamond'){co.beginPath();co.moveTo(x,y-ticksize);co.lineTo(x+ticksize,y);co.lineTo(x,y+ticksize);co.lineTo(x-ticksize,y);co.closePath();co.fill();}else if(tickmarks=='plus'){co.lineWidth=1;co.beginPath();co.moveTo(x,y-ticksize);co.lineTo(x,y+ticksize);co.moveTo(x-ticksize,y);co.lineTo(x+ticksize,y);co.stroke();}
61
- co.lineWidth=prevLinewidth;};this.getShape=this.getPoint=function(e)
62
- {var mouseXY=RG.getMouseXY(e);var mouseX=mouseXY[0];var mouseY=mouseXY[1];var overHotspot=false;var offset=prop['chart.tooltips.hotspot'];for(var i=0,len=this.coords.length;i<len;++i){var x=this.coords[i][0];var y=this.coords[i][1];var tooltip=this.coords[i][3];if(mouseX<(x+offset)&&mouseX>(x-offset)&&mouseY<(y+offset)&&mouseY>(y-offset)){var tooltip=RG.parseTooltipText(prop['chart.tooltips'],i);return{0:this,1:x,2:y,3:i,'object':this,'x':x,'y':y,'index':i,'tooltip':tooltip};}}};this.allowTooltips=this.AllowTooltips=function()
63
- {RG.PreLoadTooltipImages(this);RG.InstallWindowMousedownTooltipListener(this);RG.InstallCanvasMousemoveTooltipListener(this);RG.InstallCanvasMouseupTooltipListener(this);};this.highlight=this.Highlight=function(shape)
64
- {if(typeof prop['chart.highlight.style']==='function'){(prop['chart.highlight.style'])(shape);}else{RG.Highlight.Point(this,shape);}};this.getObjectByXY=function(e)
65
- {var mouseXY=RG.getMouseXY(e);var mouseX=mouseXY[0];var mouseY=mouseXY[1];var centerx=this.centerx;var centery=this.centery;var radius=this.radius;if(mouseX>(centerx-radius)&&mouseX<(centerx+radius)&&mouseY>(centery-radius)&&mouseY<(centery+radius)){return this;}};this.getRadius=function(value)
66
- {var max=this.max;if(value<0||value>max){return null;}
67
- var r=(value/max)*this.radius;return r;};this.parseColors=function()
68
- {if(this.original_colors.length===0){this.original_colors['data']=RG.array_clone(this.data);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.colors.default']=RG.arrayClone(prop['chart.colors.default']);this.original_colors['chart.background.grid.color']=RG.arrayClone(prop['chart.background.grid.color']);this.original_colors['chart.background.color']=RG.arrayClone(prop['chart.background.color']);this.original_colors['chart.segment.highlight.stroke']=RG.arrayClone(prop['chart.segment.highlight.stroke']);this.original_colors['chart.segment.highlight.fill']=RG.arrayClone(prop['chart.segment.highlight.fill']);}
69
- for(var i=0;i<this.data.length;i+=1){for(var j=0,len=this.data[i].length;j<len;j+=1){this.data[i][j][2]=this.parseSingleColorForGradient(this.data[i][j][2]);}}
70
- prop['chart.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.highlight.stroke']);prop['chart.highlight.fill']=this.parseSingleColorForGradient(prop['chart.highlight.fill']);prop['chart.colors.default']=this.parseSingleColorForGradient(prop['chart.colors.default']);prop['chart.background.grid.color']=this.parseSingleColorForGradient(prop['chart.background.grid.color']);prop['chart.background.color']=this.parseSingleColorForGradient(prop['chart.background.color']);prop['chart.segment.highlight.stroke']=this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);prop['chart.segment.highlight.fill']=this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);};this.reset=function()
71
- {};this.parseSingleColorForGradient=function(color)
72
- {if(!color||typeof color!='string'){return color;}
73
- if(color.match(/^gradient\((.*)\)$/i)){var parts=RegExp.$1.split(':');var grad=co.createRadialGradient(this.centerx,this.centery,0,this.centerx,this.centery,this.radius);var diff=1/(parts.length-1);grad.addColorStop(0,RG.trim(parts[0]));for(var j=1;j<parts.length;++j){grad.addColorStop(j*diff,RG.trim(parts[j]));}}
74
- return grad?grad:color;};this.interactiveKeyHighlight=function(index)
75
- {if(this.coords2&&this.coords2[index]&&this.coords2[index].length){this.coords2[index].forEach(function(value,idx,arr)
76
- {co.beginPath();co.fillStyle=prop['chart.key.interactive.highlight.chart.fill'];co.arc(value[0],value[1],prop['chart.ticksize']+2,0,RG.TWOPI,false);co.fill();});}};this.on=function(type,func)
77
- {if(type.substr(0,2)!=='on'){type='on'+type;}
78
- if(typeof this[type]!=='function'){this[type]=func;}else{RG.addCustomEventListener(this,type,func);}
79
- return this;};this.resetColorsToOriginalValues=function()
80
- {for(var i=0,len=this.original_colors['data'].length;i<len;++i){for(var j=0,len2=this.original_colors['data'][i].length;j<len2;++j){this.data[i][j][2]=RG.array_clone(this.original_colors['data'][i][j][2]);}}};this.firstDrawFunc=function()
81
- {};RG.att(ca);RG.Register(this);if(parseConfObjectForOptions){RG.parseObjectStyleConfig(this,conf.options);}};
13
+ RGraph = window.RGraph || {isRGraph: true};
14
+
15
+ /**
16
+ * The chart constuctor
17
+ *
18
+ * @param object canvas
19
+ * @param array data
20
+ */
21
+ RGraph.RScatter =
22
+ RGraph.Rscatter = function (conf)
23
+ {
24
+ /**
25
+ * Allow for object config style
26
+ */
27
+ if ( typeof conf === 'object'
28
+ && typeof conf.data === 'object'
29
+ && typeof conf.id === 'string') {
30
+
31
+ var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
32
+
33
+ this.data = new Array(conf.data.length);
34
+
35
+ // Store the data set(s)
36
+ this.data = RGraph.arrayClone(conf.data);
37
+
38
+
39
+ // Account for just one dataset being given
40
+ if (typeof conf.data === 'object' && typeof conf.data[0] === 'object' && typeof conf.data[0][0] === 'number') {
41
+ var tmp = RGraph.arrayClone(conf.data);
42
+ conf.data = new Array();
43
+ conf.data[0] = RGraph.arrayClone(tmp);
44
+
45
+ this.data = RGraph.arrayClone(conf.data);
46
+ }
47
+
48
+ } else {
49
+
50
+ var conf = {id: conf};
51
+ conf.data = arguments[1];
52
+
53
+
54
+ this.data = [];
55
+
56
+ // Handle multiple datasets being given as one argument
57
+ if (arguments[1][0] && arguments[1][0][0] && typeof arguments[1][0][0] == 'object') {
58
+ // Store the data set(s)
59
+ for (var i=0; i<arguments[1].length; ++i) {
60
+ this.data[i] = arguments[1][i];
61
+ }
62
+
63
+ // Handle multiple data sets being supplied as seperate arguments
64
+ } else {
65
+
66
+ // Store the data set(s)
67
+ for (var i=1; i<arguments.length; ++i) {
68
+ this.data[i - 1] = RGraph.arrayClone(arguments[i]);
69
+ }
70
+ }
71
+ }
72
+
73
+
74
+
75
+
76
+ this.id = conf.id
77
+ this.canvas = document.getElementById(this.id)
78
+ this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null;
79
+ this.canvas.__object__ = this;
80
+ this.type = 'rscatter';
81
+ this.hasTooltips = false;
82
+ this.isRGraph = true;
83
+ this.uid = RGraph.CreateUID();
84
+ this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
85
+ this.colorsParsed = false;
86
+ this.coordsText = [];
87
+ this.original_colors = [];
88
+ this.firstDraw = true; // After the first draw this will be false
89
+
90
+
91
+ this.centerx = 0;
92
+ this.centery = 0;
93
+ this.radius = 0;
94
+ this.max = 0;
95
+
96
+ // Convert all of the data pieces to numbers
97
+ for (var i=0; i<this.data.length; ++i) {
98
+ for (var j=0; j<this.data[i].length; ++j) {
99
+ if (typeof this.data[i][j][0] === 'string') {
100
+ this.data[i][j][0] = parseFloat(this.data[i][j][0]);
101
+ }
102
+
103
+ if (typeof this.data[i][j][1] === 'string') {
104
+ this.data[i][j][1] = parseFloat(this.data[i][j][1]);
105
+ }
106
+ }
107
+ }
108
+
109
+
110
+ this.properties =
111
+ {
112
+ 'chart.background.color': 'transparent',
113
+ 'chart.background.grid': true,
114
+ 'chart.background.grid.diagonals': true,
115
+ 'chart.background.grid.diagonals.count': null,
116
+ 'chart.background.grid.radials': true,
117
+ 'chart.background.grid.radials.count': null,
118
+ 'chart.background.grid.linewidth': 1,
119
+ 'chart.background.grid.color': '#ccc',
120
+ 'chart.radius': null,
121
+ 'chart.colors': [], // This is used internally for the key
122
+ 'chart.colors.default': 'black',
123
+ 'chart.gutter.left': 25,
124
+ 'chart.gutter.right': 25,
125
+ 'chart.gutter.top': 25,
126
+ 'chart.gutter.bottom': 25,
127
+ 'chart.title': '',
128
+ 'chart.title.background': null,
129
+ 'chart.title.hpos': null,
130
+ 'chart.title.vpos': null,
131
+ 'chart.title.bold': true,
132
+ 'chart.title.font': null,
133
+ 'chart.title.x': null,
134
+ 'chart.title.y': null,
135
+ 'chart.title.halign': null,
136
+ 'chart.title.valign': null,
137
+ 'chart.labels': null,
138
+ 'chart.labels.color': null,
139
+ 'chart.labels.axes': 'nsew',
140
+ 'chart.labels.axes.background': 'rgba(255,255,255,0.8)',
141
+ 'chart.labels.count': 5,
142
+ 'chart.text.color': 'black',
143
+ 'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
144
+ 'chart.text.size': 12,
145
+ 'chart.text.accessible': true,
146
+ 'chart.text.accessible.overflow': 'visible',
147
+ 'chart.text.accessible.pointerevents': true,
148
+ 'chart.key': null,
149
+ 'chart.key.background': 'white',
150
+ 'chart.key.position': 'graph',
151
+ 'chart.key.halign': 'right',
152
+ 'chart.key.shadow': false,
153
+ 'chart.key.shadow.color': '#666',
154
+ 'chart.key.shadow.blur': 3,
155
+ 'chart.key.shadow.offsetx': 2,
156
+ 'chart.key.shadow.offsety': 2,
157
+ 'chart.key.position.gutter.boxed':false,
158
+ 'chart.key.position.x': null,
159
+ 'chart.key.position.y': null,
160
+ 'chart.key.color.shape': 'square',
161
+ 'chart.key.rounded': true,
162
+ 'chart.key.linewidth': 1,
163
+ 'chart.key.colors': null,
164
+ 'chart.key.interactive': false,
165
+ 'chart.key.interactive.highlight.chart.fill':'rgba(255,0,0,0.9)',
166
+ 'chart.key.interactive.highlight.label':'rgba(255,0,0,0.2)',
167
+ 'chart.key.text.color': 'black',
168
+ 'chart.contextmenu': null,
169
+ 'chart.tooltips': null,
170
+ 'chart.tooltips.event': 'onmousemove',
171
+ 'chart.tooltips.effect': 'fade',
172
+ 'chart.tooltips.css.class': 'RGraph_tooltip',
173
+ 'chart.tooltips.highlight': true,
174
+ 'chart.tooltips.hotspot': 3,
175
+ 'chart.tooltips.coords.page': false,
176
+ 'chart.annotatable': false,
177
+ 'chart.annotate.color': 'black',
178
+ 'chart.zoom.factor': 1.5,
179
+ 'chart.zoom.fade.in': true,
180
+ 'chart.zoom.fade.out': true,
181
+ 'chart.zoom.hdir': 'right',
182
+ 'chart.zoom.vdir': 'down',
183
+ 'chart.zoom.frames': 25,
184
+ 'chart.zoom.delay': 16.666,
185
+ 'chart.zoom.shadow': true,
186
+ 'chart.zoom.background': true,
187
+ 'chart.zoom.action': 'zoom',
188
+ 'chart.resizable': false,
189
+ 'chart.resize.handle.background': null,
190
+ 'chart.ymax': null,
191
+ 'chart.ymin': 0,
192
+ 'chart.tickmarks': 'cross',
193
+ 'chart.ticksize': 3,
194
+ 'chart.scale.decimals': null,
195
+ 'chart.scale.point': '.',
196
+ 'chart.scale.thousand': ',',
197
+ 'chart.scale.round': false,
198
+ 'chart.scale.zerostart': true,
199
+ 'chart.units.pre': '',
200
+ 'chart.units.post': '',
201
+ 'chart.events.mousemove': null,
202
+ 'chart.events.click': null,
203
+ 'chart.highlight.stroke': 'transparent',
204
+ 'chart.highlight.fill': 'rgba(255,255,255,0.7)',
205
+ 'chart.highlight.point.radius': 3,
206
+ 'chart.axes.color': 'black',
207
+ 'chart.axes.numticks': null,
208
+ 'chart.axes.caps': true,
209
+ 'chart.segment.highlight': false,
210
+ 'chart.segment.highlight.count': null,
211
+ 'chart.segment.highlight.fill': 'rgba(0,255,0,0.5)',
212
+ 'chart.segment.highlight.stroke':'rgba(0,0,0,0)',
213
+ 'chart.line': false,
214
+ 'chart.line.close': false,
215
+ 'chart.line.linewidth': 1,
216
+ 'chart.line.colors': ['black'],
217
+ 'chart.line.shadow': false,
218
+ 'chart.line.shadow.color': 'black',
219
+ 'chart.line.shadow.blur': 2,
220
+ 'chart.line.shadow.offsetx': 3,
221
+ 'chart.line.shadow.offsety': 3,
222
+ 'chart.clearto': 'rgba(0,0,0,0)'
223
+ }
224
+
225
+
226
+
227
+
228
+ /**
229
+ * Create the $ objects so that functions can be added to them
230
+ */
231
+
232
+ for (var i=0,idx=0; i<this.data.length; ++i) {
233
+ for (var j=0,len=this.data[i].length; j<len; j+=1,idx+=1) {
234
+ this['$' + idx] = {}
235
+ }
236
+ }
237
+
238
+
239
+
240
+
241
+
242
+ /**
243
+ * Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
244
+ * done already
245
+ */
246
+ if (!this.canvas.__rgraph_aa_translated__) {
247
+ this.context.translate(0.5,0.5);
248
+
249
+ this.canvas.__rgraph_aa_translated__ = true;
250
+ }
251
+
252
+
253
+
254
+ // Short variable names
255
+ var RG = RGraph,
256
+ ca = this.canvas,
257
+ co = ca.getContext('2d'),
258
+ prop = this.properties,
259
+ pa2 = RG.path2,
260
+ win = window,
261
+ doc = document,
262
+ ma = Math
263
+
264
+
265
+
266
+ /**
267
+ * "Decorate" the object with the generic effects if the effects library has been included
268
+ */
269
+ if (RG.Effects && typeof RG.Effects.decorate === 'function') {
270
+ RG.Effects.decorate(this);
271
+ }
272
+
273
+
274
+
275
+
276
+ /**
277
+ * A simple setter
278
+ *
279
+ * @param string name The name of the property to set
280
+ * @param string value The value of the property
281
+ */
282
+ this.set =
283
+ this.Set = function (name, value)
284
+ {
285
+ var value = typeof arguments[1] === 'undefined' ? null : arguments[1];
286
+
287
+ /**
288
+ * the number of arguments is only one and it's an
289
+ * object - parse it for configuration data and return.
290
+ */
291
+ if (arguments.length === 1 && typeof name === 'object') {
292
+ RG.parseObjectStyleConfig(this, name);
293
+ return this;
294
+ }
295
+
296
+
297
+
298
+ /**
299
+ * This should be done first - prepend the property name with "chart." if necessary
300
+ */
301
+ if (name.substr(0,6) != 'chart.') {
302
+ name = 'chart.' + name;
303
+ }
304
+
305
+
306
+
307
+
308
+ // Convert uppercase letters to dot+lower case letter
309
+ while(name.match(/([A-Z])/)) {
310
+ name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
311
+ }
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+ //
320
+ // Change chart.segments.highlight* to chart.segment.highlight (no plural)
321
+ //
322
+ if (name === 'chart.segments.highlight') name = 'chart.segment.highlight';
323
+ if (name === 'chart.segments.highlight.count') name = 'chart.segment.highlight.count';
324
+ if (name === 'chart.segments.highlight.fill') name = 'chart.segment.highlight.fill';
325
+ if (name === 'chart.segments.highlight.stroke') name = 'chart.segment.highlight.stroke';
326
+
327
+ prop[name.toLowerCase()] = value;
328
+
329
+ return this;
330
+ };
331
+
332
+
333
+
334
+
335
+ /**
336
+ * A simple getter
337
+ *
338
+ * @param string name The name of the property to get
339
+ */
340
+ this.get =
341
+ this.Get = function (name)
342
+ {
343
+ /**
344
+ * This should be done first - prepend the property name with "chart." if necessary
345
+ */
346
+ if (name.substr(0,6) != 'chart.') {
347
+ name = 'chart.' + name;
348
+ }
349
+
350
+ // Convert uppercase letters to dot+lower case letter
351
+ while(name.match(/([A-Z])/)) {
352
+ name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
353
+ }
354
+
355
+ return prop[name.toLowerCase()];
356
+ };
357
+
358
+
359
+
360
+
361
+ /**
362
+ * This method draws the rose chart
363
+ */
364
+ this.draw =
365
+ this.Draw = function ()
366
+ {
367
+ /**
368
+ * Fire the onbeforedraw event
369
+ */
370
+ RG.FireCustomEvent(this, 'onbeforedraw');
371
+
372
+
373
+ /**
374
+ * This doesn't affect the chart, but is used for compatibility
375
+ */
376
+ this.gutterLeft = prop['chart.gutter.left'];
377
+ this.gutterRight = prop['chart.gutter.right'];
378
+ this.gutterTop = prop['chart.gutter.top'];
379
+ this.gutterBottom = prop['chart.gutter.bottom'];
380
+
381
+ // Calculate the radius
382
+ this.radius = (Math.min(ca.width - this.gutterLeft - this.gutterRight, ca.height - this.gutterTop - this.gutterBottom) / 2);
383
+ this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
384
+ this.centery = ((ca.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop;
385
+ this.coords = [];
386
+ this.coords2 = [];
387
+
388
+
389
+
390
+ /**
391
+ * Stop this growing uncontrollably
392
+ */
393
+ this.coordsText = [];
394
+
395
+
396
+
397
+
398
+ /**
399
+ * If there's a user specified radius/centerx/centery, use them
400
+ */
401
+ if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
402
+ if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
403
+ if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
404
+
405
+
406
+
407
+ /**
408
+ * Parse the colors for gradients. Its down here so that the center X/Y can be used
409
+ */
410
+ if (!this.colorsParsed) {
411
+
412
+ this.parseColors();
413
+
414
+ // Don't want to do this again
415
+ this.colorsParsed = true;
416
+ }
417
+
418
+
419
+ /**
420
+ * Work out the scale
421
+ */
422
+ var max = prop['chart.ymax'];
423
+ var min = prop['chart.ymin'];
424
+
425
+ if (typeof(max) == 'number') {
426
+ this.max = max;
427
+ this.scale2 = RG.getScale2(this, {
428
+ 'max':max,
429
+ 'min':min,
430
+ 'strict':true,
431
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
432
+ 'scale.point':prop['chart.scale.point'],
433
+ 'scale.thousand':prop['chart.scale.thousand'],
434
+ 'scale.round':prop['chart.scale.round'],
435
+ 'units.pre':prop['chart.units.pre'],
436
+ 'units.post':prop['chart.units.post'],
437
+ 'ylabels.count':prop['chart.labels.count']
438
+ });
439
+ } else {
440
+
441
+ for (var i=0; i<this.data.length; i+=1) {
442
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
443
+ this.max = Math.max(this.max, this.data[i][j][1]);
444
+ }
445
+ }
446
+
447
+ this.min = prop['chart.ymin'];
448
+
449
+ this.scale2 = RG.getScale2(this, {
450
+ 'max':this.max,
451
+ 'min':min,
452
+ 'scale.decimals':Number(prop['chart.scale.decimals']),
453
+ 'scale.point':prop['chart.scale.point'],
454
+ 'scale.thousand':prop['chart.scale.thousand'],
455
+ 'scale.round':prop['chart.scale.round'],
456
+ 'units.pre':prop['chart.units.pre'],
457
+ 'units.post':prop['chart.units.post'],
458
+ 'ylabels.count':prop['chart.labels.count']
459
+ });
460
+ this.max = this.scale2.max;
461
+ }
462
+
463
+ /**
464
+ * Change the centerx marginally if the key is defined
465
+ */
466
+ if (prop['chart.key'] && prop['chart.key'].length > 0 && prop['chart.key'].length >= 3) {
467
+ this.centerx = this.centerx - prop['chart.gutter.right'] + 5;
468
+ }
469
+
470
+ /**
471
+ * Populate the colors array for the purposes of generating the key
472
+ */
473
+ if (typeof(prop['chart.key']) == 'object' && RG.is_array(prop['chart.key']) && prop['chart.key'][0]) {
474
+
475
+ // Reset the colors array
476
+ prop['chart.colors'] = [];
477
+
478
+ for (var i=0; i<this.data.length; i+=1) {
479
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
480
+ if (typeof this.data[i][j][2] == 'string') {
481
+ prop['chart.colors'].push(this.data[i][j][2]);
482
+ }
483
+ }
484
+ }
485
+ }
486
+
487
+
488
+
489
+
490
+ /**
491
+ * Populate the chart.tooltips array
492
+ */
493
+ this.Set('chart.tooltips', []);
494
+
495
+ for (var i=0; i<this.data.length; i+=1) {
496
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
497
+ if (typeof this.data[i][j][3] == 'string') {
498
+ prop['chart.tooltips'].push(this.data[i][j][3]);
499
+ }
500
+ }
501
+ }
502
+
503
+
504
+
505
+ // This resets the chart drawing state
506
+ co.beginPath();
507
+
508
+ this.DrawBackground();
509
+ this.DrawRscatter();
510
+ this.DrawLabels();
511
+
512
+ /**
513
+ * Setup the context menu if required
514
+ */
515
+ if (prop['chart.contextmenu']) {
516
+ RG.ShowContext(this);
517
+ }
518
+
519
+
520
+
521
+ // Draw the title if any has been set
522
+ if (prop['chart.title']) {
523
+ RG.DrawTitle(
524
+ this,
525
+ prop['chart.title'],
526
+ this.centery - this.radius - 10,
527
+ this.centerx,
528
+ prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2
529
+ );
530
+ }
531
+
532
+
533
+ /**
534
+ * This function enables resizing
535
+ */
536
+ if (prop['chart.resizable']) {
537
+ RG.AllowResizing(this);
538
+ }
539
+
540
+
541
+ /**
542
+ * This installs the event listeners
543
+ */
544
+ RG.InstallEventListeners(this);
545
+
546
+
547
+
548
+
549
+
550
+
551
+ //
552
+ // Allow the segments to be highlighted
553
+ //
554
+ if (prop['chart.segment.highlight']) {
555
+ RG.allowSegmentHighlight({
556
+ object: this,
557
+
558
+ // This is duplicated in the drawBackground function
559
+ count: typeof prop['chart.segment.highlight.count'] === 'number' ? prop['chart.segment.highlight.count'] : ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8))),
560
+
561
+ fill: prop['chart.segment.highlight.fill'],
562
+ stroke: prop['chart.segment.highlight.stroke']
563
+ });
564
+ }
565
+
566
+
567
+
568
+
569
+ /**
570
+ * Fire the onfirstdraw event
571
+ */
572
+ if (this.firstDraw) {
573
+ RG.fireCustomEvent(this, 'onfirstdraw');
574
+ this.firstDraw = false;
575
+ this.firstDrawFunc();
576
+ }
577
+
578
+
579
+
580
+
581
+ /**
582
+ * Fire the RGraph ondraw event
583
+ */
584
+ RG.FireCustomEvent(this, 'ondraw');
585
+
586
+
587
+
588
+
589
+ return this;
590
+ };
591
+
592
+
593
+
594
+
595
+ /**
596
+ * This method draws the rscatter charts background
597
+ */
598
+ this.drawBackground =
599
+ this.DrawBackground = function ()
600
+ {
601
+ //
602
+ // Draw the background color first
603
+ //
604
+ if (prop['chart.background.color'] != 'transparent') {
605
+ pa2(co, ['b','a', this.centerx, this.centery, this.radius, 0, 2 * ma.PI, -1, 'f', prop['chart.background.color']]);
606
+ }
607
+
608
+
609
+ var gridEnabled = prop['chart.background.grid'];
610
+
611
+
612
+ if (gridEnabled) {
613
+ co.lineWidth = prop['chart.background.grid.linewidth'];
614
+
615
+
616
+
617
+ // Draw the background grey circles
618
+ if (prop['chart.background.grid.radials']) {
619
+
620
+ co.strokeStyle = prop['chart.background.grid.color'];
621
+
622
+ if (RG.isNull(prop['chart.background.grid.radials.count'])) {
623
+ prop['chart.background.grid.radials.count'] = prop['chart.labels.count'];
624
+ }
625
+
626
+ // Radius must be greater than 0 for Opera to work
627
+
628
+ var r = this.radius / prop['chart.background.grid.radials.count'];
629
+
630
+ for (var i=0,len=this.radius; i<=len; i+=r) {
631
+
632
+ // Radius must be greater than 0 for Opera to work
633
+ co.arc(this.centerx, this.centery, i, 0, RG.TWOPI, 0);
634
+ }
635
+ co.stroke();
636
+ }
637
+
638
+
639
+
640
+
641
+
642
+
643
+
644
+ // Draw the background lines that go from the center outwards
645
+ if (prop['chart.background.grid.diagonals']) {
646
+
647
+ co.strokeStyle = prop['chart.background.grid.color'];
648
+
649
+ co.beginPath();
650
+
651
+ // This is duplicated in the allowSegmentHighlight call
652
+ var inc = 360 / ((prop['chart.background.grid.diagonals.count'] ? prop['chart.background.grid.diagonals.count'] : (prop['chart.labels'] ? prop['chart.labels'].length : 8)));
653
+
654
+
655
+ for (var i=inc; i<360; i+=inc) {
656
+
657
+ // Radius must be greater than 0 for Opera to work
658
+ co.arc(
659
+ this.centerx,
660
+ this.centery,
661
+ this.radius,
662
+ (i / (180 / RG.PI)) - RG.HALFPI,
663
+ ((i + 0.01) / (180 / RG.PI)) - RG.HALFPI,
664
+ 0
665
+ );
666
+
667
+ co.lineTo(this.centerx, this.centery);
668
+ }
669
+ co.stroke();
670
+ }
671
+ }
672
+
673
+ // Reset the linewidth
674
+ co.lineWidth = 1;
675
+
676
+
677
+
678
+
679
+
680
+
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+ co.beginPath();
689
+ co.strokeStyle = prop['chart.axes.color'];
690
+
691
+ // Draw the X axis
692
+ co.moveTo(this.centerx - this.radius, Math.round(this.centery));
693
+ co.lineTo(this.centerx + this.radius, Math.round(this.centery));
694
+
695
+ // Draw the X ends
696
+ if (prop['chart.axes.caps']) {
697
+ co.moveTo(ma.round(this.centerx - this.radius), this.centery - 5);
698
+ co.lineTo(ma.round(this.centerx - this.radius), this.centery + 5);
699
+ co.moveTo(ma.round(this.centerx + this.radius), this.centery - 5);
700
+ co.lineTo(ma.round(this.centerx + this.radius), this.centery + 5);
701
+ }
702
+
703
+
704
+
705
+ if (!RG.isNull(prop['chart.axes.numticks'])) {
706
+ var numticks = prop['chart.axes.numticks']
707
+ } else {
708
+ var numticks = prop['chart.labels.count'];
709
+ }
710
+
711
+ var caps = prop['chart.axes.caps'];
712
+
713
+ if (numticks) {
714
+ // Draw the X check marks
715
+ for (var i=(this.centerx - this.radius); i<(this.centerx + this.radius); i+=(this.radius / numticks)) {
716
+ co.moveTo(ma.round(i), this.centery - 3);
717
+ co.lineTo(ma.round(i), this.centery + 3);
718
+ }
719
+
720
+ // Draw the Y check marks
721
+ for (var i=(this.centery - this.radius); i<(this.centery + this.radius); i+=(this.radius / numticks)) {
722
+ co.moveTo(this.centerx - 3, ma.round(i));
723
+ co.lineTo(this.centerx + 3, ma.round(i));
724
+ }
725
+ }
726
+
727
+ // Draw the Y axis
728
+ co.moveTo(ma.round(this.centerx), this.centery - this.radius);
729
+ co.lineTo(ma.round(this.centerx), this.centery + this.radius);
730
+
731
+ // Draw the Y ends
732
+ if (prop['chart.axes.caps']) {
733
+ co.moveTo(this.centerx - 5, ma.round(this.centery - this.radius));
734
+ co.lineTo(this.centerx + 5, ma.round(this.centery - this.radius));
735
+
736
+ co.moveTo(this.centerx - 5, ma.round(this.centery + this.radius));
737
+ co.lineTo(this.centerx + 5, ma.round(this.centery + this.radius));
738
+ }
739
+
740
+ // Stroke it
741
+ co.closePath();
742
+ co.stroke();
743
+ };
744
+
745
+
746
+
747
+
748
+ /**
749
+ * This method draws a set of data on the graph
750
+ */
751
+ this.drawRscatter =
752
+ this.DrawRscatter = function ()
753
+ {
754
+ for (var dataset=0; dataset<this.data.length; dataset+=1) {
755
+
756
+ var data = this.data[dataset];
757
+
758
+ // Don't do this
759
+ // this.coords = [];
760
+
761
+ this.coords2[dataset] = [];
762
+
763
+ var drawPoints = function (obj)
764
+ {
765
+ for (var i=0; i<data.length; ++i) {
766
+
767
+ var d1 = data[i][0],
768
+ d2 = data[i][1],
769
+ a = d1 / (180 / RG.PI), // RADIANS
770
+ r = ( (d2 - prop['chart.ymin']) / (obj.scale2.max - obj.scale2.min) ) * obj.radius,
771
+ x = ma.sin(a) * r,
772
+ y = ma.cos(a) * r,
773
+ color = data[i][2] ? data[i][2] : prop['chart.colors.default'],
774
+ tooltip = data[i][3] ? data[i][3] : null
775
+
776
+ if (tooltip && String(tooltip).length) {
777
+ obj.hasTooltips = true;
778
+ }
779
+
780
+ /**
781
+ * Account for the correct quadrant
782
+ */
783
+ x = x + obj.centerx;
784
+ y = obj.centery - y;
785
+
786
+
787
+ obj.drawTick(x, y, color);
788
+
789
+ // Populate the coords array with the coordinates and the tooltip
790
+
791
+ obj.coords.push([x, y, color, tooltip]);
792
+ obj.coords2[dataset].push([x, y, color, tooltip]);
793
+ }
794
+ }
795
+
796
+ drawPoints(this);
797
+
798
+ if (prop['chart.line']) {
799
+ this.drawLine(dataset);
800
+ }
801
+
802
+ // Causes tooltips not to appear sometimes on this demo page:
803
+ // /demos/rscatter-multiple-datasets-single-array.html
804
+ //
805
+ //drawPoints(this);
806
+ }
807
+ };
808
+
809
+
810
+
811
+
812
+ /*
813
+ * Draws a connecting line through the points if requested
814
+ *
815
+ * @param object opt The options to the line
816
+ */
817
+ this.drawLine = function (idx)
818
+ {
819
+ var opt = {
820
+ dataset: idx,
821
+ coords: this.coords2[idx],
822
+ color: prop['chart.line.colors'][idx],
823
+ shadow: prop['chart.line.shadow'],
824
+ shadowColor: prop['chart.line.shadow.color'],
825
+ shadowOffsetX: prop['chart.line.shadow.offsetx'],
826
+ shadowOffsetY: prop['chart.line.shadow.offsety'],
827
+ shadowBlur: prop['chart.line.shadow.blur'],
828
+ linewidth: prop['chart.line.linewidth']
829
+ };
830
+
831
+ co.beginPath();
832
+
833
+ co.strokeStyle = this.parseSingleColorForGradient(opt.color);
834
+ co.lineWidth = typeof prop['chart.line.linewidth'] === 'object' ? prop['chart.line.linewidth'][idx] : prop['chart.line.linewidth'];
835
+ co.lineCap = 'round';
836
+
837
+ if (opt.shadow) {
838
+ RG.setShadow(
839
+ this,
840
+ opt.shadowColor,
841
+ opt.shadowOffsetX,
842
+ opt.shadowOffsetY,
843
+ opt.shadowBlur
844
+ );
845
+ }
846
+
847
+ for (var i=0; i<this.coords2[idx].length; ++i) {
848
+ if (i === 0) {
849
+ co.moveTo(this.coords2[idx][i][0], this.coords2[idx][i][1]);
850
+
851
+ var startCoords = RG.arrayClone(this.coords2[idx]);
852
+
853
+ } else {
854
+ co.lineTo(this.coords2[idx][i][0], this.coords2[idx][i][1]);
855
+ }
856
+ }
857
+
858
+ // Draw the line back to the start?
859
+ if (
860
+ (typeof prop['chart.line.close'] === 'boolean' && prop['chart.line.close'])
861
+ || (typeof prop['chart.line.close'] === 'object' && prop['chart.line.close'][idx])
862
+ ) {
863
+ co.lineTo(this.coords2[idx][0][0], this.coords2[idx][0][1]);
864
+ }
865
+
866
+ co.stroke();
867
+
868
+ RG.noShadow(this);
869
+ };
870
+
871
+
872
+
873
+
874
+ /**
875
+ * Unsuprisingly, draws the labels
876
+ */
877
+ this.drawLabels =
878
+ this.DrawLabels = function ()
879
+ {
880
+ co.lineWidth = 1;
881
+
882
+ // Default the color to black
883
+ co.fillStyle = 'black';
884
+ co.strokeStyle = 'black';
885
+
886
+ var key = prop['chart.key'];
887
+ var r = this.radius;
888
+ var axesColor = prop['chart.axes.color'];
889
+ var color = prop['chart.text.color'];
890
+ var font = prop['chart.text.font'];
891
+ var size = prop['chart.text.size'];
892
+ var axes = prop['chart.labels.axes'].toLowerCase();
893
+ var units_pre = prop['chart.units.pre'];
894
+ var units_post = prop['chart.units.post'];
895
+ var decimals = prop['chart.scale.decimals'];
896
+ var centerx = this.centerx;
897
+ var centery = this.centery;
898
+
899
+ co.fillStyle = prop['chart.text.color'];
900
+
901
+ // Draw any labels
902
+ if (typeof prop['chart.labels'] == 'object' && prop['chart.labels']) {
903
+ this.DrawCircularLabels(co, prop['chart.labels'], font , size, r);
904
+ }
905
+
906
+
907
+ //
908
+ // If the axes are transparent - then the labels should have no offset,
909
+ // otherwise it defaults to true. Similarly the labels can or can't be
910
+ // centered if there's no axes
911
+ //
912
+ var offset = 10;
913
+ var centered = false;
914
+
915
+ if ( axesColor === 'rgba(0,0,0,0)'
916
+ || axesColor === 'rgb(0,0,0)'
917
+ || axesColor === 'transparent') {
918
+
919
+ offset = 0;
920
+ centered = true;
921
+ }
922
+
923
+ // Draw the axis labels
924
+ for (var i=0,len=this.scale2.labels.length; i<len; ++i) {
925
+ if (axes.indexOf('n') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery - (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
926
+ if (axes.indexOf('s') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - offset,'y':centery + (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':centered ? 'center' : 'right',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
927
+ if (axes.indexOf('e') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx + (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
928
+ if (axes.indexOf('w') > -1) RG.text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - (r * ((i+1) / len)),'y':centery + offset,'text':this.scale2.labels[i],'valign':centered ? 'center' : 'top','halign':'center',bounding: true, boundingFill: prop['chart.labels.axes.background'], boundingStroke: 'rgba(0,0,0,0)'});
929
+ }
930
+
931
+ // Draw the center minimum value (but only if there's at least one axes labels stipulated)
932
+ if (prop['chart.labels.axes'].length > 0 && prop['chart.scale.zerostart']) {
933
+ RG.text2(this, {
934
+ 'font':font,
935
+ 'size':size,
936
+ 'x':centerx,
937
+ 'y':centery,
938
+ 'text':RG.numberFormat(this, Number(this.scale2.min).toFixed(this.scale2.decimals), this.scale2.units_pre, this.scale2.units_post),
939
+ 'valign':'center',
940
+ 'halign':'center',
941
+ 'bounding':true,
942
+ 'boundingFill': prop['chart.labels.axes.background'],
943
+ 'boundingStroke': 'rgba(0,0,0,0)',
944
+ 'tag': 'scale'
945
+ });
946
+ }
947
+
948
+ /**
949
+ * Draw the key
950
+ */
951
+ if (key && key.length) {
952
+ RG.drawKey(this, key, prop['chart.colors']);
953
+ }
954
+ };
955
+
956
+
957
+
958
+
959
+ /**
960
+ * Draws the circular labels that go around the charts
961
+ *
962
+ * @param labels array The labels that go around the chart
963
+ */
964
+ this.drawCircularLabels =
965
+ this.DrawCircularLabels = function (context, labels, font_face, font_size, r)
966
+ {
967
+ var r = r + 10,
968
+ color = prop['chart.labels.color'];
969
+
970
+ for (var i=0; i<labels.length; ++i) {
971
+
972
+ var a = (360 / labels.length) * (i + 1) - (360 / (labels.length * 2));
973
+ var a = a - 90 + (prop['chart.labels.position'] == 'edge' ? ((360 / labels.length) / 2) : 0);
974
+
975
+ var x = ma.cos(a / (180/RG.PI) ) * r;
976
+ var y = ma.sin(a / (180/RG.PI)) * r;
977
+
978
+ RG.Text2(this, {
979
+ 'color': color,
980
+ 'font':font_face,
981
+ 'size':font_size,
982
+ 'x':this.centerx + x,
983
+ 'y':this.centery + y,
984
+ 'text':String(labels[i]),
985
+ 'valign':'center',
986
+ 'halign':( (this.centerx + x) > this.centerx) ? 'left' : 'right',
987
+ 'tag': 'labels'
988
+ });
989
+ }
990
+ };
991
+
992
+
993
+
994
+
995
+ /**
996
+ * Draws a single tickmark
997
+ */
998
+ this.drawTick =
999
+ this.DrawTick = function (x, y, color)
1000
+ {
1001
+ var tickmarks = prop['chart.tickmarks'];
1002
+ var ticksize = prop['chart.ticksize'];
1003
+
1004
+ co.strokeStyle = color;
1005
+ co.fillStyle = color;
1006
+
1007
+ // Set the linewidth for the tickmark to 1
1008
+ var prevLinewidth = co.lineWidth;
1009
+ co.lineWidth = 1;
1010
+
1011
+ // Cross
1012
+ if (tickmarks == 'cross') {
1013
+
1014
+ co.beginPath();
1015
+ co.moveTo(x + ticksize, y + ticksize);
1016
+ co.lineTo(x - ticksize, y - ticksize);
1017
+ co.stroke();
1018
+
1019
+ co.beginPath();
1020
+ co.moveTo(x - ticksize, y + ticksize);
1021
+ co.lineTo(x + ticksize, y - ticksize);
1022
+ co.stroke();
1023
+
1024
+ // Circle
1025
+ } else if (tickmarks == 'circle') {
1026
+
1027
+ co.beginPath();
1028
+ co.arc(x, y, ticksize, 0, 6.2830, false);
1029
+ co.fill();
1030
+
1031
+ // Square
1032
+ } else if (tickmarks == 'square') {
1033
+
1034
+ co.beginPath();
1035
+ co.fillRect(x - ticksize, y - ticksize, 2 * ticksize, 2 * ticksize);
1036
+ co.fill();
1037
+
1038
+ // Diamond shape tickmarks
1039
+ } else if (tickmarks == 'diamond') {
1040
+
1041
+ co.beginPath();
1042
+ co.moveTo(x, y - ticksize);
1043
+ co.lineTo(x + ticksize, y);
1044
+ co.lineTo(x, y + ticksize);
1045
+ co.lineTo(x - ticksize, y);
1046
+ co.closePath();
1047
+ co.fill();
1048
+
1049
+ // Plus style tickmarks
1050
+ } else if (tickmarks == 'plus') {
1051
+
1052
+ co.lineWidth = 1;
1053
+
1054
+ co.beginPath();
1055
+ co.moveTo(x, y - ticksize);
1056
+ co.lineTo(x, y + ticksize);
1057
+ co.moveTo(x - ticksize, y);
1058
+ co.lineTo(x + ticksize, y);
1059
+ co.stroke();
1060
+ }
1061
+
1062
+
1063
+ co.lineWidth = prevLinewidth;
1064
+ };
1065
+
1066
+
1067
+
1068
+
1069
+ /**
1070
+ * This function makes it much easier to get the (if any) point that is currently being hovered over.
1071
+ *
1072
+ * @param object e The event object
1073
+ */
1074
+ this.getShape =
1075
+ this.getPoint = function (e)
1076
+ {
1077
+ var mouseXY = RG.getMouseXY(e);
1078
+ var mouseX = mouseXY[0];
1079
+ var mouseY = mouseXY[1];
1080
+ var overHotspot = false;
1081
+ var offset = prop['chart.tooltips.hotspot']; // This is how far the hotspot extends
1082
+
1083
+ for (var i=0,len=this.coords.length; i<len; ++i) {
1084
+
1085
+ var x = this.coords[i][0];
1086
+ var y = this.coords[i][1];
1087
+ var tooltip = this.coords[i][3];
1088
+
1089
+ if (
1090
+ mouseX < (x + offset) &&
1091
+ mouseX > (x - offset) &&
1092
+ mouseY < (y + offset) &&
1093
+ mouseY > (y - offset)
1094
+ ) {
1095
+
1096
+ var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i);
1097
+
1098
+ return {0:this,1:x,2:y,3:i,'object':this, 'x':x, 'y':y, 'index':i, 'tooltip': tooltip};
1099
+ }
1100
+ }
1101
+ };
1102
+
1103
+
1104
+
1105
+
1106
+ /**
1107
+ * This function facilitates the installation of tooltip event listeners if
1108
+ * tooltips are defined.
1109
+ */
1110
+ this.allowTooltips =
1111
+ this.AllowTooltips = function ()
1112
+ {
1113
+ // Preload any tooltip images that are used in the tooltips
1114
+ RG.PreLoadTooltipImages(this);
1115
+
1116
+
1117
+ /**
1118
+ * This installs the window mousedown event listener that lears any
1119
+ * highlight that may be visible.
1120
+ */
1121
+ RG.InstallWindowMousedownTooltipListener(this);
1122
+
1123
+
1124
+ /**
1125
+ * This installs the canvas mousemove event listener. This function
1126
+ * controls the pointer shape.
1127
+ */
1128
+ RG.InstallCanvasMousemoveTooltipListener(this);
1129
+
1130
+
1131
+ /**
1132
+ * This installs the canvas mouseup event listener. This is the
1133
+ * function that actually shows the appropriate tooltip (if any).
1134
+ */
1135
+ RG.InstallCanvasMouseupTooltipListener(this);
1136
+ };
1137
+
1138
+
1139
+
1140
+
1141
+ /**
1142
+ * Each object type has its own Highlight() function which highlights the appropriate shape
1143
+ *
1144
+ * @param object shape The shape to highlight
1145
+ */
1146
+ this.highlight =
1147
+ this.Highlight = function (shape)
1148
+ {
1149
+ if (typeof prop['chart.highlight.style'] === 'function') {
1150
+ (prop['chart.highlight.style'])(shape);
1151
+ } else {
1152
+ RG.Highlight.Point(this, shape);
1153
+ }
1154
+ };
1155
+
1156
+
1157
+
1158
+
1159
+ /**
1160
+ * The getObjectByXY() worker method. Don't call this call:
1161
+ *
1162
+ * RGraph.ObjectRegistry.getObjectByXY(e)
1163
+ *
1164
+ * @param object e The event object
1165
+ */
1166
+ this.getObjectByXY = function (e)
1167
+ {
1168
+ var mouseXY = RG.getMouseXY(e);
1169
+ var mouseX = mouseXY[0];
1170
+ var mouseY = mouseXY[1];
1171
+ var centerx = this.centerx;
1172
+ var centery = this.centery;
1173
+ var radius = this.radius;
1174
+
1175
+ if (
1176
+ mouseX > (centerx - radius)
1177
+ && mouseX < (centerx + radius)
1178
+ && mouseY > (centery - radius)
1179
+ && mouseY < (centery + radius)
1180
+ ) {
1181
+
1182
+ return this;
1183
+ }
1184
+ };
1185
+
1186
+
1187
+
1188
+
1189
+ /**
1190
+ * This function positions a tooltip when it is displayed
1191
+ *
1192
+ * @param obj object The chart object
1193
+ * @param int x The X coordinate specified for the tooltip
1194
+ * @param int y The Y coordinate specified for the tooltip
1195
+ * @param objec tooltip The tooltips DIV element
1196
+ *
1197
+ this.positionTooltip = function (obj, x, y, tooltip, idx)
1198
+ {
1199
+ var coordX = obj.coords[tooltip.__index__][0];
1200
+ var coordY = obj.coords[tooltip.__index__][1];
1201
+ var canvasXY = RG.getCanvasXY(obj.canvas);
1202
+ var mouseXY = RG.getMouseXY(window.event);
1203
+ var gutterLeft = obj.gutterLeft;
1204
+ var gutterTop = obj.gutterTop;
1205
+ var width = tooltip.offsetWidth;
1206
+ var height = tooltip.offsetHeight;
1207
+
1208
+ // Set the top position
1209
+ tooltip.style.left = 0;
1210
+ tooltip.style.top = window.event.pageY - height - 5 + 'px';
1211
+
1212
+ // By default any overflow is hidden
1213
+ tooltip.style.overflow = '';
1214
+
1215
+ // Reposition the tooltip if at the edges:
1216
+
1217
+ // LEFT edge
1218
+ if (canvasXY[0] + mouseXY[0] - (width / 2) < 0) {
1219
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.1) + 'px';
1220
+
1221
+ // RIGHT edge
1222
+ } else if (canvasXY[0] + mouseXY[0] + (width / 2) > doc.body.offsetWidth) {
1223
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width * 0.9) + 'px';
1224
+
1225
+ // Default positioning - CENTERED
1226
+ } else {
1227
+ tooltip.style.left = canvasXY[0] + mouseXY[0] - (width / 2) + 'px';
1228
+ }
1229
+ };*/
1230
+
1231
+
1232
+
1233
+
1234
+ /**
1235
+ * This function returns the radius (ie the distance from the center) for a particular
1236
+ * value.
1237
+ *
1238
+ * @param number value The value you want the radius for
1239
+ */
1240
+ this.getRadius = function (value)
1241
+ {
1242
+ var max = this.max;
1243
+
1244
+ if (value < 0 || value > max) {
1245
+ return null;
1246
+ }
1247
+
1248
+ var r = (value / max) * this.radius;
1249
+
1250
+ return r;
1251
+ };
1252
+
1253
+
1254
+
1255
+
1256
+ /**
1257
+ * This allows for easy specification of gradients
1258
+ */
1259
+ this.parseColors = function ()
1260
+ {
1261
+ // Save the original colors so that they can be restored when the canvas is reset
1262
+ if (this.original_colors.length === 0) {
1263
+ this.original_colors['data'] = RG.array_clone(this.data);
1264
+ this.original_colors['chart.highlight.stroke'] = RG.arrayClone(prop['chart.highlight.stroke']);
1265
+ this.original_colors['chart.highlight.fill'] = RG.arrayClone(prop['chart.highlight.fill']);
1266
+ this.original_colors['chart.colors.default'] = RG.arrayClone(prop['chart.colors.default']);
1267
+ this.original_colors['chart.background.grid.color'] = RG.arrayClone(prop['chart.background.grid.color']);
1268
+ this.original_colors['chart.background.color'] = RG.arrayClone(prop['chart.background.color']);
1269
+ this.original_colors['chart.segment.highlight.stroke'] = RG.arrayClone(prop['chart.segment.highlight.stroke']);
1270
+ this.original_colors['chart.segment.highlight.fill'] = RG.arrayClone(prop['chart.segment.highlight.fill']);
1271
+ }
1272
+
1273
+
1274
+
1275
+
1276
+
1277
+
1278
+ // Go through the data
1279
+ for (var i=0; i<this.data.length; i+=1) {
1280
+ for (var j=0,len=this.data[i].length; j<len; j+=1) {
1281
+ this.data[i][j][2] = this.parseSingleColorForGradient(this.data[i][j][2]);
1282
+ }
1283
+ }
1284
+
1285
+ prop['chart.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.highlight.stroke']);
1286
+ prop['chart.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.highlight.fill']);
1287
+ prop['chart.colors.default'] = this.parseSingleColorForGradient(prop['chart.colors.default']);
1288
+ prop['chart.background.grid.color'] = this.parseSingleColorForGradient(prop['chart.background.grid.color']);
1289
+ prop['chart.background.color'] = this.parseSingleColorForGradient(prop['chart.background.color']);
1290
+ prop['chart.segment.highlight.stroke'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.stroke']);
1291
+ prop['chart.segment.highlight.fill'] = this.parseSingleColorForGradient(prop['chart.segment.highlight.fill']);
1292
+ };
1293
+
1294
+
1295
+
1296
+
1297
+ /**
1298
+ * Use this function to reset the object to the post-constructor state. Eg reset colors if
1299
+ * need be etc
1300
+ */
1301
+ this.reset = function ()
1302
+ {
1303
+ };
1304
+
1305
+
1306
+
1307
+
1308
+ /**
1309
+ * This parses a single color value
1310
+ */
1311
+ this.parseSingleColorForGradient = function (color)
1312
+ {
1313
+ if (!color || typeof color != 'string') {
1314
+ return color;
1315
+ }
1316
+
1317
+ if (color.match(/^gradient\((.*)\)$/i)) {
1318
+
1319
+ var parts = RegExp.$1.split(':');
1320
+
1321
+ // Create the gradient
1322
+ var grad = co.createRadialGradient(this.centerx, this.centery, 0, this.centerx, this.centery, this.radius);
1323
+
1324
+ var diff = 1 / (parts.length - 1);
1325
+
1326
+ grad.addColorStop(0, RG.trim(parts[0]));
1327
+
1328
+ for (var j=1; j<parts.length; ++j) {
1329
+ grad.addColorStop(j * diff, RG.trim(parts[j]));
1330
+ }
1331
+ }
1332
+
1333
+ return grad ? grad : color;
1334
+ };
1335
+
1336
+
1337
+
1338
+
1339
+ /**
1340
+ * This function handles highlighting an entire data-series for the interactive
1341
+ * key
1342
+ *
1343
+ * @param int index The index of the data series to be highlighted
1344
+ */
1345
+ this.interactiveKeyHighlight = function (index)
1346
+ {
1347
+ if (this.coords2 && this.coords2[index] && this.coords2[index].length) {
1348
+ this.coords2[index].forEach(function (value, idx, arr)
1349
+ {
1350
+ co.beginPath();
1351
+ co.fillStyle = prop['chart.key.interactive.highlight.chart.fill'];
1352
+ co.arc(value[0], value[1], prop['chart.ticksize'] + 2, 0, RG.TWOPI, false);
1353
+ co.fill();
1354
+ });
1355
+ }
1356
+ };
1357
+
1358
+
1359
+
1360
+
1361
+ /**
1362
+ * Using a function to add events makes it easier to facilitate method chaining
1363
+ *
1364
+ * @param string type The type of even to add
1365
+ * @param function func
1366
+ */
1367
+ this.on = function (type, func)
1368
+ {
1369
+ if (type.substr(0,2) !== 'on') {
1370
+ type = 'on' + type;
1371
+ }
1372
+
1373
+ if (typeof this[type] !== 'function') {
1374
+ this[type] = func;
1375
+ } else {
1376
+ RG.addCustomEventListener(this, type, func);
1377
+ }
1378
+
1379
+ return this;
1380
+ };
1381
+
1382
+
1383
+
1384
+
1385
+ /**
1386
+ * This helps the Gantt reset colors when the reset function is called.
1387
+ * It handles going through the data and resetting the colors.
1388
+ */
1389
+ this.resetColorsToOriginalValues = function ()
1390
+ {
1391
+ /**
1392
+ * Copy the original colors over for single-event-per-line data
1393
+ */
1394
+ for (var i=0,len=this.original_colors['data'].length; i<len; ++i) {
1395
+ for (var j=0,len2=this.original_colors['data'][i].length; j<len2;++j) {
1396
+ this.data[i][j][2] = RG.array_clone(this.original_colors['data'][i][j][2]);
1397
+ }
1398
+ }
1399
+ };
1400
+
1401
+
1402
+
1403
+
1404
+ /**
1405
+ * This function runs once only
1406
+ * (put at the end of the file (before any effects))
1407
+ */
1408
+ this.firstDrawFunc = function ()
1409
+ {
1410
+ };
1411
+
1412
+
1413
+ RG.att(ca);
1414
+
1415
+
1416
+
1417
+
1418
+ /**
1419
+ * Register the object
1420
+ */
1421
+ RG.Register(this);
1422
+
1423
+
1424
+
1425
+
1426
+ /**
1427
+ * This is the 'end' of the constructor so if the first argument
1428
+ * contains configuration data - handle that.
1429
+ */
1430
+ if (parseConfObjectForOptions) {
1431
+ RG.parseObjectStyleConfig(this, conf.options);
1432
+ }
1433
+ };