2016-02-12 04:30:53 +01:00
"use strict" ;
2015-06-13 16:15:21 +02:00
2016-02-12 04:30:53 +01:00
module . exports = function ( Chart ) {
2016-02-14 02:12:26 +01:00
var helpers = Chart . helpers ;
2015-06-13 16:15:21 +02:00
2015-06-16 03:14:11 +02:00
Chart . defaults . doughnut = {
2015-06-13 16:15:21 +02:00
animation : {
//Boolean - Whether we animate the rotation of the Doughnut
animateRotate : true ,
//Boolean - Whether we animate scaling the Doughnut from the centre
2016-02-14 23:06:00 +01:00
animateScale : false
2015-06-13 16:15:21 +02:00
} ,
2015-12-06 18:53:45 +01:00
aspectRatio : 1 ,
2015-06-13 16:15:21 +02:00
hover : {
mode : 'single'
} ,
2015-12-06 18:53:45 +01:00
legendCallback : function ( chart ) {
var text = [ ] ;
text . push ( '<ul class="' + chart . id + '-legend">' ) ;
if ( chart . data . datasets . length ) {
for ( var i = 0 ; i < chart . data . datasets [ 0 ] . data . length ; ++ i ) {
text . push ( '<li><span style="background-color:' + chart . data . datasets [ 0 ] . backgroundColor [ i ] + '">' ) ;
if ( chart . data . labels [ i ] ) {
text . push ( chart . data . labels [ i ] ) ;
}
text . push ( '</span></li>' ) ;
}
}
text . push ( '</ul>' ) ;
return text . join ( "" ) ;
} ,
legend : {
labels : {
generateLabels : function ( data ) {
2016-02-28 23:51:06 +01:00
if ( data . labels . length && data . datasets . length ) {
return data . labels . map ( function ( label , i ) {
return {
text : label ,
fillStyle : data . datasets [ 0 ] . backgroundColor [ i ] ,
hidden : isNaN ( data . datasets [ 0 ] . data [ i ] ) ,
2015-12-08 01:11:54 +01:00
2016-02-28 23:51:06 +01:00
// Extra data used for toggling the correct item
index : i
} ;
} ) ;
} else {
return [ ] ;
}
2015-12-06 18:53:45 +01:00
}
2015-12-08 03:23:20 +01:00
} ,
onClick : function ( e , legendItem ) {
helpers . each ( this . chart . data . datasets , function ( dataset ) {
dataset . metaHiddenData = dataset . metaHiddenData || [ ] ;
var idx = legendItem . index ;
if ( ! isNaN ( dataset . data [ idx ] ) ) {
dataset . metaHiddenData [ idx ] = dataset . data [ idx ] ;
dataset . data [ idx ] = NaN ;
} else if ( ! isNaN ( dataset . metaHiddenData [ idx ] ) ) {
dataset . data [ idx ] = dataset . metaHiddenData [ idx ] ;
}
} ) ;
this . chart . update ( ) ;
2015-12-06 18:53:45 +01:00
}
} ,
2015-06-13 16:15:21 +02:00
//The percentage of the chart that we cut out of the middle.
cutoutPercentage : 50 ,
2015-10-31 01:48:31 +01:00
// Need to override these to give a nice default
tooltips : {
callbacks : {
2016-02-14 23:06:00 +01:00
title : function ( ) {
return '' ;
} ,
2015-10-31 01:48:31 +01:00
label : function ( tooltipItem , data ) {
return data . labels [ tooltipItem . index ] + ': ' + data . datasets [ tooltipItem . datasetIndex ] . data [ tooltipItem . index ] ;
}
}
}
2015-06-13 16:15:21 +02:00
} ;
2015-06-16 06:47:20 +02:00
Chart . defaults . pie = helpers . clone ( Chart . defaults . doughnut ) ;
helpers . extend ( Chart . defaults . pie , {
cutoutPercentage : 0
} ) ;
2015-06-16 03:14:11 +02:00
2015-12-13 20:35:40 +01:00
Chart . controllers . doughnut = Chart . controllers . pie = Chart . DatasetController . extend ( {
2015-06-16 03:14:11 +02:00
linkScales : function ( ) {
// no scales for doughnut
} ,
addElements : function ( ) {
this . getDataset ( ) . metaData = this . getDataset ( ) . metaData || [ ] ;
helpers . each ( this . getDataset ( ) . data , function ( value , index ) {
this . getDataset ( ) . metaData [ index ] = this . getDataset ( ) . metaData [ index ] || new Chart . elements . Arc ( {
_chart : this . chart . chart ,
_datasetIndex : this . index ,
2016-02-14 23:06:00 +01:00
_index : index
2015-06-16 03:14:11 +02:00
} ) ;
} , this ) ;
} ,
2015-06-20 01:51:28 +02:00
addElementAndReset : function ( index , colorForNewElement ) {
this . getDataset ( ) . metaData = this . getDataset ( ) . metaData || [ ] ;
var arc = new Chart . elements . Arc ( {
_chart : this . chart . chart ,
_datasetIndex : this . index ,
2016-02-14 23:06:00 +01:00
_index : index
2015-06-20 01:51:28 +02:00
} ) ;
2015-08-30 20:56:48 +02:00
if ( colorForNewElement && helpers . isArray ( this . getDataset ( ) . backgroundColor ) ) {
this . getDataset ( ) . backgroundColor . splice ( index , 0 , colorForNewElement ) ;
}
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
// Reset the point
this . updateElement ( arc , index , true ) ;
// Add to the points array
this . getDataset ( ) . metaData . splice ( index , 0 , arc ) ;
} ,
2015-09-22 02:59:53 +02:00
2015-10-08 01:54:11 +02:00
getVisibleDatasetCount : function getVisibleDatasetCount ( ) {
2016-02-14 23:06:00 +01:00
return helpers . where ( this . chart . data . datasets , function ( ds ) {
return helpers . isDatasetVisible ( ds ) ;
} ) . length ;
2015-10-08 01:54:11 +02:00
} ,
// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
getRingIndex : function getRingIndex ( datasetIndex ) {
var ringIndex = 0 ;
for ( var j = 0 ; j < datasetIndex ; ++ j ) {
if ( helpers . isDatasetVisible ( this . chart . data . datasets [ j ] ) ) {
++ ringIndex ;
}
}
return ringIndex ;
} ,
2015-09-22 02:59:53 +02:00
update : function update ( reset ) {
2015-12-05 01:22:48 +01:00
var minSize = Math . min ( this . chart . chartArea . right - this . chart . chartArea . left , this . chart . chartArea . bottom - this . chart . chartArea . top ) ;
2015-09-22 02:59:53 +02:00
2015-12-05 01:22:48 +01:00
this . chart . outerRadius = Math . max ( ( minSize / 2 ) - this . chart . options . elements . arc . borderWidth / 2 , 0 ) ;
2015-09-22 02:59:53 +02:00
this . chart . innerRadius = Math . max ( this . chart . options . cutoutPercentage ? ( this . chart . outerRadius / 100 ) * ( this . chart . options . cutoutPercentage ) : 1 , 0 ) ;
2015-10-08 01:54:11 +02:00
this . chart . radiusLength = ( this . chart . outerRadius - this . chart . innerRadius ) / this . getVisibleDatasetCount ( ) ;
2015-09-22 02:59:53 +02:00
this . getDataset ( ) . total = 0 ;
helpers . each ( this . getDataset ( ) . data , function ( value ) {
2015-12-08 03:23:20 +01:00
if ( ! isNaN ( value ) ) {
this . getDataset ( ) . total += Math . abs ( value ) ;
}
2015-09-22 02:59:53 +02:00
} , this ) ;
2015-10-08 01:54:11 +02:00
this . outerRadius = this . chart . outerRadius - ( this . chart . radiusLength * this . getRingIndex ( this . index ) ) ;
2015-09-22 02:59:53 +02:00
this . innerRadius = this . outerRadius - this . chart . radiusLength ;
2015-08-30 20:56:48 +02:00
2015-06-16 03:14:11 +02:00
helpers . each ( this . getDataset ( ) . metaData , function ( arc , index ) {
2015-06-20 01:51:28 +02:00
this . updateElement ( arc , index , reset ) ;
} , this ) ;
} ,
updateElement : function ( arc , index , reset ) {
2015-12-05 01:22:48 +01:00
var centerX = ( this . chart . chartArea . left + this . chart . chartArea . right ) / 2 ;
var centerY = ( this . chart . chartArea . top + this . chart . chartArea . bottom ) / 2 ;
2016-02-27 18:32:20 +01:00
var startAngle = Math . PI * - 0.5 ; // non reset case handled later
var endAngle = Math . PI * - 0.5 ; // non reset case handled later
var circumference = reset && this . chart . options . animation . animateRotate ? 0 : this . calculateCircumference ( this . getDataset ( ) . data [ index ] ) ;
var innerRadius = reset && this . chart . options . animation . animateScale ? 0 : this . innerRadius ;
var outerRadius = reset && this . chart . options . animation . animateScale ? 0 : this . outerRadius ;
2015-06-20 01:51:28 +02:00
helpers . extend ( arc , {
// Utility
_chart : this . chart . chart ,
_datasetIndex : this . index ,
_index : index ,
// Desired view properties
2016-02-27 18:32:20 +01:00
_model : {
2015-12-05 01:22:48 +01:00
x : centerX ,
y : centerY ,
2016-02-27 18:32:20 +01:00
startAngle : startAngle ,
endAngle : endAngle ,
circumference : circumference ,
outerRadius : outerRadius ,
innerRadius : innerRadius ,
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
backgroundColor : arc . custom && arc . custom . backgroundColor ? arc . custom . backgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . backgroundColor , index , this . chart . options . elements . arc . backgroundColor ) ,
hoverBackgroundColor : arc . custom && arc . custom . hoverBackgroundColor ? arc . custom . hoverBackgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . hoverBackgroundColor , index , this . chart . options . elements . arc . hoverBackgroundColor ) ,
borderWidth : arc . custom && arc . custom . borderWidth ? arc . custom . borderWidth : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderWidth , index , this . chart . options . elements . arc . borderWidth ) ,
borderColor : arc . custom && arc . custom . borderColor ? arc . custom . borderColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderColor , index , this . chart . options . elements . arc . borderColor ) ,
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
label : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . label , index , this . chart . data . labels [ index ] )
2016-02-14 23:06:00 +01:00
}
2015-06-20 01:51:28 +02:00
} ) ;
2015-06-16 03:14:11 +02:00
2016-02-27 18:32:20 +01:00
// Set correct angles if not resetting
2015-06-20 01:51:28 +02:00
if ( ! reset ) {
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
if ( index === 0 ) {
arc . _model . startAngle = Math . PI * - 0.5 ; // use - PI / 2 instead of 3PI / 2 to make animations better. It means that we never deal with overflow during the transition function
} else {
arc . _model . startAngle = this . getDataset ( ) . metaData [ index - 1 ] . _model . endAngle ;
}
arc . _model . endAngle = arc . _model . startAngle + arc . _model . circumference ;
}
2015-06-16 03:14:11 +02:00
2015-06-20 01:51:28 +02:00
arc . pivot ( ) ;
2015-06-16 03:14:11 +02:00
} ,
draw : function ( ease ) {
var easingDecimal = ease || 1 ;
helpers . each ( this . getDataset ( ) . metaData , function ( arc , index ) {
arc . transition ( easingDecimal ) . draw ( ) ;
2016-01-14 18:17:14 +01:00
} ) ;
2015-06-16 03:14:11 +02:00
} ,
2015-06-16 06:43:24 +02:00
setHoverStyle : function ( arc ) {
var dataset = this . chart . data . datasets [ arc . _datasetIndex ] ;
var index = arc . _index ;
2015-06-16 03:14:11 +02:00
2015-06-16 06:43:24 +02:00
arc . _model . backgroundColor = arc . custom && arc . custom . hoverBackgroundColor ? arc . custom . hoverBackgroundColor : helpers . getValueAtIndexOrDefault ( dataset . hoverBackgroundColor , index , helpers . color ( arc . _model . backgroundColor ) . saturate ( 0.5 ) . darken ( 0.1 ) . rgbString ( ) ) ;
arc . _model . borderColor = arc . custom && arc . custom . hoverBorderColor ? arc . custom . hoverBorderColor : helpers . getValueAtIndexOrDefault ( dataset . hoverBorderColor , index , helpers . color ( arc . _model . borderColor ) . saturate ( 0.5 ) . darken ( 0.1 ) . rgbString ( ) ) ;
2015-08-30 20:56:48 +02:00
arc . _model . borderWidth = arc . custom && arc . custom . hoverBorderWidth ? arc . custom . hoverBorderWidth : helpers . getValueAtIndexOrDefault ( dataset . hoverBorderWidth , index , arc . _model . borderWidth ) ;
2015-06-16 03:14:11 +02:00
} ,
2015-06-16 06:43:24 +02:00
removeHoverStyle : function ( arc ) {
var dataset = this . chart . data . datasets [ arc . _datasetIndex ] ;
var index = arc . _index ;
arc . _model . backgroundColor = arc . custom && arc . custom . backgroundColor ? arc . custom . backgroundColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . backgroundColor , index , this . chart . options . elements . arc . backgroundColor ) ;
arc . _model . borderColor = arc . custom && arc . custom . borderColor ? arc . custom . borderColor : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderColor , index , this . chart . options . elements . arc . borderColor ) ;
arc . _model . borderWidth = arc . custom && arc . custom . borderWidth ? arc . custom . borderWidth : helpers . getValueAtIndexOrDefault ( this . getDataset ( ) . borderWidth , index , this . chart . options . elements . arc . borderWidth ) ;
2015-06-16 03:14:11 +02:00
} ,
calculateCircumference : function ( value ) {
2015-12-08 03:23:20 +01:00
if ( this . getDataset ( ) . total > 0 && ! isNaN ( value ) ) {
2015-06-16 19:46:50 +02:00
return ( Math . PI * 1.999999 ) * ( value / this . getDataset ( ) . total ) ;
2015-06-16 03:14:11 +02:00
} else {
return 0 ;
}
2016-02-14 23:06:00 +01:00
}
2015-06-16 03:14:11 +02:00
} ) ;
2016-02-14 23:06:00 +01:00
} ;