| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 | 
							- 'use strict';
 
- module.exports = function(Chart) {
 
- 	var helpers = Chart.helpers;
 
- 	Chart.defaults.bar = {
 
- 		hover: {
 
- 			mode: 'label'
 
- 		},
 
- 		scales: {
 
- 			xAxes: [{
 
- 				type: 'category',
 
- 				// Specific to Bar Controller
 
- 				categoryPercentage: 0.8,
 
- 				barPercentage: 0.9,
 
- 				// grid line settings
 
- 				gridLines: {
 
- 					offsetGridLines: true
 
- 				}
 
- 			}],
 
- 			yAxes: [{
 
- 				type: 'linear'
 
- 			}]
 
- 		}
 
- 	};
 
- 	Chart.controllers.bar = Chart.DatasetController.extend({
 
- 		dataElementType: Chart.elements.Rectangle,
 
- 		initialize: function(chart, datasetIndex) {
 
- 			Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
 
- 			// Use this to indicate that this is a bar dataset.
 
- 			this.getMeta().bar = true;
 
- 		},
 
- 		// Get the number of datasets that display bars. We use this to correctly calculate the bar width
 
- 		getBarCount: function() {
 
- 			var me = this;
 
- 			var barCount = 0;
 
- 			helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
 
- 				var meta = me.chart.getDatasetMeta(datasetIndex);
 
- 				if (meta.bar && me.chart.isDatasetVisible(datasetIndex)) {
 
- 					++barCount;
 
- 				}
 
- 			}, me);
 
- 			return barCount;
 
- 		},
 
- 		update: function(reset) {
 
- 			var me = this;
 
- 			helpers.each(me.getMeta().data, function(rectangle, index) {
 
- 				me.updateElement(rectangle, index, reset);
 
- 			}, me);
 
- 		},
 
- 		updateElement: function(rectangle, index, reset) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var scaleBase = yScale.getBasePixel();
 
- 			var rectangleElementOptions = me.chart.options.elements.rectangle;
 
- 			var custom = rectangle.custom || {};
 
- 			var dataset = me.getDataset();
 
- 			rectangle._xScale = xScale;
 
- 			rectangle._yScale = yScale;
 
- 			rectangle._datasetIndex = me.index;
 
- 			rectangle._index = index;
 
- 			var ruler = me.getRuler(index);
 
- 			rectangle._model = {
 
- 				x: me.calculateBarX(index, me.index, ruler),
 
- 				y: reset ? scaleBase : me.calculateBarY(index, me.index),
 
- 				// Tooltip
 
- 				label: me.chart.data.labels[index],
 
- 				datasetLabel: dataset.label,
 
- 				// Appearance
 
- 				base: reset ? scaleBase : me.calculateBarBase(me.index, index),
 
- 				width: me.calculateBarWidth(ruler),
 
- 				backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
 
- 				borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
 
- 				borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
 
- 				borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
 
- 			};
 
- 			rectangle.pivot();
 
- 		},
 
- 		calculateBarBase: function(datasetIndex, index) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var base = 0;
 
- 			if (yScale.options.stacked) {
 
- 				var chart = me.chart;
 
- 				var datasets = chart.data.datasets;
 
- 				var value = Number(datasets[datasetIndex].data[index]);
 
- 				for (var i = 0; i < datasetIndex; i++) {
 
- 					var currentDs = datasets[i];
 
- 					var currentDsMeta = chart.getDatasetMeta(i);
 
- 					if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
 
- 						var currentVal = Number(currentDs.data[index]);
 
- 						base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
 
- 					}
 
- 				}
 
- 				return yScale.getPixelForValue(base);
 
- 			}
 
- 			return yScale.getBasePixel();
 
- 		},
 
- 		getRuler: function(index) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var datasetCount = me.getBarCount();
 
- 			var tickWidth;
 
- 			if (xScale.options.type === 'category') {
 
- 				tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);
 
- 			} else {
 
- 				// Average width
 
- 				tickWidth = xScale.width / xScale.ticks.length;
 
- 			}
 
- 			var categoryWidth = tickWidth * xScale.options.categoryPercentage;
 
- 			var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;
 
- 			var fullBarWidth = categoryWidth / datasetCount;
 
- 			if (xScale.ticks.length !== me.chart.data.labels.length) {
 
- 				var perc = xScale.ticks.length / me.chart.data.labels.length;
 
- 				fullBarWidth = fullBarWidth * perc;
 
- 			}
 
- 			var barWidth = fullBarWidth * xScale.options.barPercentage;
 
- 			var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);
 
- 			return {
 
- 				datasetCount: datasetCount,
 
- 				tickWidth: tickWidth,
 
- 				categoryWidth: categoryWidth,
 
- 				categorySpacing: categorySpacing,
 
- 				fullBarWidth: fullBarWidth,
 
- 				barWidth: barWidth,
 
- 				barSpacing: barSpacing
 
- 			};
 
- 		},
 
- 		calculateBarWidth: function(ruler) {
 
- 			var xScale = this.getScaleForId(this.getMeta().xAxisID);
 
- 			if (xScale.options.barThickness) {
 
- 				return xScale.options.barThickness;
 
- 			}
 
- 			return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
 
- 		},
 
- 		// Get bar index from the given dataset index accounting for the fact that not all bars are visible
 
- 		getBarIndex: function(datasetIndex) {
 
- 			var barIndex = 0;
 
- 			var meta, j;
 
- 			for (j = 0; j < datasetIndex; ++j) {
 
- 				meta = this.chart.getDatasetMeta(j);
 
- 				if (meta.bar && this.chart.isDatasetVisible(j)) {
 
- 					++barIndex;
 
- 				}
 
- 			}
 
- 			return barIndex;
 
- 		},
 
- 		calculateBarX: function(index, datasetIndex, ruler) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var barIndex = me.getBarIndex(datasetIndex);
 
- 			var leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);
 
- 			leftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0;
 
- 			if (xScale.options.stacked) {
 
- 				return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;
 
- 			}
 
- 			return leftTick +
 
- 				(ruler.barWidth / 2) +
 
- 				ruler.categorySpacing +
 
- 				(ruler.barWidth * barIndex) +
 
- 				(ruler.barSpacing / 2) +
 
- 				(ruler.barSpacing * barIndex);
 
- 		},
 
- 		calculateBarY: function(index, datasetIndex) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var value = Number(me.getDataset().data[index]);
 
- 			if (yScale.options.stacked) {
 
- 				var sumPos = 0,
 
- 					sumNeg = 0;
 
- 				for (var i = 0; i < datasetIndex; i++) {
 
- 					var ds = me.chart.data.datasets[i];
 
- 					var dsMeta = me.chart.getDatasetMeta(i);
 
- 					if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i)) {
 
- 						var stackedVal = Number(ds.data[index]);
 
- 						if (stackedVal < 0) {
 
- 							sumNeg += stackedVal || 0;
 
- 						} else {
 
- 							sumPos += stackedVal || 0;
 
- 						}
 
- 					}
 
- 				}
 
- 				if (value < 0) {
 
- 					return yScale.getPixelForValue(sumNeg + value);
 
- 				}
 
- 				return yScale.getPixelForValue(sumPos + value);
 
- 			}
 
- 			return yScale.getPixelForValue(value);
 
- 		},
 
- 		draw: function(ease) {
 
- 			var me = this;
 
- 			var easingDecimal = ease || 1;
 
- 			var metaData = me.getMeta().data;
 
- 			var dataset = me.getDataset();
 
- 			var i, len;
 
- 			for (i = 0, len = metaData.length; i < len; ++i) {
 
- 				var d = dataset.data[i];
 
- 				if (d !== null && d !== undefined && !isNaN(d)) {
 
- 					metaData[i].transition(easingDecimal).draw();
 
- 				}
 
- 			}
 
- 		},
 
- 		setHoverStyle: function(rectangle) {
 
- 			var dataset = this.chart.data.datasets[rectangle._datasetIndex];
 
- 			var index = rectangle._index;
 
- 			var custom = rectangle.custom || {};
 
- 			var model = rectangle._model;
 
- 			model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
 
- 			model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
 
- 			model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
 
- 		},
 
- 		removeHoverStyle: function(rectangle) {
 
- 			var dataset = this.chart.data.datasets[rectangle._datasetIndex];
 
- 			var index = rectangle._index;
 
- 			var custom = rectangle.custom || {};
 
- 			var model = rectangle._model;
 
- 			var rectangleElementOptions = this.chart.options.elements.rectangle;
 
- 			model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);
 
- 			model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);
 
- 			model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);
 
- 		}
 
- 	});
 
- 	// including horizontalBar in the bar file, instead of a file of its own
 
- 	// it extends bar (like pie extends doughnut)
 
- 	Chart.defaults.horizontalBar = {
 
- 		hover: {
 
- 			mode: 'label'
 
- 		},
 
- 		scales: {
 
- 			xAxes: [{
 
- 				type: 'linear',
 
- 				position: 'bottom'
 
- 			}],
 
- 			yAxes: [{
 
- 				position: 'left',
 
- 				type: 'category',
 
- 				// Specific to Horizontal Bar Controller
 
- 				categoryPercentage: 0.8,
 
- 				barPercentage: 0.9,
 
- 				// grid line settings
 
- 				gridLines: {
 
- 					offsetGridLines: true
 
- 				}
 
- 			}]
 
- 		},
 
- 		elements: {
 
- 			rectangle: {
 
- 				borderSkipped: 'left'
 
- 			}
 
- 		},
 
- 		tooltips: {
 
- 			callbacks: {
 
- 				title: function(tooltipItems, data) {
 
- 					// Pick first xLabel for now
 
- 					var title = '';
 
- 					if (tooltipItems.length > 0) {
 
- 						if (tooltipItems[0].yLabel) {
 
- 							title = tooltipItems[0].yLabel;
 
- 						} else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {
 
- 							title = data.labels[tooltipItems[0].index];
 
- 						}
 
- 					}
 
- 					return title;
 
- 				},
 
- 				label: function(tooltipItem, data) {
 
- 					var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
 
- 					return datasetLabel + ': ' + tooltipItem.xLabel;
 
- 				}
 
- 			}
 
- 		}
 
- 	};
 
- 	Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
 
- 		updateElement: function(rectangle, index, reset) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var scaleBase = xScale.getBasePixel();
 
- 			var custom = rectangle.custom || {};
 
- 			var dataset = me.getDataset();
 
- 			var rectangleElementOptions = me.chart.options.elements.rectangle;
 
- 			rectangle._xScale = xScale;
 
- 			rectangle._yScale = yScale;
 
- 			rectangle._datasetIndex = me.index;
 
- 			rectangle._index = index;
 
- 			var ruler = me.getRuler(index);
 
- 			rectangle._model = {
 
- 				x: reset ? scaleBase : me.calculateBarX(index, me.index),
 
- 				y: me.calculateBarY(index, me.index, ruler),
 
- 				// Tooltip
 
- 				label: me.chart.data.labels[index],
 
- 				datasetLabel: dataset.label,
 
- 				// Appearance
 
- 				base: reset ? scaleBase : me.calculateBarBase(me.index, index),
 
- 				height: me.calculateBarHeight(ruler),
 
- 				backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
 
- 				borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
 
- 				borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
 
- 				borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
 
- 			};
 
- 			rectangle.draw = function() {
 
- 				var ctx = this._chart.ctx;
 
- 				var vm = this._view;
 
- 				var halfHeight = vm.height / 2,
 
- 					topY = vm.y - halfHeight,
 
- 					bottomY = vm.y + halfHeight,
 
- 					right = vm.base - (vm.base - vm.x),
 
- 					halfStroke = vm.borderWidth / 2;
 
- 				// Canvas doesn't allow us to stroke inside the width so we can
 
- 				// adjust the sizes to fit if we're setting a stroke on the line
 
- 				if (vm.borderWidth) {
 
- 					topY += halfStroke;
 
- 					bottomY -= halfStroke;
 
- 					right += halfStroke;
 
- 				}
 
- 				ctx.beginPath();
 
- 				ctx.fillStyle = vm.backgroundColor;
 
- 				ctx.strokeStyle = vm.borderColor;
 
- 				ctx.lineWidth = vm.borderWidth;
 
- 				// Corner points, from bottom-left to bottom-right clockwise
 
- 				// | 1 2 |
 
- 				// | 0 3 |
 
- 				var corners = [
 
- 					[vm.base, bottomY],
 
- 					[vm.base, topY],
 
- 					[right, topY],
 
- 					[right, bottomY]
 
- 				];
 
- 				// Find first (starting) corner with fallback to 'bottom'
 
- 				var borders = ['bottom', 'left', 'top', 'right'];
 
- 				var startCorner = borders.indexOf(vm.borderSkipped, 0);
 
- 				if (startCorner === -1) {
 
- 					startCorner = 0;
 
- 				}
 
- 				function cornerAt(cornerIndex) {
 
- 					return corners[(startCorner + cornerIndex) % 4];
 
- 				}
 
- 				// Draw rectangle from 'startCorner'
 
- 				ctx.moveTo.apply(ctx, cornerAt(0));
 
- 				for (var i = 1; i < 4; i++) {
 
- 					ctx.lineTo.apply(ctx, cornerAt(i));
 
- 				}
 
- 				ctx.fill();
 
- 				if (vm.borderWidth) {
 
- 					ctx.stroke();
 
- 				}
 
- 			};
 
- 			rectangle.pivot();
 
- 		},
 
- 		calculateBarBase: function(datasetIndex, index) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var base = 0;
 
- 			if (xScale.options.stacked) {
 
- 				var chart = me.chart;
 
- 				var datasets = chart.data.datasets;
 
- 				var value = Number(datasets[datasetIndex].data[index]);
 
- 				for (var i = 0; i < datasetIndex; i++) {
 
- 					var currentDs = datasets[i];
 
- 					var currentDsMeta = chart.getDatasetMeta(i);
 
- 					if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i)) {
 
- 						var currentVal = Number(currentDs.data[index]);
 
- 						base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
 
- 					}
 
- 				}
 
- 				return xScale.getPixelForValue(base);
 
- 			}
 
- 			return xScale.getBasePixel();
 
- 		},
 
- 		getRuler: function(index) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var datasetCount = me.getBarCount();
 
- 			var tickHeight;
 
- 			if (yScale.options.type === 'category') {
 
- 				tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);
 
- 			} else {
 
- 				// Average width
 
- 				tickHeight = yScale.width / yScale.ticks.length;
 
- 			}
 
- 			var categoryHeight = tickHeight * yScale.options.categoryPercentage;
 
- 			var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;
 
- 			var fullBarHeight = categoryHeight / datasetCount;
 
- 			if (yScale.ticks.length !== me.chart.data.labels.length) {
 
- 				var perc = yScale.ticks.length / me.chart.data.labels.length;
 
- 				fullBarHeight = fullBarHeight * perc;
 
- 			}
 
- 			var barHeight = fullBarHeight * yScale.options.barPercentage;
 
- 			var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);
 
- 			return {
 
- 				datasetCount: datasetCount,
 
- 				tickHeight: tickHeight,
 
- 				categoryHeight: categoryHeight,
 
- 				categorySpacing: categorySpacing,
 
- 				fullBarHeight: fullBarHeight,
 
- 				barHeight: barHeight,
 
- 				barSpacing: barSpacing
 
- 			};
 
- 		},
 
- 		calculateBarHeight: function(ruler) {
 
- 			var me = this;
 
- 			var yScale = me.getScaleForId(me.getMeta().yAxisID);
 
- 			if (yScale.options.barThickness) {
 
- 				return yScale.options.barThickness;
 
- 			}
 
- 			return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
 
- 		},
 
- 		calculateBarX: function(index, datasetIndex) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var xScale = me.getScaleForId(meta.xAxisID);
 
- 			var value = Number(me.getDataset().data[index]);
 
- 			if (xScale.options.stacked) {
 
- 				var sumPos = 0,
 
- 					sumNeg = 0;
 
- 				for (var i = 0; i < datasetIndex; i++) {
 
- 					var ds = me.chart.data.datasets[i];
 
- 					var dsMeta = me.chart.getDatasetMeta(i);
 
- 					if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
 
- 						var stackedVal = Number(ds.data[index]);
 
- 						if (stackedVal < 0) {
 
- 							sumNeg += stackedVal || 0;
 
- 						} else {
 
- 							sumPos += stackedVal || 0;
 
- 						}
 
- 					}
 
- 				}
 
- 				if (value < 0) {
 
- 					return xScale.getPixelForValue(sumNeg + value);
 
- 				}
 
- 				return xScale.getPixelForValue(sumPos + value);
 
- 			}
 
- 			return xScale.getPixelForValue(value);
 
- 		},
 
- 		calculateBarY: function(index, datasetIndex, ruler) {
 
- 			var me = this;
 
- 			var meta = me.getMeta();
 
- 			var yScale = me.getScaleForId(meta.yAxisID);
 
- 			var barIndex = me.getBarIndex(datasetIndex);
 
- 			var topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);
 
- 			topTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0;
 
- 			if (yScale.options.stacked) {
 
- 				return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;
 
- 			}
 
- 			return topTick +
 
- 				(ruler.barHeight / 2) +
 
- 				ruler.categorySpacing +
 
- 				(ruler.barHeight * barIndex) +
 
- 				(ruler.barSpacing / 2) +
 
- 				(ruler.barSpacing * barIndex);
 
- 		}
 
- 	});
 
- };
 
 
  |