Added more updates
[soho-sigint.git] / client-freqwatch / Chart.js / src / Chart.Doughnut.js
1 (function(){
2         "use strict";
3
4         var root = this,
5                 Chart = root.Chart,
6                 //Cache a local reference to Chart.helpers
7                 helpers = Chart.helpers;
8
9         var defaultConfig = {
10                 //Boolean - Whether we should show a stroke on each segment
11                 segmentShowStroke : true,
12
13                 //String - The colour of each segment stroke
14                 segmentStrokeColor : "#fff",
15
16                 //Number - The width of each segment stroke
17                 segmentStrokeWidth : 2,
18
19                 //The percentage of the chart that we cut out of the middle.
20                 percentageInnerCutout : 50,
21
22                 //Number - Amount of animation steps
23                 animationSteps : 100,
24
25                 //String - Animation easing effect
26                 animationEasing : "easeOutBounce",
27
28                 //Boolean - Whether we animate the rotation of the Doughnut
29                 animateRotate : true,
30
31                 //Boolean - Whether we animate scaling the Doughnut from the centre
32                 animateScale : false,
33
34                 //String - A legend template
35                 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>"
36
37         };
38
39         Chart.Type.extend({
40                 //Passing in a name registers this chart in the Chart namespace
41                 name: "Doughnut",
42                 //Providing a defaults will also register the deafults in the chart namespace
43                 defaults : defaultConfig,
44                 //Initialize is fired when the chart is initialized - Data is passed in as a parameter
45                 //Config is automatically merged by the core of Chart.js, and is available at this.options
46                 initialize:  function(data){
47
48                         //Declare segments as a static property to prevent inheriting across the Chart type prototype
49                         this.segments = [];
50                         this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
51
52                         this.SegmentArc = Chart.Arc.extend({
53                                 ctx : this.chart.ctx,
54                                 x : this.chart.width/2,
55                                 y : this.chart.height/2
56                         });
57
58                         //Set up tooltip events on the chart
59                         if (this.options.showTooltips){
60                                 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
61                                         var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
62
63                                         helpers.each(this.segments,function(segment){
64                                                 segment.restore(["fillColor"]);
65                                         });
66                                         helpers.each(activeSegments,function(activeSegment){
67                                                 activeSegment.fillColor = activeSegment.highlightColor;
68                                         });
69                                         this.showTooltip(activeSegments);
70                                 });
71                         }
72                         this.calculateTotal(data);
73
74                         helpers.each(data,function(datapoint, index){
75                                 if (!datapoint.color) {
76                                         datapoint.color = 'hsl(' + (360 * index / data.length) + ', 100%, 50%)';
77                                 }
78                                 this.addData(datapoint, index, true);
79                         },this);
80
81                         this.render();
82                 },
83                 getSegmentsAtEvent : function(e){
84                         var segmentsArray = [];
85
86                         var location = helpers.getRelativePosition(e);
87
88                         helpers.each(this.segments,function(segment){
89                                 if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
90                         },this);
91                         return segmentsArray;
92                 },
93                 addData : function(segment, atIndex, silent){
94                         var index = atIndex || this.segments.length;
95                         this.segments.splice(index, 0, new this.SegmentArc({
96                                 value : segment.value,
97                                 outerRadius : (this.options.animateScale) ? 0 : this.outerRadius,
98                                 innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout,
99                                 fillColor : segment.color,
100                                 highlightColor : segment.highlight || segment.color,
101                                 showStroke : this.options.segmentShowStroke,
102                                 strokeWidth : this.options.segmentStrokeWidth,
103                                 strokeColor : this.options.segmentStrokeColor,
104                                 startAngle : Math.PI * 1.5,
105                                 circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value),
106                                 label : segment.label
107                         }));
108                         if (!silent){
109                                 this.reflow();
110                                 this.update();
111                         }
112                 },
113                 calculateCircumference : function(value) {
114                         if ( this.total > 0 ) {
115                                 return (Math.PI*2)*(value / this.total);
116                         } else {
117                                 return 0;
118                         }
119                 },
120                 calculateTotal : function(data){
121                         this.total = 0;
122                         helpers.each(data,function(segment){
123                                 this.total += Math.abs(segment.value);
124                         },this);
125                 },
126                 update : function(){
127                         this.calculateTotal(this.segments);
128
129                         // Reset any highlight colours before updating.
130                         helpers.each(this.activeElements, function(activeElement){
131                                 activeElement.restore(['fillColor']);
132                         });
133
134                         helpers.each(this.segments,function(segment){
135                                 segment.save();
136                         });
137                         this.render();
138                 },
139
140                 removeData: function(atIndex){
141                         var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
142                         this.segments.splice(indexToDelete, 1);
143                         this.reflow();
144                         this.update();
145                 },
146
147                 reflow : function(){
148                         helpers.extend(this.SegmentArc.prototype,{
149                                 x : this.chart.width/2,
150                                 y : this.chart.height/2
151                         });
152                         this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2;
153                         helpers.each(this.segments, function(segment){
154                                 segment.update({
155                                         outerRadius : this.outerRadius,
156                                         innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
157                                 });
158                         }, this);
159                 },
160                 draw : function(easeDecimal){
161                         var animDecimal = (easeDecimal) ? easeDecimal : 1;
162                         this.clear();
163                         helpers.each(this.segments,function(segment,index){
164                                 segment.transition({
165                                         circumference : this.calculateCircumference(segment.value),
166                                         outerRadius : this.outerRadius,
167                                         innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout
168                                 },animDecimal);
169
170                                 segment.endAngle = segment.startAngle + segment.circumference;
171
172                                 segment.draw();
173                                 if (index === 0){
174                                         segment.startAngle = Math.PI * 1.5;
175                                 }
176                                 //Check to see if it's the last segment, if not get the next and update the start angle
177                                 if (index < this.segments.length-1){
178                                         this.segments[index+1].startAngle = segment.endAngle;
179                                 }
180                         },this);
181
182                 }
183         });
184
185         Chart.types.Doughnut.extend({
186                 name : "Pie",
187                 defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0})
188         });
189
190 }).call(this);