Added more updates
[soho-sigint.git] / client-freqwatch / Chart.js / src / Chart.PolarArea.js
diff --git a/client-freqwatch/Chart.js/src/Chart.PolarArea.js b/client-freqwatch/Chart.js/src/Chart.PolarArea.js
new file mode 100644 (file)
index 0000000..d1802f5
--- /dev/null
@@ -0,0 +1,250 @@
+(function(){
+       "use strict";
+
+       var root = this,
+               Chart = root.Chart,
+               //Cache a local reference to Chart.helpers
+               helpers = Chart.helpers;
+
+       var defaultConfig = {
+               //Boolean - Show a backdrop to the scale label
+               scaleShowLabelBackdrop : true,
+
+               //String - The colour of the label backdrop
+               scaleBackdropColor : "rgba(255,255,255,0.75)",
+
+               // Boolean - Whether the scale should begin at zero
+               scaleBeginAtZero : true,
+
+               //Number - The backdrop padding above & below the label in pixels
+               scaleBackdropPaddingY : 2,
+
+               //Number - The backdrop padding to the side of the label in pixels
+               scaleBackdropPaddingX : 2,
+
+               //Boolean - Show line for each value in the scale
+               scaleShowLine : true,
+
+               //Boolean - Stroke a line around each segment in the chart
+               segmentShowStroke : true,
+
+               //String - The colour of the stroke on each segment.
+               segmentStrokeColor : "#fff",
+
+               //Number - The width of the stroke value in pixels
+               segmentStrokeWidth : 2,
+
+               //Number - Amount of animation steps
+               animationSteps : 100,
+
+               //String - Animation easing effect.
+               animationEasing : "easeOutBounce",
+
+               //Boolean - Whether to animate the rotation of the chart
+               animateRotate : true,
+
+               //Boolean - Whether to animate scaling the chart from the centre
+               animateScale : false,
+
+               //String - A legend template
+               legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"><%if(segments[i].label){%><%=segments[i].label%><%}%></span></li><%}%></ul>"
+       };
+
+
+       Chart.Type.extend({
+               //Passing in a name registers this chart in the Chart namespace
+               name: "PolarArea",
+               //Providing a defaults will also register the deafults in the chart namespace
+               defaults : defaultConfig,
+               //Initialize is fired when the chart is initialized - Data is passed in as a parameter
+               //Config is automatically merged by the core of Chart.js, and is available at this.options
+               initialize:  function(data){
+                       this.segments = [];
+                       //Declare segment class as a chart instance specific class, so it can share props for this instance
+                       this.SegmentArc = Chart.Arc.extend({
+                               showStroke : this.options.segmentShowStroke,
+                               strokeWidth : this.options.segmentStrokeWidth,
+                               strokeColor : this.options.segmentStrokeColor,
+                               ctx : this.chart.ctx,
+                               innerRadius : 0,
+                               x : this.chart.width/2,
+                               y : this.chart.height/2
+                       });
+                       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,
+                               lineArc: true,
+                               width: this.chart.width,
+                               height: this.chart.height,
+                               xCenter: this.chart.width/2,
+                               yCenter: this.chart.height/2,
+                               ctx : this.chart.ctx,
+                               templateString: this.options.scaleLabel,
+                               valuesCount: data.length
+                       });
+
+                       this.updateScaleRange(data);
+
+                       this.scale.update();
+
+                       helpers.each(data,function(segment,index){
+                               this.addData(segment,index,true);
+                       },this);
+
+                       //Set up tooltip events on the chart
+                       if (this.options.showTooltips){
+                               helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
+                                       var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
+                                       helpers.each(this.segments,function(segment){
+                                               segment.restore(["fillColor"]);
+                                       });
+                                       helpers.each(activeSegments,function(activeSegment){
+                                               activeSegment.fillColor = activeSegment.highlightColor;
+                                       });
+                                       this.showTooltip(activeSegments);
+                               });
+                       }
+
+                       this.render();
+               },
+               getSegmentsAtEvent : function(e){
+                       var segmentsArray = [];
+
+                       var location = helpers.getRelativePosition(e);
+
+                       helpers.each(this.segments,function(segment){
+                               if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
+                       },this);
+                       return segmentsArray;
+               },
+               addData : function(segment, atIndex, silent){
+                       var index = atIndex || this.segments.length;
+
+                       this.segments.splice(index, 0, new this.SegmentArc({
+                               fillColor: segment.color,
+                               highlightColor: segment.highlight || segment.color,
+                               label: segment.label,
+                               value: segment.value,
+                               outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
+                               circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
+                               startAngle: Math.PI * 1.5
+                       }));
+                       if (!silent){
+                               this.reflow();
+                               this.update();
+                       }
+               },
+               removeData: function(atIndex){
+                       var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
+                       this.segments.splice(indexToDelete, 1);
+                       this.reflow();
+                       this.update();
+               },
+               calculateTotal: function(data){
+                       this.total = 0;
+                       helpers.each(data,function(segment){
+                               this.total += segment.value;
+                       },this);
+                       this.scale.valuesCount = this.segments.length;
+               },
+               updateScaleRange: function(datapoints){
+                       var valuesArray = [];
+                       helpers.each(datapoints,function(segment){
+                               valuesArray.push(segment.value);
+                       });
+
+                       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,
+                               {
+                                       size: helpers.min([this.chart.width, this.chart.height]),
+                                       xCenter: this.chart.width/2,
+                                       yCenter: this.chart.height/2
+                               }
+                       );
+
+               },
+               update : function(){
+                       this.calculateTotal(this.segments);
+
+                       helpers.each(this.segments,function(segment){
+                               segment.save();
+                       });
+                       
+                       this.reflow();
+                       this.render();
+               },
+               reflow : function(){
+                       helpers.extend(this.SegmentArc.prototype,{
+                               x : this.chart.width/2,
+                               y : this.chart.height/2
+                       });
+                       this.updateScaleRange(this.segments);
+                       this.scale.update();
+
+                       helpers.extend(this.scale,{
+                               xCenter: this.chart.width/2,
+                               yCenter: this.chart.height/2
+                       });
+
+                       helpers.each(this.segments, function(segment){
+                               segment.update({
+                                       outerRadius : this.scale.calculateCenterOffset(segment.value)
+                               });
+                       }, this);
+
+               },
+               draw : function(ease){
+                       var easingDecimal = ease || 1;
+                       //Clear & draw the canvas
+                       this.clear();
+                       helpers.each(this.segments,function(segment, index){
+                               segment.transition({
+                                       circumference : this.scale.getCircumference(),
+                                       outerRadius : this.scale.calculateCenterOffset(segment.value)
+                               },easingDecimal);
+
+                               segment.endAngle = segment.startAngle + segment.circumference;
+
+                               // If we've removed the first segment we need to set the first one to
+                               // start at the top.
+                               if (index === 0){
+                                       segment.startAngle = Math.PI * 1.5;
+                               }
+
+                               //Check to see if it's the last segment, if not get the next and update the start angle
+                               if (index < this.segments.length - 1){
+                                       this.segments[index+1].startAngle = segment.endAngle;
+                               }
+                               segment.draw();
+                       }, this);
+                       this.scale.draw();
+               }
+       });
+
+}).call(this);