Added more updates
[soho-sigint.git] / client-freqwatch / Chart.js / src / Chart.Radar.js
1 (function(){
2         "use strict";
3
4         var root = this,
5                 Chart = root.Chart,
6                 helpers = Chart.helpers;
7
8
9
10         Chart.Type.extend({
11                 name: "Radar",
12                 defaults:{
13                         //Boolean - Whether to show lines for each scale point
14                         scaleShowLine : true,
15
16                         //Boolean - Whether we show the angle lines out of the radar
17                         angleShowLineOut : true,
18
19                         //Boolean - Whether to show labels on the scale
20                         scaleShowLabels : false,
21
22                         // Boolean - Whether the scale should begin at zero
23                         scaleBeginAtZero : true,
24
25                         //String - Colour of the angle line
26                         angleLineColor : "rgba(0,0,0,.1)",
27
28                         //Number - Pixel width of the angle line
29                         angleLineWidth : 1,
30
31                         //String - Point label font declaration
32                         pointLabelFontFamily : "'Arial'",
33
34                         //String - Point label font weight
35                         pointLabelFontStyle : "normal",
36
37                         //Number - Point label font size in pixels
38                         pointLabelFontSize : 10,
39
40                         //String - Point label font colour
41                         pointLabelFontColor : "#666",
42
43                         //Boolean - Whether to show a dot for each point
44                         pointDot : true,
45
46                         //Number - Radius of each point dot in pixels
47                         pointDotRadius : 3,
48
49                         //Number - Pixel width of point dot stroke
50                         pointDotStrokeWidth : 1,
51
52                         //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
53                         pointHitDetectionRadius : 20,
54
55                         //Boolean - Whether to show a stroke for datasets
56                         datasetStroke : true,
57
58                         //Number - Pixel width of dataset stroke
59                         datasetStrokeWidth : 2,
60
61                         //Boolean - Whether to fill the dataset with a colour
62                         datasetFill : true,
63
64                         //String - A legend template
65                         legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></span></li><%}%></ul>"
66
67                 },
68
69                 initialize: function(data){
70                         this.PointClass = Chart.Point.extend({
71                                 strokeWidth : this.options.pointDotStrokeWidth,
72                                 radius : this.options.pointDotRadius,
73                                 display: this.options.pointDot,
74                                 hitDetectionRadius : this.options.pointHitDetectionRadius,
75                                 ctx : this.chart.ctx
76                         });
77
78                         this.datasets = [];
79
80                         this.buildScale(data);
81
82                         //Set up tooltip events on the chart
83                         if (this.options.showTooltips){
84                                 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
85                                         var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
86
87                                         this.eachPoints(function(point){
88                                                 point.restore(['fillColor', 'strokeColor']);
89                                         });
90                                         helpers.each(activePointsCollection, function(activePoint){
91                                                 activePoint.fillColor = activePoint.highlightFill;
92                                                 activePoint.strokeColor = activePoint.highlightStroke;
93                                         });
94
95                                         this.showTooltip(activePointsCollection);
96                                 });
97                         }
98
99                         //Iterate through each of the datasets, and build this into a property of the chart
100                         helpers.each(data.datasets,function(dataset){
101
102                                 var datasetObject = {
103                                         label: dataset.label || null,
104                                         fillColor : dataset.fillColor,
105                                         strokeColor : dataset.strokeColor,
106                                         pointColor : dataset.pointColor,
107                                         pointStrokeColor : dataset.pointStrokeColor,
108                                         points : []
109                                 };
110
111                                 this.datasets.push(datasetObject);
112
113                                 helpers.each(dataset.data,function(dataPoint,index){
114                                         //Add a new point for each piece of data, passing any required data to draw.
115                                         var pointPosition;
116                                         if (!this.scale.animation){
117                                                 pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
118                                         }
119                                         datasetObject.points.push(new this.PointClass({
120                                                 value : dataPoint,
121                                                 label : data.labels[index],
122                                                 datasetLabel: dataset.label,
123                                                 x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
124                                                 y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
125                                                 strokeColor : dataset.pointStrokeColor,
126                                                 fillColor : dataset.pointColor,
127                                                 highlightFill : dataset.pointHighlightFill || dataset.pointColor,
128                                                 highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
129                                         }));
130                                 },this);
131
132                         },this);
133
134                         this.render();
135                 },
136                 eachPoints : function(callback){
137                         helpers.each(this.datasets,function(dataset){
138                                 helpers.each(dataset.points,callback,this);
139                         },this);
140                 },
141
142                 getPointsAtEvent : function(evt){
143                         var mousePosition = helpers.getRelativePosition(evt),
144                                 fromCenter = helpers.getAngleFromPoint({
145                                         x: this.scale.xCenter,
146                                         y: this.scale.yCenter
147                                 }, mousePosition);
148
149                         var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
150                                 pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
151                                 activePointsCollection = [];
152
153                         // If we're at the top, make the pointIndex 0 to get the first of the array.
154                         if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
155                                 pointIndex = 0;
156                         }
157
158                         if (fromCenter.distance <= this.scale.drawingArea){
159                                 helpers.each(this.datasets, function(dataset){
160                                         activePointsCollection.push(dataset.points[pointIndex]);
161                                 });
162                         }
163
164                         return activePointsCollection;
165                 },
166
167                 buildScale : function(data){
168                         this.scale = new Chart.RadialScale({
169                                 display: this.options.showScale,
170                                 fontStyle: this.options.scaleFontStyle,
171                                 fontSize: this.options.scaleFontSize,
172                                 fontFamily: this.options.scaleFontFamily,
173                                 fontColor: this.options.scaleFontColor,
174                                 showLabels: this.options.scaleShowLabels,
175                                 showLabelBackdrop: this.options.scaleShowLabelBackdrop,
176                                 backdropColor: this.options.scaleBackdropColor,
177                                 backdropPaddingY : this.options.scaleBackdropPaddingY,
178                                 backdropPaddingX: this.options.scaleBackdropPaddingX,
179                                 lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
180                                 lineColor: this.options.scaleLineColor,
181                                 angleLineColor : this.options.angleLineColor,
182                                 angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
183                                 // Point labels at the edge of each line
184                                 pointLabelFontColor : this.options.pointLabelFontColor,
185                                 pointLabelFontSize : this.options.pointLabelFontSize,
186                                 pointLabelFontFamily : this.options.pointLabelFontFamily,
187                                 pointLabelFontStyle : this.options.pointLabelFontStyle,
188                                 height : this.chart.height,
189                                 width: this.chart.width,
190                                 xCenter: this.chart.width/2,
191                                 yCenter: this.chart.height/2,
192                                 ctx : this.chart.ctx,
193                                 templateString: this.options.scaleLabel,
194                                 labels: data.labels,
195                                 valuesCount: data.datasets[0].data.length
196                         });
197
198                         this.scale.setScaleSize();
199                         this.updateScaleRange(data.datasets);
200                         this.scale.buildYLabels();
201                 },
202                 updateScaleRange: function(datasets){
203                         var valuesArray = (function(){
204                                 var totalDataArray = [];
205                                 helpers.each(datasets,function(dataset){
206                                         if (dataset.data){
207                                                 totalDataArray = totalDataArray.concat(dataset.data);
208                                         }
209                                         else {
210                                                 helpers.each(dataset.points, function(point){
211                                                         totalDataArray.push(point.value);
212                                                 });
213                                         }
214                                 });
215                                 return totalDataArray;
216                         })();
217
218
219                         var scaleSizes = (this.options.scaleOverride) ?
220                                 {
221                                         steps: this.options.scaleSteps,
222                                         stepValue: this.options.scaleStepWidth,
223                                         min: this.options.scaleStartValue,
224                                         max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
225                                 } :
226                                 helpers.calculateScaleRange(
227                                         valuesArray,
228                                         helpers.min([this.chart.width, this.chart.height])/2,
229                                         this.options.scaleFontSize,
230                                         this.options.scaleBeginAtZero,
231                                         this.options.scaleIntegersOnly
232                                 );
233
234                         helpers.extend(
235                                 this.scale,
236                                 scaleSizes
237                         );
238
239                 },
240                 addData : function(valuesArray,label){
241                         //Map the values array for each of the datasets
242                         this.scale.valuesCount++;
243                         helpers.each(valuesArray,function(value,datasetIndex){
244                                 var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
245                                 this.datasets[datasetIndex].points.push(new this.PointClass({
246                                         value : value,
247                                         label : label,
248                                         datasetLabel: this.datasets[datasetIndex].label,
249                                         x: pointPosition.x,
250                                         y: pointPosition.y,
251                                         strokeColor : this.datasets[datasetIndex].pointStrokeColor,
252                                         fillColor : this.datasets[datasetIndex].pointColor
253                                 }));
254                         },this);
255
256                         this.scale.labels.push(label);
257
258                         this.reflow();
259
260                         this.update();
261                 },
262                 removeData : function(){
263                         this.scale.valuesCount--;
264                         this.scale.labels.shift();
265                         helpers.each(this.datasets,function(dataset){
266                                 dataset.points.shift();
267                         },this);
268                         this.reflow();
269                         this.update();
270                 },
271                 update : function(){
272                         this.eachPoints(function(point){
273                                 point.save();
274                         });
275                         this.reflow();
276                         this.render();
277                 },
278                 reflow: function(){
279                         helpers.extend(this.scale, {
280                                 width : this.chart.width,
281                                 height: this.chart.height,
282                                 size : helpers.min([this.chart.width, this.chart.height]),
283                                 xCenter: this.chart.width/2,
284                                 yCenter: this.chart.height/2
285                         });
286                         this.updateScaleRange(this.datasets);
287                         this.scale.setScaleSize();
288                         this.scale.buildYLabels();
289                 },
290                 draw : function(ease){
291                         var easeDecimal = ease || 1,
292                                 ctx = this.chart.ctx;
293                         this.clear();
294                         this.scale.draw();
295
296                         helpers.each(this.datasets,function(dataset){
297
298                                 //Transition each point first so that the line and point drawing isn't out of sync
299                                 helpers.each(dataset.points,function(point,index){
300                                         if (point.hasValue()){
301                                                 point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
302                                         }
303                                 },this);
304
305
306
307                                 //Draw the line between all the points
308                                 ctx.lineWidth = this.options.datasetStrokeWidth;
309                                 ctx.strokeStyle = dataset.strokeColor;
310                                 ctx.beginPath();
311                                 helpers.each(dataset.points,function(point,index){
312                                         if (index === 0){
313                                                 ctx.moveTo(point.x,point.y);
314                                         }
315                                         else{
316                                                 ctx.lineTo(point.x,point.y);
317                                         }
318                                 },this);
319                                 ctx.closePath();
320                                 ctx.stroke();
321
322                                 ctx.fillStyle = dataset.fillColor;
323                                 if(this.options.datasetFill){
324                                         ctx.fill();
325                                 }
326                                 //Now draw the points over the line
327                                 //A little inefficient double looping, but better than the line
328                                 //lagging behind the point positions
329                                 helpers.each(dataset.points,function(point){
330                                         if (point.hasValue()){
331                                                 point.draw();
332                                         }
333                                 });
334
335                         },this);
336
337                 }
338
339         });
340
341
342
343
344
345 }).call(this);