Added more updates
[soho-sigint.git] / client-freqwatch / Chart.js / src / Chart.Radar.js
diff --git a/client-freqwatch/Chart.js/src/Chart.Radar.js b/client-freqwatch/Chart.js/src/Chart.Radar.js
new file mode 100644 (file)
index 0000000..6d00eeb
--- /dev/null
@@ -0,0 +1,345 @@
+(function(){
+       "use strict";
+
+       var root = this,
+               Chart = root.Chart,
+               helpers = Chart.helpers;
+
+
+
+       Chart.Type.extend({
+               name: "Radar",
+               defaults:{
+                       //Boolean - Whether to show lines for each scale point
+                       scaleShowLine : true,
+
+                       //Boolean - Whether we show the angle lines out of the radar
+                       angleShowLineOut : true,
+
+                       //Boolean - Whether to show labels on the scale
+                       scaleShowLabels : false,
+
+                       // Boolean - Whether the scale should begin at zero
+                       scaleBeginAtZero : true,
+
+                       //String - Colour of the angle line
+                       angleLineColor : "rgba(0,0,0,.1)",
+
+                       //Number - Pixel width of the angle line
+                       angleLineWidth : 1,
+
+                       //String - Point label font declaration
+                       pointLabelFontFamily : "'Arial'",
+
+                       //String - Point label font weight
+                       pointLabelFontStyle : "normal",
+
+                       //Number - Point label font size in pixels
+                       pointLabelFontSize : 10,
+
+                       //String - Point label font colour
+                       pointLabelFontColor : "#666",
+
+                       //Boolean - Whether to show a dot for each point
+                       pointDot : true,
+
+                       //Number - Radius of each point dot in pixels
+                       pointDotRadius : 3,
+
+                       //Number - Pixel width of point dot stroke
+                       pointDotStrokeWidth : 1,
+
+                       //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
+                       pointHitDetectionRadius : 20,
+
+                       //Boolean - Whether to show a stroke for datasets
+                       datasetStroke : true,
+
+                       //Number - Pixel width of dataset stroke
+                       datasetStrokeWidth : 2,
+
+                       //Boolean - Whether to fill the dataset with a colour
+                       datasetFill : true,
+
+                       //String - A legend template
+                       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>"
+
+               },
+
+               initialize: function(data){
+                       this.PointClass = Chart.Point.extend({
+                               strokeWidth : this.options.pointDotStrokeWidth,
+                               radius : this.options.pointDotRadius,
+                               display: this.options.pointDot,
+                               hitDetectionRadius : this.options.pointHitDetectionRadius,
+                               ctx : this.chart.ctx
+                       });
+
+                       this.datasets = [];
+
+                       this.buildScale(data);
+
+                       //Set up tooltip events on the chart
+                       if (this.options.showTooltips){
+                               helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+                                       var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
+
+                                       this.eachPoints(function(point){
+                                               point.restore(['fillColor', 'strokeColor']);
+                                       });
+                                       helpers.each(activePointsCollection, function(activePoint){
+                                               activePoint.fillColor = activePoint.highlightFill;
+                                               activePoint.strokeColor = activePoint.highlightStroke;
+                                       });
+
+                                       this.showTooltip(activePointsCollection);
+                               });
+                       }
+
+                       //Iterate through each of the datasets, and build this into a property of the chart
+                       helpers.each(data.datasets,function(dataset){
+
+                               var datasetObject = {
+                                       label: dataset.label || null,
+                                       fillColor : dataset.fillColor,
+                                       strokeColor : dataset.strokeColor,
+                                       pointColor : dataset.pointColor,
+                                       pointStrokeColor : dataset.pointStrokeColor,
+                                       points : []
+                               };
+
+                               this.datasets.push(datasetObject);
+
+                               helpers.each(dataset.data,function(dataPoint,index){
+                                       //Add a new point for each piece of data, passing any required data to draw.
+                                       var pointPosition;
+                                       if (!this.scale.animation){
+                                               pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
+                                       }
+                                       datasetObject.points.push(new this.PointClass({
+                                               value : dataPoint,
+                                               label : data.labels[index],
+                                               datasetLabel: dataset.label,
+                                               x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
+                                               y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
+                                               strokeColor : dataset.pointStrokeColor,
+                                               fillColor : dataset.pointColor,
+                                               highlightFill : dataset.pointHighlightFill || dataset.pointColor,
+                                               highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
+                                       }));
+                               },this);
+
+                       },this);
+
+                       this.render();
+               },
+               eachPoints : function(callback){
+                       helpers.each(this.datasets,function(dataset){
+                               helpers.each(dataset.points,callback,this);
+                       },this);
+               },
+
+               getPointsAtEvent : function(evt){
+                       var mousePosition = helpers.getRelativePosition(evt),
+                               fromCenter = helpers.getAngleFromPoint({
+                                       x: this.scale.xCenter,
+                                       y: this.scale.yCenter
+                               }, mousePosition);
+
+                       var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
+                               pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
+                               activePointsCollection = [];
+
+                       // If we're at the top, make the pointIndex 0 to get the first of the array.
+                       if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
+                               pointIndex = 0;
+                       }
+
+                       if (fromCenter.distance <= this.scale.drawingArea){
+                               helpers.each(this.datasets, function(dataset){
+                                       activePointsCollection.push(dataset.points[pointIndex]);
+                               });
+                       }
+
+                       return activePointsCollection;
+               },
+
+               buildScale : function(data){
+                       this.scale = new Chart.RadialScale({
+                               display: this.options.showScale,
+                               fontStyle: this.options.scaleFontStyle,
+                               fontSize: this.options.scaleFontSize,
+                               fontFamily: this.options.scaleFontFamily,
+                               fontColor: this.options.scaleFontColor,
+                               showLabels: this.options.scaleShowLabels,
+                               showLabelBackdrop: this.options.scaleShowLabelBackdrop,
+                               backdropColor: this.options.scaleBackdropColor,
+                               backdropPaddingY : this.options.scaleBackdropPaddingY,
+                               backdropPaddingX: this.options.scaleBackdropPaddingX,
+                               lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
+                               lineColor: this.options.scaleLineColor,
+                               angleLineColor : this.options.angleLineColor,
+                               angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
+                               // Point labels at the edge of each line
+                               pointLabelFontColor : this.options.pointLabelFontColor,
+                               pointLabelFontSize : this.options.pointLabelFontSize,
+                               pointLabelFontFamily : this.options.pointLabelFontFamily,
+                               pointLabelFontStyle : this.options.pointLabelFontStyle,
+                               height : this.chart.height,
+                               width: this.chart.width,
+                               xCenter: this.chart.width/2,
+                               yCenter: this.chart.height/2,
+                               ctx : this.chart.ctx,
+                               templateString: this.options.scaleLabel,
+                               labels: data.labels,
+                               valuesCount: data.datasets[0].data.length
+                       });
+
+                       this.scale.setScaleSize();
+                       this.updateScaleRange(data.datasets);
+                       this.scale.buildYLabels();
+               },
+               updateScaleRange: function(datasets){
+                       var valuesArray = (function(){
+                               var totalDataArray = [];
+                               helpers.each(datasets,function(dataset){
+                                       if (dataset.data){
+                                               totalDataArray = totalDataArray.concat(dataset.data);
+                                       }
+                                       else {
+                                               helpers.each(dataset.points, function(point){
+                                                       totalDataArray.push(point.value);
+                                               });
+                                       }
+                               });
+                               return totalDataArray;
+                       })();
+
+
+                       var scaleSizes = (this.options.scaleOverride) ?
+                               {
+                                       steps: this.options.scaleSteps,
+                                       stepValue: this.options.scaleStepWidth,
+                                       min: this.options.scaleStartValue,
+                                       max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
+                               } :
+                               helpers.calculateScaleRange(
+                                       valuesArray,
+                                       helpers.min([this.chart.width, this.chart.height])/2,
+                                       this.options.scaleFontSize,
+                                       this.options.scaleBeginAtZero,
+                                       this.options.scaleIntegersOnly
+                               );
+
+                       helpers.extend(
+                               this.scale,
+                               scaleSizes
+                       );
+
+               },
+               addData : function(valuesArray,label){
+                       //Map the values array for each of the datasets
+                       this.scale.valuesCount++;
+                       helpers.each(valuesArray,function(value,datasetIndex){
+                               var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
+                               this.datasets[datasetIndex].points.push(new this.PointClass({
+                                       value : value,
+                                       label : label,
+                                       datasetLabel: this.datasets[datasetIndex].label,
+                                       x: pointPosition.x,
+                                       y: pointPosition.y,
+                                       strokeColor : this.datasets[datasetIndex].pointStrokeColor,
+                                       fillColor : this.datasets[datasetIndex].pointColor
+                               }));
+                       },this);
+
+                       this.scale.labels.push(label);
+
+                       this.reflow();
+
+                       this.update();
+               },
+               removeData : function(){
+                       this.scale.valuesCount--;
+                       this.scale.labels.shift();
+                       helpers.each(this.datasets,function(dataset){
+                               dataset.points.shift();
+                       },this);
+                       this.reflow();
+                       this.update();
+               },
+               update : function(){
+                       this.eachPoints(function(point){
+                               point.save();
+                       });
+                       this.reflow();
+                       this.render();
+               },
+               reflow: function(){
+                       helpers.extend(this.scale, {
+                               width : this.chart.width,
+                               height: this.chart.height,
+                               size : helpers.min([this.chart.width, this.chart.height]),
+                               xCenter: this.chart.width/2,
+                               yCenter: this.chart.height/2
+                       });
+                       this.updateScaleRange(this.datasets);
+                       this.scale.setScaleSize();
+                       this.scale.buildYLabels();
+               },
+               draw : function(ease){
+                       var easeDecimal = ease || 1,
+                               ctx = this.chart.ctx;
+                       this.clear();
+                       this.scale.draw();
+
+                       helpers.each(this.datasets,function(dataset){
+
+                               //Transition each point first so that the line and point drawing isn't out of sync
+                               helpers.each(dataset.points,function(point,index){
+                                       if (point.hasValue()){
+                                               point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
+                                       }
+                               },this);
+
+
+
+                               //Draw the line between all the points
+                               ctx.lineWidth = this.options.datasetStrokeWidth;
+                               ctx.strokeStyle = dataset.strokeColor;
+                               ctx.beginPath();
+                               helpers.each(dataset.points,function(point,index){
+                                       if (index === 0){
+                                               ctx.moveTo(point.x,point.y);
+                                       }
+                                       else{
+                                               ctx.lineTo(point.x,point.y);
+                                       }
+                               },this);
+                               ctx.closePath();
+                               ctx.stroke();
+
+                               ctx.fillStyle = dataset.fillColor;
+                               if(this.options.datasetFill){
+                                       ctx.fill();
+                               }
+                               //Now draw the points over the line
+                               //A little inefficient double looping, but better than the line
+                               //lagging behind the point positions
+                               helpers.each(dataset.points,function(point){
+                                       if (point.hasValue()){
+                                               point.draw();
+                                       }
+                               });
+
+                       },this);
+
+               }
+
+       });
+
+
+
+
+
+}).call(this);