* Released under the MIT license
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
*/
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/* MIT license */\r
-var colorNames = require(5);\r
+var colorNames = require('color-name');\r
\r
module.exports = {\r
getRgba: getRgba,\r
reverseNames[colorNames[name]] = name;\r
}\r
-},{"5":5}],2:[function(require,module,exports){
+},{"color-name":5}],2:[function(require,module,exports){
/* MIT license */\r
-var convert = require(4);\r
-var string = require(1);\r
+var convert = require('color-convert');\r
+var string = require('chartjs-color-string');\r
\r
var Color = function (obj) {\r
if (obj instanceof Color) {\r
\r
module.exports = Color;\r
-},{"1":1,"4":4}],3:[function(require,module,exports){
+},{"chartjs-color-string":1,"color-convert":4}],3:[function(require,module,exports){
/* MIT license */
module.exports = {
}
},{}],4:[function(require,module,exports){
-var conversions = require(3);
+var conversions = require("./conversions");
var convert = function() {
return new Converter();
});
module.exports = convert;
-},{"3":3}],5:[function(require,module,exports){
+},{"./conversions":3}],5:[function(require,module,exports){
module.exports = {\r
"aliceblue": [240, 248, 255],\r
"antiquewhite": [250, 235, 215],\r
}));
},{}],7:[function(require,module,exports){
-var Chart = require(26)();
-
-require(25)(Chart);
-require(24)(Chart);
-require(21)(Chart);
-require(22)(Chart);
-require(23)(Chart);
-require(27)(Chart);
-require(31)(Chart);
-require(29)(Chart);
-require(30)(Chart);
-require(32)(Chart);
-require(28)(Chart);
-require(33)(Chart);
-
-require(34)(Chart);
-require(35)(Chart);
-require(36)(Chart);
-require(37)(Chart);
-
-require(40)(Chart);
-require(38)(Chart);
-require(39)(Chart);
-require(41)(Chart);
-require(42)(Chart);
-require(43)(Chart);
-
-// Controllers must be loaded after elements
-// See Chart.core.datasetController.dataElementType
-require(15)(Chart);
-require(16)(Chart);
-require(17)(Chart);
-require(18)(Chart);
-require(19)(Chart);
-require(20)(Chart);
-
-require(8)(Chart);
-require(9)(Chart);
-require(10)(Chart);
-require(11)(Chart);
-require(12)(Chart);
-require(13)(Chart);
-require(14)(Chart);
-
-window.Chart = module.exports = Chart;
-
-},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42,"43":43,"8":8,"9":9}],8:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Bar = function(context, config) {
- config.type = 'bar';
-
- return new Chart(context, config);
- };
+var Chart = require('./core/core.js')();\r
+\r
+require('./core/core.helpers')(Chart);\r
+require('./core/core.element')(Chart);\r
+require('./core/core.animation')(Chart);\r
+require('./core/core.controller')(Chart);\r
+require('./core/core.datasetController')(Chart);\r
+require('./core/core.layoutService')(Chart);\r
+require('./core/core.legend')(Chart);\r
+require('./core/core.plugin.js')(Chart);\r
+require('./core/core.scale')(Chart);\r
+require('./core/core.scaleService')(Chart);\r
+require('./core/core.title')(Chart);\r
+require('./core/core.tooltip')(Chart);\r
+\r
+require('./elements/element.arc')(Chart);\r
+require('./elements/element.line')(Chart);\r
+require('./elements/element.point')(Chart);\r
+require('./elements/element.rectangle')(Chart);\r
+\r
+require('./scales/scale.category')(Chart);\r
+require('./scales/scale.linear')(Chart);\r
+require('./scales/scale.logarithmic')(Chart);\r
+require('./scales/scale.radialLinear')(Chart);\r
+require('./scales/scale.time')(Chart);\r
+\r
+// Controllers must be loaded after elements\r
+// See Chart.core.datasetController.dataElementType\r
+require('./controllers/controller.bar')(Chart);\r
+require('./controllers/controller.bubble')(Chart);\r
+require('./controllers/controller.doughnut')(Chart);\r
+require('./controllers/controller.line')(Chart);\r
+require('./controllers/controller.polarArea')(Chart);\r
+require('./controllers/controller.radar')(Chart);\r
+\r
+require('./charts/Chart.Bar')(Chart);\r
+require('./charts/Chart.Bubble')(Chart);\r
+require('./charts/Chart.Doughnut')(Chart);\r
+require('./charts/Chart.Line')(Chart);\r
+require('./charts/Chart.PolarArea')(Chart);\r
+require('./charts/Chart.Radar')(Chart);\r
+require('./charts/Chart.Scatter')(Chart);\r
+\r
+window.Chart = module.exports = Chart;\r
+},{"./charts/Chart.Bar":8,"./charts/Chart.Bubble":9,"./charts/Chart.Doughnut":10,"./charts/Chart.Line":11,"./charts/Chart.PolarArea":12,"./charts/Chart.Radar":13,"./charts/Chart.Scatter":14,"./controllers/controller.bar":15,"./controllers/controller.bubble":16,"./controllers/controller.doughnut":17,"./controllers/controller.line":18,"./controllers/controller.polarArea":19,"./controllers/controller.radar":20,"./core/core.animation":21,"./core/core.controller":22,"./core/core.datasetController":23,"./core/core.element":24,"./core/core.helpers":25,"./core/core.js":26,"./core/core.layoutService":27,"./core/core.legend":28,"./core/core.plugin.js":29,"./core/core.scale":30,"./core/core.scaleService":31,"./core/core.title":32,"./core/core.tooltip":33,"./elements/element.arc":34,"./elements/element.line":35,"./elements/element.point":36,"./elements/element.rectangle":37,"./scales/scale.category":38,"./scales/scale.linear":39,"./scales/scale.logarithmic":40,"./scales/scale.radialLinear":41,"./scales/scale.time":42}],8:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Bar = function(context, config) {\r
+ config.type = 'bar';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],9:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Bubble = function(context, config) {
- config.type = 'bubble';
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Bubble = function(context, config) {\r
+ config.type = 'bubble';\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],10:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Doughnut = function(context, config) {
- config.type = 'doughnut';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Doughnut = function(context, config) {\r
+ config.type = 'doughnut';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],11:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Line = function(context, config) {
- config.type = 'line';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Line = function(context, config) {\r
+ config.type = 'line';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],12:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.PolarArea = function(context, config) {
- config.type = 'polarArea';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.PolarArea = function(context, config) {\r
+ config.type = 'polarArea';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],13:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Radar = function(context, config) {
- config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);
- config.type = 'radar';
-
- return new Chart(context, config);
- };
-
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+ \r
+ Chart.Radar = function(context, config) {\r
+ config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);\r
+ config.type = 'radar';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
+};\r
},{}],14:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var defaultConfig = {
- hover: {
- mode: 'single'
- },
-
- scales: {
- xAxes: [{
- type: "linear", // scatter should not use a category axis
- position: "bottom",
- id: "x-axis-1" // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: "linear",
- position: "left",
- id: "y-axis-1"
- }]
- },
-
- tooltips: {
- callbacks: {
- title: function(tooltipItems, data) {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem, data) {
- return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
- }
- }
- }
- };
-
- // Register the default config for this type
- Chart.defaults.scatter = defaultConfig;
-
- // Scatter charts use line controllers
- Chart.controllers.scatter = Chart.controllers.line;
-
- Chart.Scatter = function(context, config) {
- config.type = 'scatter';
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var defaultConfig = {\r
+ hover: {\r
+ mode: 'single'\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear", // scatter should not use a category axis\r
+ position: "bottom",\r
+ id: "x-axis-1" // need an ID so datasets can reference the scale\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ position: "left",\r
+ id: "y-axis-1"\r
+ }]\r
+ },\r
+\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Title doesn't make sense for scatter since we format the data as a point\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ // Register the default config for this type\r
+ Chart.defaults.scatter = defaultConfig;\r
+\r
+ // Scatter charts use line controllers\r
+ Chart.controllers.scatter = Chart.controllers.line;\r
+\r
+ Chart.Scatter = function(context, config) {\r
+ config.type = 'scatter';\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],15:[function(require,module,exports){
-"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 getBarCount() {
- 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 update(reset) {
- var me = this;
- helpers.each(me.getMeta().data, function(rectangle, index) {
- me.updateElement(rectangle, index, reset);
- }, me);
- },
-
- updateElement: function updateElement(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();
-
- helpers.extend(rectangle, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: me.calculateBarX(index, me.index),
- 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(index),
- 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 = datasets[datasetIndex].data[index];
-
- if (value < 0) {
- for (var i = 0; i < datasetIndex; i++) {
- var negDS = datasets[i];
- var negDSMeta = chart.getDatasetMeta(i);
- if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
- }
- }
- } else {
- for (var j = 0; j < datasetIndex; j++) {
- var posDS = datasets[j];
- var posDSMeta = chart.getDatasetMeta(j);
- if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {
- base += posDS.data[index] > 0 ? posDS.data[index] : 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(index) {
- var xScale = this.getScaleForId(this.getMeta().xAxisID);
- var ruler = this.getRuler(index);
- 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) {
- var me = this;
- var meta = me.getMeta();
- var xScale = me.getScaleForId(meta.xAxisID);
- var barIndex = me.getBarIndex(datasetIndex);
-
- var ruler = me.getRuler(index);
- 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 = 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)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return yScale.getPixelForValue(sumNeg + value);
- } else {
- return yScale.getPixelForValue(sumPos + value);
- }
- }
-
- return yScale.getPixelForValue(value);
- },
-
- draw: function(ease) {
- var me = this;
- var easingDecimal = ease || 1;
- helpers.each(me.getMeta().data, function(rectangle, index) {
- var d = me.getDataset().data[index];
- if (d !== null && d !== undefined && !isNaN(d)) {
- rectangle.transition(easingDecimal).draw();
- }
- }, me);
- },
-
- 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 updateElement(rectangle, index, reset, numBars) {
- 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;
-
- helpers.extend(rectangle, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: reset ? scaleBase : me.calculateBarX(index, me.index),
- y: me.calculateBarY(index, me.index),
-
- // Tooltip
- label: me.chart.data.labels[index],
- datasetLabel: dataset.label,
-
- // Appearance
- base: reset ? scaleBase : me.calculateBarBase(me.index, index),
- height: me.calculateBarHeight(index),
- 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)
- },
-
- 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(index) {
- return corners[(startCorner + index) % 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();
- }
- },
-
- inRange: function (mouseX, mouseY) {
- var vm = this._view;
- var inRange = false;
-
- if (vm) {
- if (vm.x < vm.base) {
- inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
- } else {
- inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
- }
- }
-
- return inRange;
- }
- });
-
- 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 value = me.chart.data.datasets[datasetIndex].data[index];
-
- if (value < 0) {
- for (var i = 0; i < datasetIndex; i++) {
- var negDS = me.chart.data.datasets[i];
- var negDSMeta = me.chart.getDatasetMeta(i);
- if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
- }
- }
- } else {
- for (var j = 0; j < datasetIndex; j++) {
- var posDS = me.chart.data.datasets[j];
- var posDSMeta = me.chart.getDatasetMeta(j);
- if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(j)) {
- base += posDS.data[index] > 0 ? posDS.data[index] : 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 (index) {
- var me = this;
- var yScale = me.getScaleForId(me.getMeta().yAxisID);
- var ruler = me.getRuler(index);
- 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 = 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)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return xScale.getPixelForValue(sumNeg + value);
- } else {
- return xScale.getPixelForValue(sumPos + value);
- }
- }
-
- return xScale.getPixelForValue(value);
- },
-
- calculateBarY: function (index, datasetIndex) {
- var me = this;
- var meta = me.getMeta();
- var yScale = me.getScaleForId(meta.yAxisID);
- var barIndex = me.getBarIndex(datasetIndex);
-
- var ruler = me.getRuler(index);
- 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);
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.bar = {\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "category",\r
+\r
+ // Specific to Bar Controller\r
+ categoryPercentage: 0.8,\r
+ barPercentage: 0.9,\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ offsetGridLines: true\r
+ }\r
+ }],\r
+ yAxes: [{\r
+ type: "linear"\r
+ }]\r
+ }\r
+ };\r
+\r
+ Chart.controllers.bar = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Rectangle,\r
+\r
+ initialize: function(chart, datasetIndex) {\r
+ Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);\r
+\r
+ // Use this to indicate that this is a bar dataset.\r
+ this.getMeta().bar = true;\r
+ },\r
+\r
+ // Get the number of datasets that display bars. We use this to correctly calculate the bar width\r
+ getBarCount: function getBarCount() {\r
+ var barCount = 0;\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ var meta = this.chart.getDatasetMeta(datasetIndex);\r
+ if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {\r
+ ++barCount;\r
+ }\r
+ }, this);\r
+ return barCount;\r
+ },\r
+\r
+ update: function update(reset) {\r
+ helpers.each(this.getMeta().data, function(rectangle, index) {\r
+ this.updateElement(rectangle, index, reset);\r
+ }, this);\r
+ },\r
+\r
+ updateElement: function updateElement(rectangle, index, reset) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var scaleBase = yScale.getBasePixel();\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+ var custom = rectangle.custom || {};\r
+ var dataset = this.getDataset();\r
+\r
+ helpers.extend(rectangle, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: this.calculateBarX(index, this.index),\r
+ y: reset ? scaleBase : this.calculateBarY(index, this.index),\r
+\r
+ // Tooltip\r
+ label: this.chart.data.labels[index],\r
+ datasetLabel: dataset.label,\r
+\r
+ // Appearance\r
+ base: reset ? scaleBase : this.calculateBarBase(this.index, index),\r
+ width: this.calculateBarWidth(index),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+ borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+ }\r
+ });\r
+ rectangle.pivot();\r
+ },\r
+\r
+ calculateBarBase: function(datasetIndex, index) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var base = 0;\r
+\r
+ if (yScale.options.stacked) {\r
+ var chart = this.chart;\r
+ var datasets = chart.data.datasets;\r
+ var value = datasets[datasetIndex].data[index];\r
+\r
+ if (value < 0) {\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var negDS = datasets[i];\r
+ var negDSMeta = chart.getDatasetMeta(i);\r
+ if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {\r
+ base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
+ }\r
+ }\r
+ } else {\r
+ for (var j = 0; j < datasetIndex; j++) {\r
+ var posDS = datasets[j];\r
+ var posDSMeta = chart.getDatasetMeta(j);\r
+ if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {\r
+ base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(base);\r
+ }\r
+\r
+ return yScale.getBasePixel();\r
+ },\r
+\r
+ getRuler: function(index) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var datasetCount = this.getBarCount();\r
+\r
+ var tickWidth;\r
+\r
+ if (xScale.options.type === 'category') {\r
+ tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);\r
+ } else {\r
+ // Average width\r
+ tickWidth = xScale.width / xScale.ticks.length;\r
+ }\r
+ var categoryWidth = tickWidth * xScale.options.categoryPercentage;\r
+ var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;\r
+ var fullBarWidth = categoryWidth / datasetCount;\r
+\r
+ if (xScale.ticks.length !== this.chart.data.labels.length) {\r
+ var perc = xScale.ticks.length / this.chart.data.labels.length;\r
+ fullBarWidth = fullBarWidth * perc;\r
+ }\r
+\r
+ var barWidth = fullBarWidth * xScale.options.barPercentage;\r
+ var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);\r
+\r
+ return {\r
+ datasetCount: datasetCount,\r
+ tickWidth: tickWidth,\r
+ categoryWidth: categoryWidth,\r
+ categorySpacing: categorySpacing,\r
+ fullBarWidth: fullBarWidth,\r
+ barWidth: barWidth,\r
+ barSpacing: barSpacing\r
+ };\r
+ },\r
+\r
+ calculateBarWidth: function(index) {\r
+ var xScale = this.getScaleForId(this.getMeta().xAxisID);\r
+ var ruler = this.getRuler(index);\r
+ return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;\r
+ },\r
+\r
+ // Get bar index from the given dataset index accounting for the fact that not all bars are visible\r
+ getBarIndex: function(datasetIndex) {\r
+ var barIndex = 0;\r
+ var meta, j;\r
+\r
+ for (j = 0; j < datasetIndex; ++j) {\r
+ meta = this.chart.getDatasetMeta(j);\r
+ if (meta.bar && this.chart.isDatasetVisible(j)) {\r
+ ++barIndex;\r
+ }\r
+ }\r
+\r
+ return barIndex;\r
+ },\r
+\r
+ calculateBarX: function(index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var barIndex = this.getBarIndex(datasetIndex);\r
+\r
+ var ruler = this.getRuler(index);\r
+ var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);\r
+ leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;\r
+\r
+ if (xScale.options.stacked) {\r
+ return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;\r
+ }\r
+\r
+ return leftTick +\r
+ (ruler.barWidth / 2) +\r
+ ruler.categorySpacing +\r
+ (ruler.barWidth * barIndex) +\r
+ (ruler.barSpacing / 2) +\r
+ (ruler.barSpacing * barIndex);\r
+ },\r
+\r
+ calculateBarY: function(index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var value = this.getDataset().data[index];\r
+\r
+ if (yScale.options.stacked) {\r
+\r
+ var sumPos = 0,\r
+ sumNeg = 0;\r
+\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var ds = this.chart.data.datasets[i];\r
+ var dsMeta = this.chart.getDatasetMeta(i);\r
+ if (dsMeta.bar && dsMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return yScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return yScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(value);\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ helpers.each(this.getMeta().data, function(rectangle, index) {\r
+ var d = this.getDataset().data[index];\r
+ if (d !== null && d !== undefined && !isNaN(d)) {\r
+ rectangle.transition(easingDecimal).draw();\r
+ }\r
+ }, this);\r
+ },\r
+\r
+ setHoverStyle: function(rectangle) {\r
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+ var index = rectangle._index;\r
+\r
+ var custom = rectangle.custom || {};\r
+ var model = rectangle._model;\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(rectangle) {\r
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+ var index = rectangle._index;\r
+ var custom = rectangle.custom || {};\r
+ var model = rectangle._model;\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);\r
+ }\r
+\r
+ });\r
+\r
+\r
+ // including horizontalBar in the bar file, instead of a file of its own\r
+ // it extends bar (like pie extends doughnut)\r
+ Chart.defaults.horizontalBar = {\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear",\r
+ position: "bottom"\r
+ }],\r
+ yAxes: [{\r
+ position: "left",\r
+ type: "category",\r
+\r
+ // Specific to Horizontal Bar Controller\r
+ categoryPercentage: 0.8,\r
+ barPercentage: 0.9,\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ offsetGridLines: true\r
+ }\r
+ }]\r
+ },\r
+ elements: {\r
+ rectangle: {\r
+ borderSkipped: 'left'\r
+ }\r
+ },\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Pick first xLabel for now\r
+ var title = '';\r
+\r
+ if (tooltipItems.length > 0) {\r
+ if (tooltipItems[0].yLabel) {\r
+ title = tooltipItems[0].yLabel;\r
+ } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
+ title = data.labels[tooltipItems[0].index];\r
+ }\r
+ }\r
+\r
+ return title;\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ return datasetLabel + ': ' + tooltipItem.xLabel;\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.horizontalBar = Chart.controllers.bar.extend({\r
+ updateElement: function updateElement(rectangle, index, reset, numBars) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var scaleBase = xScale.getBasePixel();\r
+ var custom = rectangle.custom || {};\r
+ var dataset = this.getDataset();\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+\r
+ helpers.extend(rectangle, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? scaleBase : this.calculateBarX(index, this.index),\r
+ y: this.calculateBarY(index, this.index),\r
+\r
+ // Tooltip\r
+ label: this.chart.data.labels[index],\r
+ datasetLabel: dataset.label,\r
+\r
+ // Appearance\r
+ base: reset ? scaleBase : this.calculateBarBase(this.index, index),\r
+ height: this.calculateBarHeight(index),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+ borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+ },\r
+\r
+ draw: function () {\r
+\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ var halfHeight = vm.height / 2,\r
+ topY = vm.y - halfHeight,\r
+ bottomY = vm.y + halfHeight,\r
+ right = vm.base - (vm.base - vm.x),\r
+ halfStroke = vm.borderWidth / 2;\r
+\r
+ // Canvas doesn't allow us to stroke inside the width so we can\r
+ // adjust the sizes to fit if we're setting a stroke on the line\r
+ if (vm.borderWidth) {\r
+ topY += halfStroke;\r
+ bottomY -= halfStroke;\r
+ right += halfStroke;\r
+ }\r
+\r
+ ctx.beginPath();\r
+\r
+ ctx.fillStyle = vm.backgroundColor;\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ // Corner points, from bottom-left to bottom-right clockwise\r
+ // | 1 2 |\r
+ // | 0 3 |\r
+ var corners = [\r
+ [vm.base, bottomY],\r
+ [vm.base, topY],\r
+ [right, topY],\r
+ [right, bottomY]\r
+ ];\r
+\r
+ // Find first (starting) corner with fallback to 'bottom'\r
+ var borders = ['bottom', 'left', 'top', 'right'];\r
+ var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
+ if (startCorner === -1)\r
+ startCorner = 0;\r
+\r
+ function cornerAt(index) {\r
+ return corners[(startCorner + index) % 4];\r
+ }\r
+\r
+ // Draw rectangle from 'startCorner'\r
+ ctx.moveTo.apply(ctx, cornerAt(0));\r
+ for (var i = 1; i < 4; i++)\r
+ ctx.lineTo.apply(ctx, cornerAt(i));\r
+\r
+ ctx.fill();\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ },\r
+\r
+ inRange: function (mouseX, mouseY) {\r
+ var vm = this._view;\r
+ var inRange = false;\r
+\r
+ if (vm) {\r
+ if (vm.x < vm.base) {\r
+ inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);\r
+ } else {\r
+ inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);\r
+ }\r
+ }\r
+\r
+ return inRange;\r
+ }\r
+ });\r
+\r
+ rectangle.pivot();\r
+ },\r
+\r
+ calculateBarBase: function (datasetIndex, index) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var base = 0;\r
+\r
+ if (xScale.options.stacked) {\r
+\r
+ var value = this.chart.data.datasets[datasetIndex].data[index];\r
+\r
+ if (value < 0) {\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var negDS = this.chart.data.datasets[i];\r
+ var negDSMeta = this.chart.getDatasetMeta(i);\r
+ if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {\r
+ base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
+ }\r
+ }\r
+ } else {\r
+ for (var j = 0; j < datasetIndex; j++) {\r
+ var posDS = this.chart.data.datasets[j];\r
+ var posDSMeta = this.chart.getDatasetMeta(j);\r
+ if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(j)) {\r
+ base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ return xScale.getPixelForValue(base);\r
+ }\r
+\r
+ return xScale.getBasePixel();\r
+ },\r
+\r
+ getRuler: function (index) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var datasetCount = this.getBarCount();\r
+\r
+ var tickHeight;\r
+ if (yScale.options.type === 'category') {\r
+ tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);\r
+ } else {\r
+ // Average width\r
+ tickHeight = yScale.width / yScale.ticks.length;\r
+ }\r
+ var categoryHeight = tickHeight * yScale.options.categoryPercentage;\r
+ var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;\r
+ var fullBarHeight = categoryHeight / datasetCount;\r
+\r
+ if (yScale.ticks.length !== this.chart.data.labels.length) {\r
+ var perc = yScale.ticks.length / this.chart.data.labels.length;\r
+ fullBarHeight = fullBarHeight * perc;\r
+ }\r
+\r
+ var barHeight = fullBarHeight * yScale.options.barPercentage;\r
+ var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);\r
+\r
+ return {\r
+ datasetCount: datasetCount,\r
+ tickHeight: tickHeight,\r
+ categoryHeight: categoryHeight,\r
+ categorySpacing: categorySpacing,\r
+ fullBarHeight: fullBarHeight,\r
+ barHeight: barHeight,\r
+ barSpacing: barSpacing,\r
+ };\r
+ },\r
+\r
+ calculateBarHeight: function (index) {\r
+ var yScale = this.getScaleForId(this.getMeta().yAxisID);\r
+ var ruler = this.getRuler(index);\r
+ return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;\r
+ },\r
+\r
+ calculateBarX: function (index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var value = this.getDataset().data[index];\r
+\r
+ if (xScale.options.stacked) {\r
+\r
+ var sumPos = 0,\r
+ sumNeg = 0;\r
+\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var ds = this.chart.data.datasets[i];\r
+ var dsMeta = this.chart.getDatasetMeta(i);\r
+ if (dsMeta.bar && dsMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return xScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return xScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return xScale.getPixelForValue(value);\r
+ },\r
+\r
+ calculateBarY: function (index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var barIndex = this.getBarIndex(datasetIndex);\r
+\r
+ var ruler = this.getRuler(index);\r
+ var topTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);\r
+ topTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;\r
+\r
+ if (yScale.options.stacked) {\r
+ return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;\r
+ }\r
+\r
+ return topTick +\r
+ (ruler.barHeight / 2) +\r
+ ruler.categorySpacing +\r
+ (ruler.barHeight * barIndex) +\r
+ (ruler.barSpacing / 2) +\r
+ (ruler.barSpacing * barIndex);\r
+ }\r
+ });\r
+};\r
},{}],16:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.bubble = {
- hover: {
- mode: "single"
- },
-
- scales: {
- xAxes: [{
- type: "linear", // bubble should probably use a linear scale by default
- position: "bottom",
- id: "x-axis-0" // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: "linear",
- position: "left",
- id: "y-axis-0"
- }]
- },
-
- tooltips: {
- callbacks: {
- title: function(tooltipItems, data) {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
- return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';
- }
- }
- }
- };
-
- Chart.controllers.bubble = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Point,
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var points = meta.data;
-
- // Update Points
- helpers.each(points, function(point, index) {
- me.updateElement(point, index, reset);
- });
- },
-
- updateElement: function(point, index, reset) {
- var me = this;
- var meta = me.getMeta();
- var xScale = me.getScaleForId(meta.xAxisID);
- var yScale = me.getScaleForId(meta.yAxisID);
-
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var data = dataset.data[index];
- var pointElementOptions = me.chart.options.elements.point;
- var dsIndex = me.index;
-
- helpers.extend(point, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: dsIndex,
- _index: index,
-
- // Desired view properties
- _model: {
- x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, dsIndex, me.chart.isCombo),
- y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex),
- // Appearance
- radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data),
-
- // Tooltip
- hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
- }
- });
-
- // Trick to reset the styles of the point
- Chart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions);
-
- var model = point._model;
- model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));
-
- point.pivot();
- },
-
- getRadius: function(value) {
- return value.r || this.chart.options.elements.point.radius;
- },
-
- setHoverStyle: function(point) {
- var me = this;
- Chart.DatasetController.prototype.setHoverStyle.call(me, point);
-
- // Radius
- var dataset = me.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
- model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]);
- },
-
- removeHoverStyle: function(point) {
- var me = this;
- Chart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point);
-
- var dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index];
- var custom = point.custom || {};
- var model = point._model;
-
- model.radius = custom.radius ? custom.radius : me.getRadius(dataVal);
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.bubble = {\r
+ hover: {\r
+ mode: "single"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear", // bubble should probably use a linear scale by default\r
+ position: "bottom",\r
+ id: "x-axis-0" // need an ID so datasets can reference the scale\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ position: "left",\r
+ id: "y-axis-0"\r
+ }]\r
+ },\r
+\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Title doesn't make sense for scatter since we format the data as a point\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
+ return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.bubble = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ update: function update(reset) {\r
+ var meta = this.getMeta();\r
+ var points = meta.data;\r
+\r
+ // Update Points\r
+ helpers.each(points, function(point, index) {\r
+ this.updateElement(point, index, reset);\r
+ }, this);\r
+ },\r
+\r
+ updateElement: function(point, index, reset) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+\r
+ var custom = point.custom || {};\r
+ var dataset = this.getDataset();\r
+ var data = dataset.data[index];\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ helpers.extend(point, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, this.index, this.chart.isCombo),\r
+ y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, this.index),\r
+ // Appearance\r
+ radius: reset ? 0 : custom.radius ? custom.radius : this.getRadius(data),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor),\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth),\r
+\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\r
+ }\r
+ });\r
+\r
+ var model = point._model;\r
+ model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));\r
+\r
+ point.pivot();\r
+ },\r
+\r
+ getRadius: function(value) {\r
+ return value.r || this.chart.options.elements.point.radius;\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ model.radius = custom.radius ? custom.radius : this.getRadius(dataset.data[point._index]);\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth);\r
+ }\r
+ });\r
+};\r
},{}],17:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- defaults = Chart.defaults;
-
- defaults.doughnut = {
- animation: {
- //Boolean - Whether we animate the rotation of the Doughnut
- animateRotate: true,
- //Boolean - Whether we animate scaling the Doughnut from the centre
- animateScale: false
- },
- aspectRatio: 1,
- hover: {
- mode: 'single'
- },
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('</li>');
- }
- }
-
- text.push('</ul>');
- return text.join("");
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc.custom || {};
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- } else {
- return [];
- }
- }
- },
-
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
-
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- meta.data[index].hidden = !meta.data[index].hidden;
- }
-
- chart.update();
- }
- },
-
- //The percentage of the chart that we cut out of the middle.
- cutoutPercentage: 50,
-
- //The rotation of the chart, where the first data arc begins.
- rotation: Math.PI * -0.5,
-
- //The total circumference of the chart.
- circumference: Math.PI * 2.0,
-
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
- }
- }
- }
- };
-
- defaults.pie = helpers.clone(defaults.doughnut);
- helpers.extend(defaults.pie, {
- cutoutPercentage: 0
- });
-
-
- Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Arc,
-
- linkScales: helpers.noop,
-
- // 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 (this.chart.isDatasetVisible(j)) {
- ++ringIndex;
- }
- }
-
- return ringIndex;
- },
-
- update: function update(reset) {
- var me = this;
- var chart = me.chart,
- chartArea = chart.chartArea,
- opts = chart.options,
- arcOpts = opts.elements.arc,
- availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
- availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
- minSize = Math.min(availableWidth, availableHeight),
- offset = {
- x: 0,
- y: 0
- },
- meta = me.getMeta(),
- cutoutPercentage = opts.cutoutPercentage,
- circumference = opts.circumference;
-
- // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
- if (circumference < Math.PI * 2.0) {
- var startAngle = opts.rotation % (Math.PI * 2.0);
- startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
- var endAngle = startAngle + circumference;
- var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
- var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
- var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
- var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
- var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
- var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
- var cutout = cutoutPercentage / 100.0;
- var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
- var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
- var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
- minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
- offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
- }
-
- chart.outerRadius = Math.max(minSize / 2, 0);
- chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);
- chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
- chart.offsetX = offset.x * chart.outerRadius;
- chart.offsetY = offset.y * chart.outerRadius;
-
- meta.total = me.calculateTotal();
-
- me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
- me.innerRadius = me.outerRadius - chart.radiusLength;
-
- helpers.each(meta.data, function(arc, index) {
- me.updateElement(arc, index, reset);
- });
- },
-
- updateElement: function(arc, index, reset) {
- var me = this;
- var chart = me.chart,
- chartArea = chart.chartArea,
- opts = chart.options,
- animationOpts = opts.animation,
- arcOpts = opts.elements.arc,
- centerX = (chartArea.left + chartArea.right) / 2,
- centerY = (chartArea.top + chartArea.bottom) / 2,
- startAngle = opts.rotation, // non reset case handled later
- endAngle = opts.rotation, // non reset case handled later
- dataset = me.getDataset(),
- circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),
- innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius,
- outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius,
- custom = arc.custom || {},
- valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
-
- helpers.extend(arc, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: centerX + chart.offsetX,
- y: centerY + chart.offsetY,
- startAngle: startAngle,
- endAngle: endAngle,
- circumference: circumference,
- outerRadius: outerRadius,
- innerRadius: innerRadius,
- label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
- }
- });
-
- var model = arc._model;
- // Resets the visual styles
- this.removeHoverStyle(arc);
-
- // Set correct angles if not resetting
- if (!reset || !animationOpts.animateRotate) {
- if (index === 0) {
- model.startAngle = opts.rotation;
- } else {
- model.startAngle = me.getMeta().data[index - 1]._model.endAngle;
- }
-
- model.endAngle = model.startAngle + model.circumference;
- }
-
- arc.pivot();
- },
-
- removeHoverStyle: function(arc) {
- Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
- },
-
- calculateTotal: function() {
- var dataset = this.getDataset();
- var meta = this.getMeta();
- var total = 0;
- var value;
-
- helpers.each(meta.data, function(element, index) {
- value = dataset.data[index];
- if (!isNaN(value) && !element.hidden) {
- total += Math.abs(value);
- }
- });
-
- return total;
- },
-
- calculateCircumference: function(value) {
- var total = this.getMeta().total;
- if (total > 0 && !isNaN(value)) {
- return (Math.PI * 2.0) * (value / total);
- } else {
- return 0;
- }
- }
- });
-};
-
-},{}],18:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.line = {
- showLines: true,
-
- hover: {
- mode: "label"
- },
-
- scales: {
- xAxes: [{
- type: "category",
- id: 'x-axis-0'
- }],
- yAxes: [{
- type: "linear",
- id: 'y-axis-0'
- }]
- }
- };
-
- function lineEnabled(dataset, options) {
- return helpers.getValueOrDefault(dataset.showLine, options.showLines);
- }
-
- Chart.controllers.line = Chart.DatasetController.extend({
-
- datasetElementType: Chart.elements.Line,
-
- dataElementType: Chart.elements.Point,
-
- addElementAndReset: function(index) {
- var me = this;
- var options = me.chart.options;
- var meta = me.getMeta();
-
- Chart.DatasetController.prototype.addElementAndReset.call(me, index);
-
- // Make sure bezier control points are updated
- if (lineEnabled(me.getDataset(), options) && meta.dataset._model.tension !== 0) {
- me.updateBezierControlPoints();
- }
- },
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var line = meta.dataset;
- var points = meta.data || [];
- var options = me.chart.options;
- var lineElementOptions = options.elements.line;
- var scale = me.getScaleForId(meta.yAxisID);
- var i, ilen, custom;
- var dataset = me.getDataset();
- var showLine = lineEnabled(dataset, options);
-
- // Update Line
- if (showLine) {
- custom = line.custom || {};
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
- dataset.lineTension = dataset.tension;
- }
-
- // Utility
- line._scale = scale;
- line._datasetIndex = me.index;
- // Data
- line._children = points;
- // Model
- line._model = {
- // Appearance
- // The default behavior of lines is to break at null values, according
- // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
- // This option gives linse the ability to span gaps
- spanGaps: dataset.spanGaps ? dataset.spanGaps : false,
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
- borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
- borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
- borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
- borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
- borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
- fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
- // Scale
- scaleTop: scale.top,
- scaleBottom: scale.bottom,
- scaleZero: scale.getBasePixel()
- };
-
- line.pivot();
- }
-
- // Update Points
- for (i=0, ilen=points.length; i<ilen; ++i) {
- me.updateElement(points[i], i, reset);
- }
-
- if (showLine && line._model.tension !== 0) {
- me.updateBezierControlPoints();
- }
-
- // Now pivot the point for animation
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].pivot();
- }
- },
-
- getPointBackgroundColor: function(point, index) {
- var backgroundColor = this.chart.options.elements.point.backgroundColor;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.backgroundColor) {
- backgroundColor = custom.backgroundColor;
- } else if (dataset.pointBackgroundColor) {
- backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
- } else if (dataset.backgroundColor) {
- backgroundColor = dataset.backgroundColor;
- }
-
- return backgroundColor;
- },
-
- getPointBorderColor: function(point, index) {
- var borderColor = this.chart.options.elements.point.borderColor;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.borderColor) {
- borderColor = custom.borderColor;
- } else if (dataset.pointBorderColor) {
- borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
- } else if (dataset.borderColor) {
- borderColor = dataset.borderColor;
- }
-
- return borderColor;
- },
-
- getPointBorderWidth: function(point, index) {
- var borderWidth = this.chart.options.elements.point.borderWidth;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.borderWidth) {
- borderWidth = custom.borderWidth;
- } else if (dataset.pointBorderWidth) {
- borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
- } else if (dataset.borderWidth) {
- borderWidth = dataset.borderWidth;
- }
-
- return borderWidth;
- },
-
- updateElement: function(point, index, reset) {
- var me = this;
- var meta = me.getMeta();
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var datasetIndex = me.index;
- var value = dataset.data[index];
- var yScale = me.getScaleForId(meta.yAxisID);
- var xScale = me.getScaleForId(meta.xAxisID);
- var pointOptions = me.chart.options.elements.point;
- var x, y;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
- dataset.pointRadius = dataset.radius;
- }
- if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
- dataset.pointHitRadius = dataset.hitRadius;
- }
-
- x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);
- y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);
-
- // Utility
- point._xScale = xScale;
- point._yScale = yScale;
- point._datasetIndex = datasetIndex;
- point._index = index;
-
- // Desired view properties
- point._model = {
- x: x,
- y: y,
- skip: custom.skip || isNaN(x) || isNaN(y),
- // Appearance
- radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
- pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
- backgroundColor: me.getPointBackgroundColor(point, index),
- borderColor: me.getPointBorderColor(point, index),
- borderWidth: me.getPointBorderWidth(point, index),
- tension: meta.dataset._model ? meta.dataset._model.tension : 0,
- // Tooltip
- hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
- };
- },
-
- calculatePointY: function(value, index, datasetIndex, isCombo) {
- var me = this;
- var chart = me.chart;
- var meta = me.getMeta();
- var yScale = me.getScaleForId(meta.yAxisID);
- var sumPos = 0;
- var sumNeg = 0;
- var i, ds, dsMeta;
-
- if (yScale.options.stacked) {
- for (i = 0; i < datasetIndex; i++) {
- ds = chart.data.datasets[i];
- dsMeta = chart.getDatasetMeta(i);
- if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return yScale.getPixelForValue(sumNeg + value);
- } else {
- return yScale.getPixelForValue(sumPos + value);
- }
- }
-
- return yScale.getPixelForValue(value);
- },
-
- updateBezierControlPoints: function() {
- var meta = this.getMeta();
- var area = this.chart.chartArea;
- var points = meta.data || [];
- var i, ilen, point, model, controlPoints;
-
- for (i=0, ilen=points.length; i<ilen; ++i) {
- point = points[i];
- model = point._model;
- controlPoints = helpers.splineCurve(
- helpers.previousItem(points, i)._model,
- model,
- helpers.nextItem(points, i)._model,
- meta.dataset._model.tension
- );
-
- // Prevent the bezier going outside of the bounds of the graph
- model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, area.right), area.left);
- model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, area.bottom), area.top);
- model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, area.right), area.left);
- model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, area.bottom), area.top);
- }
- },
-
- draw: function(ease) {
- var me = this;
- var meta = me.getMeta();
- var points = meta.data || [];
- var easingDecimal = ease || 1;
- var i, ilen;
-
- // Transition Point Locations
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].transition(easingDecimal);
- }
-
- // Transition and Draw the line
- if (lineEnabled(me.getDataset(), me.chart.options)) {
- meta.dataset.transition(easingDecimal).draw();
- }
-
- // Draw the points
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].draw();
- }
- },
-
- setHoverStyle: function(point) {
- // Point
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
-
- model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
- model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
- },
-
- removeHoverStyle: function(point) {
- var me = this;
- var dataset = me.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
- dataset.pointRadius = dataset.radius;
- }
-
- model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);
- model.backgroundColor = me.getPointBackgroundColor(point, index);
- model.borderColor = me.getPointBorderColor(point, index);
- model.borderWidth = me.getPointBorderWidth(point, index);
- }
- });
-};
-
-},{}],19:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.polarArea = {
-
- scale: {
- type: "radialLinear",
- lineArc: true // so that lines are circular
- },
-
- //Boolean - Whether to animate the rotation of the chart
- animation: {
- animateRotate: true,
- animateScale: true
- },
-
- aspectRatio: 1,
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('</span></li>');
- }
- }
-
- text.push('</ul>');
- return text.join("");
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc.custom || {};
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- } else {
- return [];
- }
- }
- },
-
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
-
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- meta.data[index].hidden = !meta.data[index].hidden;
- }
-
- chart.update();
- }
- },
-
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;
- }
- }
- }
- };
-
- Chart.controllers.polarArea = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Arc,
-
- linkScales: helpers.noop,
-
- update: function update(reset) {
- var me = this;
- var chart = me.chart;
- var chartArea = chart.chartArea;
- var meta = me.getMeta();
- var opts = chart.options;
- var arcOpts = opts.elements.arc;
- var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
- chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);
- chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
- chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
-
- me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
- me.innerRadius = me.outerRadius - chart.radiusLength;
-
- meta.count = me.countVisibleElements();
-
- helpers.each(meta.data, function(arc, index) {
- me.updateElement(arc, index, reset);
- });
- },
-
- updateElement: function(arc, index, reset) {
- var me = this;
- var chart = me.chart;
- var chartArea = chart.chartArea;
- var dataset = me.getDataset();
- var opts = chart.options;
- var animationOpts = opts.animation;
- var arcOpts = opts.elements.arc;
- var custom = arc.custom || {};
- var scale = chart.scale;
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var labels = chart.data.labels;
-
- var circumference = me.calculateCircumference(dataset.data[index]);
- var centerX = (chartArea.left + chartArea.right) / 2;
- var centerY = (chartArea.top + chartArea.bottom) / 2;
-
- // If there is NaN data before us, we need to calculate the starting angle correctly.
- // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
- var visibleCount = 0;
- var meta = me.getMeta();
- for (var i = 0; i < index; ++i) {
- if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {
- ++visibleCount;
- }
- }
-
- var negHalfPI = -0.5 * Math.PI;
- var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
- var startAngle = (negHalfPI) + (circumference * visibleCount);
- var endAngle = startAngle + (arc.hidden ? 0 : circumference);
-
- var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
-
- helpers.extend(arc, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
- _scale: scale,
-
- // Desired view properties
- _model: {
- x: centerX,
- y: centerY,
- innerRadius: 0,
- outerRadius: reset ? resetRadius : distance,
- startAngle: reset && animationOpts.animateRotate ? negHalfPI : startAngle,
- endAngle: reset && animationOpts.animateRotate ? negHalfPI : endAngle,
- label: getValueAtIndexOrDefault(labels, index, labels[index])
- }
- });
-
- // Apply border and fill style
- me.removeHoverStyle(arc);
-
- arc.pivot();
- },
-
- removeHoverStyle: function(arc) {
- Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
- },
-
- countVisibleElements: function() {
- var dataset = this.getDataset();
- var meta = this.getMeta();
- var count = 0;
-
- helpers.each(meta.data, function(element, index) {
- if (!isNaN(dataset.data[index]) && !element.hidden) {
- count++;
- }
- });
-
- return count;
- },
-
- calculateCircumference: function(value) {
- var count = this.getMeta().count;
- if (count > 0 && !isNaN(value)) {
- return (2 * Math.PI) / count;
- } else {
- return 0;
- }
- }
- });
-};
-
-},{}],20:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.radar = {
- scale: {
- type: "radialLinear"
- },
- elements: {
- line: {
- tension: 0 // no bezier in radar
- }
- }
- };
-
- Chart.controllers.radar = Chart.DatasetController.extend({
-
- datasetElementType: Chart.elements.Line,
-
- dataElementType: Chart.elements.Point,
-
- linkScales: helpers.noop,
-
- addElementAndReset: function(index) {
- Chart.DatasetController.prototype.addElementAndReset.call(this, index);
-
- // Make sure bezier control points are updated
- this.updateBezierControlPoints();
- },
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var line = meta.dataset;
- var points = meta.data;
- var custom = line.custom || {};
- var dataset = me.getDataset();
- var lineElementOptions = me.chart.options.elements.line;
- var scale = me.chart.scale;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
- dataset.lineTension = dataset.tension;
- }
-
- helpers.extend(meta.dataset, {
- // Utility
- _datasetIndex: me.index,
- // Data
- _children: points,
- _loop: true,
- // Model
- _model: {
- // Appearance
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
- borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
- fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
- borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
- borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
- borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
- borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
-
- // Scale
- scaleTop: scale.top,
- scaleBottom: scale.bottom,
- scaleZero: scale.getBasePosition()
- }
- });
-
- meta.dataset.pivot();
-
- // Update Points
- helpers.each(points, function(point, index) {
- me.updateElement(point, index, reset);
- }, me);
-
-
- // Update bezier control points
- me.updateBezierControlPoints();
- },
- updateElement: function(point, index, reset) {
- var me = this;
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var scale = me.chart.scale;
- var pointElementOptions = me.chart.options.elements.point;
- var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
-
- helpers.extend(point, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
- _scale: scale,
-
- // Desired view properties
- _model: {
- x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
- y: reset ? scale.yCenter : pointPosition.y,
-
- // Appearance
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.tension, me.chart.options.elements.line.tension),
- radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),
- borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),
- pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),
-
- // Tooltip
- hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
- }
- });
-
- point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
- },
- updateBezierControlPoints: function() {
- var chartArea = this.chart.chartArea;
- var meta = this.getMeta();
-
- helpers.each(meta.data, function(point, index) {
- var model = point._model;
- var controlPoints = helpers.splineCurve(
- helpers.previousItem(meta.data, index, true)._model,
- model,
- helpers.nextItem(meta.data, index, true)._model,
- model.tension
- );
-
- // Prevent the bezier going outside of the bounds of the graph
- model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
- model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
-
- model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
- model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
-
- // Now pivot the point for animation
- point.pivot();
- });
- },
-
- draw: function(ease) {
- var meta = this.getMeta();
- var easingDecimal = ease || 1;
-
- // Transition Point Locations
- helpers.each(meta.data, function(point, index) {
- point.transition(easingDecimal);
- });
-
- // Transition and Draw the line
- meta.dataset.transition(easingDecimal).draw();
-
- // Draw the points
- helpers.each(meta.data, function(point) {
- point.draw();
- });
- },
-
- setHoverStyle: function(point) {
- // Point
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var custom = point.custom || {};
- var index = point._index;
- var model = point._model;
-
- model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
- model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
- },
-
- removeHoverStyle: function(point) {
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var custom = point.custom || {};
- var index = point._index;
- var model = point._model;
- var pointElementOptions = this.chart.options.elements.point;
-
- model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);
- model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);
- model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);
- model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);
- }
- });
-};
-
-},{}],21:[function(require,module,exports){
-/*global window: false */
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.animation = {
- duration: 1000,
- easing: "easeOutQuart",
- onProgress: helpers.noop,
- onComplete: helpers.noop
- };
-
- Chart.Animation = Chart.Element.extend({
- currentStep: null, // the current animation step
- numSteps: 60, // default number of steps
- easing: "", // the easing to use for this animation
- render: null, // render function used by the animation service
-
- onAnimationProgress: null, // user specified callback to fire on each step of the animation
- onAnimationComplete: null // user specified callback to fire when the animation finishes
- });
-
- Chart.animationService = {
- frameDuration: 17,
- animations: [],
- dropFrames: 0,
- request: null,
- addAnimation: function(chartInstance, animationObject, duration, lazy) {
- var me = this;
-
- if (!lazy) {
- chartInstance.animating = true;
- }
-
- for (var index = 0; index < me.animations.length; ++index) {
- if (me.animations[index].chartInstance === chartInstance) {
- // replacing an in progress animation
- me.animations[index].animationObject = animationObject;
- return;
- }
- }
-
- me.animations.push({
- chartInstance: chartInstance,
- animationObject: animationObject
- });
-
- // If there are no animations queued, manually kickstart a digest, for lack of a better word
- if (me.animations.length === 1) {
- me.requestAnimationFrame();
- }
- },
- // Cancel the animation for a given chart instance
- cancelAnimation: function(chartInstance) {
- var index = helpers.findIndex(this.animations, function(animationWrapper) {
- return animationWrapper.chartInstance === chartInstance;
- });
-
- if (index !== -1) {
- this.animations.splice(index, 1);
- chartInstance.animating = false;
- }
- },
- requestAnimationFrame: function() {
- var me = this;
- if (me.request === null) {
- // Skip animation frame requests until the active one is executed.
- // This can happen when processing mouse events, e.g. 'mousemove'
- // and 'mouseout' events will trigger multiple renders.
- me.request = helpers.requestAnimFrame.call(window, function() {
- me.request = null;
- me.startDigest();
- });
- }
- },
- startDigest: function() {
- var me = this;
-
- var startTime = Date.now();
- var framesToDrop = 0;
-
- if (me.dropFrames > 1) {
- framesToDrop = Math.floor(me.dropFrames);
- me.dropFrames = me.dropFrames % 1;
- }
-
- var i = 0;
- while (i < me.animations.length) {
- if (me.animations[i].animationObject.currentStep === null) {
- me.animations[i].animationObject.currentStep = 0;
- }
-
- me.animations[i].animationObject.currentStep += 1 + framesToDrop;
-
- if (me.animations[i].animationObject.currentStep > me.animations[i].animationObject.numSteps) {
- me.animations[i].animationObject.currentStep = me.animations[i].animationObject.numSteps;
- }
-
- me.animations[i].animationObject.render(me.animations[i].chartInstance, me.animations[i].animationObject);
- if (me.animations[i].animationObject.onAnimationProgress && me.animations[i].animationObject.onAnimationProgress.call) {
- me.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance, me.animations[i]);
- }
-
- if (me.animations[i].animationObject.currentStep === me.animations[i].animationObject.numSteps) {
- if (me.animations[i].animationObject.onAnimationComplete && me.animations[i].animationObject.onAnimationComplete.call) {
- me.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance, me.animations[i]);
- }
-
- // executed the last frame. Remove the animation.
- me.animations[i].chartInstance.animating = false;
-
- me.animations.splice(i, 1);
- } else {
- ++i;
- }
- }
-
- var endTime = Date.now();
- var dropFrames = (endTime - startTime) / me.frameDuration;
-
- me.dropFrames += dropFrames;
-
- // Do we have more stuff to animate?
- if (me.animations.length > 0) {
- me.requestAnimationFrame();
- }
- }
- };
-};
-},{}],22:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- //Create a dictionary of chart types, to allow for extension of existing types
- Chart.types = {};
-
- //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
- //Destroy method on the chart will remove the instance of the chart from this reference.
- Chart.instances = {};
-
- // Controllers available for dataset visualization eg. bar, line, slice, etc.
- Chart.controllers = {};
-
- // The main controller of a chart
- Chart.Controller = function(instance) {
-
- this.chart = instance;
- this.config = instance.config;
- this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});
- this.id = helpers.uid();
-
- Object.defineProperty(this, 'data', {
- get: function() {
- return this.config.data;
- }
- });
-
- //Add the chart instance to the global namespace
- Chart.instances[this.id] = this;
-
- if (this.options.responsive) {
- // Silent resize before chart draws
- this.resize(true);
- }
-
- this.initialize();
-
- return this;
- };
-
- helpers.extend(Chart.Controller.prototype, {
-
- initialize: function initialize() {
- var me = this;
- // Before init plugin notification
- Chart.pluginService.notifyPlugins('beforeInit', [me]);
-
- me.bindEvents();
-
- // Make sure controllers are built first so that each dataset is bound to an axis before the scales
- // are built
- me.ensureScalesHaveIDs();
- me.buildOrUpdateControllers();
- me.buildScales();
- me.updateLayout();
- me.resetElements();
- me.initToolTip();
- me.update();
-
- // After init plugin notification
- Chart.pluginService.notifyPlugins('afterInit', [me]);
-
- return me;
- },
-
- clear: function clear() {
- helpers.clear(this.chart);
- return this;
- },
-
- stop: function stop() {
- // Stops any current animation loop occuring
- Chart.animationService.cancelAnimation(this);
- return this;
- },
-
- resize: function resize(silent) {
- var me = this;
- var chart = me.chart;
- var canvas = chart.canvas;
- var newWidth = helpers.getMaximumWidth(canvas);
- var aspectRatio = chart.aspectRatio;
- var newHeight = (me.options.maintainAspectRatio && isNaN(aspectRatio) === false && isFinite(aspectRatio) && aspectRatio !== 0) ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas);
-
- var sizeChanged = chart.width !== newWidth || chart.height !== newHeight;
-
- if (!sizeChanged) {
- return me;
- }
-
- canvas.width = chart.width = newWidth;
- canvas.height = chart.height = newHeight;
-
- helpers.retinaScale(chart);
-
- // Notify any plugins about the resize
- var newSize = { width: newWidth, height: newHeight };
- Chart.pluginService.notifyPlugins('resize', [me, newSize]);
-
- // Notify of resize
- if (me.options.onResize) {
- me.options.onResize(me, newSize);
- }
-
- if (!silent) {
- me.stop();
- me.update(me.options.responsiveAnimationDuration);
- }
-
- return me;
- },
-
- ensureScalesHaveIDs: function ensureScalesHaveIDs() {
- var options = this.options;
- var scalesOptions = options.scales || {};
- var scaleOptions = options.scale;
-
- helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
- xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
- });
-
- helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {
- yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
- });
-
- if (scaleOptions) {
- scaleOptions.id = scaleOptions.id || 'scale';
- }
- },
-
- /**
- * Builds a map of scale ID to scale object for future lookup.
- */
- buildScales: function buildScales() {
- var me = this;
- var options = me.options;
- var scales = me.scales = {};
- var items = [];
-
- if (options.scales) {
- items = items.concat(
- (options.scales.xAxes || []).map(function(xAxisOptions) {
- return { options: xAxisOptions, dtype: 'category' }; }),
- (options.scales.yAxes || []).map(function(yAxisOptions) {
- return { options: yAxisOptions, dtype: 'linear' }; }));
- }
-
- if (options.scale) {
- items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });
- }
-
- helpers.each(items, function(item, index) {
- var scaleOptions = item.options;
- var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);
- var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
- if (!scaleClass) {
- return;
- }
-
- var scale = new scaleClass({
- id: scaleOptions.id,
- options: scaleOptions,
- ctx: me.chart.ctx,
- chart: me
- });
-
- scales[scale.id] = scale;
-
- // TODO(SB): I think we should be able to remove this custom case (options.scale)
- // and consider it as a regular scale part of the "scales"" map only! This would
- // make the logic easier and remove some useless? custom code.
- if (item.isDefault) {
- me.scale = scale;
- }
- });
-
- Chart.scaleService.addScalesToLayout(this);
- },
-
- updateLayout: function() {
- Chart.layoutService.update(this, this.chart.width, this.chart.height);
- },
-
- buildOrUpdateControllers: function buildOrUpdateControllers() {
- var me = this;
- var types = [];
- var newControllers = [];
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- var meta = me.getDatasetMeta(datasetIndex);
- if (!meta.type) {
- meta.type = dataset.type || me.config.type;
- }
-
- types.push(meta.type);
-
- if (meta.controller) {
- meta.controller.updateIndex(datasetIndex);
- } else {
- meta.controller = new Chart.controllers[meta.type](me, datasetIndex);
- newControllers.push(meta.controller);
- }
- }, me);
-
- if (types.length > 1) {
- for (var i = 1; i < types.length; i++) {
- if (types[i] !== types[i - 1]) {
- me.isCombo = true;
- break;
- }
- }
- }
-
- return newControllers;
- },
-
- resetElements: function resetElements() {
- var me = this;
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.reset();
- }, me);
- },
-
- update: function update(animationDuration, lazy) {
- var me = this;
- Chart.pluginService.notifyPlugins('beforeUpdate', [me]);
-
- // In case the entire data object changed
- me.tooltip._data = me.data;
-
- // Make sure dataset controllers are updated and new controllers are reset
- var newControllers = me.buildOrUpdateControllers();
-
- // Make sure all dataset controllers have correct meta data counts
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
- }, me);
-
- Chart.layoutService.update(me, me.chart.width, me.chart.height);
-
- // Apply changes to the dataets that require the scales to have been calculated i.e BorderColor chages
- Chart.pluginService.notifyPlugins('afterScaleUpdate', [me]);
-
- // Can only reset the new controllers after the scales have been updated
- helpers.each(newControllers, function(controller) {
- controller.reset();
- });
-
- // This will loop through any data and do the appropriate element update for the type
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.update();
- }, me);
-
- // Do this before render so that any plugins that need final scale updates can use it
- Chart.pluginService.notifyPlugins('afterUpdate', [me]);
-
- me.render(animationDuration, lazy);
- },
-
- render: function render(duration, lazy) {
- var me = this;
- Chart.pluginService.notifyPlugins('beforeRender', [me]);
-
- var animationOptions = me.options.animation;
- if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
- var animation = new Chart.Animation();
- animation.numSteps = (duration || animationOptions.duration) / 16.66; //60 fps
- animation.easing = animationOptions.easing;
-
- // render function
- animation.render = function(chartInstance, animationObject) {
- var easingFunction = helpers.easingEffects[animationObject.easing];
- var stepDecimal = animationObject.currentStep / animationObject.numSteps;
- var easeDecimal = easingFunction(stepDecimal);
-
- chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
- };
-
- // user events
- animation.onAnimationProgress = animationOptions.onProgress;
- animation.onAnimationComplete = animationOptions.onComplete;
-
- Chart.animationService.addAnimation(me, animation, duration, lazy);
- } else {
- me.draw();
- if (animationOptions && animationOptions.onComplete && animationOptions.onComplete.call) {
- animationOptions.onComplete.call(me);
- }
- }
- return me;
- },
-
- draw: function(ease) {
- var me = this;
- var easingDecimal = ease || 1;
- me.clear();
-
- Chart.pluginService.notifyPlugins('beforeDraw', [me, easingDecimal]);
-
- // Draw all the scales
- helpers.each(me.boxes, function(box) {
- box.draw(me.chartArea);
- }, me);
- if (me.scale) {
- me.scale.draw();
- }
-
- Chart.pluginService.notifyPlugins('beforeDatasetDraw', [me, easingDecimal]);
-
- // Draw each dataset via its respective controller (reversed to support proper line stacking)
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- me.getDatasetMeta(datasetIndex).controller.draw(ease);
- }
- }, me, true);
-
- Chart.pluginService.notifyPlugins('afterDatasetDraw', [me, easingDecimal]);
-
- // Finally draw the tooltip
- me.tooltip.transition(easingDecimal).draw();
-
- Chart.pluginService.notifyPlugins('afterDraw', [me, easingDecimal]);
- },
-
- // Get the single element that was clicked on
- // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
- getElementAtEvent: function(e) {
- var me = this;
- var eventPosition = helpers.getRelativePosition(e, me.chart);
- var elementsArray = [];
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- var meta = me.getDatasetMeta(datasetIndex);
- helpers.each(meta.data, function(element, index) {
- if (element.inRange(eventPosition.x, eventPosition.y)) {
- elementsArray.push(element);
- return elementsArray;
- }
- });
- }
- });
-
- return elementsArray;
- },
-
- getElementsAtEvent: function(e) {
- var me = this;
- var eventPosition = helpers.getRelativePosition(e, me.chart);
- var elementsArray = [];
-
- var found = (function() {
- if (me.data.datasets) {
- for (var i = 0; i < me.data.datasets.length; i++) {
- var meta = me.getDatasetMeta(i);
- if (me.isDatasetVisible(i)) {
- for (var j = 0; j < meta.data.length; j++) {
- if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {
- return meta.data[j];
- }
- }
- }
- }
- }
- }).call(me);
-
- if (!found) {
- return elementsArray;
- }
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- var meta = me.getDatasetMeta(datasetIndex);
- elementsArray.push(meta.data[found._index]);
- }
- }, me);
-
- return elementsArray;
- },
-
- getElementsAtEventForMode: function(e, mode) {
- var me = this;
- switch (mode) {
- case 'single':
- return me.getElementAtEvent(e);
- case 'label':
- return me.getElementsAtEvent(e);
- case 'dataset':
- return me.getDatasetAtEvent(e);
- default:
- return e;
- }
- },
-
- getDatasetAtEvent: function(e) {
- var elementsArray = this.getElementAtEvent(e);
-
- if (elementsArray.length > 0) {
- elementsArray = this.getDatasetMeta(elementsArray[0]._datasetIndex).data;
- }
-
- return elementsArray;
- },
-
- getDatasetMeta: function(datasetIndex) {
- var me = this;
- var dataset = me.data.datasets[datasetIndex];
- if (!dataset._meta) {
- dataset._meta = {};
- }
-
- var meta = dataset._meta[me.id];
- if (!meta) {
- meta = dataset._meta[me.id] = {
- type: null,
- data: [],
- dataset: null,
- controller: null,
- hidden: null, // See isDatasetVisible() comment
- xAxisID: null,
- yAxisID: null
- };
- }
-
- return meta;
- },
-
- getVisibleDatasetCount: function() {
- var count = 0;
- for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {
- if (this.isDatasetVisible(i)) {
- count++;
- }
- }
- return count;
- },
-
- isDatasetVisible: function(datasetIndex) {
- var meta = this.getDatasetMeta(datasetIndex);
-
- // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
- // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
- return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
- },
-
- generateLegend: function generateLegend() {
- return this.options.legendCallback(this);
- },
-
- destroy: function destroy() {
- var me = this;
- me.stop();
- me.clear();
- helpers.unbindEvents(me, me.events);
- helpers.removeResizeListener(me.chart.canvas.parentNode);
-
- // Reset canvas height/width attributes
- var canvas = me.chart.canvas;
- canvas.width = me.chart.width;
- canvas.height = me.chart.height;
-
- // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here
- if (me.chart.originalDevicePixelRatio !== undefined) {
- me.chart.ctx.scale(1 / me.chart.originalDevicePixelRatio, 1 / me.chart.originalDevicePixelRatio);
- }
-
- // Reset to the old style since it may have been changed by the device pixel ratio changes
- canvas.style.width = me.chart.originalCanvasStyleWidth;
- canvas.style.height = me.chart.originalCanvasStyleHeight;
-
- Chart.pluginService.notifyPlugins('destroy', [me]);
-
- delete Chart.instances[me.id];
- },
-
- toBase64Image: function toBase64Image() {
- return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
- },
-
- initToolTip: function initToolTip() {
- var me = this;
- me.tooltip = new Chart.Tooltip({
- _chart: me.chart,
- _chartInstance: me,
- _data: me.data,
- _options: me.options.tooltips
- }, me);
- },
-
- bindEvents: function bindEvents() {
- var me = this;
- helpers.bindEvents(me, me.options.events, function(evt) {
- me.eventHandler(evt);
- });
- },
-
- updateHoverStyle: function(elements, mode, enabled) {
- var method = enabled? 'setHoverStyle' : 'removeHoverStyle';
- var element, i, ilen;
-
- switch (mode) {
- case 'single':
- elements = [ elements[0] ];
- break;
- case 'label':
- case 'dataset':
- // elements = elements;
- break;
- default:
- // unsupported mode
- return;
- }
-
- for (i=0, ilen=elements.length; i<ilen; ++i) {
- element = elements[i];
- if (element) {
- this.getDatasetMeta(element._datasetIndex).controller[method](element);
- }
- }
- },
-
- eventHandler: function eventHandler(e) {
- var me = this;
- var tooltip = me.tooltip;
- var options = me.options || {};
- var hoverOptions = options.hover;
- var tooltipsOptions = options.tooltips;
-
- me.lastActive = me.lastActive || [];
- me.lastTooltipActive = me.lastTooltipActive || [];
-
- // Find Active Elements for hover and tooltips
- if (e.type === 'mouseout') {
- me.active = [];
- me.tooltipActive = [];
- } else {
- me.active = me.getElementsAtEventForMode(e, hoverOptions.mode);
- me.tooltipActive = me.getElementsAtEventForMode(e, tooltipsOptions.mode);
- }
-
- // On Hover hook
- if (hoverOptions.onHover) {
- hoverOptions.onHover.call(me, me.active);
- }
-
- if (e.type === 'mouseup' || e.type === 'click') {
- if (options.onClick) {
- options.onClick.call(me, e, me.active);
- }
- if (me.legend && me.legend.handleEvent) {
- me.legend.handleEvent(e);
- }
- }
-
- // Remove styling for last active (even if it may still be active)
- if (me.lastActive.length) {
- me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
- }
-
- // Built in hover styling
- if (me.active.length && hoverOptions.mode) {
- me.updateHoverStyle(me.active, hoverOptions.mode, true);
- }
-
- // Built in Tooltips
- if (tooltipsOptions.enabled || tooltipsOptions.custom) {
- tooltip.initialize();
- tooltip._active = me.tooltipActive;
- tooltip.update(true);
- }
-
- // Hover animations
- tooltip.pivot();
-
- if (!me.animating) {
- // If entering, leaving, or changing elements, animate the change via pivot
- if (!helpers.arrayEquals(me.active, me.lastActive) ||
- !helpers.arrayEquals(me.tooltipActive, me.lastTooltipActive)) {
-
- me.stop();
-
- if (tooltipsOptions.enabled || tooltipsOptions.custom) {
- tooltip.update(true);
- }
-
- // We only need to render at this point. Updating will cause scales to be
- // recomputed generating flicker & using more memory than necessary.
- me.render(hoverOptions.animationDuration, true);
- }
- }
-
- // Remember Last Actives
- me.lastActive = me.active;
- me.lastTooltipActive = me.tooltipActive;
- return me;
- }
- });
-};
-
-},{}],23:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var noop = helpers.noop;
-
- // Base class for all dataset controllers (line, bar, etc)
- Chart.DatasetController = function(chart, datasetIndex) {
- this.initialize.call(this, chart, datasetIndex);
- };
-
- helpers.extend(Chart.DatasetController.prototype, {
-
- /**
- * Element type used to generate a meta dataset (e.g. Chart.element.Line).
- * @type {Chart.core.element}
- */
- datasetElementType: null,
-
- /**
- * Element type used to generate a meta data (e.g. Chart.element.Point).
- * @type {Chart.core.element}
- */
- dataElementType: null,
-
- initialize: function(chart, datasetIndex) {
- var me = this;
- me.chart = chart;
- me.index = datasetIndex;
- me.linkScales();
- me.addElements();
- },
-
- updateIndex: function(datasetIndex) {
- this.index = datasetIndex;
- },
-
- linkScales: function() {
- var me = this;
- var meta = me.getMeta();
- var dataset = me.getDataset();
-
- if (meta.xAxisID === null) {
- meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
- }
- if (meta.yAxisID === null) {
- meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
- }
- },
-
- getDataset: function() {
- return this.chart.data.datasets[this.index];
- },
-
- getMeta: function() {
- return this.chart.getDatasetMeta(this.index);
- },
-
- getScaleForId: function(scaleID) {
- return this.chart.scales[scaleID];
- },
-
- reset: function() {
- this.update(true);
- },
-
- createMetaDataset: function() {
- var me = this;
- var type = me.datasetElementType;
- return type && new type({
- _chart: me.chart.chart,
- _datasetIndex: me.index
- });
- },
-
- createMetaData: function(index) {
- var me = this;
- var type = me.dataElementType;
- return type && new type({
- _chart: me.chart.chart,
- _datasetIndex: me.index,
- _index: index
- });
- },
-
- addElements: function() {
- var me = this;
- var meta = me.getMeta();
- var data = me.getDataset().data || [];
- var metaData = meta.data;
- var i, ilen;
-
- for (i=0, ilen=data.length; i<ilen; ++i) {
- metaData[i] = metaData[i] || me.createMetaData(meta, i);
- }
-
- meta.dataset = meta.dataset || me.createMetaDataset();
- },
-
- addElementAndReset: function(index) {
- var me = this;
- var element = me.createMetaData(index);
- me.getMeta().data.splice(index, 0, element);
- me.updateElement(element, index, true);
- },
-
- buildOrUpdateElements: function buildOrUpdateElements() {
- // Handle the number of data points changing
- var meta = this.getMeta(),
- md = meta.data,
- numData = this.getDataset().data.length,
- numMetaData = md.length;
-
- // Make sure that we handle number of datapoints changing
- if (numData < numMetaData) {
- // Remove excess bars for data points that have been removed
- md.splice(numData, numMetaData - numData);
- } else if (numData > numMetaData) {
- // Add new elements
- for (var index = numMetaData; index < numData; ++index) {
- this.addElementAndReset(index);
- }
- }
- },
-
- update: noop,
-
- draw: function(ease) {
- var easingDecimal = ease || 1;
- helpers.each(this.getMeta().data, function(element, index) {
- element.transition(easingDecimal).draw();
- });
- },
-
- removeHoverStyle: function(element, elementOpts) {
- var dataset = this.chart.data.datasets[element._datasetIndex],
- index = element._index,
- custom = element.custom || {},
- valueOrDefault = helpers.getValueAtIndexOrDefault,
- color = helpers.color,
- model = element._model;
-
- model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
- model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
- model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
- },
-
- setHoverStyle: function(element) {
- var dataset = this.chart.data.datasets[element._datasetIndex],
- index = element._index,
- custom = element.custom || {},
- valueOrDefault = helpers.getValueAtIndexOrDefault,
- color = helpers.color,
- getHoverColor = helpers.getHoverColor,
- model = element._model;
-
- model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
- }
- });
-
- Chart.DatasetController.extend = helpers.inherits;
-};
-},{}],24:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.elements = {};
-
- Chart.Element = function(configuration) {
- helpers.extend(this, configuration);
- this.initialize.apply(this, arguments);
- };
-
- helpers.extend(Chart.Element.prototype, {
-
- initialize: function() {
- this.hidden = false;
- },
-
- pivot: function() {
- var me = this;
- if (!me._view) {
- me._view = helpers.clone(me._model);
- }
- me._start = helpers.clone(me._view);
- return me;
- },
-
- transition: function(ease) {
- var me = this;
-
- if (!me._view) {
- me._view = helpers.clone(me._model);
- }
-
- // No animation -> No Transition
- if (ease === 1) {
- me._view = me._model;
- me._start = null;
- return me;
- }
-
- if (!me._start) {
- me.pivot();
- }
-
- helpers.each(me._model, function(value, key) {
-
- if (key[0] === '_') {
- // Only non-underscored properties
- }
-
- // Init if doesn't exist
- else if (!me._view.hasOwnProperty(key)) {
- if (typeof value === 'number' && !isNaN(me._view[key])) {
- me._view[key] = value * ease;
- } else {
- me._view[key] = value;
- }
- }
-
- // No unnecessary computations
- else if (value === me._view[key]) {
- // It's the same! Woohoo!
- }
-
- // Color transitions if possible
- else if (typeof value === 'string') {
- try {
- var color = helpers.color(me._model[key]).mix(helpers.color(me._start[key]), ease);
- me._view[key] = color.rgbString();
- } catch (err) {
- me._view[key] = value;
- }
- }
- // Number transitions
- else if (typeof value === 'number') {
- var startVal = me._start[key] !== undefined && isNaN(me._start[key]) === false ? me._start[key] : 0;
- me._view[key] = ((me._model[key] - startVal) * ease) + startVal;
- }
- // Everything else
- else {
- me._view[key] = value;
- }
- }, me);
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ defaults = Chart.defaults;\r
+\r
+ defaults.doughnut = {\r
+ animation: {\r
+ //Boolean - Whether we animate the rotation of the Doughnut\r
+ animateRotate: true,\r
+ //Boolean - Whether we animate scaling the Doughnut from the centre\r
+ animateScale: false\r
+ },\r
+ aspectRatio: 1,\r
+ hover: {\r
+ mode: 'single'\r
+ },\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var labels = data.labels;\r
+\r
+ if (datasets.length) {\r
+ for (var i = 0; i < datasets[0].data.length; ++i) {\r
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');\r
+ if (labels[i]) {\r
+ text.push(labels[i]);\r
+ }\r
+ text.push('</li>');\r
+ }\r
+ }\r
+\r
+ text.push('</ul>');\r
+ return text.join("");\r
+ },\r
+ legend: {\r
+ labels: {\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ if (data.labels.length && data.datasets.length) {\r
+ return data.labels.map(function(label, i) {\r
+ var meta = chart.getDatasetMeta(0);\r
+ var ds = data.datasets[0];\r
+ var arc = meta.data[i];\r
+ var custom = arc.custom || {};\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var arcOpts = chart.options.elements.arc;\r
+ var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
+ var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
+ var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
+\r
+ return {\r
+ text: label,\r
+ fillStyle: fill,\r
+ strokeStyle: stroke,\r
+ lineWidth: bw,\r
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
+\r
+ // Extra data used for toggling the correct item\r
+ index: i\r
+ };\r
+ });\r
+ } else {\r
+ return [];\r
+ }\r
+ }\r
+ },\r
+\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.index;\r
+ var chart = this.chart;\r
+ var i, ilen, meta;\r
+\r
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
+ meta = chart.getDatasetMeta(i);\r
+ meta.data[index].hidden = !meta.data[index].hidden;\r
+ }\r
+\r
+ chart.update();\r
+ }\r
+ },\r
+\r
+ //The percentage of the chart that we cut out of the middle.\r
+ cutoutPercentage: 50,\r
+\r
+ //The rotation of the chart, where the first data arc begins.\r
+ rotation: Math.PI * -0.5,\r
+\r
+ //The total circumference of the chart.\r
+ circumference: Math.PI * 2.0,\r
+\r
+ // Need to override these to give a nice default\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function() {\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ defaults.pie = helpers.clone(defaults.doughnut);\r
+ helpers.extend(defaults.pie, {\r
+ cutoutPercentage: 0\r
+ });\r
+\r
+\r
+ Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Arc,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly\r
+ getRingIndex: function getRingIndex(datasetIndex) {\r
+ var ringIndex = 0;\r
+\r
+ for (var j = 0; j < datasetIndex; ++j) {\r
+ if (this.chart.isDatasetVisible(j)) {\r
+ ++ringIndex;\r
+ }\r
+ }\r
+\r
+ return ringIndex;\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var _this = this;\r
+ var chart = _this.chart,\r
+ chartArea = chart.chartArea,\r
+ opts = chart.options,\r
+ arcOpts = opts.elements.arc,\r
+ availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,\r
+ availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,\r
+ minSize = Math.min(availableWidth, availableHeight),\r
+ offset = {\r
+ x: 0,\r
+ y: 0\r
+ },\r
+ meta = _this.getMeta(),\r
+ cutoutPercentage = opts.cutoutPercentage,\r
+ circumference = opts.circumference;\r
+\r
+ // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc\r
+ if (circumference < Math.PI * 2.0) {\r
+ var startAngle = opts.rotation % (Math.PI * 2.0);\r
+ startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);\r
+ var endAngle = startAngle + circumference;\r
+ var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};\r
+ var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};\r
+ var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);\r
+ var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);\r
+ var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);\r
+ var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);\r
+ var cutout = cutoutPercentage / 100.0;\r
+ var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};\r
+ var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};\r
+ var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};\r
+ minSize = Math.min(availableWidth / size.width, availableHeight / size.height);\r
+ offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};\r
+ }\r
+\r
+ chart.outerRadius = Math.max(minSize / 2, 0);\r
+ chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);\r
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
+ chart.offsetX = offset.x * chart.outerRadius;\r
+ chart.offsetY = offset.y * chart.outerRadius;\r
+\r
+ meta.total = _this.calculateTotal();\r
+\r
+ _this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.getRingIndex(_this.index));\r
+ _this.innerRadius = _this.outerRadius - chart.radiusLength;\r
+\r
+ helpers.each(meta.data, function(arc, index) {\r
+ _this.updateElement(arc, index, reset);\r
+ });\r
+ },\r
+\r
+ updateElement: function(arc, index, reset) {\r
+ var _this = this;\r
+ var chart = _this.chart,\r
+ chartArea = chart.chartArea,\r
+ opts = chart.options,\r
+ animationOpts = opts.animation,\r
+ arcOpts = opts.elements.arc,\r
+ centerX = (chartArea.left + chartArea.right) / 2,\r
+ centerY = (chartArea.top + chartArea.bottom) / 2,\r
+ startAngle = opts.rotation, // non reset case handled later\r
+ endAngle = opts.rotation, // non reset case handled later\r
+ dataset = _this.getDataset(),\r
+ circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : _this.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),\r
+ innerRadius = reset && animationOpts.animateScale ? 0 : _this.innerRadius,\r
+ outerRadius = reset && animationOpts.animateScale ? 0 : _this.outerRadius,\r
+ custom = arc.custom || {},\r
+ valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+\r
+ helpers.extend(arc, {\r
+ // Utility\r
+ _datasetIndex: _this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: centerX + chart.offsetX,\r
+ y: centerY + chart.offsetY,\r
+ startAngle: startAngle,\r
+ endAngle: endAngle,\r
+ circumference: circumference,\r
+ outerRadius: outerRadius,\r
+ innerRadius: innerRadius,\r
+ label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])\r
+ }\r
+ });\r
+\r
+ var model = arc._model;\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor);\r
+ model.hoverBackgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, arcOpts.hoverBackgroundColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor);\r
+\r
+ // Set correct angles if not resetting\r
+ if (!reset || !animationOpts.animateRotate) {\r
+ if (index === 0) {\r
+ model.startAngle = opts.rotation;\r
+ } else {\r
+ model.startAngle = _this.getMeta().data[index - 1]._model.endAngle;\r
+ }\r
+\r
+ model.endAngle = model.startAngle + model.circumference;\r
+ }\r
+\r
+ arc.pivot();\r
+ },\r
+\r
+ removeHoverStyle: function(arc) {\r
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\r
+ },\r
+\r
+ calculateTotal: function() {\r
+ var dataset = this.getDataset();\r
+ var meta = this.getMeta();\r
+ var total = 0;\r
+ var value;\r
+\r
+ helpers.each(meta.data, function(element, index) {\r
+ value = dataset.data[index];\r
+ if (!isNaN(value) && !element.hidden) {\r
+ total += Math.abs(value);\r
+ }\r
+ });\r
+\r
+ return total;\r
+ },\r
+\r
+ calculateCircumference: function(value) {\r
+ var total = this.getMeta().total;\r
+ if (total > 0 && !isNaN(value)) {\r
+ return (Math.PI * 2.0) * (value / total);\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ });\r
+};\r
- return me;
- },
+},{}],18:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.line = {\r
+ showLines: true,\r
+\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "category",\r
+ id: 'x-axis-0'\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ id: 'y-axis-0'\r
+ }]\r
+ }\r
+ };\r
+\r
+ Chart.controllers.line = Chart.DatasetController.extend({\r
+\r
+ datasetElementType: Chart.elements.Line,\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ addElementAndReset: function(index) {\r
+ var me = this;\r
+ var options = me.chart.options;\r
+\r
+ Chart.DatasetController.prototype.addElementAndReset.call(me, index);\r
+\r
+ // Make sure bezier control points are updated\r
+ if (options.showLines && options.elements.line.tension !== 0) {\r
+ me.updateBezierControlPoints();\r
+ }\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var line = meta.dataset;\r
+ var points = meta.data || [];\r
+ var options = me.chart.options;\r
+ var lineElementOptions = options.elements.line;\r
+ var scale = me.getScaleForId(meta.yAxisID);\r
+ var i, ilen, dataset, custom;\r
+\r
+ // Update Line\r
+ if (options.showLines) {\r
+ dataset = me.getDataset();\r
+ custom = line.custom || {};\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\r
+ dataset.lineTension = dataset.tension;\r
+ }\r
+\r
+ // Utility\r
+ line._scale = scale;\r
+ line._datasetIndex = me.index;\r
+ // Data\r
+ line._children = points;\r
+ // Model\r
+ line._model = {\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\r
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\r
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\r
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\r
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\r
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\r
+ // Scale\r
+ scaleTop: scale.top,\r
+ scaleBottom: scale.bottom,\r
+ scaleZero: scale.getBasePixel()\r
+ };\r
+\r
+ line.pivot();\r
+ }\r
+\r
+ // Update Points\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ me.updateElement(points[i], i, reset);\r
+ }\r
+\r
+ if (options.showLines && lineElementOptions.tension !== 0) {\r
+ me.updateBezierControlPoints();\r
+ }\r
+ },\r
+\r
+ getPointBackgroundColor: function(point, index) {\r
+ var backgroundColor = this.chart.options.elements.point.backgroundColor;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.backgroundColor) {\r
+ backgroundColor = custom.backgroundColor;\r
+ } else if (dataset.pointBackgroundColor) {\r
+ backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);\r
+ } else if (dataset.backgroundColor) {\r
+ backgroundColor = dataset.backgroundColor;\r
+ }\r
+\r
+ return backgroundColor;\r
+ },\r
+\r
+ getPointBorderColor: function(point, index) {\r
+ var borderColor = this.chart.options.elements.point.borderColor;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.borderColor) {\r
+ borderColor = custom.borderColor;\r
+ } else if (dataset.pointBorderColor) {\r
+ borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);\r
+ } else if (dataset.borderColor) {\r
+ borderColor = dataset.borderColor;\r
+ }\r
+\r
+ return borderColor;\r
+ },\r
+\r
+ getPointBorderWidth: function(point, index) {\r
+ var borderWidth = this.chart.options.elements.point.borderWidth;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.borderWidth) {\r
+ borderWidth = custom.borderWidth;\r
+ } else if (dataset.pointBorderWidth) {\r
+ borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);\r
+ } else if (dataset.borderWidth) {\r
+ borderWidth = dataset.borderWidth;\r
+ }\r
+\r
+ return borderWidth;\r
+ },\r
+\r
+ updateElement: function(point, index, reset) {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var custom = point.custom || {};\r
+ var dataset = me.getDataset();\r
+ var datasetIndex = me.index;\r
+ var value = dataset.data[index];\r
+ var yScale = me.getScaleForId(meta.yAxisID);\r
+ var xScale = me.getScaleForId(meta.xAxisID);\r
+ var pointOptions = me.chart.options.elements.point;\r
+ var x, y;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
+ dataset.pointRadius = dataset.radius;\r
+ }\r
+ if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {\r
+ dataset.pointHitRadius = dataset.hitRadius;\r
+ }\r
+\r
+ x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);\r
+ y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);\r
+\r
+ // Utility\r
+ point._xScale = xScale;\r
+ point._yScale = yScale;\r
+ point._datasetIndex = datasetIndex;\r
+ point._index = index;\r
+\r
+ // Desired view properties\r
+ point._model = {\r
+ x: x,\r
+ y: y,\r
+ skip: custom.skip || isNaN(x) || isNaN(y),\r
+ // Appearance\r
+ radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),\r
+ pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),\r
+ backgroundColor: me.getPointBackgroundColor(point, index),\r
+ borderColor: me.getPointBorderColor(point, index),\r
+ borderWidth: me.getPointBorderWidth(point, index),\r
+ tension: meta.dataset._model ? meta.dataset._model.tension : 0,\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)\r
+ };\r
+ },\r
+\r
+ calculatePointY: function(value, index, datasetIndex, isCombo) {\r
+ var me = this;\r
+ var chart = me.chart;\r
+ var meta = me.getMeta();\r
+ var yScale = me.getScaleForId(meta.yAxisID);\r
+ var sumPos = 0;\r
+ var sumNeg = 0;\r
+ var i, ds, dsMeta;\r
+\r
+ if (yScale.options.stacked) {\r
+ for (i = 0; i < datasetIndex; i++) {\r
+ ds = chart.data.datasets[i];\r
+ dsMeta = chart.getDatasetMeta(i);\r
+ if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return yScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return yScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(value);\r
+ },\r
+\r
+ updateBezierControlPoints: function() {\r
+ var meta = this.getMeta();\r
+ var area = this.chart.chartArea;\r
+ var points = meta.data || [];\r
+ var i, ilen, point, model, controlPoints;\r
+\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ point = points[i];\r
+ model = point._model;\r
+ controlPoints = helpers.splineCurve(\r
+ helpers.previousItem(points, i)._model,\r
+ model,\r
+ helpers.nextItem(points, i)._model,\r
+ meta.dataset._model.tension\r
+ );\r
+\r
+ // Prevent the bezier going outside of the bounds of the graph\r
+ model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, area.right), area.left);\r
+ model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, area.bottom), area.top);\r
+ model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, area.right), area.left);\r
+ model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, area.bottom), area.top);\r
+\r
+ // Now pivot the point for animation\r
+ point.pivot();\r
+ }\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var meta = this.getMeta();\r
+ var points = meta.data || [];\r
+ var easingDecimal = ease || 1;\r
+ var i, ilen;\r
+\r
+ // Transition Point Locations\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ points[i].transition(easingDecimal);\r
+ }\r
+\r
+ // Transition and Draw the line\r
+ if (this.chart.options.showLines) {\r
+ meta.dataset.transition(easingDecimal).draw();\r
+ }\r
+\r
+ // Draw the points\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ points[i].draw();\r
+ }\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\r
+ model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var me = this;\r
+ var dataset = me.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
+ dataset.pointRadius = dataset.radius;\r
+ }\r
+\r
+ model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);\r
+ model.backgroundColor = me.getPointBackgroundColor(point, index);\r
+ model.borderColor = me.getPointBorderColor(point, index);\r
+ model.borderWidth = me.getPointBorderWidth(point, index);\r
+ }\r
+ });\r
+};\r
- tooltipPosition: function() {
- return {
- x: this._model.x,
- y: this._model.y
- };
- },
+},{}],19:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.polarArea = {\r
+\r
+ scale: {\r
+ type: "radialLinear",\r
+ lineArc: true // so that lines are circular\r
+ },\r
+\r
+ //Boolean - Whether to animate the rotation of the chart\r
+ animation: {\r
+ animateRotate: true,\r
+ animateScale: true\r
+ },\r
+\r
+ aspectRatio: 1,\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var labels = data.labels;\r
+\r
+ if (datasets.length) {\r
+ for (var i = 0; i < datasets[0].data.length; ++i) {\r
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');\r
+ if (labels[i]) {\r
+ text.push(labels[i]);\r
+ }\r
+ text.push('</span></li>');\r
+ }\r
+ }\r
+\r
+ text.push('</ul>');\r
+ return text.join("");\r
+ },\r
+ legend: {\r
+ labels: {\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ if (data.labels.length && data.datasets.length) {\r
+ return data.labels.map(function(label, i) {\r
+ var meta = chart.getDatasetMeta(0);\r
+ var ds = data.datasets[0];\r
+ var arc = meta.data[i];\r
+ var custom = arc.custom || {};\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var arcOpts = chart.options.elements.arc;\r
+ var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
+ var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
+ var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
+\r
+ return {\r
+ text: label,\r
+ fillStyle: fill,\r
+ strokeStyle: stroke,\r
+ lineWidth: bw,\r
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
+\r
+ // Extra data used for toggling the correct item\r
+ index: i\r
+ };\r
+ });\r
+ } else {\r
+ return [];\r
+ }\r
+ }\r
+ },\r
+\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.index;\r
+ var chart = this.chart;\r
+ var i, ilen, meta;\r
+\r
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
+ meta = chart.getDatasetMeta(i);\r
+ meta.data[index].hidden = !meta.data[index].hidden;\r
+ }\r
+\r
+ chart.update();\r
+ }\r
+ },\r
+\r
+ // Need to override these to give a nice default\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function() {\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.polarArea = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Arc,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ update: function update(reset) {\r
+ var _this = this;\r
+ var chart = _this.chart;\r
+ var chartArea = chart.chartArea;\r
+ var meta = this.getMeta();\r
+ var opts = chart.options;\r
+ var arcOpts = opts.elements.arc;\r
+ var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\r
+ chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);\r
+ chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);\r
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
+\r
+ _this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.index);\r
+ _this.innerRadius = _this.outerRadius - chart.radiusLength;\r
+\r
+ meta.count = _this.countVisibleElements();\r
+\r
+ helpers.each(meta.data, function(arc, index) {\r
+ _this.updateElement(arc, index, reset);\r
+ });\r
+ },\r
+\r
+ updateElement: function(arc, index, reset) {\r
+ var _this = this;\r
+ var chart = _this.chart;\r
+ var chartArea = chart.chartArea;\r
+ var dataset = _this.getDataset();\r
+ var opts = chart.options;\r
+ var animationOpts = opts.animation;\r
+ var arcOpts = opts.elements.arc;\r
+ var custom = arc.custom || {};\r
+ var scale = chart.scale;\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var labels = chart.data.labels;\r
+\r
+ var circumference = _this.calculateCircumference(dataset.data[index]);\r
+ var centerX = (chartArea.left + chartArea.right) / 2;\r
+ var centerY = (chartArea.top + chartArea.bottom) / 2;\r
+\r
+ // If there is NaN data before us, we need to calculate the starting angle correctly.\r
+ // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data\r
+ var visibleCount = 0;\r
+ var meta = _this.getMeta();\r
+ for (var i = 0; i < index; ++i) {\r
+ if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {\r
+ ++visibleCount;\r
+ }\r
+ }\r
+\r
+ var distance = arc.hidden? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\r
+ var startAngle = (-0.5 * Math.PI) + (circumference * visibleCount);\r
+ var endAngle = startAngle + (arc.hidden? 0 : circumference);\r
+\r
+ var resetModel = {\r
+ x: centerX,\r
+ y: centerY,\r
+ innerRadius: 0,\r
+ outerRadius: animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]),\r
+ startAngle: animationOpts.animateRotate ? Math.PI * -0.5 : startAngle,\r
+ endAngle: animationOpts.animateRotate ? Math.PI * -0.5 : endAngle,\r
+\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),\r
+\r
+ label: getValueAtIndexOrDefault(labels, index, labels[index])\r
+ };\r
+\r
+ helpers.extend(arc, {\r
+ // Utility\r
+ _datasetIndex: _this.index,\r
+ _index: index,\r
+ _scale: scale,\r
+\r
+ // Desired view properties\r
+ _model: reset ? resetModel : {\r
+ x: centerX,\r
+ y: centerY,\r
+ innerRadius: 0,\r
+ outerRadius: distance,\r
+ startAngle: startAngle,\r
+ endAngle: endAngle,\r
+\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),\r
+\r
+ label: getValueAtIndexOrDefault(labels, index, labels[index])\r
+ }\r
+ });\r
+\r
+ arc.pivot();\r
+ },\r
+\r
+ removeHoverStyle: function(arc) {\r
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\r
+ },\r
+\r
+ countVisibleElements: function() {\r
+ var dataset = this.getDataset();\r
+ var meta = this.getMeta();\r
+ var count = 0;\r
+\r
+ helpers.each(meta.data, function(element, index) {\r
+ if (!isNaN(dataset.data[index]) && !element.hidden) {\r
+ count++;\r
+ }\r
+ });\r
+\r
+ return count;\r
+ },\r
+\r
+ calculateCircumference: function(value) {\r
+ var count = this.getMeta().count;\r
+ if (count > 0 && !isNaN(value)) {\r
+ return (2 * Math.PI) / count;\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ });\r
+};\r
- hasValue: function() {
- return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
- }
- });
+},{}],20:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.radar = {\r
+ scale: {\r
+ type: "radialLinear"\r
+ },\r
+ elements: {\r
+ line: {\r
+ tension: 0 // no bezier in radar\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.radar = Chart.DatasetController.extend({\r
+\r
+ datasetElementType: Chart.elements.Line,\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ addElementAndReset: function(index) {\r
+ Chart.DatasetController.prototype.addElementAndReset.call(this, index);\r
+\r
+ // Make sure bezier control points are updated\r
+ this.updateBezierControlPoints();\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var meta = this.getMeta();\r
+ var line = meta.dataset;\r
+ var points = meta.data;\r
+ var custom = line.custom || {};\r
+ var dataset = this.getDataset();\r
+ var lineElementOptions = this.chart.options.elements.line;\r
+ var scale = this.chart.scale;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\r
+ dataset.lineTension = dataset.tension;\r
+ }\r
+\r
+ helpers.extend(meta.dataset, {\r
+ // Utility\r
+ _datasetIndex: this.index,\r
+ // Data\r
+ _children: points,\r
+ _loop: true,\r
+ // Model\r
+ _model: {\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\r
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\r
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\r
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\r
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\r
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\r
+\r
+ // Scale\r
+ scaleTop: scale.top,\r
+ scaleBottom: scale.bottom,\r
+ scaleZero: scale.getBasePosition()\r
+ }\r
+ });\r
+\r
+ meta.dataset.pivot();\r
+\r
+ // Update Points\r
+ helpers.each(points, function(point, index) {\r
+ this.updateElement(point, index, reset);\r
+ }, this);\r
+\r
+\r
+ // Update bezier control points\r
+ this.updateBezierControlPoints();\r
+ },\r
+ updateElement: function(point, index, reset) {\r
+ var custom = point.custom || {};\r
+ var dataset = this.getDataset();\r
+ var scale = this.chart.scale;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+ var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);\r
+\r
+ helpers.extend(point, {\r
+ // Utility\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+ _scale: scale,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales\r
+ y: reset ? scale.yCenter : pointPosition.y,\r
+\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.tension, this.chart.options.elements.line.tension),\r
+ radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),\r
+ pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),\r
+\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\r
+ }\r
+ });\r
+\r
+ point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));\r
+ },\r
+ updateBezierControlPoints: function() {\r
+ var chartArea = this.chart.chartArea;\r
+ var meta = this.getMeta();\r
+\r
+ helpers.each(meta.data, function(point, index) {\r
+ var model = point._model;\r
+ var controlPoints = helpers.splineCurve(\r
+ helpers.previousItem(meta.data, index, true)._model,\r
+ model,\r
+ helpers.nextItem(meta.data, index, true)._model,\r
+ model.tension\r
+ );\r
+\r
+ // Prevent the bezier going outside of the bounds of the graph\r
+ model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);\r
+ model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);\r
+\r
+ model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);\r
+ model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);\r
+\r
+ // Now pivot the point for animation\r
+ point.pivot();\r
+ }, this);\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var meta = this.getMeta();\r
+ var easingDecimal = ease || 1;\r
+\r
+ // Transition Point Locations\r
+ helpers.each(meta.data, function(point, index) {\r
+ point.transition(easingDecimal);\r
+ });\r
+\r
+ // Transition and Draw the line\r
+ meta.dataset.transition(easingDecimal).draw();\r
+\r
+ // Draw the points\r
+ helpers.each(meta.data, function(point) {\r
+ point.draw();\r
+ });\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var custom = point.custom || {};\r
+ var index = point._index;\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var custom = point.custom || {};\r
+ var index = point._index;\r
+ var model = point._model;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);\r
+ }\r
+ });\r
+};\r
- Chart.Element.extend = helpers.inherits;
+},{}],21:[function(require,module,exports){
+/*global window: false */\r
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.animation = {\r
+ duration: 1000,\r
+ easing: "easeOutQuart",\r
+ onProgress: helpers.noop,\r
+ onComplete: helpers.noop\r
+ };\r
+\r
+ Chart.Animation = Chart.Element.extend({\r
+ currentStep: null, // the current animation step\r
+ numSteps: 60, // default number of steps\r
+ easing: "", // the easing to use for this animation\r
+ render: null, // render function used by the animation service\r
+\r
+ onAnimationProgress: null, // user specified callback to fire on each step of the animation\r
+ onAnimationComplete: null // user specified callback to fire when the animation finishes\r
+ });\r
+\r
+ Chart.animationService = {\r
+ frameDuration: 17,\r
+ animations: [],\r
+ dropFrames: 0,\r
+ request: null,\r
+ addAnimation: function(chartInstance, animationObject, duration, lazy) {\r
+\r
+ if (!lazy) {\r
+ chartInstance.animating = true;\r
+ }\r
+\r
+ for (var index = 0; index < this.animations.length; ++index) {\r
+ if (this.animations[index].chartInstance === chartInstance) {\r
+ // replacing an in progress animation\r
+ this.animations[index].animationObject = animationObject;\r
+ return;\r
+ }\r
+ }\r
+\r
+ this.animations.push({\r
+ chartInstance: chartInstance,\r
+ animationObject: animationObject\r
+ });\r
+\r
+ // If there are no animations queued, manually kickstart a digest, for lack of a better word\r
+ if (this.animations.length === 1) {\r
+ this.requestAnimationFrame();\r
+ }\r
+ },\r
+ // Cancel the animation for a given chart instance\r
+ cancelAnimation: function(chartInstance) {\r
+ var index = helpers.findIndex(this.animations, function(animationWrapper) {\r
+ return animationWrapper.chartInstance === chartInstance;\r
+ });\r
+\r
+ if (index !== -1) {\r
+ this.animations.splice(index, 1);\r
+ chartInstance.animating = false;\r
+ }\r
+ },\r
+ requestAnimationFrame: function() {\r
+ var me = this;\r
+ if (me.request === null) {\r
+ // Skip animation frame requests until the active one is executed.\r
+ // This can happen when processing mouse events, e.g. 'mousemove'\r
+ // and 'mouseout' events will trigger multiple renders.\r
+ me.request = helpers.requestAnimFrame.call(window, function() {\r
+ me.request = null;\r
+ me.startDigest();\r
+ });\r
+ }\r
+ },\r
+ startDigest: function() {\r
+\r
+ var startTime = Date.now();\r
+ var framesToDrop = 0;\r
+\r
+ if (this.dropFrames > 1) {\r
+ framesToDrop = Math.floor(this.dropFrames);\r
+ this.dropFrames = this.dropFrames % 1;\r
+ }\r
+\r
+ var i = 0;\r
+ while (i < this.animations.length) {\r
+ if (this.animations[i].animationObject.currentStep === null) {\r
+ this.animations[i].animationObject.currentStep = 0;\r
+ }\r
+\r
+ this.animations[i].animationObject.currentStep += 1 + framesToDrop;\r
+\r
+ if (this.animations[i].animationObject.currentStep > this.animations[i].animationObject.numSteps) {\r
+ this.animations[i].animationObject.currentStep = this.animations[i].animationObject.numSteps;\r
+ }\r
+\r
+ this.animations[i].animationObject.render(this.animations[i].chartInstance, this.animations[i].animationObject);\r
+ if (this.animations[i].animationObject.onAnimationProgress && this.animations[i].animationObject.onAnimationProgress.call) {\r
+ this.animations[i].animationObject.onAnimationProgress.call(this.animations[i].chartInstance, this.animations[i]);\r
+ }\r
+\r
+ if (this.animations[i].animationObject.currentStep === this.animations[i].animationObject.numSteps) {\r
+ if (this.animations[i].animationObject.onAnimationComplete && this.animations[i].animationObject.onAnimationComplete.call) {\r
+ this.animations[i].animationObject.onAnimationComplete.call(this.animations[i].chartInstance, this.animations[i]);\r
+ }\r
+\r
+ // executed the last frame. Remove the animation.\r
+ this.animations[i].chartInstance.animating = false;\r
+\r
+ this.animations.splice(i, 1);\r
+ } else {\r
+ ++i;\r
+ }\r
+ }\r
+\r
+ var endTime = Date.now();\r
+ var dropFrames = (endTime - startTime) / this.frameDuration;\r
+\r
+ this.dropFrames += dropFrames;\r
+\r
+ // Do we have more stuff to animate?\r
+ if (this.animations.length > 0) {\r
+ this.requestAnimationFrame();\r
+ }\r
+ }\r
+ };\r
+};
+},{}],22:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ //Create a dictionary of chart types, to allow for extension of existing types\r
+ Chart.types = {};\r
+\r
+ //Store a reference to each instance - allowing us to globally resize chart instances on window resize.\r
+ //Destroy method on the chart will remove the instance of the chart from this reference.\r
+ Chart.instances = {};\r
+\r
+ // Controllers available for dataset visualization eg. bar, line, slice, etc.\r
+ Chart.controllers = {};\r
+\r
+ // The main controller of a chart\r
+ Chart.Controller = function(instance) {\r
+\r
+ this.chart = instance;\r
+ this.config = instance.config;\r
+ this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});\r
+ this.id = helpers.uid();\r
+\r
+ Object.defineProperty(this, 'data', {\r
+ get: function() {\r
+ return this.config.data;\r
+ }\r
+ });\r
+\r
+ //Add the chart instance to the global namespace\r
+ Chart.instances[this.id] = this;\r
+\r
+ if (this.options.responsive) {\r
+ // Silent resize before chart draws\r
+ this.resize(true);\r
+ }\r
+\r
+ this.initialize();\r
+\r
+ return this;\r
+ };\r
+\r
+ helpers.extend(Chart.Controller.prototype, {\r
+\r
+ initialize: function initialize() {\r
+ // Before init plugin notification\r
+ Chart.pluginService.notifyPlugins('beforeInit', [this]);\r
+\r
+ this.bindEvents();\r
+\r
+ // Make sure controllers are built first so that each dataset is bound to an axis before the scales\r
+ // are built\r
+ this.ensureScalesHaveIDs();\r
+ this.buildOrUpdateControllers();\r
+ this.buildScales();\r
+ this.buildSurroundingItems();\r
+ this.updateLayout();\r
+ this.resetElements();\r
+ this.initToolTip();\r
+ this.update();\r
+\r
+ // After init plugin notification\r
+ Chart.pluginService.notifyPlugins('afterInit', [this]);\r
+\r
+ return this;\r
+ },\r
+\r
+ clear: function clear() {\r
+ helpers.clear(this.chart);\r
+ return this;\r
+ },\r
+\r
+ stop: function stop() {\r
+ // Stops any current animation loop occuring\r
+ Chart.animationService.cancelAnimation(this);\r
+ return this;\r
+ },\r
+\r
+ resize: function resize(silent) {\r
+ var canvas = this.chart.canvas;\r
+ var newWidth = helpers.getMaximumWidth(this.chart.canvas);\r
+ var newHeight = (this.options.maintainAspectRatio && isNaN(this.chart.aspectRatio) === false && isFinite(this.chart.aspectRatio) && this.chart.aspectRatio !== 0) ? newWidth / this.chart.aspectRatio : helpers.getMaximumHeight(this.chart.canvas);\r
+\r
+ var sizeChanged = this.chart.width !== newWidth || this.chart.height !== newHeight;\r
+\r
+ if (!sizeChanged)\r
+ return this;\r
+\r
+ canvas.width = this.chart.width = newWidth;\r
+ canvas.height = this.chart.height = newHeight;\r
+\r
+ helpers.retinaScale(this.chart);\r
+\r
+ if (!silent) {\r
+ this.stop();\r
+ this.update(this.options.responsiveAnimationDuration);\r
+ }\r
+\r
+ return this;\r
+ },\r
+\r
+ ensureScalesHaveIDs: function ensureScalesHaveIDs() {\r
+ var options = this.options;\r
+ var scalesOptions = options.scales || {};\r
+ var scaleOptions = options.scale;\r
+\r
+ helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {\r
+ xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);\r
+ });\r
+\r
+ helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {\r
+ yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);\r
+ });\r
+\r
+ if (scaleOptions) {\r
+ scaleOptions.id = scaleOptions.id || 'scale';\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Builds a map of scale ID to scale object for future lookup.\r
+ */\r
+ buildScales: function buildScales() {\r
+ var me = this;\r
+ var options = me.options;\r
+ var scales = me.scales = {};\r
+ var items = [];\r
+\r
+ if (options.scales) {\r
+ items = items.concat(\r
+ (options.scales.xAxes || []).map(function(xAxisOptions) {\r
+ return { options: xAxisOptions, dtype: 'category' }; }),\r
+ (options.scales.yAxes || []).map(function(yAxisOptions) {\r
+ return { options: yAxisOptions, dtype: 'linear' }; }));\r
+ }\r
+\r
+ if (options.scale) {\r
+ items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });\r
+ }\r
+\r
+ helpers.each(items, function(item, index) {\r
+ var scaleOptions = item.options;\r
+ var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);\r
+ var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);\r
+ if (!scaleClass) {\r
+ return;\r
+ }\r
+\r
+ var scale = new scaleClass({\r
+ id: scaleOptions.id,\r
+ options: scaleOptions,\r
+ ctx: me.chart.ctx,\r
+ chart: me\r
+ });\r
+\r
+ scales[scale.id] = scale;\r
+\r
+ // TODO(SB): I think we should be able to remove this custom case (options.scale)\r
+ // and consider it as a regular scale part of the "scales"" map only! This would\r
+ // make the logic easier and remove some useless? custom code.\r
+ if (item.isDefault) {\r
+ me.scale = scale;\r
+ }\r
+ });\r
+\r
+ Chart.scaleService.addScalesToLayout(this);\r
+ },\r
+\r
+ buildSurroundingItems: function() {\r
+ if (this.options.title) {\r
+ this.titleBlock = new Chart.Title({\r
+ ctx: this.chart.ctx,\r
+ options: this.options.title,\r
+ chart: this\r
+ });\r
+\r
+ Chart.layoutService.addBox(this, this.titleBlock);\r
+ }\r
+\r
+ if (this.options.legend) {\r
+ this.legend = new Chart.Legend({\r
+ ctx: this.chart.ctx,\r
+ options: this.options.legend,\r
+ chart: this\r
+ });\r
+\r
+ Chart.layoutService.addBox(this, this.legend);\r
+ }\r
+ },\r
+\r
+ updateLayout: function() {\r
+ Chart.layoutService.update(this, this.chart.width, this.chart.height);\r
+ },\r
+\r
+ buildOrUpdateControllers: function buildOrUpdateControllers() {\r
+ var types = [];\r
+ var newControllers = [];\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ if (!meta.type) {\r
+ meta.type = dataset.type || this.config.type;\r
+ }\r
+\r
+ types.push(meta.type);\r
+\r
+ if (meta.controller) {\r
+ meta.controller.updateIndex(datasetIndex);\r
+ } else {\r
+ meta.controller = new Chart.controllers[meta.type](this, datasetIndex);\r
+ newControllers.push(meta.controller);\r
+ }\r
+ }, this);\r
+\r
+ if (types.length > 1) {\r
+ for (var i = 1; i < types.length; i++) {\r
+ if (types[i] !== types[i - 1]) {\r
+ this.isCombo = true;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return newControllers;\r
+ },\r
+\r
+ resetElements: function resetElements() {\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.reset();\r
+ }, this);\r
+ },\r
+\r
+ update: function update(animationDuration, lazy) {\r
+ Chart.pluginService.notifyPlugins('beforeUpdate', [this]);\r
+\r
+ // In case the entire data object changed\r
+ this.tooltip._data = this.data;\r
+\r
+ // Make sure dataset controllers are updated and new controllers are reset\r
+ var newControllers = this.buildOrUpdateControllers();\r
+\r
+ // Make sure all dataset controllers have correct meta data counts\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();\r
+ }, this);\r
+\r
+ Chart.layoutService.update(this, this.chart.width, this.chart.height);\r
+\r
+ // Apply changes to the dataets that require the scales to have been calculated i.e BorderColor chages\r
+ Chart.pluginService.notifyPlugins('afterScaleUpdate', [this]);\r
+\r
+ // Can only reset the new controllers after the scales have been updated\r
+ helpers.each(newControllers, function(controller) {\r
+ controller.reset();\r
+ });\r
+\r
+ // This will loop through any data and do the appropriate element update for the type\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.update();\r
+ }, this);\r
+\r
+ // Do this before render so that any plugins that need final scale updates can use it\r
+ Chart.pluginService.notifyPlugins('afterUpdate', [this]);\r
+\r
+ this.render(animationDuration, lazy);\r
+ },\r
+\r
+ render: function render(duration, lazy) {\r
+ Chart.pluginService.notifyPlugins('beforeRender', [this]);\r
+\r
+ var animationOptions = this.options.animation;\r
+ if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {\r
+ var animation = new Chart.Animation();\r
+ animation.numSteps = (duration || animationOptions.duration) / 16.66; //60 fps\r
+ animation.easing = animationOptions.easing;\r
+\r
+ // render function\r
+ animation.render = function(chartInstance, animationObject) {\r
+ var easingFunction = helpers.easingEffects[animationObject.easing];\r
+ var stepDecimal = animationObject.currentStep / animationObject.numSteps;\r
+ var easeDecimal = easingFunction(stepDecimal);\r
+\r
+ chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);\r
+ };\r
+\r
+ // user events\r
+ animation.onAnimationProgress = animationOptions.onProgress;\r
+ animation.onAnimationComplete = animationOptions.onComplete;\r
+\r
+ Chart.animationService.addAnimation(this, animation, duration, lazy);\r
+ } else {\r
+ this.draw();\r
+ if (animationOptions && animationOptions.onComplete && animationOptions.onComplete.call) {\r
+ animationOptions.onComplete.call(this);\r
+ }\r
+ }\r
+ return this;\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ this.clear();\r
+\r
+ Chart.pluginService.notifyPlugins('beforeDraw', [this, easingDecimal]);\r
+\r
+ // Draw all the scales\r
+ helpers.each(this.boxes, function(box) {\r
+ box.draw(this.chartArea);\r
+ }, this);\r
+ if (this.scale) {\r
+ this.scale.draw();\r
+ }\r
+\r
+ // Clip out the chart area so that anything outside does not draw. This is necessary for zoom and pan to function\r
+ var context = this.chart.ctx;\r
+ context.save();\r
+ context.beginPath();\r
+ context.rect(this.chartArea.left, this.chartArea.top, this.chartArea.right - this.chartArea.left, this.chartArea.bottom - this.chartArea.top);\r
+ context.clip();\r
+\r
+ // Draw each dataset via its respective controller (reversed to support proper line stacking)\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ this.getDatasetMeta(datasetIndex).controller.draw(ease);\r
+ }\r
+ }, this, true);\r
+\r
+ // Restore from the clipping operation\r
+ context.restore();\r
+\r
+ // Finally draw the tooltip\r
+ this.tooltip.transition(easingDecimal).draw();\r
+\r
+ Chart.pluginService.notifyPlugins('afterDraw', [this, easingDecimal]);\r
+ },\r
+\r
+ // Get the single element that was clicked on\r
+ // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw\r
+ getElementAtEvent: function(e) {\r
+ var eventPosition = helpers.getRelativePosition(e, this.chart);\r
+ var elementsArray = [];\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ helpers.each(meta.data, function(element, index) {\r
+ if (element.inRange(eventPosition.x, eventPosition.y)) {\r
+ elementsArray.push(element);\r
+ return elementsArray;\r
+ }\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getElementsAtEvent: function(e) {\r
+ var eventPosition = helpers.getRelativePosition(e, this.chart);\r
+ var elementsArray = [];\r
+\r
+ var found = (function() {\r
+ if (this.data.datasets) {\r
+ for (var i = 0; i < this.data.datasets.length; i++) {\r
+ var meta = this.getDatasetMeta(i);\r
+ if (this.isDatasetVisible(i)) {\r
+ for (var j = 0; j < meta.data.length; j++) {\r
+ if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {\r
+ return meta.data[j];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }).call(this);\r
+\r
+ if (!found) {\r
+ return elementsArray;\r
+ }\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ elementsArray.push(meta.data[found._index]);\r
+ }\r
+ }, this);\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getElementsAtEventForMode: function(e, mode) {\r
+ var me = this;\r
+ switch (mode) {\r
+ case 'single':\r
+ return me.getElementAtEvent(e);\r
+ case 'label':\r
+ return me.getElementsAtEvent(e);\r
+ case 'dataset':\r
+ return me.getDatasetAtEvent(e);\r
+ default:\r
+ return e;\r
+ }\r
+ },\r
+\r
+ getDatasetAtEvent: function(e) {\r
+ var elementsArray = this.getElementAtEvent(e);\r
+\r
+ if (elementsArray.length > 0) {\r
+ elementsArray = this.getDatasetMeta(elementsArray[0]._datasetIndex).data;\r
+ }\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getDatasetMeta: function(datasetIndex) {\r
+ var dataset = this.data.datasets[datasetIndex];\r
+ if (!dataset._meta) {\r
+ dataset._meta = {};\r
+ }\r
+\r
+ var meta = dataset._meta[this.id];\r
+ if (!meta) {\r
+ meta = dataset._meta[this.id] = {\r
+ type: null,\r
+ data: [],\r
+ dataset: null,\r
+ controller: null,\r
+ hidden: null, // See isDatasetVisible() comment\r
+ xAxisID: null,\r
+ yAxisID: null\r
+ };\r
+ }\r
+\r
+ return meta;\r
+ },\r
+\r
+ getVisibleDatasetCount: function() {\r
+ var count = 0;\r
+ for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {\r
+ if (this.isDatasetVisible(i)) {\r
+ count++;\r
+ }\r
+ }\r
+ return count;\r
+ },\r
+\r
+ isDatasetVisible: function(datasetIndex) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+\r
+ // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,\r
+ // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.\r
+ return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;\r
+ },\r
+\r
+ generateLegend: function generateLegend() {\r
+ return this.options.legendCallback(this);\r
+ },\r
+\r
+ destroy: function destroy() {\r
+ this.clear();\r
+ helpers.unbindEvents(this, this.events);\r
+ helpers.removeResizeListener(this.chart.canvas.parentNode);\r
+\r
+ // Reset canvas height/width attributes\r
+ var canvas = this.chart.canvas;\r
+ canvas.width = this.chart.width;\r
+ canvas.height = this.chart.height;\r
+\r
+ // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here\r
+ if (this.chart.originalDevicePixelRatio !== undefined) {\r
+ this.chart.ctx.scale(1 / this.chart.originalDevicePixelRatio, 1 / this.chart.originalDevicePixelRatio);\r
+ }\r
+\r
+ // Reset to the old style since it may have been changed by the device pixel ratio changes\r
+ canvas.style.width = this.chart.originalCanvasStyleWidth;\r
+ canvas.style.height = this.chart.originalCanvasStyleHeight;\r
+\r
+ Chart.pluginService.notifyPlugins('destroy', [this]);\r
+\r
+ delete Chart.instances[this.id];\r
+ },\r
+\r
+ toBase64Image: function toBase64Image() {\r
+ return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);\r
+ },\r
+\r
+ initToolTip: function initToolTip() {\r
+ this.tooltip = new Chart.Tooltip({\r
+ _chart: this.chart,\r
+ _chartInstance: this,\r
+ _data: this.data,\r
+ _options: this.options\r
+ }, this);\r
+ },\r
+\r
+ bindEvents: function bindEvents() {\r
+ helpers.bindEvents(this, this.options.events, function(evt) {\r
+ this.eventHandler(evt);\r
+ });\r
+ },\r
+\r
+ updateHoverStyle: function(elements, mode, enabled) {\r
+ var method = enabled? 'setHoverStyle' : 'removeHoverStyle';\r
+ var element, i, ilen;\r
+\r
+ switch (mode) {\r
+ case 'single':\r
+ elements = [ elements[0] ];\r
+ break;\r
+ case 'label':\r
+ case 'dataset':\r
+ // elements = elements;\r
+ break;\r
+ default:\r
+ // unsupported mode\r
+ return;\r
+ }\r
+\r
+ for (i=0, ilen=elements.length; i<ilen; ++i) {\r
+ element = elements[i];\r
+ if (element) {\r
+ this.getDatasetMeta(element._datasetIndex).controller[method](element);\r
+ }\r
+ }\r
+ },\r
+\r
+ eventHandler: function eventHandler(e) {\r
+ var me = this;\r
+ var tooltip = me.tooltip;\r
+ var options = me.options || {};\r
+ var hoverOptions = options.hover;\r
+ var tooltipsOptions = options.tooltips;\r
+\r
+ me.lastActive = me.lastActive || [];\r
+ me.lastTooltipActive = me.lastTooltipActive || [];\r
+\r
+ // Find Active Elements for hover and tooltips\r
+ if (e.type === 'mouseout') {\r
+ me.active = [];\r
+ me.tooltipActive = [];\r
+ } else {\r
+ me.active = me.getElementsAtEventForMode(e, hoverOptions.mode);\r
+ me.tooltipActive = me.getElementsAtEventForMode(e, tooltipsOptions.mode);\r
+ }\r
+\r
+ // On Hover hook\r
+ if (hoverOptions.onHover) {\r
+ hoverOptions.onHover.call(me, me.active);\r
+ }\r
+\r
+ if (e.type === 'mouseup' || e.type === 'click') {\r
+ if (options.onClick) {\r
+ options.onClick.call(me, e, me.active);\r
+ }\r
+ if (me.legend && me.legend.handleEvent) {\r
+ me.legend.handleEvent(e);\r
+ }\r
+ }\r
+\r
+ // Remove styling for last active (even if it may still be active)\r
+ if (me.lastActive.length) {\r
+ me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);\r
+ }\r
+\r
+ // Built in hover styling\r
+ if (me.active.length && hoverOptions.mode) {\r
+ me.updateHoverStyle(me.active, hoverOptions.mode, true);\r
+ }\r
+\r
+ // Built in Tooltips\r
+ if (tooltipsOptions.enabled || tooltipsOptions.custom) {\r
+ tooltip.initialize();\r
+ tooltip._active = me.tooltipActive;\r
+ tooltip.update(true);\r
+ }\r
+\r
+ // Hover animations\r
+ tooltip.pivot();\r
+\r
+ if (!me.animating) {\r
+ // If entering, leaving, or changing elements, animate the change via pivot\r
+ if (!helpers.arrayEquals(me.active, me.lastActive) ||\r
+ !helpers.arrayEquals(me.tooltipActive, me.lastTooltipActive)) {\r
+\r
+ me.stop();\r
+\r
+ if (tooltipsOptions.enabled || tooltipsOptions.custom) {\r
+ tooltip.update(true);\r
+ }\r
+\r
+ // We only need to render at this point. Updating will cause scales to be\r
+ // recomputed generating flicker & using more memory than necessary.\r
+ me.render(hoverOptions.animationDuration, true);\r
+ }\r
+ }\r
+\r
+ // Remember Last Actives\r
+ me.lastActive = me.active;\r
+ me.lastTooltipActive = me.tooltipActive;\r
+ return me;\r
+ }\r
+ });\r
+};\r
+},{}],23:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var noop = helpers.noop;\r
+\r
+ // Base class for all dataset controllers (line, bar, etc)\r
+ Chart.DatasetController = function(chart, datasetIndex) {\r
+ this.initialize.call(this, chart, datasetIndex);\r
+ };\r
+\r
+ helpers.extend(Chart.DatasetController.prototype, {\r
+\r
+ /**\r
+ * Element type used to generate a meta dataset (e.g. Chart.element.Line).\r
+ * @type {Chart.core.element}\r
+ */\r
+ datasetElementType: null,\r
+\r
+ /**\r
+ * Element type used to generate a meta data (e.g. Chart.element.Point).\r
+ * @type {Chart.core.element}\r
+ */\r
+ dataElementType: null,\r
+\r
+ initialize: function(chart, datasetIndex) {\r
+ this.chart = chart;\r
+ this.index = datasetIndex;\r
+ this.linkScales();\r
+ this.addElements();\r
+ },\r
+\r
+ updateIndex: function(datasetIndex) {\r
+ this.index = datasetIndex;\r
+ },\r
+\r
+ linkScales: function() {\r
+ var meta = this.getMeta();\r
+ var dataset = this.getDataset();\r
+\r
+ if (meta.xAxisID === null) {\r
+ meta.xAxisID = dataset.xAxisID || this.chart.options.scales.xAxes[0].id;\r
+ }\r
+ if (meta.yAxisID === null) {\r
+ meta.yAxisID = dataset.yAxisID || this.chart.options.scales.yAxes[0].id;\r
+ }\r
+ },\r
+\r
+ getDataset: function() {\r
+ return this.chart.data.datasets[this.index];\r
+ },\r
+\r
+ getMeta: function() {\r
+ return this.chart.getDatasetMeta(this.index);\r
+ },\r
+\r
+ getScaleForId: function(scaleID) {\r
+ return this.chart.scales[scaleID];\r
+ },\r
+\r
+ reset: function() {\r
+ this.update(true);\r
+ },\r
+\r
+ createMetaDataset: function() {\r
+ var me = this;\r
+ var type = me.datasetElementType;\r
+ return type && new type({\r
+ _chart: me.chart.chart,\r
+ _datasetIndex: me.index\r
+ });\r
+ },\r
+\r
+ createMetaData: function(index) {\r
+ var me = this;\r
+ var type = me.dataElementType;\r
+ return type && new type({\r
+ _chart: me.chart.chart,\r
+ _datasetIndex: me.index,\r
+ _index: index\r
+ });\r
+ },\r
+\r
+ addElements: function() {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var data = me.getDataset().data || [];\r
+ var metaData = meta.data;\r
+ var i, ilen;\r
+\r
+ for (i=0, ilen=data.length; i<ilen; ++i) {\r
+ metaData[i] = metaData[i] || me.createMetaData(meta, i);\r
+ }\r
+\r
+ meta.dataset = meta.dataset || me.createMetaDataset();\r
+ },\r
+\r
+ addElementAndReset: function(index) {\r
+ var me = this;\r
+ var element = me.createMetaData(index);\r
+ me.getMeta().data.splice(index, 0, element);\r
+ me.updateElement(element, index, true);\r
+ },\r
+\r
+ buildOrUpdateElements: function buildOrUpdateElements() {\r
+ // Handle the number of data points changing\r
+ var meta = this.getMeta(),\r
+ md = meta.data,\r
+ numData = this.getDataset().data.length,\r
+ numMetaData = md.length;\r
+\r
+ // Make sure that we handle number of datapoints changing\r
+ if (numData < numMetaData) {\r
+ // Remove excess bars for data points that have been removed\r
+ md.splice(numData, numMetaData - numData);\r
+ } else if (numData > numMetaData) {\r
+ // Add new elements\r
+ for (var index = numMetaData; index < numData; ++index) {\r
+ this.addElementAndReset(index);\r
+ }\r
+ }\r
+ },\r
+\r
+ update: noop,\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ helpers.each(this.getMeta().data, function(element, index) {\r
+ element.transition(easingDecimal).draw();\r
+ });\r
+ },\r
+\r
+ removeHoverStyle: function(element, elementOpts) {\r
+ var dataset = this.chart.data.datasets[element._datasetIndex],\r
+ index = element._index,\r
+ custom = element.custom || {},\r
+ valueOrDefault = helpers.getValueAtIndexOrDefault,\r
+ color = helpers.color,\r
+ model = element._model;\r
+\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);\r
+ },\r
+\r
+ setHoverStyle: function(element) {\r
+ var dataset = this.chart.data.datasets[element._datasetIndex],\r
+ index = element._index,\r
+ custom = element.custom || {},\r
+ valueOrDefault = helpers.getValueAtIndexOrDefault,\r
+ color = helpers.color,\r
+ getHoverColor = helpers.getHoverColor,\r
+ model = element._model;\r
+\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ }\r
+ });\r
+\r
+ Chart.DatasetController.extend = helpers.inherits;\r
};
+},{}],24:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.elements = {};\r
+\r
+ Chart.Element = function(configuration) {\r
+ helpers.extend(this, configuration);\r
+ this.initialize.apply(this, arguments);\r
+ };\r
+ helpers.extend(Chart.Element.prototype, {\r
+ initialize: function() {\r
+ this.hidden = false;\r
+ },\r
+ pivot: function() {\r
+ if (!this._view) {\r
+ this._view = helpers.clone(this._model);\r
+ }\r
+ this._start = helpers.clone(this._view);\r
+ return this;\r
+ },\r
+ transition: function(ease) {\r
+ if (!this._view) {\r
+ this._view = helpers.clone(this._model);\r
+ }\r
+\r
+ // No animation -> No Transition\r
+ if (ease === 1) {\r
+ this._view = this._model;\r
+ this._start = null;\r
+ return this;\r
+ }\r
+\r
+ if (!this._start) {\r
+ this.pivot();\r
+ }\r
+\r
+ helpers.each(this._model, function(value, key) {\r
+\r
+ if (key[0] === '_') {\r
+ // Only non-underscored properties\r
+ }\r
+\r
+ // Init if doesn't exist\r
+ else if (!this._view.hasOwnProperty(key)) {\r
+ if (typeof value === 'number' && !isNaN(this._view[key])) {\r
+ this._view[key] = value * ease;\r
+ } else {\r
+ this._view[key] = value;\r
+ }\r
+ }\r
+\r
+ // No unnecessary computations\r
+ else if (value === this._view[key]) {\r
+ // It's the same! Woohoo!\r
+ }\r
+\r
+ // Color transitions if possible\r
+ else if (typeof value === 'string') {\r
+ try {\r
+ var color = helpers.color(this._model[key]).mix(helpers.color(this._start[key]), ease);\r
+ this._view[key] = color.rgbString();\r
+ } catch (err) {\r
+ this._view[key] = value;\r
+ }\r
+ }\r
+ // Number transitions\r
+ else if (typeof value === 'number') {\r
+ var startVal = this._start[key] !== undefined && isNaN(this._start[key]) === false ? this._start[key] : 0;\r
+ this._view[key] = ((this._model[key] - startVal) * ease) + startVal;\r
+ }\r
+ // Everything else\r
+ else {\r
+ this._view[key] = value;\r
+ }\r
+ }, this);\r
+\r
+ return this;\r
+ },\r
+ tooltipPosition: function() {\r
+ return {\r
+ x: this._model.x,\r
+ y: this._model.y\r
+ };\r
+ },\r
+ hasValue: function() {\r
+ return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);\r
+ }\r
+ });\r
+\r
+ Chart.Element.extend = helpers.inherits;\r
+\r
+};\r
},{}],25:[function(require,module,exports){
-/*global window: false */
-/*global document: false */
-"use strict";
-
-var color = require(2);
-
-module.exports = function(Chart) {
- //Global Chart helpers object for utility methods and classes
- var helpers = Chart.helpers = {};
-
- //-- Basic js utility methods
- helpers.each = function(loopable, callback, self, reverse) {
- // Check to see if null or undefined firstly.
- var i, len;
- if (helpers.isArray(loopable)) {
- len = loopable.length;
- if (reverse) {
- for (i = len - 1; i >= 0; i--) {
- callback.call(self, loopable[i], i);
- }
- } else {
- for (i = 0; i < len; i++) {
- callback.call(self, loopable[i], i);
- }
- }
- } else if (typeof loopable === 'object') {
- var keys = Object.keys(loopable);
- len = keys.length;
- for (i = 0; i < len; i++) {
- callback.call(self, loopable[keys[i]], keys[i]);
- }
- }
- };
- helpers.clone = function(obj) {
- var objClone = {};
- helpers.each(obj, function(value, key) {
- if (helpers.isArray(value)) {
- objClone[key] = value.slice(0);
- } else if (typeof value === 'object' && value !== null) {
- objClone[key] = helpers.clone(value);
- } else {
- objClone[key] = value;
- }
- });
- return objClone;
- };
- helpers.extend = function(base) {
- var len = arguments.length;
- var additionalArgs = [];
- for (var i = 1; i < len; i++) {
- additionalArgs.push(arguments[i]);
- }
- helpers.each(additionalArgs, function(extensionObject) {
- helpers.each(extensionObject, function(value, key) {
- base[key] = value;
- });
- });
- return base;
- };
- // Need a special merge function to chart configs since they are now grouped
- helpers.configMerge = function(_base) {
- var base = helpers.clone(_base);
- helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {
- helpers.each(extension, function(value, key) {
- if (key === 'scales') {
- // Scale config merging is complex. Add out own function here for that
- base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);
-
- } else if (key === 'scale') {
- // Used in polar area & radar charts since there is only one scale
- base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
- } else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
- // In this case we have an array of objects replacing another array. Rather than doing a strict replace,
- // merge. This allows easy scale option merging
- var baseArray = base[key];
-
- helpers.each(value, function(valueObj, index) {
-
- if (index < baseArray.length) {
- if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {
- // Two objects are coming together. Do a merge of them.
- baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
- } else {
- // Just overwrite in this case since there is nothing to merge
- baseArray[index] = valueObj;
- }
- } else {
- baseArray.push(valueObj); // nothing to merge
- }
- });
-
- } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
- // If we are overwriting an object with an object, do a merge of the properties.
- base[key] = helpers.configMerge(base[key], value);
-
- } else {
- // can just overwrite the value in this case
- base[key] = value;
- }
- });
- });
-
- return base;
- };
- helpers.extendDeep = function(_base) {
- return _extendDeep.apply(this, arguments);
-
- function _extendDeep(dst) {
- helpers.each(arguments, function(obj) {
- if (obj !== dst) {
- helpers.each(obj, function(value, key) {
- if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
- _extendDeep(dst[key], value);
- } else {
- dst[key] = value;
- }
- });
- }
- });
- return dst;
- }
- };
- helpers.scaleMerge = function(_base, extension) {
- var base = helpers.clone(_base);
-
- helpers.each(extension, function(value, key) {
- if (key === 'xAxes' || key === 'yAxes') {
- // These properties are arrays of items
- if (base.hasOwnProperty(key)) {
- helpers.each(value, function(valueObj, index) {
- var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
- var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);
- if (index >= base[key].length || !base[key][index].type) {
- base[key].push(helpers.configMerge(axisDefaults, valueObj));
- } else if (valueObj.type && valueObj.type !== base[key][index].type) {
- // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults
- base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);
- } else {
- // Type is the same
- base[key][index] = helpers.configMerge(base[key][index], valueObj);
- }
- });
- } else {
- base[key] = [];
- helpers.each(value, function(valueObj) {
- var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
- base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));
- });
- }
- } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
- // If we are overwriting an object with an object, do a merge of the properties.
- base[key] = helpers.configMerge(base[key], value);
-
- } else {
- // can just overwrite the value in this case
- base[key] = value;
- }
- });
-
- return base;
- };
- helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {
- if (value === undefined || value === null) {
- return defaultValue;
- }
-
- if (helpers.isArray(value)) {
- return index < value.length ? value[index] : defaultValue;
- }
-
- return value;
- };
- helpers.getValueOrDefault = function(value, defaultValue) {
- return value === undefined ? defaultValue : value;
- };
- helpers.indexOf = function(arrayToSearch, item) {
- if (Array.prototype.indexOf) {
- return arrayToSearch.indexOf(item);
- } else {
- for (var i = 0; i < arrayToSearch.length; i++) {
- if (arrayToSearch[i] === item)
- return i;
- }
- return -1;
- }
- };
- helpers.where = function(collection, filterCallback) {
- if (helpers.isArray(collection) && Array.prototype.filter) {
- return collection.filter(filterCallback);
- } else {
- var filtered = [];
-
- helpers.each(collection, function(item) {
- if (filterCallback(item)) {
- filtered.push(item);
- }
- });
-
- return filtered;
- }
- };
- helpers.findIndex = function(arrayToSearch, callback, thisArg) {
- var index = -1;
- if (Array.prototype.findIndex) {
- index = arrayToSearch.findIndex(callback, thisArg);
- } else {
- for (var i = 0; i < arrayToSearch.length; ++i) {
- thisArg = thisArg !== undefined ? thisArg : arrayToSearch;
-
- if (callback.call(thisArg, arrayToSearch[i], i, arrayToSearch)) {
- index = i;
- break;
- }
- }
- }
-
- return index;
- };
- helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
- // Default to start of the array
- if (startIndex === undefined || startIndex === null) {
- startIndex = -1;
- }
- for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
- var currentItem = arrayToSearch[i];
- if (filterCallback(currentItem)) {
- return currentItem;
- }
- }
- };
- helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
- // Default to end of the array
- if (startIndex === undefined || startIndex === null) {
- startIndex = arrayToSearch.length;
- }
- for (var i = startIndex - 1; i >= 0; i--) {
- var currentItem = arrayToSearch[i];
- if (filterCallback(currentItem)) {
- return currentItem;
- }
- }
- };
- helpers.inherits = function(extensions) {
- //Basic javascript inheritance based on the model created in Backbone.js
- var parent = this;
- var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function() {
- return parent.apply(this, arguments);
- };
-
- var Surrogate = function() {
- this.constructor = ChartElement;
- };
- Surrogate.prototype = parent.prototype;
- ChartElement.prototype = new Surrogate();
-
- ChartElement.extend = helpers.inherits;
-
- if (extensions) {
- helpers.extend(ChartElement.prototype, extensions);
- }
-
- ChartElement.__super__ = parent.prototype;
-
- return ChartElement;
- };
- helpers.noop = function() {};
- helpers.uid = (function() {
- var id = 0;
- return function() {
- return id++;
- };
- })();
- helpers.warn = function(str) {
- //Method for warning of errors
- if (console && typeof console.warn === "function") {
- console.warn(str);
- }
- };
- //-- Math methods
- helpers.isNumber = function(n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- };
- helpers.almostEquals = function(x, y, epsilon) {
- return Math.abs(x - y) < epsilon;
- };
- helpers.max = function(array) {
- return array.reduce(function(max, value) {
- if (!isNaN(value)) {
- return Math.max(max, value);
- } else {
- return max;
- }
- }, Number.NEGATIVE_INFINITY);
- };
- helpers.min = function(array) {
- return array.reduce(function(min, value) {
- if (!isNaN(value)) {
- return Math.min(min, value);
- } else {
- return min;
- }
- }, Number.POSITIVE_INFINITY);
- };
- helpers.sign = function(x) {
- if (Math.sign) {
- return Math.sign(x);
- } else {
- x = +x; // convert to a number
- if (x === 0 || isNaN(x)) {
- return x;
- }
- return x > 0 ? 1 : -1;
- }
- };
- helpers.log10 = function(x) {
- if (Math.log10) {
- return Math.log10(x);
- } else {
- return Math.log(x) / Math.LN10;
- }
- };
- helpers.toRadians = function(degrees) {
- return degrees * (Math.PI / 180);
- };
- helpers.toDegrees = function(radians) {
- return radians * (180 / Math.PI);
- };
- // Gets the angle from vertical upright to the point about a centre.
- helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
- var distanceFromXCenter = anglePoint.x - centrePoint.x,
- distanceFromYCenter = anglePoint.y - centrePoint.y,
- radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
-
- var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
-
- if (angle < (-0.5 * Math.PI)) {
- angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
- }
-
- return {
- angle: angle,
- distance: radialDistanceFromCenter
- };
- };
- helpers.aliasPixel = function(pixelWidth) {
- return (pixelWidth % 2 === 0) ? 0 : 0.5;
- };
- helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
- //Props to Rob Spencer at scaled innovation for his post on splining between points
- //http://scaledinnovation.com/analytics/splines/aboutSplines.html
-
- // This function must also respect "skipped" points
-
- var previous = firstPoint.skip ? middlePoint : firstPoint,
- current = middlePoint,
- next = afterPoint.skip ? middlePoint : afterPoint;
-
- var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
- var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
-
- var s01 = d01 / (d01 + d12);
- var s12 = d12 / (d01 + d12);
-
- // If all points are the same, s01 & s02 will be inf
- s01 = isNaN(s01) ? 0 : s01;
- s12 = isNaN(s12) ? 0 : s12;
-
- var fa = t * s01; // scaling factor for triangle Ta
- var fb = t * s12;
-
- return {
- previous: {
- x: current.x - fa * (next.x - previous.x),
- y: current.y - fa * (next.y - previous.y)
- },
- next: {
- x: current.x + fb * (next.x - previous.x),
- y: current.y + fb * (next.y - previous.y)
- }
- };
- };
- helpers.nextItem = function(collection, index, loop) {
- if (loop) {
- return index >= collection.length - 1 ? collection[0] : collection[index + 1];
- }
-
- return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
- };
- helpers.previousItem = function(collection, index, loop) {
- if (loop) {
- return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
- }
- return index <= 0 ? collection[0] : collection[index - 1];
- };
- // Implementation of the nice number algorithm used in determining where axis labels will go
- helpers.niceNum = function(range, round) {
- var exponent = Math.floor(helpers.log10(range));
- var fraction = range / Math.pow(10, exponent);
- var niceFraction;
-
- if (round) {
- if (fraction < 1.5) {
- niceFraction = 1;
- } else if (fraction < 3) {
- niceFraction = 2;
- } else if (fraction < 7) {
- niceFraction = 5;
- } else {
- niceFraction = 10;
- }
- } else {
- if (fraction <= 1.0) {
- niceFraction = 1;
- } else if (fraction <= 2) {
- niceFraction = 2;
- } else if (fraction <= 5) {
- niceFraction = 5;
- } else {
- niceFraction = 10;
- }
- }
-
- return niceFraction * Math.pow(10, exponent);
- };
- //Easing functions adapted from Robert Penner's easing equations
- //http://www.robertpenner.com/easing/
- var easingEffects = helpers.easingEffects = {
- linear: function(t) {
- return t;
- },
- easeInQuad: function(t) {
- return t * t;
- },
- easeOutQuad: function(t) {
- return -1 * t * (t - 2);
- },
- easeInOutQuad: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t;
- }
- return -1 / 2 * ((--t) * (t - 2) - 1);
- },
- easeInCubic: function(t) {
- return t * t * t;
- },
- easeOutCubic: function(t) {
- return 1 * ((t = t / 1 - 1) * t * t + 1);
- },
- easeInOutCubic: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t;
- }
- return 1 / 2 * ((t -= 2) * t * t + 2);
- },
- easeInQuart: function(t) {
- return t * t * t * t;
- },
- easeOutQuart: function(t) {
- return -1 * ((t = t / 1 - 1) * t * t * t - 1);
- },
- easeInOutQuart: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t * t;
- }
- return -1 / 2 * ((t -= 2) * t * t * t - 2);
- },
- easeInQuint: function(t) {
- return 1 * (t /= 1) * t * t * t * t;
- },
- easeOutQuint: function(t) {
- return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
- },
- easeInOutQuint: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t * t * t;
- }
- return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
- },
- easeInSine: function(t) {
- return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
- },
- easeOutSine: function(t) {
- return 1 * Math.sin(t / 1 * (Math.PI / 2));
- },
- easeInOutSine: function(t) {
- return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
- },
- easeInExpo: function(t) {
- return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
- },
- easeOutExpo: function(t) {
- return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
- },
- easeInOutExpo: function(t) {
- if (t === 0) {
- return 0;
- }
- if (t === 1) {
- return 1;
- }
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * Math.pow(2, 10 * (t - 1));
- }
- return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
- },
- easeInCirc: function(t) {
- if (t >= 1) {
- return t;
- }
- return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
- },
- easeOutCirc: function(t) {
- return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
- },
- easeInOutCirc: function(t) {
- if ((t /= 1 / 2) < 1) {
- return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
- }
- return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
- },
- easeInElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1) === 1) {
- return 1;
- }
- if (!p) {
- p = 1 * 0.3;
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
- },
- easeOutElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1) === 1) {
- return 1;
- }
- if (!p) {
- p = 1 * 0.3;
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
- },
- easeInOutElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1 / 2) === 2) {
- return 1;
- }
- if (!p) {
- p = 1 * (0.3 * 1.5);
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- if (t < 1) {
- return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
- }
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
- },
- easeInBack: function(t) {
- var s = 1.70158;
- return 1 * (t /= 1) * t * ((s + 1) * t - s);
- },
- easeOutBack: function(t) {
- var s = 1.70158;
- return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
- },
- easeInOutBack: function(t) {
- var s = 1.70158;
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
- }
- return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
- },
- easeInBounce: function(t) {
- return 1 - easingEffects.easeOutBounce(1 - t);
- },
- easeOutBounce: function(t) {
- if ((t /= 1) < (1 / 2.75)) {
- return 1 * (7.5625 * t * t);
- } else if (t < (2 / 2.75)) {
- return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
- } else if (t < (2.5 / 2.75)) {
- return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
- } else {
- return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
- }
- },
- easeInOutBounce: function(t) {
- if (t < 1 / 2) {
- return easingEffects.easeInBounce(t * 2) * 0.5;
- }
- return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
- }
- };
- //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
- helpers.requestAnimFrame = (function() {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function(callback) {
- return window.setTimeout(callback, 1000 / 60);
- };
- })();
- helpers.cancelAnimFrame = (function() {
- return window.cancelAnimationFrame ||
- window.webkitCancelAnimationFrame ||
- window.mozCancelAnimationFrame ||
- window.oCancelAnimationFrame ||
- window.msCancelAnimationFrame ||
- function(callback) {
- return window.clearTimeout(callback, 1000 / 60);
- };
- })();
- //-- DOM methods
- helpers.getRelativePosition = function(evt, chart) {
- var mouseX, mouseY;
- var e = evt.originalEvent || evt,
- canvas = evt.currentTarget || evt.srcElement,
- boundingRect = canvas.getBoundingClientRect();
-
- var touches = e.touches;
- if (touches && touches.length > 0) {
- mouseX = touches[0].clientX;
- mouseY = touches[0].clientY;
-
- } else {
- mouseX = e.clientX;
- mouseY = e.clientY;
- }
-
- // Scale mouse coordinates into canvas coordinates
- // by following the pattern laid out by 'jerryj' in the comments of
- // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
- var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));
- var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));
- var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));
- var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));
- var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
- var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
-
- // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
- // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
- mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
- mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
-
- return {
- x: mouseX,
- y: mouseY
- };
-
- };
- helpers.addEvent = function(node, eventType, method) {
- if (node.addEventListener) {
- node.addEventListener(eventType, method);
- } else if (node.attachEvent) {
- node.attachEvent("on" + eventType, method);
- } else {
- node["on" + eventType] = method;
- }
- };
- helpers.removeEvent = function(node, eventType, handler) {
- if (node.removeEventListener) {
- node.removeEventListener(eventType, handler, false);
- } else if (node.detachEvent) {
- node.detachEvent("on" + eventType, handler);
- } else {
- node["on" + eventType] = helpers.noop;
- }
- };
- helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {
- // Create the events object if it's not already present
- var events = chartInstance.events = chartInstance.events || {};
-
- helpers.each(arrayOfEvents, function(eventName) {
- events[eventName] = function() {
- handler.apply(chartInstance, arguments);
- };
- helpers.addEvent(chartInstance.chart.canvas, eventName, events[eventName]);
- });
- };
- helpers.unbindEvents = function(chartInstance, arrayOfEvents) {
- var canvas = chartInstance.chart.canvas;
- helpers.each(arrayOfEvents, function(handler, eventName) {
- helpers.removeEvent(canvas, eventName, handler);
- });
- };
-
- // Private helper function to convert max-width/max-height values that may be percentages into a number
- function parseMaxStyle(styleValue, node, parentProperty) {
- var valueInPixels;
- if (typeof(styleValue) === 'string') {
- valueInPixels = parseInt(styleValue, 10);
-
- if (styleValue.indexOf('%') != -1) {
- // percentage * size in dimension
- valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
- }
- } else {
- valueInPixels = styleValue;
- }
-
- return valueInPixels;
- }
-
- /**
- * Returns if the given value contains an effective constraint.
- * @private
- */
- function isConstrainedValue(value) {
- return value !== undefined && value !== null && value !== 'none';
- }
-
- // Private helper to get a constraint dimension
- // @param domNode : the node to check the constraint on
- // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)
- // @param percentageProperty : property of parent to use when calculating width as a percentage
- // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser
- function getConstraintDimension(domNode, maxStyle, percentageProperty) {
- var view = document.defaultView;
- var parentNode = domNode.parentNode;
- var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
- var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
- var hasCNode = isConstrainedValue(constrainedNode);
- var hasCContainer = isConstrainedValue(constrainedContainer);
- var infinity = Number.POSITIVE_INFINITY;
-
- if (hasCNode || hasCContainer) {
- return Math.min(
- hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
- hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
- }
-
- return 'none';
- }
- // returns Number or undefined if no constraint
- helpers.getConstraintWidth = function(domNode) {
- return getConstraintDimension(domNode, 'max-width', 'clientWidth');
- };
- // returns Number or undefined if no constraint
- helpers.getConstraintHeight = function(domNode) {
- return getConstraintDimension(domNode, 'max-height', 'clientHeight');
- };
- helpers.getMaximumWidth = function(domNode) {
- var container = domNode.parentNode;
- var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));
- var w = container.clientWidth - padding;
- var cw = helpers.getConstraintWidth(domNode);
- return isNaN(cw)? w : Math.min(w, cw);
- };
- helpers.getMaximumHeight = function(domNode) {
- var container = domNode.parentNode;
- var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));
- var h = container.clientHeight - padding;
- var ch = helpers.getConstraintHeight(domNode);
- return isNaN(ch)? h : Math.min(h, ch);
- };
- helpers.getStyle = function(el, property) {
- return el.currentStyle ?
- el.currentStyle[property] :
- document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
- };
- helpers.retinaScale = function(chart) {
- var ctx = chart.ctx;
- var canvas = chart.canvas;
- var width = canvas.width;
- var height = canvas.height;
- var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
-
- if (pixelRatio !== 1) {
- canvas.height = height * pixelRatio;
- canvas.width = width * pixelRatio;
- ctx.scale(pixelRatio, pixelRatio);
-
- // Store the device pixel ratio so that we can go backwards in `destroy`.
- // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same
- // when destroy is called
- chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
- }
-
- canvas.style.width = width + 'px';
- canvas.style.height = height + 'px';
- };
- //-- Canvas methods
- helpers.clear = function(chart) {
- chart.ctx.clearRect(0, 0, chart.width, chart.height);
- };
- helpers.fontString = function(pixelSize, fontStyle, fontFamily) {
- return fontStyle + " " + pixelSize + "px " + fontFamily;
- };
- helpers.longestText = function(ctx, font, arrayOfThings, cache) {
- cache = cache || {};
- var data = cache.data = cache.data || {};
- var gc = cache.garbageCollect = cache.garbageCollect || [];
-
- if (cache.font !== font) {
- data = cache.data = {};
- gc = cache.garbageCollect = [];
- cache.font = font;
- }
-
- ctx.font = font;
- var longest = 0;
- helpers.each(arrayOfThings, function(thing) {
- // Undefined strings and arrays should not be measured
- if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) {
- longest = helpers.measureText(ctx, data, gc, longest, thing);
- } else if (helpers.isArray(thing)) {
- // if it is an array lets measure each element
- // to do maybe simplify this function a bit so we can do this more recursively?
- helpers.each(thing, function(nestedThing) {
- // Undefined strings and arrays should not be measured
- if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) {
- longest = helpers.measureText(ctx, data, gc, longest, nestedThing);
- }
- });
- }
- });
-
- var gcLen = gc.length / 2;
- if (gcLen > arrayOfThings.length) {
- for (var i = 0; i < gcLen; i++) {
- delete data[gc[i]];
- }
- gc.splice(0, gcLen);
- }
- return longest;
- };
- helpers.measureText = function (ctx, data, gc, longest, string) {
- var textWidth = data[string];
- if (!textWidth) {
- textWidth = data[string] = ctx.measureText(string).width;
- gc.push(string);
- }
- if (textWidth > longest) {
- longest = textWidth;
- }
- return longest;
- };
- helpers.numberOfLabelLines = function(arrayOfThings) {
- var numberOfLines = 1;
- helpers.each(arrayOfThings, function(thing) {
- if (helpers.isArray(thing)) {
- if (thing.length > numberOfLines) {
- numberOfLines = thing.length;
- }
- }
- });
- return numberOfLines;
- };
- helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) {
- ctx.beginPath();
- ctx.moveTo(x + radius, y);
- ctx.lineTo(x + width - radius, y);
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
- ctx.lineTo(x + width, y + height - radius);
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
- ctx.lineTo(x + radius, y + height);
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
- ctx.lineTo(x, y + radius);
- ctx.quadraticCurveTo(x, y, x + radius, y);
- ctx.closePath();
- };
- helpers.color = function(c) {
- if (!color) {
- console.log('Color.js not found!');
- return c;
- }
-
- /* global CanvasGradient */
- if (c instanceof CanvasGradient) {
- return color(Chart.defaults.global.defaultColor);
- }
-
- return color(c);
- };
- helpers.addResizeListener = function(node, callback) {
- // Hide an iframe before the node
- var hiddenIframe = document.createElement('iframe');
- var hiddenIframeClass = 'chartjs-hidden-iframe';
-
- if (hiddenIframe.classlist) {
- // can use classlist
- hiddenIframe.classlist.add(hiddenIframeClass);
- } else {
- hiddenIframe.setAttribute('class', hiddenIframeClass);
- }
-
- // Set the style
- var style = hiddenIframe.style;
- style.width = '100%';
- style.display = 'block';
- style.border = 0;
- style.height = 0;
- style.margin = 0;
- style.position = 'absolute';
- style.left = 0;
- style.right = 0;
- style.top = 0;
- style.bottom = 0;
-
- // Insert the iframe so that contentWindow is available
- node.insertBefore(hiddenIframe, node.firstChild);
-
- (hiddenIframe.contentWindow || hiddenIframe).onresize = function() {
- if (callback) {
- callback();
- }
- };
- };
- helpers.removeResizeListener = function(node) {
- var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');
-
- // Remove the resize detect iframe
- if (hiddenIframe) {
- hiddenIframe.parentNode.removeChild(hiddenIframe);
- }
- };
- helpers.isArray = function(obj) {
- if (!Array.isArray) {
- return Object.prototype.toString.call(obj) === '[object Array]';
- }
- return Array.isArray(obj);
- };
- //! @see http://stackoverflow.com/a/14853974
- helpers.arrayEquals = function(a0, a1) {
- var i, ilen, v0, v1;
-
- if (!a0 || !a1 || a0.length != a1.length) {
- return false;
- }
-
- for (i = 0, ilen=a0.length; i < ilen; ++i) {
- v0 = a0[i];
- v1 = a1[i];
-
- if (v0 instanceof Array && v1 instanceof Array) {
- if (!helpers.arrayEquals(v0, v1)) {
- return false;
- }
- } else if (v0 != v1) {
- // NOTE: two different object instances will never be equal: {x:20} != {x:20}
- return false;
- }
- }
-
- return true;
- };
- helpers.callCallback = function(fn, args, _tArg) {
- if (fn && typeof fn.call === 'function') {
- fn.apply(_tArg, args);
- }
- };
- helpers.getHoverColor = function(color) {
- /* global CanvasPattern */
- return (color instanceof CanvasPattern) ?
- color :
- helpers.color(color).saturate(0.5).darken(0.1).rgbString();
- };
-};
-
-},{"2":2}],26:[function(require,module,exports){
-"use strict";
-
-module.exports = function() {
-
- //Occupy the global variable of Chart, and create a simple base class
- var Chart = function(context, config) {
- var me = this;
- var helpers = Chart.helpers;
- me.config = config;
-
- // Support a jQuery'd canvas element
- if (context.length && context[0].getContext) {
- context = context[0];
- }
-
- // Support a canvas domnode
- if (context.getContext) {
- context = context.getContext("2d");
- }
-
- me.ctx = context;
- me.canvas = context.canvas;
-
- context.canvas.style.display = context.canvas.style.display || 'block';
-
- // Figure out what the size of the chart will be.
- // If the canvas has a specified width and height, we use those else
- // we look to see if the canvas node has a CSS width and height.
- // If there is still no height, fill the parent container
- me.width = context.canvas.width || parseInt(helpers.getStyle(context.canvas, 'width'), 10) || helpers.getMaximumWidth(context.canvas);
- me.height = context.canvas.height || parseInt(helpers.getStyle(context.canvas, 'height'), 10) || helpers.getMaximumHeight(context.canvas);
-
- me.aspectRatio = me.width / me.height;
-
- if (isNaN(me.aspectRatio) || isFinite(me.aspectRatio) === false) {
- // If the canvas has no size, try and figure out what the aspect ratio will be.
- // Some charts prefer square canvases (pie, radar, etc). If that is specified, use that
- // else use the canvas default ratio of 2
- me.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;
- }
-
- // Store the original style of the element so we can set it back
- me.originalCanvasStyleWidth = context.canvas.style.width;
- me.originalCanvasStyleHeight = context.canvas.style.height;
-
- // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
- helpers.retinaScale(me);
-
- if (config) {
- me.controller = new Chart.Controller(me);
- }
-
- // Always bind this so that if the responsive state changes we still work
- helpers.addResizeListener(context.canvas.parentNode, function() {
- if (me.controller && me.controller.config.options.responsive) {
- me.controller.resize();
- }
- });
-
- return me.controller ? me.controller : me;
-
- };
-
- //Globally expose the defaults to allow for user updating/changing
- Chart.defaults = {
- global: {
- responsive: true,
- responsiveAnimationDuration: 0,
- maintainAspectRatio: true,
- events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],
- hover: {
- onHover: null,
- mode: 'single',
- animationDuration: 400
- },
- onClick: null,
- defaultColor: 'rgba(0,0,0,0.1)',
- defaultFontColor: '#666',
- defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
- defaultFontSize: 12,
- defaultFontStyle: 'normal',
- showLines: true,
-
- // Element defaults defined in element extensions
- elements: {},
-
- // Legend callback string
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
- for (var i = 0; i < chart.data.datasets.length; i++) {
- text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
- if (chart.data.datasets[i].label) {
- text.push(chart.data.datasets[i].label);
- }
- text.push('</li>');
- }
- text.push('</ul>');
-
- return text.join("");
- }
- }
- };
-
- Chart.Chart = Chart;
-
- return Chart;
+/*global window: false */\r
+/*global document: false */\r
+"use strict";\r
+\r
+var color = require('chartjs-color');\r
+\r
+module.exports = function(Chart) {\r
+ //Global Chart helpers object for utility methods and classes\r
+ var helpers = Chart.helpers = {};\r
+\r
+ //-- Basic js utility methods\r
+ helpers.each = function(loopable, callback, self, reverse) {\r
+ // Check to see if null or undefined firstly.\r
+ var i, len;\r
+ if (helpers.isArray(loopable)) {\r
+ len = loopable.length;\r
+ if (reverse) {\r
+ for (i = len - 1; i >= 0; i--) {\r
+ callback.call(self, loopable[i], i);\r
+ }\r
+ } else {\r
+ for (i = 0; i < len; i++) {\r
+ callback.call(self, loopable[i], i);\r
+ }\r
+ }\r
+ } else if (typeof loopable === 'object') {\r
+ var keys = Object.keys(loopable);\r
+ len = keys.length;\r
+ for (i = 0; i < len; i++) {\r
+ callback.call(self, loopable[keys[i]], keys[i]);\r
+ }\r
+ }\r
+ };\r
+ helpers.clone = function(obj) {\r
+ var objClone = {};\r
+ helpers.each(obj, function(value, key) {\r
+ if (helpers.isArray(value)) {\r
+ objClone[key] = value.slice(0);\r
+ } else if (typeof value === 'object' && value !== null) {\r
+ objClone[key] = helpers.clone(value);\r
+ } else {\r
+ objClone[key] = value;\r
+ }\r
+ });\r
+ return objClone;\r
+ };\r
+ helpers.extend = function(base) {\r
+ var len = arguments.length;\r
+ var additionalArgs = [];\r
+ for (var i = 1; i < len; i++) {\r
+ additionalArgs.push(arguments[i]);\r
+ }\r
+ helpers.each(additionalArgs, function(extensionObject) {\r
+ helpers.each(extensionObject, function(value, key) {\r
+ base[key] = value;\r
+ });\r
+ });\r
+ return base;\r
+ };\r
+ // Need a special merge function to chart configs since they are now grouped\r
+ helpers.configMerge = function(_base) {\r
+ var base = helpers.clone(_base);\r
+ helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {\r
+ helpers.each(extension, function(value, key) {\r
+ if (key === 'scales') {\r
+ // Scale config merging is complex. Add out own function here for that\r
+ base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);\r
+\r
+ } else if (key === 'scale') {\r
+ // Used in polar area & radar charts since there is only one scale\r
+ base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);\r
+ } else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {\r
+ // In this case we have an array of objects replacing another array. Rather than doing a strict replace,\r
+ // merge. This allows easy scale option merging\r
+ var baseArray = base[key];\r
+\r
+ helpers.each(value, function(valueObj, index) {\r
+\r
+ if (index < baseArray.length) {\r
+ if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {\r
+ // Two objects are coming together. Do a merge of them.\r
+ baseArray[index] = helpers.configMerge(baseArray[index], valueObj);\r
+ } else {\r
+ // Just overwrite in this case since there is nothing to merge\r
+ baseArray[index] = valueObj;\r
+ }\r
+ } else {\r
+ baseArray.push(valueObj); // nothing to merge\r
+ }\r
+ });\r
+\r
+ } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {\r
+ // If we are overwriting an object with an object, do a merge of the properties.\r
+ base[key] = helpers.configMerge(base[key], value);\r
+\r
+ } else {\r
+ // can just overwrite the value in this case\r
+ base[key] = value;\r
+ }\r
+ });\r
+ });\r
+\r
+ return base;\r
+ };\r
+ helpers.extendDeep = function(_base) {\r
+ return _extendDeep.apply(this, arguments);\r
+\r
+ function _extendDeep(dst) {\r
+ helpers.each(arguments, function(obj) {\r
+ if (obj !== dst) {\r
+ helpers.each(obj, function(value, key) {\r
+ if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {\r
+ _extendDeep(dst[key], value);\r
+ } else {\r
+ dst[key] = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ return dst;\r
+ }\r
+ };\r
+ helpers.scaleMerge = function(_base, extension) {\r
+ var base = helpers.clone(_base);\r
+\r
+ helpers.each(extension, function(value, key) {\r
+ if (key === 'xAxes' || key === 'yAxes') {\r
+ // These properties are arrays of items\r
+ if (base.hasOwnProperty(key)) {\r
+ helpers.each(value, function(valueObj, index) {\r
+ var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');\r
+ var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);\r
+ if (index >= base[key].length || !base[key][index].type) {\r
+ base[key].push(helpers.configMerge(axisDefaults, valueObj));\r
+ } else if (valueObj.type && valueObj.type !== base[key][index].type) {\r
+ // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults\r
+ base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);\r
+ } else {\r
+ // Type is the same\r
+ base[key][index] = helpers.configMerge(base[key][index], valueObj);\r
+ }\r
+ });\r
+ } else {\r
+ base[key] = [];\r
+ helpers.each(value, function(valueObj) {\r
+ var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');\r
+ base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));\r
+ });\r
+ }\r
+ } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {\r
+ // If we are overwriting an object with an object, do a merge of the properties.\r
+ base[key] = helpers.configMerge(base[key], value);\r
+\r
+ } else {\r
+ // can just overwrite the value in this case\r
+ base[key] = value;\r
+ }\r
+ });\r
+\r
+ return base;\r
+ };\r
+ helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {\r
+ if (value === undefined || value === null) {\r
+ return defaultValue;\r
+ }\r
+\r
+ if (helpers.isArray(value)) {\r
+ return index < value.length ? value[index] : defaultValue;\r
+ }\r
+\r
+ return value;\r
+ };\r
+ helpers.getValueOrDefault = function(value, defaultValue) {\r
+ return value === undefined ? defaultValue : value;\r
+ };\r
+ helpers.indexOf = function(arrayToSearch, item) {\r
+ if (Array.prototype.indexOf) {\r
+ return arrayToSearch.indexOf(item);\r
+ } else {\r
+ for (var i = 0; i < arrayToSearch.length; i++) {\r
+ if (arrayToSearch[i] === item)\r
+ return i;\r
+ }\r
+ return -1;\r
+ }\r
+ };\r
+ helpers.where = function(collection, filterCallback) {\r
+ if (helpers.isArray(collection) && Array.prototype.filter) {\r
+ return collection.filter(filterCallback);\r
+ } else {\r
+ var filtered = [];\r
+\r
+ helpers.each(collection, function(item) {\r
+ if (filterCallback(item)) {\r
+ filtered.push(item);\r
+ }\r
+ });\r
+\r
+ return filtered;\r
+ }\r
+ };\r
+ helpers.findIndex = function(arrayToSearch, callback, thisArg) {\r
+ var index = -1;\r
+ if (Array.prototype.findIndex) {\r
+ index = arrayToSearch.findIndex(callback, thisArg);\r
+ } else {\r
+ for (var i = 0; i < arrayToSearch.length; ++i) {\r
+ thisArg = thisArg !== undefined ? thisArg : arrayToSearch;\r
+\r
+ if (callback.call(thisArg, arrayToSearch[i], i, arrayToSearch)) {\r
+ index = i;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return index;\r
+ };\r
+ helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {\r
+ // Default to start of the array\r
+ if (startIndex === undefined || startIndex === null) {\r
+ startIndex = -1;\r
+ }\r
+ for (var i = startIndex + 1; i < arrayToSearch.length; i++) {\r
+ var currentItem = arrayToSearch[i];\r
+ if (filterCallback(currentItem)) {\r
+ return currentItem;\r
+ }\r
+ }\r
+ };\r
+ helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {\r
+ // Default to end of the array\r
+ if (startIndex === undefined || startIndex === null) {\r
+ startIndex = arrayToSearch.length;\r
+ }\r
+ for (var i = startIndex - 1; i >= 0; i--) {\r
+ var currentItem = arrayToSearch[i];\r
+ if (filterCallback(currentItem)) {\r
+ return currentItem;\r
+ }\r
+ }\r
+ };\r
+ helpers.inherits = function(extensions) {\r
+ //Basic javascript inheritance based on the model created in Backbone.js\r
+ var parent = this;\r
+ var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function() {\r
+ return parent.apply(this, arguments);\r
+ };\r
+\r
+ var Surrogate = function() {\r
+ this.constructor = ChartElement;\r
+ };\r
+ Surrogate.prototype = parent.prototype;\r
+ ChartElement.prototype = new Surrogate();\r
+\r
+ ChartElement.extend = helpers.inherits;\r
+\r
+ if (extensions) {\r
+ helpers.extend(ChartElement.prototype, extensions);\r
+ }\r
+\r
+ ChartElement.__super__ = parent.prototype;\r
+\r
+ return ChartElement;\r
+ };\r
+ helpers.noop = function() {};\r
+ helpers.uid = (function() {\r
+ var id = 0;\r
+ return function() {\r
+ return id++;\r
+ };\r
+ })();\r
+ helpers.warn = function(str) {\r
+ //Method for warning of errors\r
+ if (console && typeof console.warn === "function") {\r
+ console.warn(str);\r
+ }\r
+ };\r
+ //-- Math methods\r
+ helpers.isNumber = function(n) {\r
+ return !isNaN(parseFloat(n)) && isFinite(n);\r
+ };\r
+ helpers.almostEquals = function(x, y, epsilon) {\r
+ return Math.abs(x - y) < epsilon;\r
+ };\r
+ helpers.max = function(array) {\r
+ return array.reduce(function(max, value) {\r
+ if (!isNaN(value)) {\r
+ return Math.max(max, value);\r
+ } else {\r
+ return max;\r
+ }\r
+ }, Number.NEGATIVE_INFINITY);\r
+ };\r
+ helpers.min = function(array) {\r
+ return array.reduce(function(min, value) {\r
+ if (!isNaN(value)) {\r
+ return Math.min(min, value);\r
+ } else {\r
+ return min;\r
+ }\r
+ }, Number.POSITIVE_INFINITY);\r
+ };\r
+ helpers.sign = function(x) {\r
+ if (Math.sign) {\r
+ return Math.sign(x);\r
+ } else {\r
+ x = +x; // convert to a number\r
+ if (x === 0 || isNaN(x)) {\r
+ return x;\r
+ }\r
+ return x > 0 ? 1 : -1;\r
+ }\r
+ };\r
+ helpers.log10 = function(x) {\r
+ if (Math.log10) {\r
+ return Math.log10(x);\r
+ } else {\r
+ return Math.log(x) / Math.LN10;\r
+ }\r
+ };\r
+ helpers.toRadians = function(degrees) {\r
+ return degrees * (Math.PI / 180);\r
+ };\r
+ helpers.toDegrees = function(radians) {\r
+ return radians * (180 / Math.PI);\r
+ };\r
+ // Gets the angle from vertical upright to the point about a centre.\r
+ helpers.getAngleFromPoint = function(centrePoint, anglePoint) {\r
+ var distanceFromXCenter = anglePoint.x - centrePoint.x,\r
+ distanceFromYCenter = anglePoint.y - centrePoint.y,\r
+ radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\r
+\r
+ var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);\r
+\r
+ if (angle < (-0.5 * Math.PI)) {\r
+ angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]\r
+ }\r
+\r
+ return {\r
+ angle: angle,\r
+ distance: radialDistanceFromCenter\r
+ };\r
+ };\r
+ helpers.aliasPixel = function(pixelWidth) {\r
+ return (pixelWidth % 2 === 0) ? 0 : 0.5;\r
+ };\r
+ helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {\r
+ //Props to Rob Spencer at scaled innovation for his post on splining between points\r
+ //http://scaledinnovation.com/analytics/splines/aboutSplines.html\r
+\r
+ // This function must also respect "skipped" points\r
+\r
+ var previous = firstPoint.skip ? middlePoint : firstPoint,\r
+ current = middlePoint,\r
+ next = afterPoint.skip ? middlePoint : afterPoint;\r
+\r
+ var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));\r
+ var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));\r
+\r
+ var s01 = d01 / (d01 + d12);\r
+ var s12 = d12 / (d01 + d12);\r
+\r
+ // If all points are the same, s01 & s02 will be inf\r
+ s01 = isNaN(s01) ? 0 : s01;\r
+ s12 = isNaN(s12) ? 0 : s12;\r
+\r
+ var fa = t * s01; // scaling factor for triangle Ta\r
+ var fb = t * s12;\r
+\r
+ return {\r
+ previous: {\r
+ x: current.x - fa * (next.x - previous.x),\r
+ y: current.y - fa * (next.y - previous.y)\r
+ },\r
+ next: {\r
+ x: current.x + fb * (next.x - previous.x),\r
+ y: current.y + fb * (next.y - previous.y)\r
+ }\r
+ };\r
+ };\r
+ helpers.nextItem = function(collection, index, loop) {\r
+ if (loop) {\r
+ return index >= collection.length - 1 ? collection[0] : collection[index + 1];\r
+ }\r
+\r
+ return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];\r
+ };\r
+ helpers.previousItem = function(collection, index, loop) {\r
+ if (loop) {\r
+ return index <= 0 ? collection[collection.length - 1] : collection[index - 1];\r
+ }\r
+ return index <= 0 ? collection[0] : collection[index - 1];\r
+ };\r
+ // Implementation of the nice number algorithm used in determining where axis labels will go\r
+ helpers.niceNum = function(range, round) {\r
+ var exponent = Math.floor(helpers.log10(range));\r
+ var fraction = range / Math.pow(10, exponent);\r
+ var niceFraction;\r
+\r
+ if (round) {\r
+ if (fraction < 1.5) {\r
+ niceFraction = 1;\r
+ } else if (fraction < 3) {\r
+ niceFraction = 2;\r
+ } else if (fraction < 7) {\r
+ niceFraction = 5;\r
+ } else {\r
+ niceFraction = 10;\r
+ }\r
+ } else {\r
+ if (fraction <= 1.0) {\r
+ niceFraction = 1;\r
+ } else if (fraction <= 2) {\r
+ niceFraction = 2;\r
+ } else if (fraction <= 5) {\r
+ niceFraction = 5;\r
+ } else {\r
+ niceFraction = 10;\r
+ }\r
+ }\r
+\r
+ return niceFraction * Math.pow(10, exponent);\r
+ };\r
+ //Easing functions adapted from Robert Penner's easing equations\r
+ //http://www.robertpenner.com/easing/\r
+ var easingEffects = helpers.easingEffects = {\r
+ linear: function(t) {\r
+ return t;\r
+ },\r
+ easeInQuad: function(t) {\r
+ return t * t;\r
+ },\r
+ easeOutQuad: function(t) {\r
+ return -1 * t * (t - 2);\r
+ },\r
+ easeInOutQuad: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t;\r
+ }\r
+ return -1 / 2 * ((--t) * (t - 2) - 1);\r
+ },\r
+ easeInCubic: function(t) {\r
+ return t * t * t;\r
+ },\r
+ easeOutCubic: function(t) {\r
+ return 1 * ((t = t / 1 - 1) * t * t + 1);\r
+ },\r
+ easeInOutCubic: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t;\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * t + 2);\r
+ },\r
+ easeInQuart: function(t) {\r
+ return t * t * t * t;\r
+ },\r
+ easeOutQuart: function(t) {\r
+ return -1 * ((t = t / 1 - 1) * t * t * t - 1);\r
+ },\r
+ easeInOutQuart: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t * t;\r
+ }\r
+ return -1 / 2 * ((t -= 2) * t * t * t - 2);\r
+ },\r
+ easeInQuint: function(t) {\r
+ return 1 * (t /= 1) * t * t * t * t;\r
+ },\r
+ easeOutQuint: function(t) {\r
+ return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);\r
+ },\r
+ easeInOutQuint: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t * t * t;\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * t * t * t + 2);\r
+ },\r
+ easeInSine: function(t) {\r
+ return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;\r
+ },\r
+ easeOutSine: function(t) {\r
+ return 1 * Math.sin(t / 1 * (Math.PI / 2));\r
+ },\r
+ easeInOutSine: function(t) {\r
+ return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);\r
+ },\r
+ easeInExpo: function(t) {\r
+ return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));\r
+ },\r
+ easeOutExpo: function(t) {\r
+ return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);\r
+ },\r
+ easeInOutExpo: function(t) {\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if (t === 1) {\r
+ return 1;\r
+ }\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * Math.pow(2, 10 * (t - 1));\r
+ }\r
+ return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);\r
+ },\r
+ easeInCirc: function(t) {\r
+ if (t >= 1) {\r
+ return t;\r
+ }\r
+ return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);\r
+ },\r
+ easeOutCirc: function(t) {\r
+ return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);\r
+ },\r
+ easeInOutCirc: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return -1 / 2 * (Math.sqrt(1 - t * t) - 1);\r
+ }\r
+ return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);\r
+ },\r
+ easeInElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1) === 1) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * 0.3;\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\r
+ },\r
+ easeOutElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1) === 1) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * 0.3;\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;\r
+ },\r
+ easeInOutElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1 / 2) === 2) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * (0.3 * 1.5);\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ if (t < 1) {\r
+ return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\r
+ }\r
+ return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;\r
+ },\r
+ easeInBack: function(t) {\r
+ var s = 1.70158;\r
+ return 1 * (t /= 1) * t * ((s + 1) * t - s);\r
+ },\r
+ easeOutBack: function(t) {\r
+ var s = 1.70158;\r
+ return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);\r
+ },\r
+ easeInOutBack: function(t) {\r
+ var s = 1.70158;\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);\r
+ },\r
+ easeInBounce: function(t) {\r
+ return 1 - easingEffects.easeOutBounce(1 - t);\r
+ },\r
+ easeOutBounce: function(t) {\r
+ if ((t /= 1) < (1 / 2.75)) {\r
+ return 1 * (7.5625 * t * t);\r
+ } else if (t < (2 / 2.75)) {\r
+ return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);\r
+ } else if (t < (2.5 / 2.75)) {\r
+ return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);\r
+ } else {\r
+ return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);\r
+ }\r
+ },\r
+ easeInOutBounce: function(t) {\r
+ if (t < 1 / 2) {\r
+ return easingEffects.easeInBounce(t * 2) * 0.5;\r
+ }\r
+ return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;\r
+ }\r
+ };\r
+ //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\r
+ helpers.requestAnimFrame = (function() {\r
+ return window.requestAnimationFrame ||\r
+ window.webkitRequestAnimationFrame ||\r
+ window.mozRequestAnimationFrame ||\r
+ window.oRequestAnimationFrame ||\r
+ window.msRequestAnimationFrame ||\r
+ function(callback) {\r
+ return window.setTimeout(callback, 1000 / 60);\r
+ };\r
+ })();\r
+ helpers.cancelAnimFrame = (function() {\r
+ return window.cancelAnimationFrame ||\r
+ window.webkitCancelAnimationFrame ||\r
+ window.mozCancelAnimationFrame ||\r
+ window.oCancelAnimationFrame ||\r
+ window.msCancelAnimationFrame ||\r
+ function(callback) {\r
+ return window.clearTimeout(callback, 1000 / 60);\r
+ };\r
+ })();\r
+ //-- DOM methods\r
+ helpers.getRelativePosition = function(evt, chart) {\r
+ var mouseX, mouseY;\r
+ var e = evt.originalEvent || evt,\r
+ canvas = evt.currentTarget || evt.srcElement,\r
+ boundingRect = canvas.getBoundingClientRect();\r
+\r
+ var touches = e.touches;\r
+ if (touches && touches.length > 0) {\r
+ mouseX = touches[0].clientX;\r
+ mouseY = touches[0].clientY;\r
+\r
+ } else {\r
+ mouseX = e.clientX;\r
+ mouseY = e.clientY;\r
+ }\r
+\r
+ // Scale mouse coordinates into canvas coordinates\r
+ // by following the pattern laid out by 'jerryj' in the comments of\r
+ // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/\r
+ var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));\r
+ var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));\r
+ var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));\r
+ var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));\r
+ var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;\r
+ var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;\r
+\r
+ // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However\r
+ // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here\r
+ mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);\r
+ mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);\r
+\r
+ return {\r
+ x: mouseX,\r
+ y: mouseY\r
+ };\r
+\r
+ };\r
+ helpers.addEvent = function(node, eventType, method) {\r
+ if (node.addEventListener) {\r
+ node.addEventListener(eventType, method);\r
+ } else if (node.attachEvent) {\r
+ node.attachEvent("on" + eventType, method);\r
+ } else {\r
+ node["on" + eventType] = method;\r
+ }\r
+ };\r
+ helpers.removeEvent = function(node, eventType, handler) {\r
+ if (node.removeEventListener) {\r
+ node.removeEventListener(eventType, handler, false);\r
+ } else if (node.detachEvent) {\r
+ node.detachEvent("on" + eventType, handler);\r
+ } else {\r
+ node["on" + eventType] = helpers.noop;\r
+ }\r
+ };\r
+ helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {\r
+ // Create the events object if it's not already present\r
+ var events = chartInstance.events = chartInstance.events || {};\r
+\r
+ helpers.each(arrayOfEvents, function(eventName) {\r
+ events[eventName] = function() {\r
+ handler.apply(chartInstance, arguments);\r
+ };\r
+ helpers.addEvent(chartInstance.chart.canvas, eventName, events[eventName]);\r
+ });\r
+ };\r
+ helpers.unbindEvents = function(chartInstance, arrayOfEvents) {\r
+ var canvas = chartInstance.chart.canvas;\r
+ helpers.each(arrayOfEvents, function(handler, eventName) {\r
+ helpers.removeEvent(canvas, eventName, handler);\r
+ });\r
+ };\r
+\r
+ // Private helper function to convert max-width/max-height values that may be percentages into a number\r
+ function parseMaxStyle(styleValue, node, parentProperty) {\r
+ var valueInPixels;\r
+ if (typeof(styleValue) === 'string') {\r
+ valueInPixels = parseInt(styleValue, 10);\r
+\r
+ if (styleValue.indexOf('%') != -1) {\r
+ // percentage * size in dimension\r
+ valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];\r
+ }\r
+ } else {\r
+ valueInPixels = styleValue;\r
+ }\r
+\r
+ return valueInPixels;\r
+ }\r
+\r
+ /**\r
+ * Returns if the given value contains an effective constraint.\r
+ * @private\r
+ */\r
+ function isConstrainedValue(value) {\r
+ return value !== undefined && value !== null && value !== 'none';\r
+ }\r
+\r
+ // Private helper to get a constraint dimension\r
+ // @param domNode : the node to check the constraint on\r
+ // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)\r
+ // @param percentageProperty : property of parent to use when calculating width as a percentage\r
+ // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser\r
+ function getConstraintDimension(domNode, maxStyle, percentageProperty) {\r
+ var view = document.defaultView;\r
+ var parentNode = domNode.parentNode;\r
+ var constrainedNode = view.getComputedStyle(domNode)[maxStyle];\r
+ var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];\r
+ var hasCNode = isConstrainedValue(constrainedNode);\r
+ var hasCContainer = isConstrainedValue(constrainedContainer);\r
+ var infinity = Number.POSITIVE_INFINITY;\r
+\r
+ if (hasCNode || hasCContainer) {\r
+ return Math.min(\r
+ hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,\r
+ hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);\r
+ }\r
+\r
+ return 'none';\r
+ }\r
+ // returns Number or undefined if no constraint\r
+ helpers.getConstraintWidth = function(domNode) {\r
+ return getConstraintDimension(domNode, 'max-width', 'clientWidth');\r
+ };\r
+ // returns Number or undefined if no constraint\r
+ helpers.getConstraintHeight = function(domNode) {\r
+ return getConstraintDimension(domNode, 'max-height', 'clientHeight');\r
+ };\r
+ helpers.getMaximumWidth = function(domNode) {\r
+ var container = domNode.parentNode;\r
+ var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));\r
+ var w = container.clientWidth - padding;\r
+ var cw = helpers.getConstraintWidth(domNode);\r
+ return isNaN(cw)? w : Math.min(w, cw);\r
+ };\r
+ helpers.getMaximumHeight = function(domNode) {\r
+ var container = domNode.parentNode;\r
+ var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));\r
+ var h = container.clientHeight - padding;\r
+ var ch = helpers.getConstraintHeight(domNode);\r
+ return isNaN(ch)? h : Math.min(h, ch);\r
+ };\r
+ helpers.getStyle = function(el, property) {\r
+ return el.currentStyle ?\r
+ el.currentStyle[property] :\r
+ document.defaultView.getComputedStyle(el, null).getPropertyValue(property);\r
+ };\r
+ helpers.retinaScale = function(chart) {\r
+ var ctx = chart.ctx;\r
+ var canvas = chart.canvas;\r
+ var width = canvas.width;\r
+ var height = canvas.height;\r
+ var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;\r
+\r
+ if (pixelRatio !== 1) {\r
+ canvas.height = height * pixelRatio;\r
+ canvas.width = width * pixelRatio;\r
+ ctx.scale(pixelRatio, pixelRatio);\r
+\r
+ // Store the device pixel ratio so that we can go backwards in `destroy`.\r
+ // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same\r
+ // when destroy is called\r
+ chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;\r
+ }\r
+\r
+ canvas.style.width = width + 'px';\r
+ canvas.style.height = height + 'px';\r
+ };\r
+ //-- Canvas methods\r
+ helpers.clear = function(chart) {\r
+ chart.ctx.clearRect(0, 0, chart.width, chart.height);\r
+ };\r
+ helpers.fontString = function(pixelSize, fontStyle, fontFamily) {\r
+ return fontStyle + " " + pixelSize + "px " + fontFamily;\r
+ };\r
+ helpers.longestText = function(ctx, font, arrayOfStrings, cache) {\r
+ cache = cache || {};\r
+ var data = cache.data = cache.data || {};\r
+ var gc = cache.garbageCollect = cache.garbageCollect || [];\r
+\r
+ if (cache.font !== font) {\r
+ data = cache.data = {};\r
+ gc = cache.garbageCollect = [];\r
+ cache.font = font;\r
+ }\r
+\r
+ ctx.font = font;\r
+ var longest = 0;\r
+ helpers.each(arrayOfStrings, function(string) {\r
+ // Undefined strings should not be measured\r
+ if (string !== undefined && string !== null) {\r
+ var textWidth = data[string];\r
+ if (!textWidth) {\r
+ textWidth = data[string] = ctx.measureText(string).width;\r
+ gc.push(string);\r
+ }\r
+\r
+ if (textWidth > longest) {\r
+ longest = textWidth;\r
+ }\r
+ }\r
+ });\r
+\r
+ var gcLen = gc.length / 2;\r
+ if (gcLen > arrayOfStrings.length) {\r
+ for (var i = 0; i < gcLen; i++) {\r
+ delete data[gc[i]];\r
+ }\r
+ gc.splice(0, gcLen);\r
+ }\r
+\r
+ return longest;\r
+ };\r
+ helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) {\r
+ ctx.beginPath();\r
+ ctx.moveTo(x + radius, y);\r
+ ctx.lineTo(x + width - radius, y);\r
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\r
+ ctx.lineTo(x + width, y + height - radius);\r
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\r
+ ctx.lineTo(x + radius, y + height);\r
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\r
+ ctx.lineTo(x, y + radius);\r
+ ctx.quadraticCurveTo(x, y, x + radius, y);\r
+ ctx.closePath();\r
+ };\r
+ helpers.color = function(c) {\r
+ if (!color) {\r
+ console.log('Color.js not found!');\r
+ return c;\r
+ }\r
+\r
+ /* global CanvasGradient */\r
+ if (c instanceof CanvasGradient) {\r
+ return color(Chart.defaults.global.defaultColor);\r
+ }\r
+\r
+ return color(c);\r
+ };\r
+ helpers.addResizeListener = function(node, callback) {\r
+ // Hide an iframe before the node\r
+ var hiddenIframe = document.createElement('iframe');\r
+ var hiddenIframeClass = 'chartjs-hidden-iframe';\r
+\r
+ if (hiddenIframe.classlist) {\r
+ // can use classlist\r
+ hiddenIframe.classlist.add(hiddenIframeClass);\r
+ } else {\r
+ hiddenIframe.setAttribute('class', hiddenIframeClass);\r
+ }\r
+\r
+ // Set the style\r
+ var style = hiddenIframe.style;\r
+ style.width = '100%';\r
+ style.display = 'block';\r
+ style.border = 0;\r
+ style.height = 0;\r
+ style.margin = 0;\r
+ style.position = 'absolute';\r
+ style.left = 0;\r
+ style.right = 0;\r
+ style.top = 0;\r
+ style.bottom = 0;\r
+\r
+ // Insert the iframe so that contentWindow is available\r
+ node.insertBefore(hiddenIframe, node.firstChild);\r
+\r
+ (hiddenIframe.contentWindow || hiddenIframe).onresize = function() {\r
+ if (callback) {\r
+ callback();\r
+ }\r
+ };\r
+ };\r
+ helpers.removeResizeListener = function(node) {\r
+ var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');\r
+\r
+ // Remove the resize detect iframe\r
+ if (hiddenIframe) {\r
+ hiddenIframe.parentNode.removeChild(hiddenIframe);\r
+ }\r
+ };\r
+ helpers.isArray = function(obj) {\r
+ if (!Array.isArray) {\r
+ return Object.prototype.toString.call(obj) === '[object Array]';\r
+ }\r
+ return Array.isArray(obj);\r
+ };\r
+ //! @see http://stackoverflow.com/a/14853974\r
+ helpers.arrayEquals = function(a0, a1) {\r
+ var i, ilen, v0, v1;\r
+\r
+ if (!a0 || !a1 || a0.length != a1.length) {\r
+ return false;\r
+ }\r
+\r
+ for (i = 0, ilen=a0.length; i < ilen; ++i) {\r
+ v0 = a0[i];\r
+ v1 = a1[i];\r
+\r
+ if (v0 instanceof Array && v1 instanceof Array) {\r
+ if (!helpers.arrayEquals(v0, v1)) {\r
+ return false;\r
+ }\r
+ } else if (v0 != v1) {\r
+ // NOTE: two different object instances will never be equal: {x:20} != {x:20}\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ };\r
+ helpers.pushAllIfDefined = function(element, array) {\r
+ if (typeof element === "undefined") {\r
+ return;\r
+ }\r
+\r
+ if (helpers.isArray(element)) {\r
+ array.push.apply(array, element);\r
+ } else {\r
+ array.push(element);\r
+ }\r
+ };\r
+ helpers.callCallback = function(fn, args, _tArg) {\r
+ if (fn && typeof fn.call === 'function') {\r
+ fn.apply(_tArg, args);\r
+ }\r
+ };\r
+ helpers.getHoverColor = function(color) {\r
+ /* global CanvasPattern */\r
+ return (color instanceof CanvasPattern) ?\r
+ color :\r
+ helpers.color(color).saturate(0.5).darken(0.1).rgbString();\r
+ };\r
+};\r
-};
+},{"chartjs-color":2}],26:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function() {\r
+\r
+ //Occupy the global variable of Chart, and create a simple base class\r
+ var Chart = function(context, config) {\r
+ this.config = config;\r
+\r
+ // Support a jQuery'd canvas element\r
+ if (context.length && context[0].getContext) {\r
+ context = context[0];\r
+ }\r
+\r
+ // Support a canvas domnode\r
+ if (context.getContext) {\r
+ context = context.getContext("2d");\r
+ }\r
+\r
+ this.ctx = context;\r
+ this.canvas = context.canvas;\r
+\r
+ // Figure out what the size of the chart will be.\r
+ // If the canvas has a specified width and height, we use those else\r
+ // we look to see if the canvas node has a CSS width and height.\r
+ // If there is still no height, fill the parent container\r
+ this.width = context.canvas.width || parseInt(Chart.helpers.getStyle(context.canvas, 'width')) || Chart.helpers.getMaximumWidth(context.canvas);\r
+ this.height = context.canvas.height || parseInt(Chart.helpers.getStyle(context.canvas, 'height')) || Chart.helpers.getMaximumHeight(context.canvas);\r
+\r
+ this.aspectRatio = this.width / this.height;\r
+\r
+ if (isNaN(this.aspectRatio) || isFinite(this.aspectRatio) === false) {\r
+ // If the canvas has no size, try and figure out what the aspect ratio will be.\r
+ // Some charts prefer square canvases (pie, radar, etc). If that is specified, use that\r
+ // else use the canvas default ratio of 2\r
+ this.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;\r
+ }\r
+\r
+ // Store the original style of the element so we can set it back\r
+ this.originalCanvasStyleWidth = context.canvas.style.width;\r
+ this.originalCanvasStyleHeight = context.canvas.style.height;\r
+\r
+ // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.\r
+ Chart.helpers.retinaScale(this);\r
+\r
+ if (config) {\r
+ this.controller = new Chart.Controller(this);\r
+ }\r
+\r
+ // Always bind this so that if the responsive state changes we still work\r
+ var _this = this;\r
+ Chart.helpers.addResizeListener(context.canvas.parentNode, function() {\r
+ if (_this.controller && _this.controller.config.options.responsive) {\r
+ _this.controller.resize();\r
+ }\r
+ });\r
+\r
+ return this.controller ? this.controller : this;\r
+\r
+ };\r
+\r
+ //Globally expose the defaults to allow for user updating/changing\r
+ Chart.defaults = {\r
+ global: {\r
+ responsive: true,\r
+ responsiveAnimationDuration: 0,\r
+ maintainAspectRatio: true,\r
+ events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],\r
+ hover: {\r
+ onHover: null,\r
+ mode: 'single',\r
+ animationDuration: 400\r
+ },\r
+ onClick: null,\r
+ defaultColor: 'rgba(0,0,0,0.1)',\r
+ defaultFontColor: '#666',\r
+ defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",\r
+ defaultFontSize: 12,\r
+ defaultFontStyle: 'normal',\r
+ showLines: true,\r
+\r
+ // Element defaults defined in element extensions\r
+ elements: {},\r
+\r
+ // Legend callback string\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+ for (var i = 0; i < chart.data.datasets.length; i++) {\r
+ text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');\r
+ if (chart.data.datasets[i].label) {\r
+ text.push(chart.data.datasets[i].label);\r
+ }\r
+ text.push('</li>');\r
+ }\r
+ text.push('</ul>');\r
+\r
+ return text.join("");\r
+ }\r
+ }\r
+ };\r
+\r
+ return Chart;\r
+\r
+};\r
},{}],27:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- // The layout service is very self explanatory. It's responsible for the layout within a chart.
- // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
- // It is this service's responsibility of carrying out that layout.
- Chart.layoutService = {
- defaults: {},
-
- // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins.
- addBox: function(chartInstance, box) {
- if (!chartInstance.boxes) {
- chartInstance.boxes = [];
- }
- chartInstance.boxes.push(box);
- },
-
- removeBox: function(chartInstance, box) {
- if (!chartInstance.boxes) {
- return;
- }
- chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1);
- },
-
- // The most important function
- update: function(chartInstance, width, height) {
-
- if (!chartInstance) {
- return;
- }
-
- var xPadding = 0;
- var yPadding = 0;
-
- var leftBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "left";
- });
- var rightBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "right";
- });
- var topBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "top";
- });
- var bottomBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "bottom";
- });
-
- // Boxes that overlay the chartarea such as the radialLinear scale
- var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "chartArea";
- });
-
- // Ensure that full width boxes are at the very top / bottom
- topBoxes.sort(function(a, b) {
- return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0);
- });
- bottomBoxes.sort(function(a, b) {
- return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0);
- });
-
- // Essentially we now have any number of boxes on each of the 4 sides.
- // Our canvas looks like the following.
- // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
- // B1 is the bottom axis
- // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
- // These locations are single-box locations only, when trying to register a chartArea location that is already taken,
- // an error will be thrown.
- //
- // |----------------------------------------------------|
- // | T1 (Full Width) |
- // |----------------------------------------------------|
- // | | | T2 | |
- // | |----|-------------------------------------|----|
- // | | | C1 | | C2 | |
- // | | |----| |----| |
- // | | | | |
- // | L1 | L2 | ChartArea (C0) | R1 |
- // | | | | |
- // | | |----| |----| |
- // | | | C3 | | C4 | |
- // | |----|-------------------------------------|----|
- // | | | B1 | |
- // |----------------------------------------------------|
- // | B2 (Full Width) |
- // |----------------------------------------------------|
- //
- // What we do to find the best sizing, we do the following
- // 1. Determine the minimum size of the chart area.
- // 2. Split the remaining width equally between each vertical axis
- // 3. Split the remaining height equally between each horizontal axis
- // 4. Give each layout the maximum size it can be. The layout will return it's minimum size
- // 5. Adjust the sizes of each axis based on it's minimum reported size.
- // 6. Refit each axis
- // 7. Position each axis in the final location
- // 8. Tell the chart the final location of the chart area
- // 9. Tell any axes that overlay the chart area the positions of the chart area
-
- // Step 1
- var chartWidth = width - (2 * xPadding);
- var chartHeight = height - (2 * yPadding);
- var chartAreaWidth = chartWidth / 2; // min 50%
- var chartAreaHeight = chartHeight / 2; // min 50%
-
- // Step 2
- var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
-
- // Step 3
- var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
-
- // Step 4
- var maxChartAreaWidth = chartWidth;
- var maxChartAreaHeight = chartHeight;
- var minBoxSizes = [];
-
- helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
-
- function getMinimumBoxSize(box) {
- var minSize;
- var isHorizontal = box.isHorizontal();
-
- if (isHorizontal) {
- minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
- maxChartAreaHeight -= minSize.height;
- } else {
- minSize = box.update(verticalBoxWidth, chartAreaHeight);
- maxChartAreaWidth -= minSize.width;
- }
-
- minBoxSizes.push({
- horizontal: isHorizontal,
- minSize: minSize,
- box: box
- });
- }
-
- // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
- // be if the axes are drawn at their minimum sizes.
-
- // Steps 5 & 6
- var totalLeftBoxesWidth = xPadding;
- var totalRightBoxesWidth = xPadding;
- var totalTopBoxesHeight = yPadding;
- var totalBottomBoxesHeight = yPadding;
-
- // Update, and calculate the left and right margins for the horizontal boxes
- helpers.each(leftBoxes.concat(rightBoxes), fitBox);
-
- helpers.each(leftBoxes, function(box) {
- totalLeftBoxesWidth += box.width;
- });
-
- helpers.each(rightBoxes, function(box) {
- totalRightBoxesWidth += box.width;
- });
-
- // Set the Left and Right margins for the horizontal boxes
- helpers.each(topBoxes.concat(bottomBoxes), fitBox);
-
- // Function to fit a box
- function fitBox(box) {
- var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
- return minBoxSize.box === box;
- });
-
- if (minBoxSize) {
- if (box.isHorizontal()) {
- var scaleMargin = {
- left: totalLeftBoxesWidth,
- right: totalRightBoxesWidth,
- top: 0,
- bottom: 0
- };
-
- // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
- // on the margin. Sometimes they need to increase in size slightly
- box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
- } else {
- box.update(minBoxSize.minSize.width, maxChartAreaHeight);
- }
- }
- }
-
- // Figure out how much margin is on the top and bottom of the vertical boxes
- helpers.each(topBoxes, function(box) {
- totalTopBoxesHeight += box.height;
- });
-
- helpers.each(bottomBoxes, function(box) {
- totalBottomBoxesHeight += box.height;
- });
-
- // Let the left layout know the final margin
- helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
-
- function finalFitVerticalBox(box) {
- var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
- return minBoxSize.box === box;
- });
-
- var scaleMargin = {
- left: 0,
- right: 0,
- top: totalTopBoxesHeight,
- bottom: totalBottomBoxesHeight
- };
-
- if (minBoxSize) {
- box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
- }
- }
-
- // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
- totalLeftBoxesWidth = xPadding;
- totalRightBoxesWidth = xPadding;
- totalTopBoxesHeight = yPadding;
- totalBottomBoxesHeight = yPadding;
-
- helpers.each(leftBoxes, function(box) {
- totalLeftBoxesWidth += box.width;
- });
-
- helpers.each(rightBoxes, function(box) {
- totalRightBoxesWidth += box.width;
- });
-
- helpers.each(topBoxes, function(box) {
- totalTopBoxesHeight += box.height;
- });
- helpers.each(bottomBoxes, function(box) {
- totalBottomBoxesHeight += box.height;
- });
-
- // Figure out if our chart area changed. This would occur if the dataset layout label rotation
- // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
- // without calling `fit` again
- var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
- var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
-
- if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
- helpers.each(leftBoxes, function(box) {
- box.height = newMaxChartAreaHeight;
- });
-
- helpers.each(rightBoxes, function(box) {
- box.height = newMaxChartAreaHeight;
- });
-
- helpers.each(topBoxes, function(box) {
- if (!box.options.fullWidth) {
- box.width = newMaxChartAreaWidth;
- }
- });
-
- helpers.each(bottomBoxes, function(box) {
- if (!box.options.fullWidth) {
- box.width = newMaxChartAreaWidth;
- }
- });
-
- maxChartAreaHeight = newMaxChartAreaHeight;
- maxChartAreaWidth = newMaxChartAreaWidth;
- }
-
- // Step 7 - Position the boxes
- var left = xPadding;
- var top = yPadding;
- var right = 0;
- var bottom = 0;
-
- helpers.each(leftBoxes.concat(topBoxes), placeBox);
-
- // Account for chart width and height
- left += maxChartAreaWidth;
- top += maxChartAreaHeight;
-
- helpers.each(rightBoxes, placeBox);
- helpers.each(bottomBoxes, placeBox);
-
- function placeBox(box) {
- if (box.isHorizontal()) {
- box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth;
- box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth;
- box.top = top;
- box.bottom = top + box.height;
-
- // Move to next point
- top = box.bottom;
-
- } else {
-
- box.left = left;
- box.right = left + box.width;
- box.top = totalTopBoxesHeight;
- box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
-
- // Move to next point
- left = box.right;
- }
- }
-
- // Step 8
- chartInstance.chartArea = {
- left: totalLeftBoxesWidth,
- top: totalTopBoxesHeight,
- right: totalLeftBoxesWidth + maxChartAreaWidth,
- bottom: totalTopBoxesHeight + maxChartAreaHeight
- };
-
- // Step 9
- helpers.each(chartAreaBoxes, function(box) {
- box.left = chartInstance.chartArea.left;
- box.top = chartInstance.chartArea.top;
- box.right = chartInstance.chartArea.right;
- box.bottom = chartInstance.chartArea.bottom;
-
- box.update(maxChartAreaWidth, maxChartAreaHeight);
- });
- }
- };
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ // The layout service is very self explanatory. It's responsible for the layout within a chart.\r
+ // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need\r
+ // It is this service's responsibility of carrying out that layout.\r
+ Chart.layoutService = {\r
+ defaults: {},\r
+\r
+ // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins.\r
+ addBox: function(chartInstance, box) {\r
+ if (!chartInstance.boxes) {\r
+ chartInstance.boxes = [];\r
+ }\r
+ chartInstance.boxes.push(box);\r
+ },\r
+\r
+ removeBox: function(chartInstance, box) {\r
+ if (!chartInstance.boxes) {\r
+ return;\r
+ }\r
+ chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1);\r
+ },\r
+\r
+ // The most important function\r
+ update: function(chartInstance, width, height) {\r
+\r
+ if (!chartInstance) {\r
+ return;\r
+ }\r
+\r
+ var xPadding = 0;\r
+ var yPadding = 0;\r
+\r
+ var leftBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "left";\r
+ });\r
+ var rightBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "right";\r
+ });\r
+ var topBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "top";\r
+ });\r
+ var bottomBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "bottom";\r
+ });\r
+\r
+ // Boxes that overlay the chartarea such as the radialLinear scale\r
+ var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "chartArea";\r
+ });\r
+\r
+ // Ensure that full width boxes are at the very top / bottom\r
+ topBoxes.sort(function(a, b) {\r
+ return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0);\r
+ });\r
+ bottomBoxes.sort(function(a, b) {\r
+ return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0);\r
+ });\r
+\r
+ // Essentially we now have any number of boxes on each of the 4 sides.\r
+ // Our canvas looks like the following.\r
+ // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and\r
+ // B1 is the bottom axis\r
+ // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays\r
+ // These locations are single-box locations only, when trying to register a chartArea location that is already taken,\r
+ // an error will be thrown.\r
+ //\r
+ // |----------------------------------------------------|\r
+ // | T1 (Full Width) |\r
+ // |----------------------------------------------------|\r
+ // | | | T2 | |\r
+ // | |----|-------------------------------------|----|\r
+ // | | | C1 | | C2 | |\r
+ // | | |----| |----| |\r
+ // | | | | |\r
+ // | L1 | L2 | ChartArea (C0) | R1 |\r
+ // | | | | |\r
+ // | | |----| |----| |\r
+ // | | | C3 | | C4 | |\r
+ // | |----|-------------------------------------|----|\r
+ // | | | B1 | |\r
+ // |----------------------------------------------------|\r
+ // | B2 (Full Width) |\r
+ // |----------------------------------------------------|\r
+ //\r
+ // What we do to find the best sizing, we do the following\r
+ // 1. Determine the minimum size of the chart area.\r
+ // 2. Split the remaining width equally between each vertical axis\r
+ // 3. Split the remaining height equally between each horizontal axis\r
+ // 4. Give each layout the maximum size it can be. The layout will return it's minimum size\r
+ // 5. Adjust the sizes of each axis based on it's minimum reported size.\r
+ // 6. Refit each axis\r
+ // 7. Position each axis in the final location\r
+ // 8. Tell the chart the final location of the chart area\r
+ // 9. Tell any axes that overlay the chart area the positions of the chart area\r
+\r
+ // Step 1\r
+ var chartWidth = width - (2 * xPadding);\r
+ var chartHeight = height - (2 * yPadding);\r
+ var chartAreaWidth = chartWidth / 2; // min 50%\r
+ var chartAreaHeight = chartHeight / 2; // min 50%\r
+\r
+ // Step 2\r
+ var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);\r
+\r
+ // Step 3\r
+ var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);\r
+\r
+ // Step 4\r
+ var maxChartAreaWidth = chartWidth;\r
+ var maxChartAreaHeight = chartHeight;\r
+ var minBoxSizes = [];\r
+\r
+ helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);\r
+\r
+ function getMinimumBoxSize(box) {\r
+ var minSize;\r
+ var isHorizontal = box.isHorizontal();\r
+\r
+ if (isHorizontal) {\r
+ minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);\r
+ maxChartAreaHeight -= minSize.height;\r
+ } else {\r
+ minSize = box.update(verticalBoxWidth, chartAreaHeight);\r
+ maxChartAreaWidth -= minSize.width;\r
+ }\r
+\r
+ minBoxSizes.push({\r
+ horizontal: isHorizontal,\r
+ minSize: minSize,\r
+ box: box\r
+ });\r
+ }\r
+\r
+ // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could\r
+ // be if the axes are drawn at their minimum sizes.\r
+\r
+ // Steps 5 & 6\r
+ var totalLeftBoxesWidth = xPadding;\r
+ var totalRightBoxesWidth = xPadding;\r
+ var totalTopBoxesHeight = yPadding;\r
+ var totalBottomBoxesHeight = yPadding;\r
+\r
+ // Update, and calculate the left and right margins for the horizontal boxes\r
+ helpers.each(leftBoxes.concat(rightBoxes), fitBox);\r
+\r
+ helpers.each(leftBoxes, function(box) {\r
+ totalLeftBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ totalRightBoxesWidth += box.width;\r
+ });\r
+\r
+ // Set the Left and Right margins for the horizontal boxes\r
+ helpers.each(topBoxes.concat(bottomBoxes), fitBox);\r
+\r
+ // Function to fit a box\r
+ function fitBox(box) {\r
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {\r
+ return minBoxSize.box === box;\r
+ });\r
+\r
+ if (minBoxSize) {\r
+ if (box.isHorizontal()) {\r
+ var scaleMargin = {\r
+ left: totalLeftBoxesWidth,\r
+ right: totalRightBoxesWidth,\r
+ top: 0,\r
+ bottom: 0\r
+ };\r
+\r
+ // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends\r
+ // on the margin. Sometimes they need to increase in size slightly\r
+ box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);\r
+ } else {\r
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Figure out how much margin is on the top and bottom of the vertical boxes\r
+ helpers.each(topBoxes, function(box) {\r
+ totalTopBoxesHeight += box.height;\r
+ });\r
+\r
+ helpers.each(bottomBoxes, function(box) {\r
+ totalBottomBoxesHeight += box.height;\r
+ });\r
+\r
+ // Let the left layout know the final margin\r
+ helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);\r
+\r
+ function finalFitVerticalBox(box) {\r
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {\r
+ return minBoxSize.box === box;\r
+ });\r
+\r
+ var scaleMargin = {\r
+ left: 0,\r
+ right: 0,\r
+ top: totalTopBoxesHeight,\r
+ bottom: totalBottomBoxesHeight\r
+ };\r
+\r
+ if (minBoxSize) {\r
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);\r
+ }\r
+ }\r
+\r
+ // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)\r
+ totalLeftBoxesWidth = xPadding;\r
+ totalRightBoxesWidth = xPadding;\r
+ totalTopBoxesHeight = yPadding;\r
+ totalBottomBoxesHeight = yPadding;\r
+\r
+ helpers.each(leftBoxes, function(box) {\r
+ totalLeftBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ totalRightBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(topBoxes, function(box) {\r
+ totalTopBoxesHeight += box.height;\r
+ });\r
+ helpers.each(bottomBoxes, function(box) {\r
+ totalBottomBoxesHeight += box.height;\r
+ });\r
+\r
+ // Figure out if our chart area changed. This would occur if the dataset layout label rotation\r
+ // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do\r
+ // without calling `fit` again\r
+ var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;\r
+ var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;\r
+\r
+ if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {\r
+ helpers.each(leftBoxes, function(box) {\r
+ box.height = newMaxChartAreaHeight;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ box.height = newMaxChartAreaHeight;\r
+ });\r
+\r
+ helpers.each(topBoxes, function(box) {\r
+ if (!box.options.fullWidth) {\r
+ box.width = newMaxChartAreaWidth;\r
+ }\r
+ });\r
+\r
+ helpers.each(bottomBoxes, function(box) {\r
+ if (!box.options.fullWidth) {\r
+ box.width = newMaxChartAreaWidth;\r
+ }\r
+ });\r
+\r
+ maxChartAreaHeight = newMaxChartAreaHeight;\r
+ maxChartAreaWidth = newMaxChartAreaWidth;\r
+ }\r
+\r
+ // Step 7 - Position the boxes\r
+ var left = xPadding;\r
+ var top = yPadding;\r
+ var right = 0;\r
+ var bottom = 0;\r
+\r
+ helpers.each(leftBoxes.concat(topBoxes), placeBox);\r
+\r
+ // Account for chart width and height\r
+ left += maxChartAreaWidth;\r
+ top += maxChartAreaHeight;\r
+\r
+ helpers.each(rightBoxes, placeBox);\r
+ helpers.each(bottomBoxes, placeBox);\r
+\r
+ function placeBox(box) {\r
+ if (box.isHorizontal()) {\r
+ box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth;\r
+ box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth;\r
+ box.top = top;\r
+ box.bottom = top + box.height;\r
+\r
+ // Move to next point\r
+ top = box.bottom;\r
+\r
+ } else {\r
+\r
+ box.left = left;\r
+ box.right = left + box.width;\r
+ box.top = totalTopBoxesHeight;\r
+ box.bottom = totalTopBoxesHeight + maxChartAreaHeight;\r
+\r
+ // Move to next point\r
+ left = box.right;\r
+ }\r
+ }\r
+\r
+ // Step 8\r
+ chartInstance.chartArea = {\r
+ left: totalLeftBoxesWidth,\r
+ top: totalTopBoxesHeight,\r
+ right: totalLeftBoxesWidth + maxChartAreaWidth,\r
+ bottom: totalTopBoxesHeight + maxChartAreaHeight\r
+ };\r
+\r
+ // Step 9\r
+ helpers.each(chartAreaBoxes, function(box) {\r
+ box.left = chartInstance.chartArea.left;\r
+ box.top = chartInstance.chartArea.top;\r
+ box.right = chartInstance.chartArea.right;\r
+ box.bottom = chartInstance.chartArea.bottom;\r
+\r
+ box.update(maxChartAreaWidth, maxChartAreaHeight);\r
+ });\r
+ }\r
+ };\r
+};\r
},{}],28:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var noop = helpers.noop;
-
- Chart.defaults.global.legend = {
-
- display: true,
- position: 'top',
- fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
- reverse: false,
-
- // a callback that will handle
- onClick: function(e, legendItem) {
- var index = legendItem.datasetIndex;
- var ci = this.chart;
- var meta = ci.getDatasetMeta(index);
-
- // See controller.isDatasetVisible comment
- meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
-
- // We hid a dataset ... rerender the chart
- ci.update();
- },
-
- labels: {
- boxWidth: 40,
- padding: 10,
- // Generates labels shown in the legend
- // Valid properties to return:
- // text : text to display
- // fillStyle : fill of coloured box
- // strokeStyle: stroke of coloured box
- // hidden : if this legend item refers to a hidden item
- // lineCap : cap style for line
- // lineDash
- // lineDashOffset :
- // lineJoin :
- // lineWidth :
- generateLabels: function(chart) {
- var data = chart.data;
- return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
- return {
- text: dataset.label,
- fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
- hidden: !chart.isDatasetVisible(i),
- lineCap: dataset.borderCapStyle,
- lineDash: dataset.borderDash,
- lineDashOffset: dataset.borderDashOffset,
- lineJoin: dataset.borderJoinStyle,
- lineWidth: dataset.borderWidth,
- strokeStyle: dataset.borderColor,
-
- // Below is extra data used for toggling the datasets
- datasetIndex: i
- };
- }, this) : [];
- }
- }
- };
-
- Chart.Legend = Chart.Element.extend({
-
- initialize: function(config) {
- helpers.extend(this, config);
-
- // Contains hit boxes for each dataset (in dataset order)
- this.legendHitBoxes = [];
-
- // Are we in doughnut mode which has a different data type
- this.doughnutMode = false;
- },
-
- // These methods are ordered by lifecyle. Utilities then follow.
- // Any function defined here is inherited by all legend types.
- // Any function can be extended by the legend type
-
- beforeUpdate: noop,
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = margins;
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
- // Labels
- me.beforeBuildLabels();
- me.buildLabels();
- me.afterBuildLabels();
-
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
- },
- afterUpdate: noop,
-
- //
-
- beforeSetDimensions: noop,
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
-
- // Reset minSize
- me.minSize = {
- width: 0,
- height: 0
- };
- },
- afterSetDimensions: noop,
-
- //
-
- beforeBuildLabels: noop,
- buildLabels: function() {
- var me = this;
- me.legendItems = me.options.labels.generateLabels.call(me, me.chart);
- if(me.options.reverse){
- me.legendItems.reverse();
- }
- },
- afterBuildLabels: noop,
-
- //
-
- beforeFit: noop,
- fit: function() {
- var me = this;
- var opts = me.options;
- var labelOpts = opts.labels;
- var display = opts.display;
-
- var ctx = me.ctx;
-
- var globalDefault = Chart.defaults.global,
- itemOrDefault = helpers.getValueOrDefault,
- fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
- fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
- fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
- labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
-
- // Reset hit boxes
- var hitboxes = me.legendHitBoxes = [];
-
- var minSize = me.minSize;
- var isHorizontal = me.isHorizontal();
-
- if (isHorizontal) {
- minSize.width = me.maxWidth; // fill all the width
- minSize.height = display ? 10 : 0;
- } else {
- minSize.width = display ? 10 : 0;
- minSize.height = me.maxHeight; // fill all the height
- }
-
- // Increase sizes here
- if (display) {
- if (isHorizontal) {
- // Labels
-
- // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
- var lineWidths = me.lineWidths = [0];
- var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0;
-
- ctx.textAlign = "left";
- ctx.textBaseline = 'top';
- ctx.font = labelFont;
-
- helpers.each(me.legendItems, function(legendItem, i) {
- var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
- if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) {
- totalHeight += fontSize + (labelOpts.padding);
- lineWidths[lineWidths.length] = me.left;
- }
-
- // Store the hitbox width and height here. Final position will be updated in `draw`
- hitboxes[i] = {
- left: 0,
- top: 0,
- width: width,
- height: fontSize
- };
-
- lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
- }, me);
-
- minSize.height += totalHeight;
-
- } else {
- // TODO vertical
- }
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
- },
- afterFit: noop,
-
- // Shared Methods
- isHorizontal: function() {
- return this.options.position === "top" || this.options.position === "bottom";
- },
-
- // Actualy draw the legend on the canvas
- draw: function() {
- var me = this;
- var opts = me.options;
- var labelOpts = opts.labels;
- var globalDefault = Chart.defaults.global,
- lineDefault = globalDefault.elements.line,
- legendWidth = me.width,
- lineWidths = me.lineWidths;
-
- if (opts.display) {
- var ctx = me.ctx,
- cursor = {
- x: me.left + ((legendWidth - lineWidths[0]) / 2),
- y: me.top + labelOpts.padding,
- line: 0
- },
- itemOrDefault = helpers.getValueOrDefault,
- fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),
- fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
- fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
- fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
- labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
-
- // Horizontal
- if (me.isHorizontal()) {
- // Labels
- ctx.textAlign = "left";
- ctx.textBaseline = 'top';
- ctx.lineWidth = 0.5;
- ctx.strokeStyle = fontColor; // for strikethrough effect
- ctx.fillStyle = fontColor; // render in correct colour
- ctx.font = labelFont;
-
- var boxWidth = labelOpts.boxWidth,
- hitboxes = me.legendHitBoxes;
-
- helpers.each(me.legendItems, function(legendItem, i) {
- var textWidth = ctx.measureText(legendItem.text).width,
- width = boxWidth + (fontSize / 2) + textWidth,
- x = cursor.x,
- y = cursor.y;
-
- if (x + width >= legendWidth) {
- y = cursor.y += fontSize + (labelOpts.padding);
- cursor.line++;
- x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
- }
-
- // Set the ctx for the box
- ctx.save();
-
- ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
- ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
- ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
- ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
- ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
- ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
-
- if (ctx.setLineDash) {
- // IE 9 and 10 do not support line dash
- ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));
- }
-
- // Draw the box
- ctx.strokeRect(x, y, boxWidth, fontSize);
- ctx.fillRect(x, y, boxWidth, fontSize);
-
- ctx.restore();
-
- hitboxes[i].left = x;
- hitboxes[i].top = y;
-
- // Fill the actual label
- ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);
-
- if (legendItem.hidden) {
- // Strikethrough the text if hidden
- ctx.beginPath();
- ctx.lineWidth = 2;
- ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));
- ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));
- ctx.stroke();
- }
-
- cursor.x += width + (labelOpts.padding);
- }, me);
- } else {
-
- }
- }
- },
-
- // Handle an event
- handleEvent: function(e) {
- var me = this;
- var position = helpers.getRelativePosition(e, me.chart.chart),
- x = position.x,
- y = position.y,
- opts = me.options;
-
- if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
- // See if we are touching one of the dataset boxes
- var lh = me.legendHitBoxes;
- for (var i = 0; i < lh.length; ++i) {
- var hitBox = lh[i];
-
- if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
- // Touching an element
- if (opts.onClick) {
- opts.onClick.call(me, e, me.legendItems[i]);
- }
- break;
- }
- }
- }
- }
- });
-
- // Register the legend plugin
- Chart.pluginService.register({
- beforeInit: function(chartInstance) {
- var opts = chartInstance.options;
- var legendOpts = opts.legend;
-
- if (legendOpts) {
- chartInstance.legend = new Chart.Legend({
- ctx: chartInstance.chart.ctx,
- options: legendOpts,
- chart: chartInstance
- });
-
- Chart.layoutService.addBox(chartInstance, chartInstance.legend);
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var noop = helpers.noop;\r
+\r
+ Chart.defaults.global.legend = {\r
+\r
+ display: true,\r
+ position: 'top',\r
+ fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)\r
+ reverse: false,\r
+\r
+ // a callback that will handle\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.datasetIndex;\r
+ var ci = this.chart;\r
+ var meta = ci.getDatasetMeta(index);\r
+\r
+ // See controller.isDatasetVisible comment\r
+ meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;\r
+\r
+ // We hid a dataset ... rerender the chart\r
+ ci.update();\r
+ },\r
+\r
+ labels: {\r
+ boxWidth: 40,\r
+ padding: 10,\r
+ // Generates labels shown in the legend\r
+ // Valid properties to return:\r
+ // text : text to display\r
+ // fillStyle : fill of coloured box\r
+ // strokeStyle: stroke of coloured box\r
+ // hidden : if this legend item refers to a hidden item\r
+ // lineCap : cap style for line\r
+ // lineDash\r
+ // lineDashOffset :\r
+ // lineJoin :\r
+ // lineWidth :\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {\r
+ return {\r
+ text: dataset.label,\r
+ fillStyle: dataset.backgroundColor,\r
+ hidden: !chart.isDatasetVisible(i),\r
+ lineCap: dataset.borderCapStyle,\r
+ lineDash: dataset.borderDash,\r
+ lineDashOffset: dataset.borderDashOffset,\r
+ lineJoin: dataset.borderJoinStyle,\r
+ lineWidth: dataset.borderWidth,\r
+ strokeStyle: dataset.borderColor,\r
+\r
+ // Below is extra data used for toggling the datasets\r
+ datasetIndex: i\r
+ };\r
+ }, this) : [];\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.Legend = Chart.Element.extend({\r
+\r
+ initialize: function(config) {\r
+ helpers.extend(this, config);\r
+\r
+ // Contains hit boxes for each dataset (in dataset order)\r
+ this.legendHitBoxes = [];\r
+\r
+ // Are we in doughnut mode which has a different data type\r
+ this.doughnutMode = false;\r
+ },\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+ // Any function defined here is inherited by all legend types.\r
+ // Any function can be extended by the legend type\r
+\r
+ beforeUpdate: noop,\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = margins;\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+ // Labels\r
+ this.beforeBuildLabels();\r
+ this.buildLabels();\r
+ this.afterBuildLabels();\r
+\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+ },\r
+ afterUpdate: noop,\r
+\r
+ //\r
+\r
+ beforeSetDimensions: noop,\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+\r
+ // Reset minSize\r
+ this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+ },\r
+ afterSetDimensions: noop,\r
+\r
+ //\r
+\r
+ beforeBuildLabels: noop,\r
+ buildLabels: function() {\r
+ this.legendItems = this.options.labels.generateLabels.call(this, this.chart);\r
+ if(this.options.reverse){\r
+ this.legendItems.reverse();\r
+ }\r
+ },\r
+ afterBuildLabels: noop,\r
+\r
+ //\r
+\r
+ beforeFit: noop,\r
+ fit: function() {\r
+ var opts = this.options;\r
+ var labelOpts = opts.labels;\r
+ var display = opts.display;\r
+\r
+ var ctx = this.ctx;\r
+\r
+ var globalDefault = Chart.defaults.global,\r
+ itemOrDefault = helpers.getValueOrDefault,\r
+ fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),\r
+ fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),\r
+ fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),\r
+ labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);\r
+\r
+ // Reset hit boxes\r
+ var hitboxes = this.legendHitBoxes = [];\r
+\r
+ var minSize = this.minSize;\r
+ var isHorizontal = this.isHorizontal();\r
+\r
+ if (isHorizontal) {\r
+ minSize.width = this.maxWidth; // fill all the width\r
+ minSize.height = display ? 10 : 0;\r
+ } else {\r
+ minSize.width = display ? 10 : 0;\r
+ minSize.height = this.maxHeight; // fill all the height\r
+ }\r
+\r
+ // Increase sizes here\r
+ if (display) {\r
+ if (isHorizontal) {\r
+ // Labels\r
+\r
+ // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one\r
+ var lineWidths = this.lineWidths = [0];\r
+ var totalHeight = this.legendItems.length ? fontSize + (labelOpts.padding) : 0;\r
+\r
+ ctx.textAlign = "left";\r
+ ctx.textBaseline = 'top';\r
+ ctx.font = labelFont;\r
+\r
+ helpers.each(this.legendItems, function(legendItem, i) {\r
+ var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;\r
+ if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= this.width) {\r
+ totalHeight += fontSize + (labelOpts.padding);\r
+ lineWidths[lineWidths.length] = this.left;\r
+ }\r
+\r
+ // Store the hitbox width and height here. Final position will be updated in `draw`\r
+ hitboxes[i] = {\r
+ left: 0,\r
+ top: 0,\r
+ width: width,\r
+ height: fontSize\r
+ };\r
+\r
+ lineWidths[lineWidths.length - 1] += width + labelOpts.padding;\r
+ }, this);\r
+\r
+ minSize.height += totalHeight;\r
+\r
+ } else {\r
+ // TODO vertical\r
+ }\r
+ }\r
+\r
+ this.width = minSize.width;\r
+ this.height = minSize.height;\r
+ },\r
+ afterFit: noop,\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ return this.options.position === "top" || this.options.position === "bottom";\r
+ },\r
+\r
+ // Actualy draw the legend on the canvas\r
+ draw: function() {\r
+ var opts = this.options;\r
+ var labelOpts = opts.labels;\r
+ var globalDefault = Chart.defaults.global,\r
+ lineDefault = globalDefault.elements.line,\r
+ legendWidth = this.width,\r
+ lineWidths = this.lineWidths;\r
+\r
+ if (opts.display) {\r
+ var ctx = this.ctx,\r
+ cursor = {\r
+ x: this.left + ((legendWidth - lineWidths[0]) / 2),\r
+ y: this.top + labelOpts.padding,\r
+ line: 0\r
+ },\r
+ itemOrDefault = helpers.getValueOrDefault,\r
+ fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),\r
+ fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),\r
+ fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),\r
+ fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),\r
+ labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);\r
+\r
+ // Horizontal\r
+ if (this.isHorizontal()) {\r
+ // Labels\r
+ ctx.textAlign = "left";\r
+ ctx.textBaseline = 'top';\r
+ ctx.lineWidth = 0.5;\r
+ ctx.strokeStyle = fontColor; // for strikethrough effect\r
+ ctx.fillStyle = fontColor; // render in correct colour\r
+ ctx.font = labelFont;\r
+\r
+ var boxWidth = labelOpts.boxWidth,\r
+ hitboxes = this.legendHitBoxes;\r
+\r
+ helpers.each(this.legendItems, function(legendItem, i) {\r
+ var textWidth = ctx.measureText(legendItem.text).width,\r
+ width = boxWidth + (fontSize / 2) + textWidth,\r
+ x = cursor.x,\r
+ y = cursor.y;\r
+\r
+ if (x + width >= legendWidth) {\r
+ y = cursor.y += fontSize + (labelOpts.padding);\r
+ cursor.line++;\r
+ x = cursor.x = this.left + ((legendWidth - lineWidths[cursor.line]) / 2);\r
+ }\r
+\r
+ // Set the ctx for the box\r
+ ctx.save();\r
+\r
+ ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);\r
+ ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);\r
+ ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);\r
+ ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);\r
+ ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);\r
+ ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);\r
+\r
+ if (ctx.setLineDash) {\r
+ // IE 9 and 10 do not support line dash\r
+ ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));\r
+ }\r
+\r
+ // Draw the box\r
+ ctx.strokeRect(x, y, boxWidth, fontSize);\r
+ ctx.fillRect(x, y, boxWidth, fontSize);\r
+\r
+ ctx.restore();\r
+\r
+ hitboxes[i].left = x;\r
+ hitboxes[i].top = y;\r
+\r
+ // Fill the actual label\r
+ ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);\r
+\r
+ if (legendItem.hidden) {\r
+ // Strikethrough the text if hidden\r
+ ctx.beginPath();\r
+ ctx.lineWidth = 2;\r
+ ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));\r
+ ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));\r
+ ctx.stroke();\r
+ }\r
+\r
+ cursor.x += width + (labelOpts.padding);\r
+ }, this);\r
+ } else {\r
+\r
+ }\r
+ }\r
+ },\r
+\r
+ // Handle an event\r
+ handleEvent: function(e) {\r
+ var position = helpers.getRelativePosition(e, this.chart.chart),\r
+ x = position.x,\r
+ y = position.y,\r
+ opts = this.options;\r
+\r
+ if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {\r
+ // See if we are touching one of the dataset boxes\r
+ var lh = this.legendHitBoxes;\r
+ for (var i = 0; i < lh.length; ++i) {\r
+ var hitBox = lh[i];\r
+\r
+ if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {\r
+ // Touching an element\r
+ if (opts.onClick) {\r
+ opts.onClick.call(this, e, this.legendItems[i]);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+};\r
},{}],29:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
- var helpers = Chart.helpers;
-
- // Plugins are stored here
- Chart.plugins = [];
- Chart.pluginService = {
- // Register a new plugin
- register: function(plugin) {
- var p = Chart.plugins;
- if (p.indexOf(plugin) === -1) {
- p.push(plugin);
- }
- },
-
- // Remove a registered plugin
- remove: function(plugin) {
- var p = Chart.plugins;
- var idx = p.indexOf(plugin);
- if (idx !== -1) {
- p.splice(idx, 1);
- }
- },
-
- // Iterate over all plugins
- notifyPlugins: function(method, args, scope) {
- helpers.each(Chart.plugins, function(plugin) {
- if (plugin[method] && typeof plugin[method] === 'function') {
- plugin[method].apply(scope, args);
- }
- }, scope);
- }
- };
-
- var noop = helpers.noop;
- Chart.PluginBase = Chart.Element.extend({
- // Plugin methods. All functions are passed the chart instance
-
- // Called at start of chart init
- beforeInit: noop,
-
- // Called at end of chart init
- afterInit: noop,
-
- // Called at start of update
- beforeUpdate: noop,
-
- // Called at end of update
- afterUpdate: noop,
-
- // Called at start of draw
- beforeDraw: noop,
-
- // Called at end of draw
- afterDraw: noop,
-
- // Called during destroy
- destroy: noop
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+ var helpers = Chart.helpers;\r
+\r
+ // Plugins are stored here\r
+ Chart.plugins = [];\r
+ Chart.pluginService = {\r
+ // Register a new plugin\r
+ register: function(plugin) {\r
+ var p = Chart.plugins;\r
+ if (p.indexOf(plugin) === -1) {\r
+ p.push(plugin);\r
+ }\r
+ },\r
+\r
+ // Remove a registered plugin\r
+ remove: function(plugin) {\r
+ var p = Chart.plugins;\r
+ var idx = p.indexOf(plugin);\r
+ if (idx !== -1) {\r
+ p.splice(idx, 1);\r
+ }\r
+ },\r
+\r
+ // Iterate over all plugins\r
+ notifyPlugins: function(method, args, scope) {\r
+ helpers.each(Chart.plugins, function(plugin) {\r
+ if (plugin[method] && typeof plugin[method] === 'function') {\r
+ plugin[method].apply(scope, args);\r
+ }\r
+ }, scope);\r
+ }\r
+ };\r
+\r
+ var noop = helpers.noop;\r
+ Chart.PluginBase = Chart.Element.extend({\r
+ // Plugin methods. All functions are passed the chart instance\r
+\r
+ // Called at start of chart init\r
+ beforeInit: noop,\r
+\r
+ // Called at end of chart init\r
+ afterInit: noop,\r
+\r
+ // Called at start of update\r
+ beforeUpdate: noop,\r
+\r
+ // Called at end of update\r
+ afterUpdate: noop,\r
+\r
+ // Called at start of draw\r
+ beforeDraw: noop,\r
+\r
+ // Called at end of draw\r
+ afterDraw: noop,\r
+\r
+ // Called during destroy\r
+ destroy: noop\r
+ });\r
+};\r
},{}],30:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.scale = {
- display: true,
- position: "left",
-
- // grid line settings
- gridLines: {
- display: true,
- color: "rgba(0, 0, 0, 0.1)",
- lineWidth: 1,
- drawBorder: true,
- drawOnChartArea: true,
- drawTicks: true,
- tickMarkLength: 10,
- zeroLineWidth: 1,
- zeroLineColor: "rgba(0,0,0,0.25)",
- offsetGridLines: false
- },
-
- // scale label
- scaleLabel: {
- // actual label
- labelString: '',
-
- // display property
- display: false
- },
-
- // label settings
- ticks: {
- beginAtZero: false,
- minRotation: 0,
- maxRotation: 50,
- mirror: false,
- padding: 10,
- reverse: false,
- display: true,
- autoSkip: true,
- autoSkipPadding: 0,
- labelOffset: 0,
- // We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
- callback: function(value) {
- return helpers.isArray(value) ? value : '' + value;
- }
- }
- };
-
- Chart.Scale = Chart.Element.extend({
-
- // These methods are ordered by lifecyle. Utilities then follow.
- // Any function defined here is inherited by all scale types.
- // Any function can be extended by the scale type
-
- beforeUpdate: function() {
- helpers.callCallback(this.options.beforeUpdate, [this]);
- },
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = helpers.extend({
- left: 0,
- right: 0,
- top: 0,
- bottom: 0
- }, margins);
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
-
- // Data min/max
- me.beforeDataLimits();
- me.determineDataLimits();
- me.afterDataLimits();
-
- // Ticks
- me.beforeBuildTicks();
- me.buildTicks();
- me.afterBuildTicks();
-
- me.beforeTickToLabelConversion();
- me.convertTicksToLabels();
- me.afterTickToLabelConversion();
-
- // Tick Rotation
- me.beforeCalculateTickRotation();
- me.calculateTickRotation();
- me.afterCalculateTickRotation();
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
-
- },
- afterUpdate: function() {
- helpers.callCallback(this.options.afterUpdate, [this]);
- },
-
- //
-
- beforeSetDimensions: function() {
- helpers.callCallback(this.options.beforeSetDimensions, [this]);
- },
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
- },
- afterSetDimensions: function() {
- helpers.callCallback(this.options.afterSetDimensions, [this]);
- },
-
- // Data limits
- beforeDataLimits: function() {
- helpers.callCallback(this.options.beforeDataLimits, [this]);
- },
- determineDataLimits: helpers.noop,
- afterDataLimits: function() {
- helpers.callCallback(this.options.afterDataLimits, [this]);
- },
-
- //
- beforeBuildTicks: function() {
- helpers.callCallback(this.options.beforeBuildTicks, [this]);
- },
- buildTicks: helpers.noop,
- afterBuildTicks: function() {
- helpers.callCallback(this.options.afterBuildTicks, [this]);
- },
-
- beforeTickToLabelConversion: function() {
- helpers.callCallback(this.options.beforeTickToLabelConversion, [this]);
- },
- convertTicksToLabels: function() {
- var me = this;
- // Convert ticks to strings
- me.ticks = me.ticks.map(function(numericalTick, index, ticks) {
- if (me.options.ticks.userCallback) {
- return me.options.ticks.userCallback(numericalTick, index, ticks);
- }
- return me.options.ticks.callback(numericalTick, index, ticks);
- },
- me);
- },
- afterTickToLabelConversion: function() {
- helpers.callCallback(this.options.afterTickToLabelConversion, [this]);
- },
-
- //
-
- beforeCalculateTickRotation: function() {
- helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);
- },
- calculateTickRotation: function() {
- var me = this;
- var context = me.ctx;
- var globalDefaults = Chart.defaults.global;
- var optionTicks = me.options.ticks;
-
- //Get the width of each grid by calculating the difference
- //between x offsets between 0 and 1.
- var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- context.font = tickLabelFont;
-
- var firstWidth = context.measureText(me.ticks[0]).width;
- var lastWidth = context.measureText(me.ticks[me.ticks.length - 1]).width;
- var firstRotated;
-
- me.labelRotation = optionTicks.minRotation || 0;
- me.paddingRight = 0;
- me.paddingLeft = 0;
-
- if (me.options.display) {
- if (me.isHorizontal()) {
- me.paddingRight = lastWidth / 2 + 3;
- me.paddingLeft = firstWidth / 2 + 3;
-
- if (!me.longestTextCache) {
- me.longestTextCache = {};
- }
- var originalLabelWidth = helpers.longestText(context, tickLabelFont, me.ticks, me.longestTextCache);
- var labelWidth = originalLabelWidth;
- var cosRotation;
- var sinRotation;
-
- // Allow 3 pixels x2 padding either side for label readability
- // only the index matters for a dataset scale, but we want a consistent interface between scales
- var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
-
- //Max label rotation can be set or default to 90 - also act as a loop counter
- while (labelWidth > tickWidth && me.labelRotation < optionTicks.maxRotation) {
- cosRotation = Math.cos(helpers.toRadians(me.labelRotation));
- sinRotation = Math.sin(helpers.toRadians(me.labelRotation));
-
- firstRotated = cosRotation * firstWidth;
-
- // We're right aligning the text now.
- if (firstRotated + tickFontSize / 2 > me.yLabelWidth) {
- me.paddingLeft = firstRotated + tickFontSize / 2;
- }
-
- me.paddingRight = tickFontSize / 2;
-
- if (sinRotation * originalLabelWidth > me.maxHeight) {
- // go back one step
- me.labelRotation--;
- break;
- }
-
- me.labelRotation++;
- labelWidth = cosRotation * originalLabelWidth;
- }
- }
- }
-
- if (me.margins) {
- me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
- me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
- }
- },
- afterCalculateTickRotation: function() {
- helpers.callCallback(this.options.afterCalculateTickRotation, [this]);
- },
-
- //
-
- beforeFit: function() {
- helpers.callCallback(this.options.beforeFit, [this]);
- },
- fit: function() {
- var me = this;
- // Reset
- var minSize = me.minSize = {
- width: 0,
- height: 0
- };
-
- var opts = me.options;
- var globalDefaults = Chart.defaults.global;
- var tickOpts = opts.ticks;
- var scaleLabelOpts = opts.scaleLabel;
- var display = opts.display;
- var isHorizontal = me.isHorizontal();
-
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
-
- var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);
- var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
- var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
- var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
-
- var tickMarkLength = opts.gridLines.tickMarkLength;
-
- // Width
- if (isHorizontal) {
- // subtract the margins to line up with the chartArea if we are a full width scale
- minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
- } else {
- minSize.width = display ? tickMarkLength : 0;
- }
-
- // height
- if (isHorizontal) {
- minSize.height = display ? tickMarkLength : 0;
- } else {
- minSize.height = me.maxHeight; // fill all the height
- }
-
- // Are we showing a title for the scale?
- if (scaleLabelOpts.display && display) {
- if (isHorizontal) {
- minSize.height += (scaleLabelFontSize * 1.5);
- } else {
- minSize.width += (scaleLabelFontSize * 1.5);
- }
- }
-
- if (tickOpts.display && display) {
- // Don't bother fitting the ticks if we are not showing them
- if (!me.longestTextCache) {
- me.longestTextCache = {};
- }
-
- var largestTextWidth = helpers.longestText(me.ctx, tickLabelFont, me.ticks, me.longestTextCache);
- var tallestLabelHeightInLines = helpers.numberOfLabelLines(me.ticks);
- var lineSpace = tickFontSize * 0.5;
-
- if (isHorizontal) {
- // A horizontal axis is more constrained by the height.
- me.longestLabelWidth = largestTextWidth;
-
- // TODO - improve this calculation
- var labelHeight = (Math.sin(helpers.toRadians(me.labelRotation)) * me.longestLabelWidth) + (tickFontSize * tallestLabelHeightInLines) + (lineSpace * tallestLabelHeightInLines);
-
- minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight);
- me.ctx.font = tickLabelFont;
-
- var firstLabelWidth = me.ctx.measureText(me.ticks[0]).width;
- var lastLabelWidth = me.ctx.measureText(me.ticks[me.ticks.length - 1]).width;
-
- // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated
- // by the font height
- var cosRotation = Math.cos(helpers.toRadians(me.labelRotation));
- var sinRotation = Math.sin(helpers.toRadians(me.labelRotation));
- me.paddingLeft = me.labelRotation !== 0 ? (cosRotation * firstLabelWidth) + 3 : firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
- me.paddingRight = me.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated
- } else {
- // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first
- var maxLabelWidth = me.maxWidth - minSize.width;
-
- // Account for padding
- var mirror = tickOpts.mirror;
- if (!mirror) {
- largestTextWidth += me.options.ticks.padding;
- } else {
- // If mirrored text is on the inside so don't expand
- largestTextWidth = 0;
- }
-
- if (largestTextWidth < maxLabelWidth) {
- // We don't need all the room
- minSize.width += largestTextWidth;
- } else {
- // Expand to max size
- minSize.width = me.maxWidth;
- }
-
- me.paddingTop = tickFontSize / 2;
- me.paddingBottom = tickFontSize / 2;
- }
- }
-
- if (me.margins) {
- me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
- me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0);
- me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
- me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0);
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
-
- },
- afterFit: function() {
- helpers.callCallback(this.options.afterFit, [this]);
- },
-
- // Shared Methods
- isHorizontal: function() {
- return this.options.position === "top" || this.options.position === "bottom";
- },
- isFullWidth: function() {
- return (this.options.fullWidth);
- },
-
- // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
- getRightValue: function getRightValue(rawValue) {
- // Null and undefined values first
- if (rawValue === null || typeof(rawValue) === 'undefined') {
- return NaN;
- }
- // isNaN(object) returns true, so make sure NaN is checking for a number
- if (typeof(rawValue) === 'number' && isNaN(rawValue)) {
- return NaN;
- }
- // If it is in fact an object, dive in one more level
- if (typeof(rawValue) === "object") {
- if ((rawValue instanceof Date) || (rawValue.isValid)) {
- return rawValue;
- } else {
- return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
- }
- }
-
- // Value is good, return it
- return rawValue;
- },
-
- // Used to get the value to display in the tooltip for the data at the given index
- // function getLabelForIndex(index, datasetIndex)
- getLabelForIndex: helpers.noop,
-
- // Used to get data value locations. Value can either be an index or a numerical value
- getPixelForValue: helpers.noop,
-
- // Used to get the data value from a given pixel. This is the inverse of getPixelForValue
- getValueForPixel: helpers.noop,
-
- // Used for tick location, should
- getPixelForTick: function(index, includeOffset) {
- var me = this;
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var tickWidth = innerWidth / Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
- var pixel = (tickWidth * index) + me.paddingLeft;
-
- if (includeOffset) {
- pixel += tickWidth / 2;
- }
-
- var finalVal = me.left + Math.round(pixel);
- finalVal += me.isFullWidth() ? me.margins.left : 0;
- return finalVal;
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- return me.top + (index * (innerHeight / (me.ticks.length - 1)));
- }
- },
-
- // Utility for getting the pixel location of a percentage of scale
- getPixelForDecimal: function(decimal /*, includeOffset*/ ) {
- var me = this;
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueOffset = (innerWidth * decimal) + me.paddingLeft;
-
- var finalVal = me.left + Math.round(valueOffset);
- finalVal += me.isFullWidth() ? me.margins.left : 0;
- return finalVal;
- } else {
- return me.top + (decimal * me.height);
- }
- },
-
- getBasePixel: function() {
- var me = this;
- var min = me.min;
- var max = me.max;
-
- return me.getPixelForValue(
- me.beginAtZero? 0:
- min < 0 && max < 0? max :
- min > 0 && max > 0? min :
- 0);
- },
-
- // Actualy draw the scale on the canvas
- // @param {rectangle} chartArea : the area of the chart to draw full grid lines on
- draw: function(chartArea) {
- var me = this;
- var options = me.options;
- if (!options.display) {
- return;
- }
-
- var context = me.ctx;
- var globalDefaults = Chart.defaults.global;
- var optionTicks = options.ticks;
- var gridLines = options.gridLines;
- var scaleLabel = options.scaleLabel;
-
- var setContextLineSettings;
- var isRotated = me.labelRotation !== 0;
- var skipRatio;
- var scaleLabelX;
- var scaleLabelY;
- var useAutoskipper = optionTicks.autoSkip;
-
- // figure out the maximum number of gridlines to show
- var maxTicks;
- if (optionTicks.maxTicksLimit) {
- maxTicks = optionTicks.maxTicksLimit;
- }
-
- var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
- var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- var tl = gridLines.tickMarkLength;
-
- var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
- var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);
- var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabel.fontStyle, globalDefaults.defaultFontStyle);
- var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabel.fontFamily, globalDefaults.defaultFontFamily);
- var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
-
- var labelRotationRadians = helpers.toRadians(me.labelRotation);
- var cosRotation = Math.cos(labelRotationRadians);
- var sinRotation = Math.sin(labelRotationRadians);
- var longestRotatedLabel = me.longestLabelWidth * cosRotation;
- var rotatedLabelHeight = tickFontSize * sinRotation;
-
- // Make sure we draw text in the correct color and font
- context.fillStyle = tickFontColor;
-
- if (me.isHorizontal()) {
- setContextLineSettings = true;
- var yTickStart = options.position === "bottom" ? me.top : me.bottom - tl;
- var yTickEnd = options.position === "bottom" ? me.top + tl : me.bottom;
- skipRatio = false;
-
- // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation
- // See #2584
- if (isRotated) {
- longestRotatedLabel /= 2;
- }
-
- if ((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length > (me.width - (me.paddingLeft + me.paddingRight))) {
- skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length) / (me.width - (me.paddingLeft + me.paddingRight)));
- }
-
- // if they defined a max number of optionTicks,
- // increase skipRatio until that number is met
- if (maxTicks && me.ticks.length > maxTicks) {
- while (!skipRatio || me.ticks.length / (skipRatio || 1) > maxTicks) {
- if (!skipRatio) {
- skipRatio = 1;
- }
- skipRatio += 1;
- }
- }
-
- if (!useAutoskipper) {
- skipRatio = false;
- }
-
- helpers.each(me.ticks, function (label, index) {
- // Blank optionTicks
- var isLastTick = me.ticks.length === index + 1;
-
- // Since we always show the last tick,we need may need to hide the last shown one before
- var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= me.ticks.length);
- if (shouldSkip && !isLastTick || (label === undefined || label === null)) {
- return;
- }
- var xLineValue = me.getPixelForTick(index); // xvalues for grid lines
- var xLabelValue = me.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
-
- if (gridLines.display) {
- if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) {
- // Draw the first index specially
- context.lineWidth = gridLines.zeroLineWidth;
- context.strokeStyle = gridLines.zeroLineColor;
- setContextLineSettings = true; // reset next time
- } else if (setContextLineSettings) {
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- setContextLineSettings = false;
- }
-
- xLineValue += helpers.aliasPixel(context.lineWidth);
-
- // Draw the label area
- context.beginPath();
-
- if (gridLines.drawTicks) {
- context.moveTo(xLineValue, yTickStart);
- context.lineTo(xLineValue, yTickEnd);
- }
-
- // Draw the chart area
- if (gridLines.drawOnChartArea) {
- context.moveTo(xLineValue, chartArea.top);
- context.lineTo(xLineValue, chartArea.bottom);
- }
-
- // Need to stroke in the loop because we are potentially changing line widths & colours
- context.stroke();
- }
-
- if (optionTicks.display) {
- context.save();
- context.translate(xLabelValue + optionTicks.labelOffset, (isRotated) ? me.top + 12 : options.position === "top" ? me.bottom - tl : me.top + tl);
- context.rotate(labelRotationRadians * -1);
- context.font = tickLabelFont;
- context.textAlign = (isRotated) ? "right" : "center";
- context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top";
-
- if (helpers.isArray(label)) {
- for (var i = 0, y = 0; i < label.length; ++i) {
- // We just make sure the multiline element is a string here..
- context.fillText('' + label[i], 0, y);
- // apply same lineSpacing as calculated @ L#320
- y += (tickFontSize * 1.5);
- }
- } else {
- context.fillText(label, 0, 0);
- }
-
- context.restore();
- }
- }, me);
-
- if (scaleLabel.display) {
- // Draw the scale label
- context.textAlign = "center";
- context.textBaseline = 'middle';
- context.fillStyle = scaleLabelFontColor; // render in correct colour
- context.font = scaleLabelFont;
-
- scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
- scaleLabelY = options.position === 'bottom' ? me.bottom - (scaleLabelFontSize / 2) : me.top + (scaleLabelFontSize / 2);
-
- context.fillText(scaleLabel.labelString, scaleLabelX, scaleLabelY);
- }
-
- } else {
- setContextLineSettings = true;
- var xTickStart = options.position === "right" ? me.left : me.right - 5;
- var xTickEnd = options.position === "right" ? me.left + 5 : me.right;
-
- helpers.each(me.ticks, function (label, index) {
- // If the callback returned a null or undefined value, do not draw this line
- if (label === undefined || label === null) {
- return;
- }
-
- var yLineValue = me.getPixelForTick(index); // xvalues for grid lines
-
- if (gridLines.display) {
- if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) {
- // Draw the first index specially
- context.lineWidth = gridLines.zeroLineWidth;
- context.strokeStyle = gridLines.zeroLineColor;
- setContextLineSettings = true; // reset next time
- } else if (setContextLineSettings) {
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- setContextLineSettings = false;
- }
-
- yLineValue += helpers.aliasPixel(context.lineWidth);
-
- // Draw the label area
- context.beginPath();
-
- if (gridLines.drawTicks) {
- context.moveTo(xTickStart, yLineValue);
- context.lineTo(xTickEnd, yLineValue);
- }
-
- // Draw the chart area
- if (gridLines.drawOnChartArea) {
- context.moveTo(chartArea.left, yLineValue);
- context.lineTo(chartArea.right, yLineValue);
- }
-
- // Need to stroke in the loop because we are potentially changing line widths & colours
- context.stroke();
- }
-
- if (optionTicks.display) {
- var xLabelValue;
- var yLabelValue = me.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
-
- context.save();
-
- if (options.position === "left") {
- if (optionTicks.mirror) {
- xLabelValue = me.right + optionTicks.padding;
- context.textAlign = "left";
- } else {
- xLabelValue = me.right - optionTicks.padding;
- context.textAlign = "right";
- }
- } else {
- // right side
- if (optionTicks.mirror) {
- xLabelValue = me.left - optionTicks.padding;
- context.textAlign = "right";
- } else {
- xLabelValue = me.left + optionTicks.padding;
- context.textAlign = "left";
- }
- }
-
- context.translate(xLabelValue, yLabelValue + optionTicks.labelOffset);
- context.rotate(labelRotationRadians * -1);
- context.font = tickLabelFont;
- context.textBaseline = "middle";
- context.fillText(label, 0, 0);
- context.restore();
- }
- }, me);
-
- if (scaleLabel.display) {
- // Draw the scale label
- scaleLabelX = options.position === 'left' ? me.left + (scaleLabelFontSize / 2) : me.right - (scaleLabelFontSize / 2);
- scaleLabelY = me.top + ((me.bottom - me.top) / 2);
- var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
-
- context.save();
- context.translate(scaleLabelX, scaleLabelY);
- context.rotate(rotation);
- context.textAlign = "center";
- context.fillStyle = scaleLabelFontColor; // render in correct colour
- context.font = scaleLabelFont;
- context.textBaseline = 'middle';
- context.fillText(scaleLabel.labelString, 0, 0);
- context.restore();
- }
- }
-
- if (gridLines.drawBorder) {
- // Draw the line at the edge of the axis
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- var x1 = me.left,
- x2 = me.right,
- y1 = me.top,
- y2 = me.bottom;
-
- var aliasPixel = helpers.aliasPixel(context.lineWidth);
- if (me.isHorizontal()) {
- y1 = y2 = options.position === 'top' ? me.bottom : me.top;
- y1 += aliasPixel;
- y2 += aliasPixel;
- } else {
- x1 = x2 = options.position === 'left' ? me.right : me.left;
- x1 += aliasPixel;
- x2 += aliasPixel;
- }
-
- context.beginPath();
- context.moveTo(x1, y1);
- context.lineTo(x2, y2);
- context.stroke();
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.scale = {\r
+ display: true,\r
+ position: "left",\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ display: true,\r
+ color: "rgba(0, 0, 0, 0.1)",\r
+ lineWidth: 1,\r
+ drawBorder: true,\r
+ drawOnChartArea: true,\r
+ drawTicks: true,\r
+ tickMarkLength: 10,\r
+ zeroLineWidth: 1,\r
+ zeroLineColor: "rgba(0,0,0,0.25)",\r
+ offsetGridLines: false\r
+ },\r
+\r
+ // scale label\r
+ scaleLabel: {\r
+ // actual label\r
+ labelString: '',\r
+\r
+ // display property\r
+ display: false\r
+ },\r
+\r
+ // label settings\r
+ ticks: {\r
+ beginAtZero: false,\r
+ minRotation: 0,\r
+ maxRotation: 50,\r
+ mirror: false,\r
+ padding: 10,\r
+ reverse: false,\r
+ display: true,\r
+ autoSkip: true,\r
+ autoSkipPadding: 0,\r
+ labelOffset: 0,\r
+ callback: function(value) {\r
+ return '' + value;\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.Scale = Chart.Element.extend({\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+ // Any function defined here is inherited by all scale types.\r
+ // Any function can be extended by the scale type\r
+\r
+ beforeUpdate: function() {\r
+ helpers.callCallback(this.options.beforeUpdate, [this]);\r
+ },\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = helpers.extend({\r
+ left: 0,\r
+ right: 0,\r
+ top: 0,\r
+ bottom: 0\r
+ }, margins);\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+\r
+ // Data min/max\r
+ this.beforeDataLimits();\r
+ this.determineDataLimits();\r
+ this.afterDataLimits();\r
+\r
+ // Ticks\r
+ this.beforeBuildTicks();\r
+ this.buildTicks();\r
+ this.afterBuildTicks();\r
+\r
+ this.beforeTickToLabelConversion();\r
+ this.convertTicksToLabels();\r
+ this.afterTickToLabelConversion();\r
+\r
+ // Tick Rotation\r
+ this.beforeCalculateTickRotation();\r
+ this.calculateTickRotation();\r
+ this.afterCalculateTickRotation();\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+\r
+ },\r
+ afterUpdate: function() {\r
+ helpers.callCallback(this.options.afterUpdate, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeSetDimensions: function() {\r
+ helpers.callCallback(this.options.beforeSetDimensions, [this]);\r
+ },\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+ },\r
+ afterSetDimensions: function() {\r
+ helpers.callCallback(this.options.afterSetDimensions, [this]);\r
+ },\r
+\r
+ // Data limits\r
+ beforeDataLimits: function() {\r
+ helpers.callCallback(this.options.beforeDataLimits, [this]);\r
+ },\r
+ determineDataLimits: helpers.noop,\r
+ afterDataLimits: function() {\r
+ helpers.callCallback(this.options.afterDataLimits, [this]);\r
+ },\r
+\r
+ //\r
+ beforeBuildTicks: function() {\r
+ helpers.callCallback(this.options.beforeBuildTicks, [this]);\r
+ },\r
+ buildTicks: helpers.noop,\r
+ afterBuildTicks: function() {\r
+ helpers.callCallback(this.options.afterBuildTicks, [this]);\r
+ },\r
+\r
+ beforeTickToLabelConversion: function() {\r
+ helpers.callCallback(this.options.beforeTickToLabelConversion, [this]);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ // Convert ticks to strings\r
+ this.ticks = this.ticks.map(function(numericalTick, index, ticks) {\r
+ if (this.options.ticks.userCallback) {\r
+ return this.options.ticks.userCallback(numericalTick, index, ticks);\r
+ }\r
+ return this.options.ticks.callback(numericalTick, index, ticks);\r
+ },\r
+ this);\r
+ },\r
+ afterTickToLabelConversion: function() {\r
+ helpers.callCallback(this.options.afterTickToLabelConversion, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeCalculateTickRotation: function() {\r
+ helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);\r
+ },\r
+ calculateTickRotation: function() {\r
+ var context = this.ctx;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var optionTicks = this.options.ticks;\r
+\r
+ //Get the width of each grid by calculating the difference\r
+ //between x offsets between 0 and 1.\r
+ var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ context.font = tickLabelFont;\r
+\r
+ var firstWidth = context.measureText(this.ticks[0]).width;\r
+ var lastWidth = context.measureText(this.ticks[this.ticks.length - 1]).width;\r
+ var firstRotated;\r
+\r
+ this.labelRotation = optionTicks.minRotation || 0;\r
+ this.paddingRight = 0;\r
+ this.paddingLeft = 0;\r
+\r
+ if (this.options.display) {\r
+ if (this.isHorizontal()) {\r
+ this.paddingRight = lastWidth / 2 + 3;\r
+ this.paddingLeft = firstWidth / 2 + 3;\r
+\r
+ if (!this.longestTextCache) {\r
+ this.longestTextCache = {};\r
+ }\r
+ var originalLabelWidth = helpers.longestText(context, tickLabelFont, this.ticks, this.longestTextCache);\r
+ var labelWidth = originalLabelWidth;\r
+ var cosRotation;\r
+ var sinRotation;\r
+\r
+ // Allow 3 pixels x2 padding either side for label readability\r
+ // only the index matters for a dataset scale, but we want a consistent interface between scales\r
+ var tickWidth = this.getPixelForTick(1) - this.getPixelForTick(0) - 6;\r
+\r
+ //Max label rotation can be set or default to 90 - also act as a loop counter\r
+ while (labelWidth > tickWidth && this.labelRotation < optionTicks.maxRotation) {\r
+ cosRotation = Math.cos(helpers.toRadians(this.labelRotation));\r
+ sinRotation = Math.sin(helpers.toRadians(this.labelRotation));\r
+\r
+ firstRotated = cosRotation * firstWidth;\r
+\r
+ // We're right aligning the text now.\r
+ if (firstRotated + tickFontSize / 2 > this.yLabelWidth) {\r
+ this.paddingLeft = firstRotated + tickFontSize / 2;\r
+ }\r
+\r
+ this.paddingRight = tickFontSize / 2;\r
+\r
+ if (sinRotation * originalLabelWidth > this.maxHeight) {\r
+ // go back one step\r
+ this.labelRotation--;\r
+ break;\r
+ }\r
+\r
+ this.labelRotation++;\r
+ labelWidth = cosRotation * originalLabelWidth;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (this.margins) {\r
+ this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);\r
+ this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);\r
+ }\r
+ },\r
+ afterCalculateTickRotation: function() {\r
+ helpers.callCallback(this.options.afterCalculateTickRotation, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeFit: function() {\r
+ helpers.callCallback(this.options.beforeFit, [this]);\r
+ },\r
+ fit: function() {\r
+ // Reset\r
+ var minSize = this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+\r
+ var opts = this.options;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var tickOpts = opts.ticks;\r
+ var scaleLabelOpts = opts.scaleLabel;\r
+ var display = opts.display;\r
+ var isHorizontal = this.isHorizontal();\r
+\r
+ var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+\r
+ var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);\r
+ var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);\r
+ var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);\r
+ var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);\r
+\r
+ var tickMarkLength = opts.gridLines.tickMarkLength;\r
+\r
+ // Width\r
+ if (isHorizontal) {\r
+ // subtract the margins to line up with the chartArea if we are a full width scale\r
+ minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth;\r
+ } else {\r
+ minSize.width = display ? tickMarkLength : 0;\r
+ }\r
+\r
+ // height\r
+ if (isHorizontal) {\r
+ minSize.height = display ? tickMarkLength : 0;\r
+ } else {\r
+ minSize.height = this.maxHeight; // fill all the height\r
+ }\r
+\r
+ // Are we showing a title for the scale?\r
+ if (scaleLabelOpts.display && display) {\r
+ if (isHorizontal) {\r
+ minSize.height += (scaleLabelFontSize * 1.5);\r
+ } else {\r
+ minSize.width += (scaleLabelFontSize * 1.5);\r
+ }\r
+ }\r
+\r
+ if (tickOpts.display && display) {\r
+ // Don't bother fitting the ticks if we are not showing them\r
+ if (!this.longestTextCache) {\r
+ this.longestTextCache = {};\r
+ }\r
+\r
+ var largestTextWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);\r
+\r
+ if (isHorizontal) {\r
+ // A horizontal axis is more constrained by the height.\r
+ this.longestLabelWidth = largestTextWidth;\r
+\r
+ // TODO - improve this calculation\r
+ var labelHeight = (Math.sin(helpers.toRadians(this.labelRotation)) * this.longestLabelWidth) + 1.5 * tickFontSize;\r
+\r
+ minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight);\r
+ this.ctx.font = tickLabelFont;\r
+\r
+ var firstLabelWidth = this.ctx.measureText(this.ticks[0]).width;\r
+ var lastLabelWidth = this.ctx.measureText(this.ticks[this.ticks.length - 1]).width;\r
+\r
+ // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated\r
+ // by the font height\r
+ var cosRotation = Math.cos(helpers.toRadians(this.labelRotation));\r
+ var sinRotation = Math.sin(helpers.toRadians(this.labelRotation));\r
+ this.paddingLeft = this.labelRotation !== 0 ? (cosRotation * firstLabelWidth) + 3 : firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges\r
+ this.paddingRight = this.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated\r
+ } else {\r
+ // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first\r
+ var maxLabelWidth = this.maxWidth - minSize.width;\r
+\r
+ // Account for padding\r
+ var mirror = tickOpts.mirror;\r
+ if (!mirror) {\r
+ largestTextWidth += this.options.ticks.padding;\r
+ } else {\r
+ // If mirrored text is on the inside so don't expand\r
+ largestTextWidth = 0;\r
+ }\r
+\r
+ if (largestTextWidth < maxLabelWidth) {\r
+ // We don't need all the room\r
+ minSize.width += largestTextWidth;\r
+ } else {\r
+ // Expand to max size\r
+ minSize.width = this.maxWidth;\r
+ }\r
+\r
+ this.paddingTop = tickFontSize / 2;\r
+ this.paddingBottom = tickFontSize / 2;\r
+ }\r
+ }\r
+\r
+ if (this.margins) {\r
+ this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);\r
+ this.paddingTop = Math.max(this.paddingTop - this.margins.top, 0);\r
+ this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);\r
+ this.paddingBottom = Math.max(this.paddingBottom - this.margins.bottom, 0);\r
+ }\r
+\r
+ this.width = minSize.width;\r
+ this.height = minSize.height;\r
+\r
+ },\r
+ afterFit: function() {\r
+ helpers.callCallback(this.options.afterFit, [this]);\r
+ },\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ return this.options.position === "top" || this.options.position === "bottom";\r
+ },\r
+ isFullWidth: function() {\r
+ return (this.options.fullWidth);\r
+ },\r
+\r
+ // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not\r
+ getRightValue: function getRightValue(rawValue) {\r
+ // Null and undefined values first\r
+ if (rawValue === null || typeof(rawValue) === 'undefined') {\r
+ return NaN;\r
+ }\r
+ // isNaN(object) returns true, so make sure NaN is checking for a number\r
+ if (typeof(rawValue) === 'number' && isNaN(rawValue)) {\r
+ return NaN;\r
+ }\r
+ // If it is in fact an object, dive in one more level\r
+ if (typeof(rawValue) === "object") {\r
+ if ((rawValue instanceof Date) || (rawValue.isValid)) {\r
+ return rawValue;\r
+ } else {\r
+ return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);\r
+ }\r
+ }\r
+\r
+ // Value is good, return it\r
+ return rawValue;\r
+ },\r
+\r
+ // Used to get the value to display in the tooltip for the data at the given index\r
+ // function getLabelForIndex(index, datasetIndex)\r
+ getLabelForIndex: helpers.noop,\r
+\r
+ // Used to get data value locations. Value can either be an index or a numerical value\r
+ getPixelForValue: helpers.noop,\r
+\r
+ // Used to get the data value from a given pixel. This is the inverse of getPixelForValue\r
+ getValueForPixel: helpers.noop,\r
+\r
+ // Used for tick location, should\r
+ getPixelForTick: function(index, includeOffset) {\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var tickWidth = innerWidth / Math.max((this.ticks.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+ var pixel = (tickWidth * index) + this.paddingLeft;\r
+\r
+ if (includeOffset) {\r
+ pixel += tickWidth / 2;\r
+ }\r
+\r
+ var finalVal = this.left + Math.round(pixel);\r
+ finalVal += this.isFullWidth() ? this.margins.left : 0;\r
+ return finalVal;\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ return this.top + (index * (innerHeight / (this.ticks.length - 1)));\r
+ }\r
+ },\r
+\r
+ // Utility for getting the pixel location of a percentage of scale\r
+ getPixelForDecimal: function(decimal /*, includeOffset*/ ) {\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueOffset = (innerWidth * decimal) + this.paddingLeft;\r
+\r
+ var finalVal = this.left + Math.round(valueOffset);\r
+ finalVal += this.isFullWidth() ? this.margins.left : 0;\r
+ return finalVal;\r
+ } else {\r
+ return this.top + (decimal * this.height);\r
+ }\r
+ },\r
+\r
+ getBasePixel: function() {\r
+ var me = this;\r
+ var min = me.min;\r
+ var max = me.max;\r
+\r
+ return me.getPixelForValue(\r
+ me.beginAtZero? 0:\r
+ min < 0 && max < 0? max :\r
+ min > 0 && max > 0? min :\r
+ 0);\r
+ },\r
+\r
+ // Actualy draw the scale on the canvas\r
+ // @param {rectangle} chartArea : the area of the chart to draw full grid lines on\r
+ draw: function(chartArea) {\r
+ var options = this.options;\r
+ if (!options.display) {\r
+ return;\r
+ }\r
+\r
+ var context = this.ctx;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var optionTicks = options.ticks;\r
+ var gridLines = options.gridLines;\r
+ var scaleLabel = options.scaleLabel;\r
+\r
+ var setContextLineSettings;\r
+ var isRotated = this.labelRotation !== 0;\r
+ var skipRatio;\r
+ var scaleLabelX;\r
+ var scaleLabelY;\r
+ var useAutoskipper = optionTicks.autoSkip;\r
+\r
+ // figure out the maximum number of gridlines to show\r
+ var maxTicks;\r
+ if (optionTicks.maxTicksLimit) {\r
+ maxTicks = optionTicks.maxTicksLimit;\r
+ }\r
+\r
+ var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);\r
+ var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ var tl = gridLines.tickMarkLength;\r
+\r
+ var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);\r
+ var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);\r
+ var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabel.fontStyle, globalDefaults.defaultFontStyle);\r
+ var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabel.fontFamily, globalDefaults.defaultFontFamily);\r
+ var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);\r
+\r
+ var labelRotationRadians = helpers.toRadians(this.labelRotation);\r
+ var cosRotation = Math.cos(labelRotationRadians);\r
+ var sinRotation = Math.sin(labelRotationRadians);\r
+ var longestRotatedLabel = this.longestLabelWidth * cosRotation;\r
+ var rotatedLabelHeight = tickFontSize * sinRotation;\r
+\r
+ // Make sure we draw text in the correct color and font\r
+ context.fillStyle = tickFontColor;\r
+\r
+ if (this.isHorizontal()) {\r
+ setContextLineSettings = true;\r
+ var yTickStart = options.position === "bottom" ? this.top : this.bottom - tl;\r
+ var yTickEnd = options.position === "bottom" ? this.top + tl : this.bottom;\r
+ skipRatio = false;\r
+\r
+ // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation\r
+ // See #2584\r
+ if (isRotated) {\r
+ longestRotatedLabel /= 2;\r
+ }\r
+\r
+ if ((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length > (this.width - (this.paddingLeft + this.paddingRight))) {\r
+ skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length) / (this.width - (this.paddingLeft + this.paddingRight)));\r
+ }\r
+\r
+ // if they defined a max number of optionTicks,\r
+ // increase skipRatio until that number is met\r
+ if (maxTicks && this.ticks.length > maxTicks) {\r
+ while (!skipRatio || this.ticks.length / (skipRatio || 1) > maxTicks) {\r
+ if (!skipRatio) {\r
+ skipRatio = 1;\r
+ }\r
+ skipRatio += 1;\r
+ }\r
+ }\r
+\r
+ if (!useAutoskipper) {\r
+ skipRatio = false;\r
+ }\r
+\r
+ helpers.each(this.ticks, function (label, index) {\r
+ // Blank optionTicks\r
+ var isLastTick = this.ticks.length === index + 1;\r
+\r
+ // Since we always show the last tick,we need may need to hide the last shown one before\r
+ var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= this.ticks.length);\r
+ if (shouldSkip && !isLastTick || (label === undefined || label === null)) {\r
+ return;\r
+ }\r
+ var xLineValue = this.getPixelForTick(index); // xvalues for grid lines\r
+ var xLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)\r
+\r
+ if (gridLines.display) {\r
+ if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {\r
+ // Draw the first index specially\r
+ context.lineWidth = gridLines.zeroLineWidth;\r
+ context.strokeStyle = gridLines.zeroLineColor;\r
+ setContextLineSettings = true; // reset next time\r
+ } else if (setContextLineSettings) {\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ setContextLineSettings = false;\r
+ }\r
+\r
+ xLineValue += helpers.aliasPixel(context.lineWidth);\r
+\r
+ // Draw the label area\r
+ context.beginPath();\r
+\r
+ if (gridLines.drawTicks) {\r
+ context.moveTo(xLineValue, yTickStart);\r
+ context.lineTo(xLineValue, yTickEnd);\r
+ }\r
+\r
+ // Draw the chart area\r
+ if (gridLines.drawOnChartArea) {\r
+ context.moveTo(xLineValue, chartArea.top);\r
+ context.lineTo(xLineValue, chartArea.bottom);\r
+ }\r
+\r
+ // Need to stroke in the loop because we are potentially changing line widths & colours\r
+ context.stroke();\r
+ }\r
+\r
+ if (optionTicks.display) {\r
+ context.save();\r
+ context.translate(xLabelValue + optionTicks.labelOffset, (isRotated) ? this.top + 12 : options.position === "top" ? this.bottom - tl : this.top + tl);\r
+ context.rotate(labelRotationRadians * -1);\r
+ context.font = tickLabelFont;\r
+ context.textAlign = (isRotated) ? "right" : "center";\r
+ context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top";\r
+ context.fillText(label, 0, 0);\r
+ context.restore();\r
+ }\r
+ }, this);\r
+\r
+ if (scaleLabel.display) {\r
+ // Draw the scale label\r
+ context.textAlign = "center";\r
+ context.textBaseline = 'middle';\r
+ context.fillStyle = scaleLabelFontColor; // render in correct colour\r
+ context.font = scaleLabelFont;\r
+\r
+ scaleLabelX = this.left + ((this.right - this.left) / 2); // midpoint of the width\r
+ scaleLabelY = options.position === 'bottom' ? this.bottom - (scaleLabelFontSize / 2) : this.top + (scaleLabelFontSize / 2);\r
+\r
+ context.fillText(scaleLabel.labelString, scaleLabelX, scaleLabelY);\r
+ }\r
+\r
+ } else {\r
+ setContextLineSettings = true;\r
+ var xTickStart = options.position === "right" ? this.left : this.right - 5;\r
+ var xTickEnd = options.position === "right" ? this.left + 5 : this.right;\r
+\r
+ helpers.each(this.ticks, function (label, index) {\r
+ // If the callback returned a null or undefined value, do not draw this line\r
+ if (label === undefined || label === null) {\r
+ return;\r
+ }\r
+\r
+ var yLineValue = this.getPixelForTick(index); // xvalues for grid lines\r
+\r
+ if (gridLines.display) {\r
+ if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {\r
+ // Draw the first index specially\r
+ context.lineWidth = gridLines.zeroLineWidth;\r
+ context.strokeStyle = gridLines.zeroLineColor;\r
+ setContextLineSettings = true; // reset next time\r
+ } else if (setContextLineSettings) {\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ setContextLineSettings = false;\r
+ }\r
+\r
+ yLineValue += helpers.aliasPixel(context.lineWidth);\r
+\r
+ // Draw the label area\r
+ context.beginPath();\r
+\r
+ if (gridLines.drawTicks) {\r
+ context.moveTo(xTickStart, yLineValue);\r
+ context.lineTo(xTickEnd, yLineValue);\r
+ }\r
+\r
+ // Draw the chart area\r
+ if (gridLines.drawOnChartArea) {\r
+ context.moveTo(chartArea.left, yLineValue);\r
+ context.lineTo(chartArea.right, yLineValue);\r
+ }\r
+\r
+ // Need to stroke in the loop because we are potentially changing line widths & colours\r
+ context.stroke();\r
+ }\r
+\r
+ if (optionTicks.display) {\r
+ var xLabelValue;\r
+ var yLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)\r
+\r
+ context.save();\r
+\r
+ if (options.position === "left") {\r
+ if (optionTicks.mirror) {\r
+ xLabelValue = this.right + optionTicks.padding;\r
+ context.textAlign = "left";\r
+ } else {\r
+ xLabelValue = this.right - optionTicks.padding;\r
+ context.textAlign = "right";\r
+ }\r
+ } else {\r
+ // right side\r
+ if (optionTicks.mirror) {\r
+ xLabelValue = this.left - optionTicks.padding;\r
+ context.textAlign = "right";\r
+ } else {\r
+ xLabelValue = this.left + optionTicks.padding;\r
+ context.textAlign = "left";\r
+ }\r
+ }\r
+\r
+ context.translate(xLabelValue, yLabelValue + optionTicks.labelOffset);\r
+ context.rotate(labelRotationRadians * -1);\r
+ context.font = tickLabelFont;\r
+ context.textBaseline = "middle";\r
+ context.fillText(label, 0, 0);\r
+ context.restore();\r
+ }\r
+ }, this);\r
+\r
+ if (scaleLabel.display) {\r
+ // Draw the scale label\r
+ scaleLabelX = options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);\r
+ scaleLabelY = this.top + ((this.bottom - this.top) / 2);\r
+ var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;\r
+\r
+ context.save();\r
+ context.translate(scaleLabelX, scaleLabelY);\r
+ context.rotate(rotation);\r
+ context.textAlign = "center";\r
+ context.fillStyle = scaleLabelFontColor; // render in correct colour\r
+ context.font = scaleLabelFont;\r
+ context.textBaseline = 'middle';\r
+ context.fillText(scaleLabel.labelString, 0, 0);\r
+ context.restore();\r
+ }\r
+ }\r
+\r
+ if (gridLines.drawBorder) {\r
+ // Draw the line at the edge of the axis\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ var x1 = this.left,\r
+ x2 = this.right,\r
+ y1 = this.top,\r
+ y2 = this.bottom;\r
+\r
+ var aliasPixel = helpers.aliasPixel(context.lineWidth);\r
+ if (this.isHorizontal()) {\r
+ y1 = y2 = options.position === 'top' ? this.bottom : this.top;\r
+ y1 += aliasPixel;\r
+ y2 += aliasPixel;\r
+ } else {\r
+ x1 = x2 = options.position === 'left' ? this.right : this.left;\r
+ x1 += aliasPixel;\r
+ x2 += aliasPixel;\r
+ }\r
+\r
+ context.beginPath();\r
+ context.moveTo(x1, y1);\r
+ context.lineTo(x2, y2);\r
+ context.stroke();\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],31:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.scaleService = {
- // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
- // use the new chart options to grab the correct scale
- constructors: {},
- // Use a registration function so that we can move to an ES6 map when we no longer need to support
- // old browsers
-
- // Scale config defaults
- defaults: {},
- registerScaleType: function(type, scaleConstructor, defaults) {
- this.constructors[type] = scaleConstructor;
- this.defaults[type] = helpers.clone(defaults);
- },
- getScaleConstructor: function(type) {
- return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
- },
- getScaleDefaults: function(type) {
- // Return the scale defaults merged with the global settings so that we always use the latest ones
- return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};
- },
- updateScaleDefaults: function(type, additions) {
- var defaults = this.defaults;
- if (defaults.hasOwnProperty(type)) {
- defaults[type] = helpers.extend(defaults[type], additions);
- }
- },
- addScalesToLayout: function(chartInstance) {
- // Adds each scale to the chart.boxes array to be sized accordingly
- helpers.each(chartInstance.scales, function(scale) {
- Chart.layoutService.addBox(chartInstance, scale);
- });
- }
- };
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.scaleService = {\r
+ // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then\r
+ // use the new chart options to grab the correct scale\r
+ constructors: {},\r
+ // Use a registration function so that we can move to an ES6 map when we no longer need to support\r
+ // old browsers\r
+\r
+ // Scale config defaults\r
+ defaults: {},\r
+ registerScaleType: function(type, scaleConstructor, defaults) {\r
+ this.constructors[type] = scaleConstructor;\r
+ this.defaults[type] = helpers.clone(defaults);\r
+ },\r
+ getScaleConstructor: function(type) {\r
+ return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;\r
+ },\r
+ getScaleDefaults: function(type) {\r
+ // Return the scale defaults merged with the global settings so that we always use the latest ones\r
+ return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};\r
+ },\r
+ updateScaleDefaults: function(type, additions) {\r
+ var defaults = this.defaults;\r
+ if (defaults.hasOwnProperty(type)) {\r
+ defaults[type] = helpers.extend(defaults[type], additions);\r
+ }\r
+ },\r
+ addScalesToLayout: function(chartInstance) {\r
+ // Adds each scale to the chart.boxes array to be sized accordingly\r
+ helpers.each(chartInstance.scales, function(scale) {\r
+ Chart.layoutService.addBox(chartInstance, scale);\r
+ });\r
+ }\r
+ };\r
};
},{}],32:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.title = {
- display: false,
- position: 'top',
- fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
-
- fontStyle: 'bold',
- padding: 10,
-
- // actual title
- text: ''
- };
-
- var noop = helpers.noop;
- Chart.Title = Chart.Element.extend({
-
- initialize: function(config) {
- var me = this;
- helpers.extend(me, config);
- me.options = helpers.configMerge(Chart.defaults.global.title, config.options);
-
- // Contains hit boxes for each dataset (in dataset order)
- me.legendHitBoxes = [];
- },
-
- // These methods are ordered by lifecyle. Utilities then follow.
-
- beforeUpdate: function () {
- var chartOpts = this.chart.options;
- if (chartOpts && chartOpts.title) {
- this.options = helpers.configMerge(Chart.defaults.global.title, chartOpts.title);
- }
- },
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = margins;
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
- // Labels
- me.beforeBuildLabels();
- me.buildLabels();
- me.afterBuildLabels();
-
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
-
- },
- afterUpdate: noop,
-
- //
-
- beforeSetDimensions: noop,
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
-
- // Reset minSize
- me.minSize = {
- width: 0,
- height: 0
- };
- },
- afterSetDimensions: noop,
-
- //
-
- beforeBuildLabels: noop,
- buildLabels: noop,
- afterBuildLabels: noop,
-
- //
-
- beforeFit: noop,
- fit: function() {
-
- var me = this,
- ctx = me.ctx,
- valueOrDefault = helpers.getValueOrDefault,
- opts = me.options,
- globalDefaults = Chart.defaults.global,
- display = opts.display,
- fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
- minSize = me.minSize;
-
- if (me.isHorizontal()) {
- minSize.width = me.maxWidth; // fill all the width
- minSize.height = display ? fontSize + (opts.padding * 2) : 0;
- } else {
- minSize.width = display ? fontSize + (opts.padding * 2) : 0;
- minSize.height = me.maxHeight; // fill all the height
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
-
- },
- afterFit: noop,
-
- // Shared Methods
- isHorizontal: function() {
- var pos = this.options.position;
- return pos === "top" || pos === "bottom";
- },
-
- // Actualy draw the title block on the canvas
- draw: function() {
- var me = this,
- ctx = me.ctx,
- valueOrDefault = helpers.getValueOrDefault,
- opts = me.options,
- globalDefaults = Chart.defaults.global;
-
- if (opts.display) {
- var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
- fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),
- fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),
- titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),
- rotation = 0,
- titleX,
- titleY,
- top = me.top,
- left = me.left,
- bottom = me.bottom,
- right = me.right;
-
- ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour
- ctx.font = titleFont;
-
- // Horizontal
- if (me.isHorizontal()) {
- titleX = left + ((right - left) / 2); // midpoint of the width
- titleY = top + ((bottom - top) / 2); // midpoint of the height
- } else {
- titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);
- titleY = top + ((bottom - top) / 2);
- rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
- }
-
- ctx.save();
- ctx.translate(titleX, titleY);
- ctx.rotate(rotation);
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- ctx.fillText(opts.text, 0, 0);
- ctx.restore();
- }
- }
- });
-
- // Register the title plugin
- Chart.pluginService.register({
- beforeInit: function(chartInstance) {
- var opts = chartInstance.options;
- var titleOpts = opts.title;
-
- if (titleOpts) {
- chartInstance.titleBlock = new Chart.Title({
- ctx: chartInstance.chart.ctx,
- options: titleOpts,
- chart: chartInstance
- });
-
- Chart.layoutService.addBox(chartInstance, chartInstance.titleBlock);
- }
- }
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.title = {\r
+ display: false,\r
+ position: 'top',\r
+ fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)\r
+\r
+ fontStyle: 'bold',\r
+ padding: 10,\r
+\r
+ // actual title\r
+ text: ''\r
+ };\r
+\r
+ var noop = helpers.noop;\r
+ Chart.Title = Chart.Element.extend({\r
+\r
+ initialize: function(config) {\r
+ helpers.extend(this, config);\r
+ this.options = helpers.configMerge(Chart.defaults.global.title, config.options);\r
+\r
+ // Contains hit boxes for each dataset (in dataset order)\r
+ this.legendHitBoxes = [];\r
+ },\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+\r
+ beforeUpdate: noop,\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = margins;\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+ // Labels\r
+ this.beforeBuildLabels();\r
+ this.buildLabels();\r
+ this.afterBuildLabels();\r
+\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+\r
+ },\r
+ afterUpdate: noop,\r
+\r
+ //\r
+\r
+ beforeSetDimensions: noop,\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+\r
+ // Reset minSize\r
+ this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+ },\r
+ afterSetDimensions: noop,\r
+\r
+ //\r
+\r
+ beforeBuildLabels: noop,\r
+ buildLabels: noop,\r
+ afterBuildLabels: noop,\r
+\r
+ //\r
+\r
+ beforeFit: noop,\r
+ fit: function() {\r
+\r
+ var _this = this,\r
+ ctx = _this.ctx,\r
+ valueOrDefault = helpers.getValueOrDefault,\r
+ opts = _this.options,\r
+ globalDefaults = Chart.defaults.global,\r
+ display = opts.display,\r
+ fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),\r
+ minSize = _this.minSize;\r
+\r
+ if (_this.isHorizontal()) {\r
+ minSize.width = _this.maxWidth; // fill all the width\r
+ minSize.height = display ? fontSize + (opts.padding * 2) : 0;\r
+ } else {\r
+ minSize.width = display ? fontSize + (opts.padding * 2) : 0;\r
+ minSize.height = _this.maxHeight; // fill all the height\r
+ }\r
+\r
+ _this.width = minSize.width;\r
+ _this.height = minSize.height;\r
+\r
+ },\r
+ afterFit: noop,\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ var pos = this.options.position;\r
+ return pos === "top" || pos === "bottom";\r
+ },\r
+\r
+ // Actualy draw the title block on the canvas\r
+ draw: function() {\r
+ var _this = this,\r
+ ctx = _this.ctx,\r
+ valueOrDefault = helpers.getValueOrDefault,\r
+ opts = _this.options,\r
+ globalDefaults = Chart.defaults.global;\r
+\r
+ if (opts.display) {\r
+ var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),\r
+ fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),\r
+ fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),\r
+ titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),\r
+ rotation = 0,\r
+ titleX, \r
+ titleY,\r
+ top = _this.top,\r
+ left = _this.left,\r
+ bottom = _this.bottom,\r
+ right = _this.right;\r
+\r
+ ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour\r
+ ctx.font = titleFont;\r
+\r
+ // Horizontal\r
+ if (_this.isHorizontal()) {\r
+ titleX = left + ((right - left) / 2); // midpoint of the width\r
+ titleY = top + ((bottom - top) / 2); // midpoint of the height\r
+ } else {\r
+ titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);\r
+ titleY = top + ((bottom - top) / 2);\r
+ rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);\r
+ }\r
+\r
+ ctx.save();\r
+ ctx.translate(titleX, titleY);\r
+ ctx.rotate(rotation);\r
+ ctx.textAlign = 'center';\r
+ ctx.textBaseline = 'middle';\r
+ ctx.fillText(opts.text, 0, 0);\r
+ ctx.restore();\r
+ }\r
+ }\r
+ });\r
};
-
},{}],33:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.tooltips = {
- enabled: true,
- custom: null,
- mode: 'single',
- backgroundColor: "rgba(0,0,0,0.8)",
- titleFontStyle: "bold",
- titleSpacing: 2,
- titleMarginBottom: 6,
- titleColor: "#fff",
- titleAlign: "left",
- bodySpacing: 2,
- bodyColor: "#fff",
- bodyAlign: "left",
- footerFontStyle: "bold",
- footerSpacing: 2,
- footerMarginTop: 6,
- footerColor: "#fff",
- footerAlign: "left",
- yPadding: 6,
- xPadding: 6,
- yAlign : 'center',
- xAlign : 'center',
- caretSize: 5,
- cornerRadius: 6,
- multiKeyBackground: '#fff',
- callbacks: {
- // Args are: (tooltipItems, data)
- beforeTitle: helpers.noop,
- title: function(tooltipItems, data) {
- // Pick first xLabel for now
- var title = '';
- var labels = data.labels;
- var labelCount = labels ? labels.length : 0;
-
- if (tooltipItems.length > 0) {
- var item = tooltipItems[0];
-
- if (item.xLabel) {
- title = item.xLabel;
- } else if (labelCount > 0 && item.index < labelCount) {
- title = labels[item.index];
- }
- }
-
- return title;
- },
- afterTitle: helpers.noop,
-
- // Args are: (tooltipItems, data)
- beforeBody: helpers.noop,
-
- // Args are: (tooltipItem, data)
- beforeLabel: helpers.noop,
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- return datasetLabel + ': ' + tooltipItem.yLabel;
- },
- labelColor: function(tooltipItem, chartInstance) {
- var meta = chartInstance.getDatasetMeta(tooltipItem.datasetIndex);
- var activeElement = meta.data[tooltipItem.index];
- var view = activeElement._view;
- return {
- borderColor: view.borderColor,
- backgroundColor: view.backgroundColor
- };
- },
- afterLabel: helpers.noop,
-
- // Args are: (tooltipItems, data)
- afterBody: helpers.noop,
-
- // Args are: (tooltipItems, data)
- beforeFooter: helpers.noop,
- footer: helpers.noop,
- afterFooter: helpers.noop
- }
- };
-
- // Helper to push or concat based on if the 2nd parameter is an array or not
- function pushOrConcat(base, toPush) {
- if (toPush) {
- if (helpers.isArray(toPush)) {
- base = base.concat(toPush);
- } else {
- base.push(toPush);
- }
- }
-
- return base;
- }
-
- function getAveragePosition(elements) {
- if (!elements.length) {
- return false;
- }
-
- var i, len;
- var xPositions = [];
- var yPositions = [];
-
- for (i = 0, len = elements.length; i < len; ++i) {
- var el = elements[i];
- if (el && el.hasValue()){
- var pos = el.tooltipPosition();
- xPositions.push(pos.x);
- yPositions.push(pos.y);
- }
- }
-
- var x = 0,
- y = 0;
- for (i = 0, len - xPositions.length; i < len; ++i) {
- x += xPositions[i];
- y += yPositions[i];
- }
-
- return {
- x: Math.round(x / xPositions.length),
- y: Math.round(y / xPositions.length)
- };
- }
-
- // Private helper to create a tooltip iteam model
- // @param element : the chart element (point, arc, bar) to create the tooltip item for
- // @return : new tooltip item
- function createTooltipItem(element) {
- var xScale = element._xScale;
- var yScale = element._yScale || element._scale; // handle radar || polarArea charts
- var index = element._index,
- datasetIndex = element._datasetIndex;
-
- return {
- xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '',
- yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '',
- index: index,
- datasetIndex: datasetIndex
- };
- }
-
- Chart.Tooltip = Chart.Element.extend({
- initialize: function() {
- var me = this;
- var globalDefaults = Chart.defaults.global;
- var tooltipOpts = me._options;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- helpers.extend(me, {
- _model: {
- // Positioning
- xPadding: tooltipOpts.xPadding,
- yPadding: tooltipOpts.yPadding,
- xAlign : tooltipOpts.yAlign,
- yAlign : tooltipOpts.xAlign,
-
- // Body
- bodyColor: tooltipOpts.bodyColor,
- _bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
- _bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
- _bodyAlign: tooltipOpts.bodyAlign,
- bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
- bodySpacing: tooltipOpts.bodySpacing,
-
- // Title
- titleColor: tooltipOpts.titleColor,
- _titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
- _titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
- titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
- _titleAlign: tooltipOpts.titleAlign,
- titleSpacing: tooltipOpts.titleSpacing,
- titleMarginBottom: tooltipOpts.titleMarginBottom,
-
- // Footer
- footerColor: tooltipOpts.footerColor,
- _footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
- _footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
- footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
- _footerAlign: tooltipOpts.footerAlign,
- footerSpacing: tooltipOpts.footerSpacing,
- footerMarginTop: tooltipOpts.footerMarginTop,
-
- // Appearance
- caretSize: tooltipOpts.caretSize,
- cornerRadius: tooltipOpts.cornerRadius,
- backgroundColor: tooltipOpts.backgroundColor,
- opacity: 0,
- legendColorBackground: tooltipOpts.multiKeyBackground
- }
- });
- },
-
- // Get the title
- // Args are: (tooltipItem, data)
- getTitle: function() {
- var me = this;
- var opts = me._options;
- var callbacks = opts.callbacks;
-
- var beforeTitle = callbacks.beforeTitle.apply(me, arguments),
- title = callbacks.title.apply(me, arguments),
- afterTitle = callbacks.afterTitle.apply(me, arguments);
-
- var lines = [];
- lines = pushOrConcat(lines, beforeTitle);
- lines = pushOrConcat(lines, title);
- lines = pushOrConcat(lines, afterTitle);
-
- return lines;
- },
-
- // Args are: (tooltipItem, data)
- getBeforeBody: function() {
- var lines = this._options.callbacks.beforeBody.apply(this, arguments);
- return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
- },
-
- // Args are: (tooltipItem, data)
- getBody: function(tooltipItems, data) {
- var me = this;
- var callbacks = me._options.callbacks;
- var bodyItems = [];
-
- helpers.each(tooltipItems, function(tooltipItem) {
- var bodyItem = {
- before: [],
- lines: [],
- after: []
- };
- pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data));
- pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data));
- pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data));
-
- bodyItems.push(bodyItem);
- });
-
- return bodyItems;
- },
-
- // Args are: (tooltipItem, data)
- getAfterBody: function() {
- var lines = this._options.callbacks.afterBody.apply(this, arguments);
- return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
- },
-
- // Get the footer and beforeFooter and afterFooter lines
- // Args are: (tooltipItem, data)
- getFooter: function() {
- var me = this;
- var callbacks = me._options.callbacks;
-
- var beforeFooter = callbacks.beforeFooter.apply(me, arguments);
- var footer = callbacks.footer.apply(me, arguments);
- var afterFooter = callbacks.afterFooter.apply(me, arguments);
-
- var lines = [];
- lines = pushOrConcat(lines, beforeFooter);
- lines = pushOrConcat(lines, footer);
- lines = pushOrConcat(lines, afterFooter);
-
- return lines;
- },
-
- update: function(changed) {
- var me = this;
- var opts = me._options;
- var model = me._model;
- var active = me._active;
-
- var data = me._data;
- var chartInstance = me._chartInstance;
-
- var i, len;
-
- if (active.length) {
- model.opacity = 1;
-
- var labelColors = [],
- tooltipPosition = getAveragePosition(active);
-
- var tooltipItems = [];
- for (i = 0, len = active.length; i < len; ++i) {
- tooltipItems.push(createTooltipItem(active[i]));
- }
-
- // If the user provided a sorting function, use it to modify the tooltip items
- if (opts.itemSort) {
- tooltipItems = tooltipItems.sort(opts.itemSort);
- }
-
- // If there is more than one item, show color items
- if (active.length > 1) {
- helpers.each(tooltipItems, function(tooltipItem) {
- labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, chartInstance));
- });
- }
-
- // Build the Text Lines
- helpers.extend(model, {
- title: me.getTitle(tooltipItems, data),
- beforeBody: me.getBeforeBody(tooltipItems, data),
- body: me.getBody(tooltipItems, data),
- afterBody: me.getAfterBody(tooltipItems, data),
- footer: me.getFooter(tooltipItems, data),
- x: Math.round(tooltipPosition.x),
- y: Math.round(tooltipPosition.y),
- caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),
- labelColors: labelColors
- });
-
- // We need to determine alignment of
- var tooltipSize = me.getTooltipSize(model);
- me.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas
-
- helpers.extend(model, me.getBackgroundPoint(model, tooltipSize));
- } else {
- me._model.opacity = 0;
- }
-
- if (changed && opts.custom) {
- opts.custom.call(me, model);
- }
-
- return me;
- },
- getTooltipSize: function getTooltipSize(vm) {
- var ctx = this._chart.ctx;
-
- var size = {
- height: vm.yPadding * 2, // Tooltip Padding
- width: 0
- };
-
- // Count of all lines in the body
- var body = vm.body;
- var combinedBodyLength = body.reduce(function(count, bodyItem) {
- return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
- }, 0);
- combinedBodyLength += vm.beforeBody.length + vm.afterBody.length;
-
- var titleLineCount = vm.title.length;
- var footerLineCount = vm.footer.length;
- var titleFontSize = vm.titleFontSize,
- bodyFontSize = vm.bodyFontSize,
- footerFontSize = vm.footerFontSize;
-
- size.height += titleLineCount * titleFontSize; // Title Lines
- size.height += (titleLineCount - 1) * vm.titleSpacing; // Title Line Spacing
- size.height += titleLineCount ? vm.titleMarginBottom : 0; // Title's bottom Margin
- size.height += combinedBodyLength * bodyFontSize; // Body Lines
- size.height += combinedBodyLength ? (combinedBodyLength - 1) * vm.bodySpacing : 0; // Body Line Spacing
- size.height += footerLineCount ? vm.footerMarginTop : 0; // Footer Margin
- size.height += footerLineCount * (footerFontSize); // Footer Lines
- size.height += footerLineCount ? (footerLineCount - 1) * vm.footerSpacing : 0; // Footer Line Spacing
-
- // Title width
- var widthPadding = 0;
- var maxLineWidth = function(line) {
- size.width = Math.max(size.width, ctx.measureText(line).width + widthPadding);
- };
-
- ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
- helpers.each(vm.title, maxLineWidth);
-
- // Body width
- ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
- helpers.each(vm.beforeBody.concat(vm.afterBody), maxLineWidth);
-
- // Body lines may include some extra width due to the color box
- widthPadding = body.length > 1 ? (bodyFontSize + 2) : 0;
- helpers.each(body, function(bodyItem) {
- helpers.each(bodyItem.before, maxLineWidth);
- helpers.each(bodyItem.lines, maxLineWidth);
- helpers.each(bodyItem.after, maxLineWidth);
- });
-
- // Reset back to 0
- widthPadding = 0;
-
- // Footer width
- ctx.font = helpers.fontString(footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
- helpers.each(vm.footer, maxLineWidth);
-
- // Add padding
- size.width += 2 * vm.xPadding;
-
- return size;
- },
- determineAlignment: function determineAlignment(size) {
- var me = this;
- var model = me._model;
- var chart = me._chart;
- var chartArea = me._chartInstance.chartArea;
-
- if (model.y < size.height) {
- model.yAlign = 'top';
- } else if (model.y > (chart.height - size.height)) {
- model.yAlign = 'bottom';
- }
-
- var lf, rf; // functions to determine left, right alignment
- var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
- var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
- var midX = (chartArea.left + chartArea.right) / 2;
- var midY = (chartArea.top + chartArea.bottom) / 2;
-
- if (model.yAlign === 'center') {
- lf = function(x) {
- return x <= midX;
- };
- rf = function(x) {
- return x > midX;
- };
- } else {
- lf = function(x) {
- return x <= (size.width / 2);
- };
- rf = function(x) {
- return x >= (chart.width - (size.width / 2));
- };
- }
-
- olf = function(x) {
- return x + size.width > chart.width;
- };
- orf = function(x) {
- return x - size.width < 0;
- };
- yf = function(y) {
- return y <= midY ? 'top' : 'bottom';
- };
-
- if (lf(model.x)) {
- model.xAlign = 'left';
-
- // Is tooltip too wide and goes over the right side of the chart.?
- if (olf(model.x)) {
- model.xAlign = 'center';
- model.yAlign = yf(model.y);
- }
- } else if (rf(model.x)) {
- model.xAlign = 'right';
-
- // Is tooltip too wide and goes outside left edge of canvas?
- if (orf(model.x)) {
- model.xAlign = 'center';
- model.yAlign = yf(model.y);
- }
- }
- },
- getBackgroundPoint: function getBackgroundPoint(vm, size) {
- // Background Position
- var pt = {
- x: vm.x,
- y: vm.y
- };
-
- var caretSize = vm.caretSize,
- caretPadding = vm.caretPadding,
- cornerRadius = vm.cornerRadius,
- xAlign = vm.xAlign,
- yAlign = vm.yAlign,
- paddingAndSize = caretSize + caretPadding,
- radiusAndPadding = cornerRadius + caretPadding;
-
- if (xAlign === 'right') {
- pt.x -= size.width;
- } else if (xAlign === 'center') {
- pt.x -= (size.width / 2);
- }
-
- if (yAlign === 'top') {
- pt.y += paddingAndSize;
- } else if (yAlign === 'bottom') {
- pt.y -= size.height + paddingAndSize;
- } else {
- pt.y -= (size.height / 2);
- }
-
- if (yAlign === 'center') {
- if (xAlign === 'left') {
- pt.x += paddingAndSize;
- } else if (xAlign === 'right') {
- pt.x -= paddingAndSize;
- }
- } else {
- if (xAlign === 'left') {
- pt.x -= radiusAndPadding;
- } else if (xAlign === 'right') {
- pt.x += radiusAndPadding;
- }
- }
-
- return pt;
- },
- drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {
- var vm = this._view;
- var ctx = this._chart.ctx;
- var x1, x2, x3;
- var y1, y2, y3;
- var caretSize = vm.caretSize;
- var cornerRadius = vm.cornerRadius;
- var xAlign = vm.xAlign,
- yAlign = vm.yAlign;
- var ptX = tooltipPoint.x,
- ptY = tooltipPoint.y;
- var width = size.width,
- height = size.height;
-
- if (yAlign === 'center') {
- // Left or right side
- if (xAlign === 'left') {
- x1 = ptX;
- x2 = x1 - caretSize;
- x3 = x1;
- } else {
- x1 = ptX + width;
- x2 = x1 + caretSize;
- x3 = x1;
- }
-
- y2 = ptY + (height / 2);
- y1 = y2 - caretSize;
- y3 = y2 + caretSize;
- } else {
- if (xAlign === 'left') {
- x1 = ptX + cornerRadius;
- x2 = x1 + caretSize;
- x3 = x2 + caretSize;
- } else if (xAlign === 'right') {
- x1 = ptX + width - cornerRadius;
- x2 = x1 - caretSize;
- x3 = x2 - caretSize;
- } else {
- x2 = ptX + (width / 2);
- x1 = x2 - caretSize;
- x3 = x2 + caretSize;
- }
-
- if (yAlign === 'top') {
- y1 = ptY;
- y2 = y1 - caretSize;
- y3 = y1;
- } else {
- y1 = ptY + height;
- y2 = y1 + caretSize;
- y3 = y1;
- }
- }
-
- var bgColor = helpers.color(vm.backgroundColor);
- ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.lineTo(x3, y3);
- ctx.closePath();
- ctx.fill();
- },
- drawTitle: function drawTitle(pt, vm, ctx, opacity) {
- var title = vm.title;
-
- if (title.length) {
- ctx.textAlign = vm._titleAlign;
- ctx.textBaseline = "top";
-
- var titleFontSize = vm.titleFontSize,
- titleSpacing = vm.titleSpacing;
-
- var titleColor = helpers.color(vm.titleColor);
- ctx.fillStyle = titleColor.alpha(opacity * titleColor.alpha()).rgbString();
- ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
-
- var i, len;
- for (i = 0, len = title.length; i < len; ++i) {
- ctx.fillText(title[i], pt.x, pt.y);
- pt.y += titleFontSize + titleSpacing; // Line Height and spacing
-
- if (i + 1 === title.length) {
- pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
- }
- }
- }
- },
- drawBody: function drawBody(pt, vm, ctx, opacity) {
- var bodyFontSize = vm.bodyFontSize;
- var bodySpacing = vm.bodySpacing;
- var body = vm.body;
-
- ctx.textAlign = vm._bodyAlign;
- ctx.textBaseline = "top";
-
- var bodyColor = helpers.color(vm.bodyColor);
- var textColor = bodyColor.alpha(opacity * bodyColor.alpha()).rgbString();
- ctx.fillStyle = textColor;
- ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
-
- // Before Body
- var xLinePadding = 0;
- var fillLineOfText = function(line) {
- ctx.fillText(line, pt.x + xLinePadding, pt.y);
- pt.y += bodyFontSize + bodySpacing;
- };
-
- // Before body lines
- helpers.each(vm.beforeBody, fillLineOfText);
-
- var drawColorBoxes = body.length > 1;
- xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0;
-
- // Draw body lines now
- helpers.each(body, function(bodyItem, i) {
- helpers.each(bodyItem.before, fillLineOfText);
-
- helpers.each(bodyItem.lines, function(line) {
- // Draw Legend-like boxes if needed
- if (drawColorBoxes) {
- // Fill a white rect so that colours merge nicely if the opacity is < 1
- ctx.fillStyle = helpers.color(vm.legendColorBackground).alpha(opacity).rgbaString();
- ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
-
- // Border
- ctx.strokeStyle = helpers.color(vm.labelColors[i].borderColor).alpha(opacity).rgbaString();
- ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
-
- // Inner square
- ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(opacity).rgbaString();
- ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
-
- ctx.fillStyle = textColor;
- }
-
- fillLineOfText(line);
- });
-
- helpers.each(bodyItem.after, fillLineOfText);
- });
-
- // Reset back to 0 for after body
- xLinePadding = 0;
-
- // After body lines
- helpers.each(vm.afterBody, fillLineOfText);
- pt.y -= bodySpacing; // Remove last body spacing
- },
- drawFooter: function drawFooter(pt, vm, ctx, opacity) {
- var footer = vm.footer;
-
- if (footer.length) {
- pt.y += vm.footerMarginTop;
-
- ctx.textAlign = vm._footerAlign;
- ctx.textBaseline = "top";
-
- var footerColor = helpers.color(vm.footerColor);
- ctx.fillStyle = footerColor.alpha(opacity * footerColor.alpha()).rgbString();
- ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
-
- helpers.each(footer, function(line) {
- ctx.fillText(line, pt.x, pt.y);
- pt.y += vm.footerFontSize + vm.footerSpacing;
- });
- }
- },
- draw: function draw() {
- var ctx = this._chart.ctx;
- var vm = this._view;
-
- if (vm.opacity === 0) {
- return;
- }
-
- var tooltipSize = this.getTooltipSize(vm);
- var pt = {
- x: vm.x,
- y: vm.y
- };
-
- // IE11/Edge does not like very small opacities, so snap to 0
- var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
-
- if (this._options.enabled) {
- // Draw Background
- var bgColor = helpers.color(vm.backgroundColor);
- ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();
- helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);
- ctx.fill();
-
- // Draw Caret
- this.drawCaret(pt, tooltipSize, opacity, vm.caretPadding);
-
- // Draw Title, Body, and Footer
- pt.x += vm.xPadding;
- pt.y += vm.yPadding;
-
- // Titles
- this.drawTitle(pt, vm, ctx, opacity);
-
- // Body
- this.drawBody(pt, vm, ctx, opacity);
-
- // Footer
- this.drawFooter(pt, vm, ctx, opacity);
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.tooltips = {\r
+ enabled: true,\r
+ custom: null,\r
+ mode: 'single',\r
+ backgroundColor: "rgba(0,0,0,0.8)",\r
+ titleFontStyle: "bold",\r
+ titleSpacing: 2,\r
+ titleMarginBottom: 6,\r
+ titleColor: "#fff",\r
+ titleAlign: "left",\r
+ bodySpacing: 2,\r
+ bodyColor: "#fff",\r
+ bodyAlign: "left",\r
+ footerFontStyle: "bold",\r
+ footerSpacing: 2,\r
+ footerMarginTop: 6,\r
+ footerColor: "#fff",\r
+ footerAlign: "left",\r
+ yPadding: 6,\r
+ xPadding: 6,\r
+ yAlign : 'center',\r
+ xAlign : 'center',\r
+ caretSize: 5,\r
+ cornerRadius: 6,\r
+ multiKeyBackground: '#fff',\r
+ callbacks: {\r
+ // Args are: (tooltipItems, data)\r
+ beforeTitle: helpers.noop,\r
+ title: function(tooltipItems, data) {\r
+ // Pick first xLabel for now\r
+ var title = '';\r
+\r
+ if (tooltipItems.length > 0) {\r
+ if (tooltipItems[0].xLabel) {\r
+ title = tooltipItems[0].xLabel;\r
+ } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
+ title = data.labels[tooltipItems[0].index];\r
+ }\r
+ }\r
+\r
+ return title;\r
+ },\r
+ afterTitle: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ beforeBody: helpers.noop,\r
+\r
+ // Args are: (tooltipItem, data)\r
+ beforeLabel: helpers.noop,\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ return datasetLabel + ': ' + tooltipItem.yLabel;\r
+ },\r
+ afterLabel: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ afterBody: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ beforeFooter: helpers.noop,\r
+ footer: helpers.noop,\r
+ afterFooter: helpers.noop\r
+ }\r
+ };\r
+\r
+ // Helper to push or concat based on if the 2nd parameter is an array or not\r
+ function pushOrConcat(base, toPush) {\r
+ if (toPush) {\r
+ if (helpers.isArray(toPush)) {\r
+ base = base.concat(toPush);\r
+ } else {\r
+ base.push(toPush);\r
+ }\r
+ }\r
+\r
+ return base;\r
+ }\r
+\r
+ Chart.Tooltip = Chart.Element.extend({\r
+ initialize: function() {\r
+ var globalDefaults = Chart.defaults.global;\r
+ var options = this._options;\r
+ var tooltips = options.tooltips;\r
+\r
+ helpers.extend(this, {\r
+ _model: {\r
+ // Positioning\r
+ xPadding: tooltips.xPadding,\r
+ yPadding: tooltips.yPadding,\r
+ xAlign : tooltips.yAlign,\r
+ yAlign : tooltips.xAlign,\r
+\r
+ // Body\r
+ bodyColor: tooltips.bodyColor,\r
+ _bodyFontFamily: helpers.getValueOrDefault(tooltips.bodyFontFamily, globalDefaults.defaultFontFamily),\r
+ _bodyFontStyle: helpers.getValueOrDefault(tooltips.bodyFontStyle, globalDefaults.defaultFontStyle),\r
+ _bodyAlign: tooltips.bodyAlign,\r
+ bodyFontSize: helpers.getValueOrDefault(tooltips.bodyFontSize, globalDefaults.defaultFontSize),\r
+ bodySpacing: tooltips.bodySpacing,\r
+\r
+ // Title\r
+ titleColor: tooltips.titleColor,\r
+ _titleFontFamily: helpers.getValueOrDefault(tooltips.titleFontFamily, globalDefaults.defaultFontFamily),\r
+ _titleFontStyle: helpers.getValueOrDefault(tooltips.titleFontStyle, globalDefaults.defaultFontStyle),\r
+ titleFontSize: helpers.getValueOrDefault(tooltips.titleFontSize, globalDefaults.defaultFontSize),\r
+ _titleAlign: tooltips.titleAlign,\r
+ titleSpacing: tooltips.titleSpacing,\r
+ titleMarginBottom: tooltips.titleMarginBottom,\r
+\r
+ // Footer\r
+ footerColor: tooltips.footerColor,\r
+ _footerFontFamily: helpers.getValueOrDefault(tooltips.footerFontFamily, globalDefaults.defaultFontFamily),\r
+ _footerFontStyle: helpers.getValueOrDefault(tooltips.footerFontStyle, globalDefaults.defaultFontStyle),\r
+ footerFontSize: helpers.getValueOrDefault(tooltips.footerFontSize, globalDefaults.defaultFontSize),\r
+ _footerAlign: tooltips.footerAlign,\r
+ footerSpacing: tooltips.footerSpacing,\r
+ footerMarginTop: tooltips.footerMarginTop,\r
+\r
+ // Appearance\r
+ caretSize: tooltips.caretSize,\r
+ cornerRadius: tooltips.cornerRadius,\r
+ backgroundColor: tooltips.backgroundColor,\r
+ opacity: 0,\r
+ legendColorBackground: tooltips.multiKeyBackground\r
+ }\r
+ });\r
+ },\r
+\r
+ // Get the title\r
+ // Args are: (tooltipItem, data)\r
+ getTitle: function() {\r
+ var beforeTitle = this._options.tooltips.callbacks.beforeTitle.apply(this, arguments),\r
+ title = this._options.tooltips.callbacks.title.apply(this, arguments),\r
+ afterTitle = this._options.tooltips.callbacks.afterTitle.apply(this, arguments);\r
+\r
+ var lines = [];\r
+ lines = pushOrConcat(lines, beforeTitle);\r
+ lines = pushOrConcat(lines, title);\r
+ lines = pushOrConcat(lines, afterTitle);\r
+\r
+ return lines;\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getBeforeBody: function() {\r
+ var lines = this._options.tooltips.callbacks.beforeBody.apply(this, arguments);\r
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getBody: function(tooltipItems, data) {\r
+ var lines = [];\r
+\r
+ helpers.each(tooltipItems, function(bodyItem) {\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.beforeLabel.call(this, bodyItem, data), lines);\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.label.call(this, bodyItem, data), lines);\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.afterLabel.call(this, bodyItem, data), lines);\r
+ }, this);\r
+\r
+ return lines;\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getAfterBody: function() {\r
+ var lines = this._options.tooltips.callbacks.afterBody.apply(this, arguments);\r
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];\r
+ },\r
+\r
+ // Get the footer and beforeFooter and afterFooter lines\r
+ // Args are: (tooltipItem, data)\r
+ getFooter: function() {\r
+ var beforeFooter = this._options.tooltips.callbacks.beforeFooter.apply(this, arguments);\r
+ var footer = this._options.tooltips.callbacks.footer.apply(this, arguments);\r
+ var afterFooter = this._options.tooltips.callbacks.afterFooter.apply(this, arguments);\r
+\r
+ var lines = [];\r
+ lines = pushOrConcat(lines, beforeFooter);\r
+ lines = pushOrConcat(lines, footer);\r
+ lines = pushOrConcat(lines, afterFooter);\r
+\r
+ return lines;\r
+ },\r
+\r
+ getAveragePosition: function(elements) {\r
+\r
+ if (!elements.length) {\r
+ return false;\r
+ }\r
+\r
+ var xPositions = [];\r
+ var yPositions = [];\r
+\r
+ helpers.each(elements, function(el) {\r
+ if (el && el.hasValue()){\r
+ var pos = el.tooltipPosition();\r
+ xPositions.push(pos.x);\r
+ yPositions.push(pos.y);\r
+ }\r
+ });\r
+\r
+ var x = 0,\r
+ y = 0;\r
+ for (var i = 0; i < xPositions.length; i++) {\r
+ x += xPositions[i];\r
+ y += yPositions[i];\r
+ }\r
+\r
+ return {\r
+ x: Math.round(x / xPositions.length),\r
+ y: Math.round(y / xPositions.length)\r
+ };\r
+\r
+ },\r
+\r
+ update: function(changed) {\r
+ if (this._active.length) {\r
+ this._model.opacity = 1;\r
+\r
+ var element = this._active[0],\r
+ labelColors = [],\r
+ tooltipPosition;\r
+\r
+ var tooltipItems = [];\r
+\r
+ if (this._options.tooltips.mode === 'single') {\r
+ var yScale = element._yScale || element._scale; // handle radar || polarArea charts\r
+ tooltipItems.push({\r
+ xLabel: element._xScale ? element._xScale.getLabelForIndex(element._index, element._datasetIndex) : '',\r
+ yLabel: yScale ? yScale.getLabelForIndex(element._index, element._datasetIndex) : '',\r
+ index: element._index,\r
+ datasetIndex: element._datasetIndex\r
+ });\r
+ tooltipPosition = this.getAveragePosition(this._active);\r
+ } else {\r
+ helpers.each(this._data.datasets, function(dataset, datasetIndex) {\r
+ if (!this._chartInstance.isDatasetVisible(datasetIndex)) {\r
+ return;\r
+ }\r
+\r
+ var meta = this._chartInstance.getDatasetMeta(datasetIndex);\r
+ var currentElement = meta.data[element._index];\r
+ if (currentElement) {\r
+ var yScale = element._yScale || element._scale; // handle radar || polarArea charts\r
+\r
+ tooltipItems.push({\r
+ xLabel: currentElement._xScale ? currentElement._xScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',\r
+ yLabel: yScale ? yScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',\r
+ index: element._index,\r
+ datasetIndex: datasetIndex\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ helpers.each(this._active, function(active) {\r
+ if (active) {\r
+ labelColors.push({\r
+ borderColor: active._view.borderColor,\r
+ backgroundColor: active._view.backgroundColor\r
+ });\r
+ }\r
+ }, null);\r
+\r
+ tooltipPosition = this.getAveragePosition(this._active);\r
+ }\r
+\r
+ // Build the Text Lines\r
+ helpers.extend(this._model, {\r
+ title: this.getTitle(tooltipItems, this._data),\r
+ beforeBody: this.getBeforeBody(tooltipItems, this._data),\r
+ body: this.getBody(tooltipItems, this._data),\r
+ afterBody: this.getAfterBody(tooltipItems, this._data),\r
+ footer: this.getFooter(tooltipItems, this._data)\r
+ });\r
+\r
+ helpers.extend(this._model, {\r
+ x: Math.round(tooltipPosition.x),\r
+ y: Math.round(tooltipPosition.y),\r
+ caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),\r
+ labelColors: labelColors\r
+ });\r
+\r
+ // We need to determine alignment of\r
+ var tooltipSize = this.getTooltipSize(this._model);\r
+ this.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas\r
+\r
+ helpers.extend(this._model, this.getBackgroundPoint(this._model, tooltipSize));\r
+ } else {\r
+ this._model.opacity = 0;\r
+ }\r
+\r
+ if (changed && this._options.tooltips.custom) {\r
+ this._options.tooltips.custom.call(this, this._model);\r
+ }\r
+\r
+ return this;\r
+ },\r
+ getTooltipSize: function getTooltipSize(vm) {\r
+ var ctx = this._chart.ctx;\r
+\r
+ var size = {\r
+ height: vm.yPadding * 2, // Tooltip Padding\r
+ width: 0\r
+ };\r
+ var combinedBodyLength = vm.body.length + vm.beforeBody.length + vm.afterBody.length;\r
+\r
+ size.height += vm.title.length * vm.titleFontSize; // Title Lines\r
+ size.height += (vm.title.length - 1) * vm.titleSpacing; // Title Line Spacing\r
+ size.height += vm.title.length ? vm.titleMarginBottom : 0; // Title's bottom Margin\r
+ size.height += combinedBodyLength * vm.bodyFontSize; // Body Lines\r
+ size.height += combinedBodyLength ? (combinedBodyLength - 1) * vm.bodySpacing : 0; // Body Line Spacing\r
+ size.height += vm.footer.length ? vm.footerMarginTop : 0; // Footer Margin\r
+ size.height += vm.footer.length * (vm.footerFontSize); // Footer Lines\r
+ size.height += vm.footer.length ? (vm.footer.length - 1) * vm.footerSpacing : 0; // Footer Line Spacing\r
+\r
+ // Width\r
+ ctx.font = helpers.fontString(vm.titleFontSize, vm._titleFontStyle, vm._titleFontFamily);\r
+ helpers.each(vm.title, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+\r
+ ctx.font = helpers.fontString(vm.bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);\r
+ helpers.each(vm.beforeBody.concat(vm.afterBody), function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+ helpers.each(vm.body, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width + (this._options.tooltips.mode !== 'single' ? (vm.bodyFontSize + 2) : 0));\r
+ }, this);\r
+\r
+ ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);\r
+ helpers.each(vm.footer, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+ size.width += 2 * vm.xPadding;\r
+\r
+ return size;\r
+ },\r
+ determineAlignment: function determineAlignment(size) {\r
+ if (this._model.y < size.height) {\r
+ this._model.yAlign = 'top';\r
+ } else if (this._model.y > (this._chart.height - size.height)) {\r
+ this._model.yAlign = 'bottom';\r
+ }\r
+\r
+ var lf, rf; // functions to determine left, right alignment\r
+ var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart\r
+ var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges\r
+ var _this = this;\r
+ var midX = (this._chartInstance.chartArea.left + this._chartInstance.chartArea.right) / 2;\r
+ var midY = (this._chartInstance.chartArea.top + this._chartInstance.chartArea.bottom) / 2;\r
+\r
+ if (this._model.yAlign === 'center') {\r
+ lf = function(x) {\r
+ return x <= midX;\r
+ };\r
+ rf = function(x) {\r
+ return x > midX;\r
+ };\r
+ } else {\r
+ lf = function(x) {\r
+ return x <= (size.width / 2);\r
+ };\r
+ rf = function(x) {\r
+ return x >= (_this._chart.width - (size.width / 2));\r
+ };\r
+ }\r
+\r
+ olf = function(x) {\r
+ return x + size.width > _this._chart.width;\r
+ };\r
+ orf = function(x) {\r
+ return x - size.width < 0;\r
+ };\r
+ yf = function(y) {\r
+ return y <= midY ? 'top' : 'bottom';\r
+ };\r
+\r
+ if (lf(this._model.x)) {\r
+ this._model.xAlign = 'left';\r
+\r
+ // Is tooltip too wide and goes over the right side of the chart.?\r
+ if (olf(this._model.x)) {\r
+ this._model.xAlign = 'center';\r
+ this._model.yAlign = yf(this._model.y);\r
+ }\r
+ } else if (rf(this._model.x)) {\r
+ this._model.xAlign = 'right';\r
+\r
+ // Is tooltip too wide and goes outside left edge of canvas?\r
+ if (orf(this._model.x)) {\r
+ this._model.xAlign = 'center';\r
+ this._model.yAlign = yf(this._model.y);\r
+ }\r
+ }\r
+ },\r
+ getBackgroundPoint: function getBackgroundPoint(vm, size) {\r
+ // Background Position\r
+ var pt = {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+\r
+ if (vm.xAlign === 'right') {\r
+ pt.x -= size.width;\r
+ } else if (vm.xAlign === 'center') {\r
+ pt.x -= (size.width / 2);\r
+ }\r
+\r
+ if (vm.yAlign === 'top') {\r
+ pt.y += vm.caretPadding + vm.caretSize;\r
+ } else if (vm.yAlign === 'bottom') {\r
+ pt.y -= size.height + vm.caretPadding + vm.caretSize;\r
+ } else {\r
+ pt.y -= (size.height / 2);\r
+ }\r
+\r
+ if (vm.yAlign === 'center') {\r
+ if (vm.xAlign === 'left') {\r
+ pt.x += vm.caretPadding + vm.caretSize;\r
+ } else if (vm.xAlign === 'right') {\r
+ pt.x -= vm.caretPadding + vm.caretSize;\r
+ }\r
+ } else {\r
+ if (vm.xAlign === 'left') {\r
+ pt.x -= vm.cornerRadius + vm.caretPadding;\r
+ } else if (vm.xAlign === 'right') {\r
+ pt.x += vm.cornerRadius + vm.caretPadding;\r
+ }\r
+ }\r
+\r
+ return pt;\r
+ },\r
+ drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var x1, x2, x3;\r
+ var y1, y2, y3;\r
+\r
+ if (vm.yAlign === 'center') {\r
+ // Left or right side\r
+ if (vm.xAlign === 'left') {\r
+ x1 = tooltipPoint.x;\r
+ x2 = x1 - vm.caretSize;\r
+ x3 = x1;\r
+ } else {\r
+ x1 = tooltipPoint.x + size.width;\r
+ x2 = x1 + vm.caretSize;\r
+ x3 = x1;\r
+ }\r
+\r
+ y2 = tooltipPoint.y + (size.height / 2);\r
+ y1 = y2 - vm.caretSize;\r
+ y3 = y2 + vm.caretSize;\r
+ } else {\r
+ if (vm.xAlign === 'left') {\r
+ x1 = tooltipPoint.x + vm.cornerRadius;\r
+ x2 = x1 + vm.caretSize;\r
+ x3 = x2 + vm.caretSize;\r
+ } else if (vm.xAlign === 'right') {\r
+ x1 = tooltipPoint.x + size.width - vm.cornerRadius;\r
+ x2 = x1 - vm.caretSize;\r
+ x3 = x2 - vm.caretSize;\r
+ } else {\r
+ x2 = tooltipPoint.x + (size.width / 2);\r
+ x1 = x2 - vm.caretSize;\r
+ x3 = x2 + vm.caretSize;\r
+ }\r
+\r
+ if (vm.yAlign === 'top') {\r
+ y1 = tooltipPoint.y;\r
+ y2 = y1 - vm.caretSize;\r
+ y3 = y1;\r
+ } else {\r
+ y1 = tooltipPoint.y + size.height;\r
+ y2 = y1 + vm.caretSize;\r
+ y3 = y1;\r
+ }\r
+ }\r
+\r
+ var bgColor = helpers.color(vm.backgroundColor);\r
+ ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();\r
+ ctx.beginPath();\r
+ ctx.moveTo(x1, y1);\r
+ ctx.lineTo(x2, y2);\r
+ ctx.lineTo(x3, y3);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ },\r
+ drawTitle: function drawTitle(pt, vm, ctx, opacity) {\r
+ if (vm.title.length) {\r
+ ctx.textAlign = vm._titleAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var titleColor = helpers.color(vm.titleColor);\r
+ ctx.fillStyle = titleColor.alpha(opacity * titleColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.titleFontSize, vm._titleFontStyle, vm._titleFontFamily);\r
+\r
+ helpers.each(vm.title, function(title, i) {\r
+ ctx.fillText(title, pt.x, pt.y);\r
+ pt.y += vm.titleFontSize + vm.titleSpacing; // Line Height and spacing\r
+\r
+ if (i + 1 === vm.title.length) {\r
+ pt.y += vm.titleMarginBottom - vm.titleSpacing; // If Last, add margin, remove spacing\r
+ }\r
+ });\r
+ }\r
+ },\r
+ drawBody: function drawBody(pt, vm, ctx, opacity) {\r
+ ctx.textAlign = vm._bodyAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var bodyColor = helpers.color(vm.bodyColor);\r
+ ctx.fillStyle = bodyColor.alpha(opacity * bodyColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);\r
+\r
+ // Before Body\r
+ helpers.each(vm.beforeBody, function(beforeBody) {\r
+ ctx.fillText(beforeBody, pt.x, pt.y);\r
+ pt.y += vm.bodyFontSize + vm.bodySpacing;\r
+ });\r
+\r
+ helpers.each(vm.body, function(body, i) {\r
+ // Draw Legend-like boxes if needed\r
+ if (this._options.tooltips.mode !== 'single') {\r
+ // Fill a white rect so that colours merge nicely if the opacity is < 1\r
+ ctx.fillStyle = helpers.color(vm.legendColorBackground).alpha(opacity).rgbaString();\r
+ ctx.fillRect(pt.x, pt.y, vm.bodyFontSize, vm.bodyFontSize);\r
+\r
+ // Border\r
+ ctx.strokeStyle = helpers.color(vm.labelColors[i].borderColor).alpha(opacity).rgbaString();\r
+ ctx.strokeRect(pt.x, pt.y, vm.bodyFontSize, vm.bodyFontSize);\r
+\r
+ // Inner square\r
+ ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(opacity).rgbaString();\r
+ ctx.fillRect(pt.x + 1, pt.y + 1, vm.bodyFontSize - 2, vm.bodyFontSize - 2);\r
+\r
+ ctx.fillStyle = helpers.color(vm.bodyColor).alpha(opacity).rgbaString(); // Return fill style for text\r
+ }\r
+\r
+ // Body Line\r
+ ctx.fillText(body, pt.x + (this._options.tooltips.mode !== 'single' ? (vm.bodyFontSize + 2) : 0), pt.y);\r
+\r
+ pt.y += vm.bodyFontSize + vm.bodySpacing;\r
+ }, this);\r
+\r
+ // After Body\r
+ helpers.each(vm.afterBody, function(afterBody) {\r
+ ctx.fillText(afterBody, pt.x, pt.y);\r
+ pt.y += vm.bodyFontSize;\r
+ });\r
+\r
+ pt.y -= vm.bodySpacing; // Remove last body spacing\r
+ },\r
+ drawFooter: function drawFooter(pt, vm, ctx, opacity) {\r
+ if (vm.footer.length) {\r
+ pt.y += vm.footerMarginTop;\r
+\r
+ ctx.textAlign = vm._footerAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var footerColor = helpers.color(vm.footerColor);\r
+ ctx.fillStyle = footerColor.alpha(opacity * footerColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);\r
+\r
+ helpers.each(vm.footer, function(footer) {\r
+ ctx.fillText(footer, pt.x, pt.y);\r
+ pt.y += vm.footerFontSize + vm.footerSpacing;\r
+ });\r
+ }\r
+ },\r
+ draw: function draw() {\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ if (vm.opacity === 0) {\r
+ return;\r
+ }\r
+\r
+ var caretPadding = vm.caretPadding;\r
+ var tooltipSize = this.getTooltipSize(vm);\r
+ var pt = {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+\r
+ // IE11/Edge does not like very small opacities, so snap to 0\r
+ var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;\r
+\r
+ if (this._options.tooltips.enabled) {\r
+ // Draw Background\r
+ var bgColor = helpers.color(vm.backgroundColor);\r
+ ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();\r
+ helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);\r
+ ctx.fill();\r
+\r
+ // Draw Caret\r
+ this.drawCaret(pt, tooltipSize, opacity, caretPadding);\r
+\r
+ // Draw Title, Body, and Footer\r
+ pt.x += vm.xPadding;\r
+ pt.y += vm.yPadding;\r
+\r
+ // Titles\r
+ this.drawTitle(pt, vm, ctx, opacity);\r
+\r
+ // Body\r
+ this.drawBody(pt, vm, ctx, opacity);\r
+\r
+ // Footer\r
+ this.drawFooter(pt, vm, ctx, opacity);\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],34:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart, moment) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global;
-
- globalOpts.elements.arc = {
- backgroundColor: globalOpts.defaultColor,
- borderColor: "#fff",
- borderWidth: 2
- };
-
- Chart.elements.Arc = Chart.Element.extend({
- inLabelRange: function(mouseX) {
- var vm = this._view;
-
- if (vm) {
- return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
- } else {
- return false;
- }
- },
- inRange: function(chartX, chartY) {
- var vm = this._view;
-
- if (vm) {
- var pointRelativePosition = helpers.getAngleFromPoint(vm, {
- x: chartX,
- y: chartY
- }),
- angle = pointRelativePosition.angle,
- distance = pointRelativePosition.distance;
-
- //Sanitise angle range
- var startAngle = vm.startAngle;
- var endAngle = vm.endAngle;
- while (endAngle < startAngle) {
- endAngle += 2.0 * Math.PI;
- }
- while (angle > endAngle) {
- angle -= 2.0 * Math.PI;
- }
- while (angle < startAngle) {
- angle += 2.0 * Math.PI;
- }
-
- //Check if within the range of the open/close angle
- var betweenAngles = (angle >= startAngle && angle <= endAngle),
- withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
-
- return (betweenAngles && withinRadius);
- } else {
- return false;
- }
- },
- tooltipPosition: function() {
- var vm = this._view;
-
- var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2),
- rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
- return {
- x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
- y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
- };
- },
- draw: function() {
-
- var ctx = this._chart.ctx,
- vm = this._view,
- sA = vm.startAngle,
- eA = vm.endAngle;
-
- ctx.beginPath();
-
- ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
- ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
-
- ctx.closePath();
- ctx.strokeStyle = vm.borderColor;
- ctx.lineWidth = vm.borderWidth;
-
- ctx.fillStyle = vm.backgroundColor;
-
- ctx.fill();
- ctx.lineJoin = 'bevel';
-
- if (vm.borderWidth) {
- ctx.stroke();
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart, moment) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global;\r
+\r
+ globalOpts.elements.arc = {\r
+ backgroundColor: globalOpts.defaultColor,\r
+ borderColor: "#fff",\r
+ borderWidth: 2\r
+ };\r
+\r
+ Chart.elements.Arc = Chart.Element.extend({\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+\r
+ if (vm) {\r
+ return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));\r
+ } else {\r
+ return false;\r
+ }\r
+ },\r
+ inRange: function(chartX, chartY) {\r
+ var vm = this._view;\r
+\r
+ if (vm) {\r
+ var pointRelativePosition = helpers.getAngleFromPoint(vm, {\r
+ x: chartX,\r
+ y: chartY\r
+ }),\r
+ angle = pointRelativePosition.angle,\r
+ distance = pointRelativePosition.distance;\r
+\r
+ //Sanitise angle range\r
+ var startAngle = vm.startAngle;\r
+ var endAngle = vm.endAngle;\r
+ while (endAngle < startAngle) {\r
+ endAngle += 2.0 * Math.PI;\r
+ }\r
+ while (angle > endAngle) {\r
+ angle -= 2.0 * Math.PI;\r
+ }\r
+ while (angle < startAngle) {\r
+ angle += 2.0 * Math.PI;\r
+ }\r
+\r
+ //Check if within the range of the open/close angle\r
+ var betweenAngles = (angle >= startAngle && angle <= endAngle),\r
+ withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);\r
+\r
+ return (betweenAngles && withinRadius);\r
+ } else {\r
+ return false;\r
+ }\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+\r
+ var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2),\r
+ rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;\r
+ return {\r
+ x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),\r
+ y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)\r
+ };\r
+ },\r
+ draw: function() {\r
+\r
+ var ctx = this._chart.ctx,\r
+ vm = this._view,\r
+ sA = vm.startAngle,\r
+ eA = vm.endAngle;\r
+\r
+ ctx.beginPath();\r
+\r
+ ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);\r
+ ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);\r
+\r
+ ctx.closePath();\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ ctx.fillStyle = vm.backgroundColor;\r
+\r
+ ctx.fill();\r
+ ctx.lineJoin = 'bevel';\r
+\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],35:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var globalDefaults = Chart.defaults.global;
-
- Chart.defaults.global.elements.line = {
- tension: 0.4,
- backgroundColor: globalDefaults.defaultColor,
- borderWidth: 3,
- borderColor: globalDefaults.defaultColor,
- borderCapStyle: 'butt',
- borderDash: [],
- borderDashOffset: 0.0,
- borderJoinStyle: 'miter',
- fill: true // do we fill in the area between the line and its base axis
- };
-
- Chart.elements.Line = Chart.Element.extend({
- lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
- var me = this;
- var ctx = me._chart.ctx;
- var spanGaps = me._view ? me._view.spanGaps : false;
-
- if (point._view.skip && !spanGaps) {
- skipHandler.call(me, previousPoint, point, nextPoint);
- } else if (previousPoint._view.skip && !spanGaps) {
- previousSkipHandler.call(me, previousPoint, point, nextPoint);
- } else if (point._view.tension === 0) {
- ctx.lineTo(point._view.x, point._view.y);
- } else {
- // Line between points
- ctx.bezierCurveTo(
- previousPoint._view.controlPointNextX,
- previousPoint._view.controlPointNextY,
- point._view.controlPointPreviousX,
- point._view.controlPointPreviousY,
- point._view.x,
- point._view.y
- );
- }
- },
-
- draw: function() {
- var me = this;
-
- var vm = me._view;
- var ctx = me._chart.ctx;
- var first = me._children[0];
- var last = me._children[me._children.length - 1];
-
- function loopBackToStart(drawLineToCenter) {
- if (!first._view.skip && !last._view.skip) {
- // Draw a bezier line from last to first
- ctx.bezierCurveTo(
- last._view.controlPointNextX,
- last._view.controlPointNextY,
- first._view.controlPointPreviousX,
- first._view.controlPointPreviousY,
- first._view.x,
- first._view.y
- );
- } else if (drawLineToCenter) {
- // Go to center
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
- }
- }
-
- ctx.save();
-
- // If we had points and want to fill this line, do so.
- if (me._children.length > 0 && vm.fill) {
- // Draw the background first (so the border is always on top)
- ctx.beginPath();
-
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
-
- // First point moves to it's starting position no matter what
- if (index === 0) {
- if (me._loop) {
- ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
- } else {
- ctx.moveTo(point._view.x, vm.scaleZero);
- }
-
- if (point._view.skip) {
- if (!me._loop) {
- ctx.moveTo(next._view.x, me._view.scaleZero);
- }
- } else {
- ctx.lineTo(point._view.x, point._view.y);
- }
- } else {
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
- if (me._loop) {
- // Go to center
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
- } else {
- ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
- ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
- }
- }, function(previousPoint, point) {
- // If we skipped the last point, draw a line to ourselves so that the fill is nice
- ctx.lineTo(point._view.x, point._view.y);
- });
- }
- }, me);
-
- // For radial scales, loop back around to the first point
- if (me._loop) {
- loopBackToStart(true);
- } else {
- //Round off the line by going to the base of the chart, back to the start, then fill.
- ctx.lineTo(me._children[me._children.length - 1]._view.x, vm.scaleZero);
- ctx.lineTo(me._children[0]._view.x, vm.scaleZero);
- }
-
- ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
- ctx.closePath();
- ctx.fill();
- }
-
- var globalOptionLineElements = globalDefaults.elements.line;
- // Now draw the line between all the points with any borders
- ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
-
- // IE 9 and 10 do not support line dash
- if (ctx.setLineDash) {
- ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
- }
-
- ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
- ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
- ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
- ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
- ctx.beginPath();
-
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
-
- if (index === 0) {
- ctx.moveTo(point._view.x, point._view.y);
- } else {
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
- ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
- }, function(previousPoint, point) {
- // If we skipped the last point, move up to our point preventing a line from being drawn
- ctx.moveTo(point._view.x, point._view.y);
- });
- }
- }, me);
-
- if (me._loop && me._children.length > 0) {
- loopBackToStart();
- }
-
- ctx.stroke();
- ctx.restore();
- }
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var globalDefaults = Chart.defaults.global;\r
+\r
+ Chart.defaults.global.elements.line = {\r
+ tension: 0.4,\r
+ backgroundColor: globalDefaults.defaultColor,\r
+ borderWidth: 3,\r
+ borderColor: globalDefaults.defaultColor,\r
+ borderCapStyle: 'butt',\r
+ borderDash: [],\r
+ borderDashOffset: 0.0,\r
+ borderJoinStyle: 'miter',\r
+ fill: true // do we fill in the area between the line and its base axis\r
+ };\r
+\r
+ Chart.elements.Line = Chart.Element.extend({\r
+ lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {\r
+ var ctx = this._chart.ctx;\r
+\r
+ if (point._view.skip) {\r
+ skipHandler.call(this, previousPoint, point, nextPoint);\r
+ } else if (previousPoint._view.skip) {\r
+ previousSkipHandler.call(this, previousPoint, point, nextPoint);\r
+ } else if (point._view.tension === 0) {\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ } else {\r
+ // Line between points\r
+ ctx.bezierCurveTo(\r
+ previousPoint._view.controlPointNextX,\r
+ previousPoint._view.controlPointNextY,\r
+ point._view.controlPointPreviousX,\r
+ point._view.controlPointPreviousY,\r
+ point._view.x,\r
+ point._view.y\r
+ );\r
+ }\r
+ },\r
+\r
+ draw: function() {\r
+ var _this = this;\r
+\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var first = this._children[0];\r
+ var last = this._children[this._children.length - 1];\r
+\r
+ function loopBackToStart(drawLineToCenter) {\r
+ if (!first._view.skip && !last._view.skip) {\r
+ // Draw a bezier line from last to first\r
+ ctx.bezierCurveTo(\r
+ last._view.controlPointNextX,\r
+ last._view.controlPointNextY,\r
+ first._view.controlPointPreviousX,\r
+ first._view.controlPointPreviousY,\r
+ first._view.x,\r
+ first._view.y\r
+ );\r
+ } else if (drawLineToCenter) {\r
+ // Go to center\r
+ ctx.lineTo(_this._view.scaleZero.x, _this._view.scaleZero.y);\r
+ }\r
+ }\r
+\r
+ ctx.save();\r
+\r
+ // If we had points and want to fill this line, do so.\r
+ if (this._children.length > 0 && vm.fill) {\r
+ // Draw the background first (so the border is always on top)\r
+ ctx.beginPath();\r
+\r
+ helpers.each(this._children, function(point, index) {\r
+ var previous = helpers.previousItem(this._children, index);\r
+ var next = helpers.nextItem(this._children, index);\r
+\r
+ // First point moves to it's starting position no matter what\r
+ if (index === 0) {\r
+ if (this._loop) {\r
+ ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);\r
+ } else {\r
+ ctx.moveTo(point._view.x, vm.scaleZero);\r
+ }\r
+\r
+ if (point._view.skip) {\r
+ if (!this._loop) {\r
+ ctx.moveTo(next._view.x, this._view.scaleZero);\r
+ }\r
+ } else {\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ }\r
+ } else {\r
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {\r
+ if (this._loop) {\r
+ // Go to center\r
+ ctx.lineTo(this._view.scaleZero.x, this._view.scaleZero.y);\r
+ } else {\r
+ ctx.lineTo(previousPoint._view.x, this._view.scaleZero);\r
+ ctx.moveTo(nextPoint._view.x, this._view.scaleZero);\r
+ }\r
+ }, function(previousPoint, point) {\r
+ // If we skipped the last point, draw a line to ourselves so that the fill is nice\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ // For radial scales, loop back around to the first point\r
+ if (this._loop) {\r
+ loopBackToStart(true);\r
+ } else {\r
+ //Round off the line by going to the base of the chart, back to the start, then fill.\r
+ ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);\r
+ ctx.lineTo(this._children[0]._view.x, vm.scaleZero);\r
+ }\r
+\r
+ ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ }\r
+\r
+ var globalOptionLineElements = globalDefaults.elements.line;\r
+ // Now draw the line between all the points with any borders\r
+ ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;\r
+\r
+ // IE 9 and 10 do not support line dash\r
+ if (ctx.setLineDash) {\r
+ ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);\r
+ }\r
+\r
+ ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;\r
+ ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;\r
+ ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;\r
+ ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;\r
+ ctx.beginPath();\r
+\r
+ helpers.each(this._children, function(point, index) {\r
+ var previous = helpers.previousItem(this._children, index);\r
+ var next = helpers.nextItem(this._children, index);\r
+\r
+ if (index === 0) {\r
+ ctx.moveTo(point._view.x, point._view.y);\r
+ } else {\r
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {\r
+ ctx.moveTo(nextPoint._view.x, nextPoint._view.y);\r
+ }, function(previousPoint, point) {\r
+ // If we skipped the last point, move up to our point preventing a line from being drawn\r
+ ctx.moveTo(point._view.x, point._view.y);\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ if (this._loop && this._children.length > 0) {\r
+ loopBackToStart();\r
+ }\r
+\r
+ ctx.stroke();\r
+ ctx.restore();\r
+ }\r
+ });\r
};
},{}],36:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global,
- defaultColor = globalOpts.defaultColor;
-
- globalOpts.elements.point = {
- radius: 3,
- pointStyle: 'circle',
- backgroundColor: defaultColor,
- borderWidth: 1,
- borderColor: defaultColor,
- // Hover
- hitRadius: 1,
- hoverRadius: 4,
- hoverBorderWidth: 1
- };
-
- Chart.elements.Point = Chart.Element.extend({
- inRange: function(mouseX, mouseY) {
- var vm = this._view;
- return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
- },
- inLabelRange: function(mouseX) {
- var vm = this._view;
- return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;
- },
- tooltipPosition: function() {
- var vm = this._view;
- return {
- x: vm.x,
- y: vm.y,
- padding: vm.radius + vm.borderWidth
- };
- },
- draw: function() {
- var vm = this._view;
- var ctx = this._chart.ctx;
- var pointStyle = vm.pointStyle;
- var radius = vm.radius;
- var x = vm.x;
- var y = vm.y;
- var type, edgeLength, xOffset, yOffset, height, size;
-
- if (vm.skip) {
- return;
- }
-
- if (typeof pointStyle === 'object') {
- type = pointStyle.toString();
- if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
- ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);
- return;
- }
- }
-
- if (isNaN(radius) || radius <= 0) {
- return;
- }
-
- ctx.strokeStyle = vm.borderColor || defaultColor;
- ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);
- ctx.fillStyle = vm.backgroundColor || defaultColor;
-
- switch (pointStyle) {
- // Default includes circle
- default:
- ctx.beginPath();
- ctx.arc(x, y, radius, 0, Math.PI * 2);
- ctx.closePath();
- ctx.fill();
- break;
- case 'triangle':
- ctx.beginPath();
- edgeLength = 3 * radius / Math.sqrt(3);
- height = edgeLength * Math.sqrt(3) / 2;
- ctx.moveTo(x - edgeLength / 2, y + height / 3);
- ctx.lineTo(x + edgeLength / 2, y + height / 3);
- ctx.lineTo(x, y - 2 * height / 3);
- ctx.closePath();
- ctx.fill();
- break;
- case 'rect':
- size = 1 / Math.SQRT2 * radius;
- ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
- ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
- break;
- case 'rectRot':
- size = 1 / Math.SQRT2 * radius;
- ctx.beginPath();
- ctx.moveTo(x - size, y);
- ctx.lineTo(x, y + size);
- ctx.lineTo(x + size, y);
- ctx.lineTo(x, y - size);
- ctx.closePath();
- ctx.fill();
- break;
- case 'cross':
- ctx.beginPath();
- ctx.moveTo(x, y + radius);
- ctx.lineTo(x, y - radius);
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- case 'crossRot':
- ctx.beginPath();
- xOffset = Math.cos(Math.PI / 4) * radius;
- yOffset = Math.sin(Math.PI / 4) * radius;
- ctx.moveTo(x - xOffset, y - yOffset);
- ctx.lineTo(x + xOffset, y + yOffset);
- ctx.moveTo(x - xOffset, y + yOffset);
- ctx.lineTo(x + xOffset, y - yOffset);
- ctx.closePath();
- break;
- case 'star':
- ctx.beginPath();
- ctx.moveTo(x, y + radius);
- ctx.lineTo(x, y - radius);
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- xOffset = Math.cos(Math.PI / 4) * radius;
- yOffset = Math.sin(Math.PI / 4) * radius;
- ctx.moveTo(x - xOffset, y - yOffset);
- ctx.lineTo(x + xOffset, y + yOffset);
- ctx.moveTo(x - xOffset, y + yOffset);
- ctx.lineTo(x + xOffset, y - yOffset);
- ctx.closePath();
- break;
- case 'line':
- ctx.beginPath();
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- case 'dash':
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- }
-
- ctx.stroke();
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global,\r
+ defaultColor = globalOpts.defaultColor;\r
+\r
+ globalOpts.elements.point = {\r
+ radius: 3,\r
+ pointStyle: 'circle',\r
+ backgroundColor: defaultColor,\r
+ borderWidth: 1,\r
+ borderColor: defaultColor,\r
+ // Hover\r
+ hitRadius: 1,\r
+ hoverRadius: 4,\r
+ hoverBorderWidth: 1\r
+ };\r
+\r
+ Chart.elements.Point = Chart.Element.extend({\r
+ inRange: function(mouseX, mouseY) {\r
+ var vm = this._view;\r
+ return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;\r
+ },\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+ return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+ return {\r
+ x: vm.x,\r
+ y: vm.y,\r
+ padding: vm.radius + vm.borderWidth\r
+ };\r
+ },\r
+ draw: function() {\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var pointStyle = vm.pointStyle;\r
+ var radius = vm.radius;\r
+ var x = vm.x;\r
+ var y = vm.y;\r
+ var type, edgeLength, xOffset, yOffset, height, size;\r
+\r
+ if (vm.skip) {\r
+ return;\r
+ }\r
+\r
+ if (typeof pointStyle === 'object') {\r
+ type = pointStyle.toString();\r
+ if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\r
+ ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (isNaN(radius) || radius <= 0) {\r
+ return;\r
+ }\r
+\r
+ ctx.strokeStyle = vm.borderColor || defaultColor;\r
+ ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);\r
+ ctx.fillStyle = vm.backgroundColor || defaultColor;\r
+\r
+ switch (pointStyle) {\r
+ // Default includes circle\r
+ default:\r
+ ctx.beginPath();\r
+ ctx.arc(x, y, radius, 0, Math.PI * 2);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ break;\r
+ case 'triangle':\r
+ ctx.beginPath();\r
+ edgeLength = 3 * radius / Math.sqrt(3);\r
+ height = edgeLength * Math.sqrt(3) / 2;\r
+ ctx.moveTo(x - edgeLength / 2, y + height / 3);\r
+ ctx.lineTo(x + edgeLength / 2, y + height / 3);\r
+ ctx.lineTo(x, y - 2 * height / 3);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ break;\r
+ case 'rect':\r
+ size = 1 / Math.SQRT2 * radius;\r
+ ctx.fillRect(x - size, y - size, 2 * size, 2 * size);\r
+ ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);\r
+ break;\r
+ case 'rectRot':\r
+ ctx.translate(x, y);\r
+ ctx.rotate(Math.PI / 4);\r
+ size = 1 / Math.SQRT2 * radius;\r
+ ctx.fillRect(-size, -size, 2 * size, 2 * size);\r
+ ctx.strokeRect(-size, -size, 2 * size, 2 * size);\r
+ ctx.setTransform(1, 0, 0, 1, 0, 0);\r
+ break;\r
+ case 'cross':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y + radius);\r
+ ctx.lineTo(x, y - radius);\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ case 'crossRot':\r
+ ctx.beginPath();\r
+ xOffset = Math.cos(Math.PI / 4) * radius;\r
+ yOffset = Math.sin(Math.PI / 4) * radius;\r
+ ctx.moveTo(x - xOffset, y - yOffset);\r
+ ctx.lineTo(x + xOffset, y + yOffset);\r
+ ctx.moveTo(x - xOffset, y + yOffset);\r
+ ctx.lineTo(x + xOffset, y - yOffset);\r
+ ctx.closePath();\r
+ break;\r
+ case 'star':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y + radius);\r
+ ctx.lineTo(x, y - radius);\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ xOffset = Math.cos(Math.PI / 4) * radius;\r
+ yOffset = Math.sin(Math.PI / 4) * radius;\r
+ ctx.moveTo(x - xOffset, y - yOffset);\r
+ ctx.lineTo(x + xOffset, y + yOffset);\r
+ ctx.moveTo(x - xOffset, y + yOffset);\r
+ ctx.lineTo(x + xOffset, y - yOffset);\r
+ ctx.closePath();\r
+ break;\r
+ case 'line':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ case 'dash':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ }\r
+\r
+ ctx.stroke();\r
+ }\r
+ });\r
+};\r
},{}],37:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global;
-
- globalOpts.elements.rectangle = {
- backgroundColor: globalOpts.defaultColor,
- borderWidth: 0,
- borderColor: globalOpts.defaultColor,
- borderSkipped: 'bottom'
- };
-
- Chart.elements.Rectangle = Chart.Element.extend({
- draw: function() {
- var ctx = this._chart.ctx;
- var vm = this._view;
-
- var halfWidth = vm.width / 2,
- leftX = vm.x - halfWidth,
- rightX = vm.x + halfWidth,
- top = vm.base - (vm.base - vm.y),
- 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) {
- leftX += halfStroke;
- rightX -= halfStroke;
- top += 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 = [
- [leftX, vm.base],
- [leftX, top],
- [rightX, top],
- [rightX, vm.base]
- ];
-
- // 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(index) {
- return corners[(startCorner + index) % 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();
- }
- },
- height: function() {
- var vm = this._view;
- return vm.base - vm.y;
- },
- inRange: function(mouseX, mouseY) {
- var vm = this._view;
- return vm ?
- (vm.y < vm.base ?
- (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base) :
- (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y)) :
- false;
- },
- inLabelRange: function(mouseX) {
- var vm = this._view;
- return vm ? (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) : false;
- },
- tooltipPosition: function() {
- var vm = this._view;
- return {
- x: vm.x,
- y: vm.y
- };
- }
- });
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global;\r
+\r
+ globalOpts.elements.rectangle = {\r
+ backgroundColor: globalOpts.defaultColor,\r
+ borderWidth: 0,\r
+ borderColor: globalOpts.defaultColor,\r
+ borderSkipped: 'bottom'\r
+ };\r
+\r
+ Chart.elements.Rectangle = Chart.Element.extend({\r
+ draw: function() {\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ var halfWidth = vm.width / 2,\r
+ leftX = vm.x - halfWidth,\r
+ rightX = vm.x + halfWidth,\r
+ top = vm.base - (vm.base - vm.y),\r
+ halfStroke = vm.borderWidth / 2;\r
+\r
+ // Canvas doesn't allow us to stroke inside the width so we can\r
+ // adjust the sizes to fit if we're setting a stroke on the line\r
+ if (vm.borderWidth) {\r
+ leftX += halfStroke;\r
+ rightX -= halfStroke;\r
+ top += halfStroke;\r
+ }\r
+\r
+ ctx.beginPath();\r
+ ctx.fillStyle = vm.backgroundColor;\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ // Corner points, from bottom-left to bottom-right clockwise\r
+ // | 1 2 |\r
+ // | 0 3 |\r
+ var corners = [\r
+ [leftX, vm.base],\r
+ [leftX, top],\r
+ [rightX, top],\r
+ [rightX, vm.base]\r
+ ];\r
+\r
+ // Find first (starting) corner with fallback to 'bottom' \r
+ var borders = ['bottom', 'left', 'top', 'right'];\r
+ var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
+ if (startCorner === -1)\r
+ startCorner = 0;\r
+\r
+ function cornerAt(index) {\r
+ return corners[(startCorner + index) % 4];\r
+ }\r
+\r
+ // Draw rectangle from 'startCorner'\r
+ ctx.moveTo.apply(ctx, cornerAt(0));\r
+ for (var i = 1; i < 4; i++)\r
+ ctx.lineTo.apply(ctx, cornerAt(i));\r
+\r
+ ctx.fill();\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ },\r
+ height: function() {\r
+ var vm = this._view;\r
+ return vm.base - vm.y;\r
+ },\r
+ inRange: function(mouseX, mouseY) {\r
+ var vm = this._view;\r
+ return vm ? \r
+ (vm.y < vm.base ? \r
+ (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base) :\r
+ (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y)) :\r
+ false;\r
+ },\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+ return vm ? (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) : false;\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+ return {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+ }\r
+ });\r
+\r
};
},{}],38:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- // Default config for a category scale
- var defaultConfig = {
- position: "bottom"
- };
-
- var DatasetScale = Chart.Scale.extend({
- // Implement this so that
- determineDataLimits: function() {
- var me = this;
- me.minIndex = 0;
- me.maxIndex = me.chart.data.labels.length - 1;
- var findIndex;
-
- if (me.options.ticks.min !== undefined) {
- // user specified min value
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.min);
- me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
- }
-
- if (me.options.ticks.max !== undefined) {
- // user specified max value
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.max);
- me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
- }
-
- me.min = me.chart.data.labels[me.minIndex];
- me.max = me.chart.data.labels[me.maxIndex];
- },
-
- buildTicks: function(index) {
- var me = this;
- // If we are viewing some subset of labels, slice the original array
- me.ticks = (me.minIndex === 0 && me.maxIndex === me.chart.data.labels.length - 1) ? me.chart.data.labels : me.chart.data.labels.slice(me.minIndex, me.maxIndex + 1);
- },
-
- getLabelForIndex: function(index, datasetIndex) {
- return this.ticks[index];
- },
-
- // Used to get data value locations. Value can either be an index or a numerical value
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- // 1 is added because we need the length but we have the indexes
- var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
-
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueWidth = innerWidth / offsetAmt;
- var widthOffset = (valueWidth * (index - me.minIndex)) + me.paddingLeft;
-
- if (me.options.gridLines.offsetGridLines && includeOffset) {
- widthOffset += (valueWidth / 2);
- }
-
- return me.left + Math.round(widthOffset);
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- var valueHeight = innerHeight / offsetAmt;
- var heightOffset = (valueHeight * (index - me.minIndex)) + me.paddingTop;
-
- if (me.options.gridLines.offsetGridLines && includeOffset) {
- heightOffset += (valueHeight / 2);
- }
-
- return me.top + Math.round(heightOffset);
- }
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset);
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var value;
- var offsetAmt = Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
- var horz = me.isHorizontal();
- var innerDimension = horz ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
- var valueDimension = innerDimension / offsetAmt;
-
- if (me.options.gridLines.offsetGridLines) {
- pixel -= (valueDimension / 2);
- }
- pixel -= horz ? me.paddingLeft : me.paddingTop;
-
- if (pixel <= 0) {
- value = 0;
- } else {
- value = Math.round(pixel / valueDimension);
- }
-
- return value;
- }
- });
-
- Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ // Default config for a category scale\r
+ var defaultConfig = {\r
+ position: "bottom"\r
+ };\r
+\r
+ var DatasetScale = Chart.Scale.extend({\r
+ // Implement this so that \r
+ determineDataLimits: function() {\r
+ this.minIndex = 0;\r
+ this.maxIndex = this.chart.data.labels.length - 1;\r
+ var findIndex;\r
+\r
+ if (this.options.ticks.min !== undefined) {\r
+ // user specified min value\r
+ findIndex = helpers.indexOf(this.chart.data.labels, this.options.ticks.min);\r
+ this.minIndex = findIndex !== -1 ? findIndex : this.minIndex;\r
+ }\r
+\r
+ if (this.options.ticks.max !== undefined) {\r
+ // user specified max value\r
+ findIndex = helpers.indexOf(this.chart.data.labels, this.options.ticks.max);\r
+ this.maxIndex = findIndex !== -1 ? findIndex : this.maxIndex;\r
+ }\r
+\r
+ this.min = this.chart.data.labels[this.minIndex];\r
+ this.max = this.chart.data.labels[this.maxIndex];\r
+ },\r
+\r
+ buildTicks: function(index) {\r
+ // If we are viewing some subset of labels, slice the original array\r
+ this.ticks = (this.minIndex === 0 && this.maxIndex === this.chart.data.labels.length - 1) ? this.chart.data.labels : this.chart.data.labels.slice(this.minIndex, this.maxIndex + 1);\r
+ },\r
+\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return this.ticks[index];\r
+ },\r
+\r
+ // Used to get data value locations. Value can either be an index or a numerical value\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ // 1 is added because we need the length but we have the indexes\r
+ var offsetAmt = Math.max((this.maxIndex + 1 - this.minIndex - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueWidth = innerWidth / offsetAmt;\r
+ var widthOffset = (valueWidth * (index - this.minIndex)) + this.paddingLeft;\r
+\r
+ if (this.options.gridLines.offsetGridLines && includeOffset) {\r
+ widthOffset += (valueWidth / 2);\r
+ }\r
+\r
+ return this.left + Math.round(widthOffset);\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueHeight = innerHeight / offsetAmt;\r
+ var heightOffset = (valueHeight * (index - this.minIndex)) + this.paddingTop;\r
+\r
+ if (this.options.gridLines.offsetGridLines && includeOffset) {\r
+ heightOffset += (valueHeight / 2);\r
+ }\r
+\r
+ return this.top + Math.round(heightOffset);\r
+ }\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset);\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var value\r
+; var offsetAmt = Math.max((this.ticks.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+ var horz = this.isHorizontal();\r
+ var innerDimension = horz ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueDimension = innerDimension / offsetAmt;\r
+\r
+ if (this.options.gridLines.offsetGridLines) {\r
+ pixel -= (valueDimension / 2);\r
+ }\r
+ pixel -= horz ? this.paddingLeft : this.paddingTop;\r
+\r
+ if (pixel <= 0) {\r
+ value = 0;\r
+ } else {\r
+ value = Math.round(pixel / valueDimension);\r
+ }\r
+\r
+ return value;\r
+ }\r
+ });\r
+\r
+ Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);\r
+\r
};
},{}],39:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- var defaultConfig = {
- position: "left",
- ticks: {
- callback: function(tickValue, index, ticks) {
- // If we have lots of ticks, don't use the ones
- var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
-
- // If we have a number like 2.5 as the delta, figure out how many decimal places we need
- if (Math.abs(delta) > 1) {
- if (tickValue !== Math.floor(tickValue)) {
- // not an integer
- delta = tickValue - Math.floor(tickValue);
- }
- }
-
- var logDelta = helpers.log10(Math.abs(delta));
- var tickString = '';
-
- if (tickValue !== 0) {
- var numDecimal = -1 * Math.floor(logDelta);
- numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
- tickString = tickValue.toFixed(numDecimal);
- } else {
- tickString = '0'; // never show decimal places for 0
- }
-
- return tickString;
- }
- }
- };
-
- var LinearScale = Chart.LinearScaleBase.extend({
- determineDataLimits: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var chart = me.chart;
- var data = chart.data;
- var datasets = data.datasets;
- var isHorizontal = me.isHorizontal();
-
- function IDMatches(meta) {
- return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
- }
-
- // First Calculate the range
- me.min = null;
- me.max = null;
-
- if (opts.stacked) {
- var valuesPerType = {};
- var hasPositiveValues = false;
- var hasNegativeValues = false;
-
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (valuesPerType[meta.type] === undefined) {
- valuesPerType[meta.type] = {
- positiveValues: [],
- negativeValues: []
- };
- }
-
- // Store these per type
- var positiveValues = valuesPerType[meta.type].positiveValues;
- var negativeValues = valuesPerType[meta.type].negativeValues;
-
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- positiveValues[index] = positiveValues[index] || 0;
- negativeValues[index] = negativeValues[index] || 0;
-
- if (opts.relativePoints) {
- positiveValues[index] = 100;
- } else {
- if (value < 0) {
- hasNegativeValues = true;
- negativeValues[index] += value;
- } else {
- hasPositiveValues = true;
- positiveValues[index] += value;
- }
- }
- });
- }
- });
-
- helpers.each(valuesPerType, function(valuesForType) {
- var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
- var minVal = helpers.min(values);
- var maxVal = helpers.max(values);
- me.min = me.min === null ? minVal : Math.min(me.min, minVal);
- me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
- });
-
- } else {
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
- }
-
- // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
- this.handleTickRangeOptions();
- },
- getTickLimit: function() {
- var maxTicks;
- var me = this;
- var tickOpts = me.options.ticks;
-
- if (me.isHorizontal()) {
- maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
- } else {
- // The factor of 2 used to scale the font size has been experimentally determined.
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);
- maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
- }
-
- return maxTicks;
- },
- // Called after the ticks are built. We need
- handleDirectionalChanges: function() {
- if (!this.isHorizontal()) {
- // We are in a vertical orientation. The top value is the highest. So reverse the array
- this.ticks.reverse();
- }
- },
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- // Utils
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- // This must be called after fit has been run so that
- // this.left, this.top, this.right, and this.bottom have been defined
- var me = this;
- var paddingLeft = me.paddingLeft;
- var paddingBottom = me.paddingBottom;
- var start = me.start;
-
- var rightValue = +me.getRightValue(value);
- var pixel;
- var innerDimension;
- var range = me.end - start;
-
- if (me.isHorizontal()) {
- innerDimension = me.width - (paddingLeft + me.paddingRight);
- pixel = me.left + (innerDimension / range * (rightValue - start));
- return Math.round(pixel + paddingLeft);
- } else {
- innerDimension = me.height - (me.paddingTop + paddingBottom);
- pixel = (me.bottom - paddingBottom) - (innerDimension / range * (rightValue - start));
- return Math.round(pixel);
- }
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var isHorizontal = me.isHorizontal();
- var paddingLeft = me.paddingLeft;
- var paddingBottom = me.paddingBottom;
- var innerDimension = isHorizontal ? me.width - (paddingLeft + me.paddingRight) : me.height - (me.paddingTop + paddingBottom);
- var offset = (isHorizontal ? pixel - me.left - paddingLeft : me.bottom - paddingBottom - pixel) / innerDimension;
- return me.start + ((me.end - me.start) * offset);
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);
- }
- });
- Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ var defaultConfig = {\r
+ position: "left",\r
+ ticks: {\r
+ callback: function(tickValue, index, ticks) {\r
+ // If we have lots of ticks, don't use the ones\r
+ var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];\r
+\r
+ // If we have a number like 2.5 as the delta, figure out how many decimal places we need\r
+ if (Math.abs(delta) > 1) {\r
+ if (tickValue !== Math.floor(tickValue)) {\r
+ // not an integer\r
+ delta = tickValue - Math.floor(tickValue);\r
+ }\r
+ }\r
+\r
+ var logDelta = helpers.log10(Math.abs(delta));\r
+ var tickString = '';\r
+\r
+ if (tickValue !== 0) {\r
+ var numDecimal = -1 * Math.floor(logDelta);\r
+ numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places\r
+ tickString = tickValue.toFixed(numDecimal);\r
+ } else {\r
+ tickString = '0'; // never show decimal places for 0\r
+ }\r
+\r
+ return tickString;\r
+ }\r
+ }\r
+ };\r
+\r
+ var LinearScale = Chart.Scale.extend({\r
+ determineDataLimits: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var chart = _this.chart;\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var isHorizontal = _this.isHorizontal();\r
+\r
+ function IDMatches(meta) {\r
+ return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;\r
+ }\r
+\r
+ // First Calculate the range\r
+ _this.min = null;\r
+ _this.max = null;\r
+\r
+ if (opts.stacked) {\r
+ var valuesPerType = {};\r
+ var hasPositiveValues = false;\r
+ var hasNegativeValues = false;\r
+\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (valuesPerType[meta.type] === undefined) {\r
+ valuesPerType[meta.type] = {\r
+ positiveValues: [],\r
+ negativeValues: []\r
+ };\r
+ }\r
+\r
+ // Store these per type\r
+ var positiveValues = valuesPerType[meta.type].positiveValues;\r
+ var negativeValues = valuesPerType[meta.type].negativeValues;\r
+\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ positiveValues[index] = positiveValues[index] || 0;\r
+ negativeValues[index] = negativeValues[index] || 0;\r
+\r
+ if (opts.relativePoints) {\r
+ positiveValues[index] = 100;\r
+ } else {\r
+ if (value < 0) {\r
+ hasNegativeValues = true;\r
+ negativeValues[index] += value;\r
+ } else {\r
+ hasPositiveValues = true;\r
+ positiveValues[index] += value;\r
+ }\r
+ }\r
+ });\r
+ }\r
+ });\r
+\r
+ helpers.each(valuesPerType, function(valuesForType) {\r
+ var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);\r
+ var minVal = helpers.min(values);\r
+ var maxVal = helpers.max(values);\r
+ _this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);\r
+ _this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);\r
+ });\r
+\r
+ } else {\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (_this.min === null) {\r
+ _this.min = value;\r
+ } else if (value < _this.min) {\r
+ _this.min = value;\r
+ }\r
+\r
+ if (_this.max === null) {\r
+ _this.max = value;\r
+ } else if (value > _this.max) {\r
+ _this.max = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ }\r
+\r
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,\r
+ // do nothing since that would make the chart weird. If the user really wants a weird chart\r
+ // axis, they can manually override it\r
+ if (tickOpts.beginAtZero) {\r
+ var minSign = helpers.sign(_this.min);\r
+ var maxSign = helpers.sign(_this.max);\r
+\r
+ if (minSign < 0 && maxSign < 0) {\r
+ // move the top up to 0\r
+ _this.max = 0;\r
+ } else if (minSign > 0 && maxSign > 0) {\r
+ // move the botttom down to 0\r
+ _this.min = 0;\r
+ }\r
+ }\r
+\r
+ if (tickOpts.min !== undefined) {\r
+ _this.min = tickOpts.min;\r
+ } else if (tickOpts.suggestedMin !== undefined) {\r
+ _this.min = Math.min(_this.min, tickOpts.suggestedMin);\r
+ }\r
+\r
+ if (tickOpts.max !== undefined) {\r
+ _this.max = tickOpts.max;\r
+ } else if (tickOpts.suggestedMax !== undefined) {\r
+ _this.max = Math.max(_this.max, tickOpts.suggestedMax);\r
+ }\r
+\r
+ if (_this.min === _this.max) {\r
+ _this.max++;\r
+\r
+ if (!tickOpts.beginAtZero) {\r
+ _this.min--;\r
+ }\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+ var isHorizontal = _this.isHorizontal();\r
+\r
+ var ticks = _this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+\r
+ var maxTicks;\r
+\r
+ if (isHorizontal) {\r
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.width / 50));\r
+ } else {\r
+ // The factor of 2 used to scale the font size has been experimentally determined.\r
+ var tickFontSize = getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);\r
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.height / (2 * tickFontSize)));\r
+ }\r
+\r
+ // Make sure we always have at least 2 ticks\r
+ maxTicks = Math.max(2, maxTicks);\r
+\r
+ // To get a "nice" value for the tick spacing, we will use the appropriately named\r
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks\r
+ // for details.\r
+\r
+ var spacing;\r
+ var fixedStepSizeSet = (tickOpts.fixedStepSize && tickOpts.fixedStepSize > 0) || (tickOpts.stepSize && tickOpts.stepSize > 0);\r
+ if (fixedStepSizeSet) {\r
+ spacing = getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize);\r
+ } else {\r
+ var niceRange = helpers.niceNum(_this.max - _this.min, false);\r
+ spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);\r
+ }\r
+ var niceMin = Math.floor(_this.min / spacing) * spacing;\r
+ var niceMax = Math.ceil(_this.max / spacing) * spacing;\r
+ var numSpaces = (niceMax - niceMin) / spacing;\r
+\r
+ // If very close to our rounded value, use it.\r
+ if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {\r
+ numSpaces = Math.round(numSpaces);\r
+ } else {\r
+ numSpaces = Math.ceil(numSpaces);\r
+ }\r
+\r
+ // Put the values into the ticks array\r
+ ticks.push(tickOpts.min !== undefined ? tickOpts.min : niceMin);\r
+ for (var j = 1; j < numSpaces; ++j) {\r
+ ticks.push(niceMin + (j * spacing));\r
+ }\r
+ ticks.push(tickOpts.max !== undefined ? tickOpts.max : niceMax);\r
+\r
+ if (!isHorizontal) {\r
+ // We are in a vertical orientation. The top value is the highest. So reverse the array\r
+ ticks.reverse();\r
+ }\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ _this.max = helpers.max(ticks);\r
+ _this.min = helpers.min(ticks);\r
+\r
+ if (tickOpts.reverse) {\r
+ ticks.reverse();\r
+\r
+ _this.start = _this.max;\r
+ _this.end = _this.min;\r
+ } else {\r
+ _this.start = _this.min;\r
+ _this.end = _this.max;\r
+ }\r
+ },\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ var _this = this;\r
+ _this.ticksAsNumbers = _this.ticks.slice();\r
+ _this.zeroLineIndex = _this.ticks.indexOf(0);\r
+\r
+ Chart.Scale.prototype.convertTicksToLabels.call(_this);\r
+ },\r
+ // Utils\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ // This must be called after fit has been run so that\r
+ // this.left, this.top, this.right, and this.bottom have been defined\r
+ var _this = this;\r
+ var paddingLeft = _this.paddingLeft;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var start = _this.start;\r
+\r
+ var rightValue = +_this.getRightValue(value);\r
+ var pixel;\r
+ var innerDimension;\r
+ var range = _this.end - start;\r
+\r
+ if (_this.isHorizontal()) {\r
+ innerDimension = _this.width - (paddingLeft + _this.paddingRight);\r
+ pixel = _this.left + (innerDimension / range * (rightValue - start));\r
+ return Math.round(pixel + paddingLeft);\r
+ } else {\r
+ innerDimension = _this.height - (_this.paddingTop + paddingBottom);\r
+ pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (rightValue - start));\r
+ return Math.round(pixel);\r
+ }\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var _this = this;\r
+ var isHorizontal = _this.isHorizontal();\r
+ var paddingLeft = _this.paddingLeft;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var innerDimension = isHorizontal ? _this.width - (paddingLeft + _this.paddingRight) : _this.height - (_this.paddingTop + paddingBottom);\r
+ var offset = (isHorizontal ? pixel - _this.left - paddingLeft : _this.bottom - paddingBottom - pixel) / innerDimension;\r
+ return _this.start + ((_this.end - _this.start) * offset);\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);\r
+\r
};
},{}],40:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- noop = helpers.noop;
-
- Chart.LinearScaleBase = Chart.Scale.extend({
- handleTickRangeOptions: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
-
- // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
- // do nothing since that would make the chart weird. If the user really wants a weird chart
- // axis, they can manually override it
- if (tickOpts.beginAtZero) {
- var minSign = helpers.sign(me.min);
- var maxSign = helpers.sign(me.max);
-
- if (minSign < 0 && maxSign < 0) {
- // move the top up to 0
- me.max = 0;
- } else if (minSign > 0 && maxSign > 0) {
- // move the botttom down to 0
- me.min = 0;
- }
- }
-
- if (tickOpts.min !== undefined) {
- me.min = tickOpts.min;
- } else if (tickOpts.suggestedMin !== undefined) {
- me.min = Math.min(me.min, tickOpts.suggestedMin);
- }
-
- if (tickOpts.max !== undefined) {
- me.max = tickOpts.max;
- } else if (tickOpts.suggestedMax !== undefined) {
- me.max = Math.max(me.max, tickOpts.suggestedMax);
- }
-
- if (me.min === me.max) {
- me.max++;
-
- if (!tickOpts.beginAtZero) {
- me.min--;
- }
- }
- },
- getTickLimit: noop,
- handleDirectionalChanges: noop,
-
- buildTicks: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var getValueOrDefault = helpers.getValueOrDefault;
- var isHorizontal = me.isHorizontal();
-
- var ticks = me.ticks = [];
-
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
-
- var maxTicks = me.getTickLimit();
-
- // Make sure we always have at least 2 ticks
- maxTicks = Math.max(2, maxTicks);
-
- // To get a "nice" value for the tick spacing, we will use the appropriately named
- // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
- // for details.
-
- var spacing;
- var fixedStepSizeSet = (tickOpts.fixedStepSize && tickOpts.fixedStepSize > 0) || (tickOpts.stepSize && tickOpts.stepSize > 0);
- if (fixedStepSizeSet) {
- spacing = getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize);
- } else {
- var niceRange = helpers.niceNum(me.max - me.min, false);
- spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
- }
- var niceMin = Math.floor(me.min / spacing) * spacing;
- var niceMax = Math.ceil(me.max / spacing) * spacing;
- var numSpaces = (niceMax - niceMin) / spacing;
-
- // If very close to our rounded value, use it.
- if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
- numSpaces = Math.round(numSpaces);
- } else {
- numSpaces = Math.ceil(numSpaces);
- }
-
- // Put the values into the ticks array
- ticks.push(tickOpts.min !== undefined ? tickOpts.min : niceMin);
- for (var j = 1; j < numSpaces; ++j) {
- ticks.push(niceMin + (j * spacing));
- }
- ticks.push(tickOpts.max !== undefined ? tickOpts.max : niceMax);
-
- me.handleDirectionalChanges();
-
- // At this point, we need to update our max and min given the tick values since we have expanded the
- // range of the scale
- me.max = helpers.max(ticks);
- me.min = helpers.min(ticks);
-
- if (tickOpts.reverse) {
- ticks.reverse();
-
- me.start = me.max;
- me.end = me.min;
- } else {
- me.start = me.min;
- me.end = me.max;
- }
- },
- convertTicksToLabels: function() {
- var me = this;
- me.ticksAsNumbers = me.ticks.slice();
- me.zeroLineIndex = me.ticks.indexOf(0);
-
- Chart.Scale.prototype.convertTicksToLabels.call(me);
- },
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ var defaultConfig = {\r
+ position: "left",\r
+\r
+ // label settings\r
+ ticks: {\r
+ callback: function(value, index, arr) {\r
+ var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));\r
+\r
+ if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {\r
+ return value.toExponential();\r
+ } else {\r
+ return '';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ var LogarithmicScale = Chart.Scale.extend({\r
+ determineDataLimits: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var chart = _this.chart;\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+ var isHorizontal = _this.isHorizontal();\r
+ function IDMatches(meta) {\r
+ return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;\r
+ }\r
+\r
+ // Calculate Range\r
+ _this.min = null;\r
+ _this.max = null;\r
+\r
+ if (opts.stacked) {\r
+ var valuesPerType = {};\r
+\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ if (valuesPerType[meta.type] === undefined) {\r
+ valuesPerType[meta.type] = [];\r
+ }\r
+\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var values = valuesPerType[meta.type];\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ values[index] = values[index] || 0;\r
+\r
+ if (opts.relativePoints) {\r
+ values[index] = 100;\r
+ } else {\r
+ // Don't need to split positive and negative since the log scale can't handle a 0 crossing\r
+ values[index] += value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+\r
+ helpers.each(valuesPerType, function(valuesForType) {\r
+ var minVal = helpers.min(valuesForType);\r
+ var maxVal = helpers.max(valuesForType);\r
+ _this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);\r
+ _this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);\r
+ });\r
+\r
+ } else {\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (_this.min === null) {\r
+ _this.min = value;\r
+ } else if (value < _this.min) {\r
+ _this.min = value;\r
+ }\r
+\r
+ if (_this.max === null) {\r
+ _this.max = value;\r
+ } else if (value > _this.max) {\r
+ _this.max = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ }\r
+\r
+ _this.min = getValueOrDefault(tickOpts.min, _this.min);\r
+ _this.max = getValueOrDefault(tickOpts.max, _this.max);\r
+\r
+ if (_this.min === _this.max) {\r
+ if (_this.min !== 0 && _this.min !== null) {\r
+ _this.min = Math.pow(10, Math.floor(helpers.log10(_this.min)) - 1);\r
+ _this.max = Math.pow(10, Math.floor(helpers.log10(_this.max)) + 1);\r
+ } else {\r
+ _this.min = 1;\r
+ _this.max = 10;\r
+ }\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+\r
+ // Reset the ticks array. Later on, we will draw a grid line at these positions\r
+ // The array simply contains the numerical value of the spots where ticks will be\r
+ var ticks = _this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+\r
+ var tickVal = getValueOrDefault(tickOpts.min, Math.pow(10, Math.floor(helpers.log10(_this.min))));\r
+\r
+ while (tickVal < _this.max) {\r
+ ticks.push(tickVal);\r
+\r
+ var exp = Math.floor(helpers.log10(tickVal));\r
+ var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;\r
+\r
+ if (significand === 10) {\r
+ significand = 1;\r
+ ++exp;\r
+ }\r
+\r
+ tickVal = significand * Math.pow(10, exp);\r
+ }\r
+\r
+ var lastTick = getValueOrDefault(tickOpts.max, tickVal);\r
+ ticks.push(lastTick);\r
+\r
+ if (!_this.isHorizontal()) {\r
+ // We are in a vertical orientation. The top value is the highest. So reverse the array\r
+ ticks.reverse();\r
+ }\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ _this.max = helpers.max(ticks);\r
+ _this.min = helpers.min(ticks);\r
+\r
+ if (tickOpts.reverse) {\r
+ ticks.reverse();\r
+\r
+ _this.start = _this.max;\r
+ _this.end = _this.min;\r
+ } else {\r
+ _this.start = _this.min;\r
+ _this.end = _this.max;\r
+ }\r
+ },\r
+ convertTicksToLabels: function() {\r
+ this.tickValues = this.ticks.slice();\r
+\r
+ Chart.Scale.prototype.convertTicksToLabels.call(this);\r
+ },\r
+ // Get the correct tooltip label\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);\r
+ },\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ var _this = this;\r
+ var innerDimension;\r
+ var pixel;\r
+\r
+ var start = _this.start;\r
+ var newVal = +_this.getRightValue(value);\r
+ var range = helpers.log10(_this.end) - helpers.log10(start);\r
+ var paddingTop = _this.paddingTop;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var paddingLeft = _this.paddingLeft;\r
+\r
+ if (_this.isHorizontal()) {\r
+\r
+ if (newVal === 0) {\r
+ pixel = _this.left + paddingLeft;\r
+ } else {\r
+ innerDimension = _this.width - (paddingLeft + _this.paddingRight);\r
+ pixel = _this.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));\r
+ pixel += paddingLeft;\r
+ }\r
+ } else {\r
+ // Bottom - top since pixels increase downard on a screen\r
+ if (newVal === 0) {\r
+ pixel = _this.top + paddingTop;\r
+ } else {\r
+ innerDimension = _this.height - (paddingTop + paddingBottom);\r
+ pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));\r
+ }\r
+ }\r
+\r
+ return pixel;\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var _this = this;\r
+ var offset;\r
+ var range = helpers.log10(_this.end) - helpers.log10(_this.start);\r
+ var value;\r
+ var innerDimension;\r
+\r
+ if (_this.isHorizontal()) {\r
+ innerDimension = _this.width - (_this.paddingLeft + _this.paddingRight);\r
+ value = _this.start * Math.pow(10, (pixel - _this.left - _this.paddingLeft) * range / innerDimension);\r
+ } else {\r
+ innerDimension = _this.height - (_this.paddingTop + _this.paddingBottom);\r
+ value = Math.pow(10, (_this.bottom - _this.paddingBottom - pixel) * range / innerDimension) / _this.start;\r
+ }\r
+\r
+ return value;\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);\r
+\r
};
},{}],41:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- var defaultConfig = {
- position: "left",
-
- // label settings
- ticks: {
- callback: function(value, index, arr) {
- var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));
-
- if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {
- return value.toExponential();
- } else {
- return '';
- }
- }
- }
- };
-
- var LogarithmicScale = Chart.Scale.extend({
- determineDataLimits: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var chart = me.chart;
- var data = chart.data;
- var datasets = data.datasets;
- var getValueOrDefault = helpers.getValueOrDefault;
- var isHorizontal = me.isHorizontal();
- function IDMatches(meta) {
- return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
- }
-
- // Calculate Range
- me.min = null;
- me.max = null;
-
- if (opts.stacked) {
- var valuesPerType = {};
-
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- if (valuesPerType[meta.type] === undefined) {
- valuesPerType[meta.type] = [];
- }
-
- helpers.each(dataset.data, function(rawValue, index) {
- var values = valuesPerType[meta.type];
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- values[index] = values[index] || 0;
-
- if (opts.relativePoints) {
- values[index] = 100;
- } else {
- // Don't need to split positive and negative since the log scale can't handle a 0 crossing
- values[index] += value;
- }
- });
- }
- });
-
- helpers.each(valuesPerType, function(valuesForType) {
- var minVal = helpers.min(valuesForType);
- var maxVal = helpers.max(valuesForType);
- me.min = me.min === null ? minVal : Math.min(me.min, minVal);
- me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
- });
-
- } else {
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
- }
-
- me.min = getValueOrDefault(tickOpts.min, me.min);
- me.max = getValueOrDefault(tickOpts.max, me.max);
-
- if (me.min === me.max) {
- if (me.min !== 0 && me.min !== null) {
- me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1);
- me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1);
- } else {
- me.min = 1;
- me.max = 10;
- }
- }
- },
- buildTicks: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- // Reset the ticks array. Later on, we will draw a grid line at these positions
- // The array simply contains the numerical value of the spots where ticks will be
- var ticks = me.ticks = [];
-
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
-
- var tickVal = getValueOrDefault(tickOpts.min, Math.pow(10, Math.floor(helpers.log10(me.min))));
-
- while (tickVal < me.max) {
- ticks.push(tickVal);
-
- var exp = Math.floor(helpers.log10(tickVal));
- var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;
-
- if (significand === 10) {
- significand = 1;
- ++exp;
- }
-
- tickVal = significand * Math.pow(10, exp);
- }
-
- var lastTick = getValueOrDefault(tickOpts.max, tickVal);
- ticks.push(lastTick);
-
- if (!me.isHorizontal()) {
- // We are in a vertical orientation. The top value is the highest. So reverse the array
- ticks.reverse();
- }
-
- // At this point, we need to update our max and min given the tick values since we have expanded the
- // range of the scale
- me.max = helpers.max(ticks);
- me.min = helpers.min(ticks);
-
- if (tickOpts.reverse) {
- ticks.reverse();
-
- me.start = me.max;
- me.end = me.min;
- } else {
- me.start = me.min;
- me.end = me.max;
- }
- },
- convertTicksToLabels: function() {
- this.tickValues = this.ticks.slice();
-
- Chart.Scale.prototype.convertTicksToLabels.call(this);
- },
- // Get the correct tooltip label
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);
- },
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- var innerDimension;
- var pixel;
-
- var start = me.start;
- var newVal = +me.getRightValue(value);
- var range = helpers.log10(me.end) - helpers.log10(start);
- var paddingTop = me.paddingTop;
- var paddingBottom = me.paddingBottom;
- var paddingLeft = me.paddingLeft;
-
- if (me.isHorizontal()) {
-
- if (newVal === 0) {
- pixel = me.left + paddingLeft;
- } else {
- innerDimension = me.width - (paddingLeft + me.paddingRight);
- pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
- pixel += paddingLeft;
- }
- } else {
- // Bottom - top since pixels increase downard on a screen
- if (newVal === 0) {
- pixel = me.top + paddingTop;
- } else {
- innerDimension = me.height - (paddingTop + paddingBottom);
- pixel = (me.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
- }
- }
-
- return pixel;
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var offset;
- var range = helpers.log10(me.end) - helpers.log10(me.start);
- var value;
- var innerDimension;
-
- if (me.isHorizontal()) {
- innerDimension = me.width - (me.paddingLeft + me.paddingRight);
- value = me.start * Math.pow(10, (pixel - me.left - me.paddingLeft) * range / innerDimension);
- } else {
- innerDimension = me.height - (me.paddingTop + me.paddingBottom);
- value = Math.pow(10, (me.bottom - me.paddingBottom - pixel) * range / innerDimension) / me.start;
- }
-
- return value;
- }
- });
- Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var globalDefaults = Chart.defaults.global;\r
+\r
+ var defaultConfig = {\r
+ display: true,\r
+\r
+ //Boolean - Whether to animate scaling the chart from the centre\r
+ animate: true,\r
+ lineArc: false,\r
+ position: "chartArea",\r
+\r
+ angleLines: {\r
+ display: true,\r
+ color: "rgba(0, 0, 0, 0.1)",\r
+ lineWidth: 1\r
+ },\r
+\r
+ // label settings\r
+ ticks: {\r
+ //Boolean - Show a backdrop to the scale label\r
+ showLabelBackdrop: true,\r
+\r
+ //String - The colour of the label backdrop\r
+ backdropColor: "rgba(255,255,255,0.75)",\r
+\r
+ //Number - The backdrop padding above & below the label in pixels\r
+ backdropPaddingY: 2,\r
+\r
+ //Number - The backdrop padding to the side of the label in pixels\r
+ backdropPaddingX: 2\r
+ },\r
+\r
+ pointLabels: {\r
+ //Number - Point label font size in pixels\r
+ fontSize: 10,\r
+\r
+ //Function - Used to convert point labels\r
+ callback: function(label) {\r
+ return label;\r
+ }\r
+ }\r
+ };\r
+\r
+ var LinearRadialScale = Chart.Scale.extend({\r
+ getValueCount: function() {\r
+ return this.chart.data.labels.length;\r
+ },\r
+ setDimensions: function() {\r
+ var options = this.options;\r
+ // Set the unconstrained dimension before label rotation\r
+ this.width = this.maxWidth;\r
+ this.height = this.maxHeight;\r
+ this.xCenter = Math.round(this.width / 2);\r
+ this.yCenter = Math.round(this.height / 2);\r
+\r
+ var minSize = helpers.min([this.height, this.width]);\r
+ var tickFontSize = helpers.getValueOrDefault(options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ this.drawingArea = (options.display) ? (minSize / 2) - (tickFontSize / 2 + options.ticks.backdropPaddingY) : (minSize / 2);\r
+ },\r
+ determineDataLimits: function() {\r
+ this.min = null;\r
+ this.max = null;\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.chart.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.chart.getDatasetMeta(datasetIndex);\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (this.min === null) {\r
+ this.min = value;\r
+ } else if (value < this.min) {\r
+ this.min = value;\r
+ }\r
+\r
+ if (this.max === null) {\r
+ this.max = value;\r
+ } else if (value > this.max) {\r
+ this.max = value;\r
+ }\r
+ }, this);\r
+ }\r
+ }, this);\r
+\r
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,\r
+ // do nothing since that would make the chart weird. If the user really wants a weird chart\r
+ // axis, they can manually override it\r
+ if (this.options.ticks.beginAtZero) {\r
+ var minSign = helpers.sign(this.min);\r
+ var maxSign = helpers.sign(this.max);\r
+\r
+ if (minSign < 0 && maxSign < 0) {\r
+ // move the top up to 0\r
+ this.max = 0;\r
+ } else if (minSign > 0 && maxSign > 0) {\r
+ // move the botttom down to 0\r
+ this.min = 0;\r
+ }\r
+ }\r
+\r
+ if (this.options.ticks.min !== undefined) {\r
+ this.min = this.options.ticks.min;\r
+ } else if (this.options.ticks.suggestedMin !== undefined) {\r
+ this.min = Math.min(this.min, this.options.ticks.suggestedMin);\r
+ }\r
+\r
+ if (this.options.ticks.max !== undefined) {\r
+ this.max = this.options.ticks.max;\r
+ } else if (this.options.ticks.suggestedMax !== undefined) {\r
+ this.max = Math.max(this.max, this.options.ticks.suggestedMax);\r
+ }\r
+\r
+ if (this.min === this.max) {\r
+ this.min--;\r
+ this.max++;\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+\r
+\r
+ this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ var maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));\r
+ maxTicks = Math.max(2, maxTicks); // Make sure we always have at least 2 ticks\r
+\r
+ // To get a "nice" value for the tick spacing, we will use the appropriately named\r
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks\r
+ // for details.\r
+\r
+ var niceRange = helpers.niceNum(this.max - this.min, false);\r
+ var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);\r
+ var niceMin = Math.floor(this.min / spacing) * spacing;\r
+ var niceMax = Math.ceil(this.max / spacing) * spacing;\r
+\r
+ var numSpaces = Math.ceil((niceMax - niceMin) / spacing);\r
+\r
+ // Put the values into the ticks array\r
+ this.ticks.push(this.options.ticks.min !== undefined ? this.options.ticks.min : niceMin);\r
+ for (var j = 1; j < numSpaces; ++j) {\r
+ this.ticks.push(niceMin + (j * spacing));\r
+ }\r
+ this.ticks.push(this.options.ticks.max !== undefined ? this.options.ticks.max : niceMax);\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ this.max = helpers.max(this.ticks);\r
+ this.min = helpers.min(this.ticks);\r
+\r
+ if (this.options.ticks.reverse) {\r
+ this.ticks.reverse();\r
+\r
+ this.start = this.max;\r
+ this.end = this.min;\r
+ } else {\r
+ this.start = this.min;\r
+ this.end = this.max;\r
+ }\r
+\r
+ this.zeroLineIndex = this.ticks.indexOf(0);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ Chart.Scale.prototype.convertTicksToLabels.call(this);\r
+\r
+ // Point labels\r
+ this.pointLabels = this.chart.data.labels.map(this.options.pointLabels.callback, this);\r
+ },\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ fit: function() {\r
+ /*\r
+ * Right, this is really confusing and there is a lot of maths going on here\r
+ * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9\r
+ *\r
+ * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif\r
+ *\r
+ * Solution:\r
+ *\r
+ * We assume the radius of the polygon is half the size of the canvas at first\r
+ * at each index we check if the text overlaps.\r
+ *\r
+ * Where it does, we store that angle and that index.\r
+ *\r
+ * After finding the largest index and angle we calculate how much we need to remove\r
+ * from the shape radius to move the point inwards by that x.\r
+ *\r
+ * We average the left and right distances to get the maximum shape radius that can fit in the box\r
+ * along with labels.\r
+ *\r
+ * Once we have that, we can find the centre point for the chart, by taking the x text protrusion\r
+ * on each side, removing that from the size, halving it and adding the left x protrusion width.\r
+ *\r
+ * This will mean we have a shape fitted to the canvas, as large as it can be with the labels\r
+ * and position it in the most space efficient manner\r
+ *\r
+ * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif\r
+ */\r
+\r
+ var pointLabels = this.options.pointLabels;\r
+ var pointLabelFontSize = helpers.getValueOrDefault(pointLabels.fontSize, globalDefaults.defaultFontSize);\r
+ var pointLabeFontStyle = helpers.getValueOrDefault(pointLabels.fontStyle, globalDefaults.defaultFontStyle);\r
+ var pointLabeFontFamily = helpers.getValueOrDefault(pointLabels.fontFamily, globalDefaults.defaultFontFamily);\r
+ var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);\r
+\r
+ // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.\r
+ // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points\r
+ var largestPossibleRadius = helpers.min([(this.height / 2 - pointLabelFontSize - 5), this.width / 2]),\r
+ pointPosition,\r
+ i,\r
+ textWidth,\r
+ halfTextWidth,\r
+ furthestRight = this.width,\r
+ furthestRightIndex,\r
+ furthestRightAngle,\r
+ furthestLeft = 0,\r
+ furthestLeftIndex,\r
+ furthestLeftAngle,\r
+ xProtrusionLeft,\r
+ xProtrusionRight,\r
+ radiusReductionRight,\r
+ radiusReductionLeft,\r
+ maxWidthRadius;\r
+ this.ctx.font = pointLabeFont;\r
+\r
+ for (i = 0; i < this.getValueCount(); i++) {\r
+ // 5px to space the text slightly out - similar to what we do in the draw function.\r
+ pointPosition = this.getPointPosition(i, largestPossibleRadius);\r
+ textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;\r
+ if (i === 0 || i === this.getValueCount() / 2) {\r
+ // If we're at index zero, or exactly the middle, we're at exactly the top/bottom\r
+ // of the radar chart, so text will be aligned centrally, so we'll half it and compare\r
+ // w/left and right text sizes\r
+ halfTextWidth = textWidth / 2;\r
+ if (pointPosition.x + halfTextWidth > furthestRight) {\r
+ furthestRight = pointPosition.x + halfTextWidth;\r
+ furthestRightIndex = i;\r
+ }\r
+ if (pointPosition.x - halfTextWidth < furthestLeft) {\r
+ furthestLeft = pointPosition.x - halfTextWidth;\r
+ furthestLeftIndex = i;\r
+ }\r
+ } else if (i < this.getValueCount() / 2) {\r
+ // Less than half the values means we'll left align the text\r
+ if (pointPosition.x + textWidth > furthestRight) {\r
+ furthestRight = pointPosition.x + textWidth;\r
+ furthestRightIndex = i;\r
+ }\r
+ } else if (i > this.getValueCount() / 2) {\r
+ // More than half the values means we'll right align the text\r
+ if (pointPosition.x - textWidth < furthestLeft) {\r
+ furthestLeft = pointPosition.x - textWidth;\r
+ furthestLeftIndex = i;\r
+ }\r
+ }\r
+ }\r
+\r
+ xProtrusionLeft = furthestLeft;\r
+ xProtrusionRight = Math.ceil(furthestRight - this.width);\r
+\r
+ furthestRightAngle = this.getIndexAngle(furthestRightIndex);\r
+ furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);\r
+\r
+ radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI / 2);\r
+ radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI / 2);\r
+\r
+ // Ensure we actually need to reduce the size of the chart\r
+ radiusReductionRight = (helpers.isNumber(radiusReductionRight)) ? radiusReductionRight : 0;\r
+ radiusReductionLeft = (helpers.isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;\r
+\r
+ this.drawingArea = Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2);\r
+ this.setCenterPoint(radiusReductionLeft, radiusReductionRight);\r
+ },\r
+ setCenterPoint: function(leftMovement, rightMovement) {\r
+\r
+ var maxRight = this.width - rightMovement - this.drawingArea,\r
+ maxLeft = leftMovement + this.drawingArea;\r
+\r
+ this.xCenter = Math.round(((maxLeft + maxRight) / 2) + this.left);\r
+ // Always vertically in the centre as the text height doesn't change\r
+ this.yCenter = Math.round((this.height / 2) + this.top);\r
+ },\r
+\r
+ getIndexAngle: function(index) {\r
+ var angleMultiplier = (Math.PI * 2) / this.getValueCount();\r
+ // Start from the top instead of right, so remove a quarter of the circle\r
+\r
+ return index * angleMultiplier - (Math.PI / 2);\r
+ },\r
+ getDistanceFromCenterForValue: function(value) {\r
+ if (value === null) {\r
+ return 0; // null always in center\r
+ }\r
+\r
+ // Take into account half font size + the yPadding of the top value\r
+ var scalingFactor = this.drawingArea / (this.max - this.min);\r
+ if (this.options.reverse) {\r
+ return (this.max - value) * scalingFactor;\r
+ } else {\r
+ return (value - this.min) * scalingFactor;\r
+ }\r
+ },\r
+ getPointPosition: function(index, distanceFromCenter) {\r
+ var thisAngle = this.getIndexAngle(index);\r
+ return {\r
+ x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,\r
+ y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + this.yCenter\r
+ };\r
+ },\r
+ getPointPositionForValue: function(index, value) {\r
+ return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));\r
+ },\r
+\r
+ getBasePosition: function() {\r
+ var me = this;\r
+ var min = me.min;\r
+ var max = me.max;\r
+\r
+ return me.getPointPositionForValue(0,\r
+ me.beginAtZero? 0:\r
+ min < 0 && max < 0? max :\r
+ min > 0 && max > 0? min :\r
+ 0);\r
+ },\r
+\r
+ draw: function() {\r
+ if (this.options.display) {\r
+ var ctx = this.ctx;\r
+ helpers.each(this.ticks, function(label, index) {\r
+ // Don't draw a centre value (if it is minimum)\r
+ if (index > 0 || this.options.reverse) {\r
+ var yCenterOffset = this.getDistanceFromCenterForValue(this.ticks[index]);\r
+ var yHeight = this.yCenter - yCenterOffset;\r
+\r
+ // Draw circular lines around the scale\r
+ if (this.options.gridLines.display) {\r
+ ctx.strokeStyle = this.options.gridLines.color;\r
+ ctx.lineWidth = this.options.gridLines.lineWidth;\r
+\r
+ if (this.options.lineArc) {\r
+ // Draw circular arcs between the points\r
+ ctx.beginPath();\r
+ ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI * 2);\r
+ ctx.closePath();\r
+ ctx.stroke();\r
+ } else {\r
+ // Draw straight lines connecting each index\r
+ ctx.beginPath();\r
+ for (var i = 0; i < this.getValueCount(); i++) {\r
+ var pointPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.ticks[index]));\r
+ if (i === 0) {\r
+ ctx.moveTo(pointPosition.x, pointPosition.y);\r
+ } else {\r
+ ctx.lineTo(pointPosition.x, pointPosition.y);\r
+ }\r
+ }\r
+ ctx.closePath();\r
+ ctx.stroke();\r
+ }\r
+ }\r
+\r
+ if (this.options.ticks.display) {\r
+ var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, globalDefaults.defaultFontColor);\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ ctx.font = tickLabelFont;\r
+\r
+ if (this.options.ticks.showLabelBackdrop) {\r
+ var labelWidth = ctx.measureText(label).width;\r
+ ctx.fillStyle = this.options.ticks.backdropColor;\r
+ ctx.fillRect(\r
+ this.xCenter - labelWidth / 2 - this.options.ticks.backdropPaddingX,\r
+ yHeight - tickFontSize / 2 - this.options.ticks.backdropPaddingY,\r
+ labelWidth + this.options.ticks.backdropPaddingX * 2,\r
+ tickFontSize + this.options.ticks.backdropPaddingY * 2\r
+ );\r
+ }\r
+\r
+ ctx.textAlign = 'center';\r
+ ctx.textBaseline = "middle";\r
+ ctx.fillStyle = tickFontColor;\r
+ ctx.fillText(label, this.xCenter, yHeight);\r
+ }\r
+ }\r
+ }, this);\r
+\r
+ if (!this.options.lineArc) {\r
+ ctx.lineWidth = this.options.angleLines.lineWidth;\r
+ ctx.strokeStyle = this.options.angleLines.color;\r
+\r
+ for (var i = this.getValueCount() - 1; i >= 0; i--) {\r
+ if (this.options.angleLines.display) {\r
+ var outerPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max));\r
+ ctx.beginPath();\r
+ ctx.moveTo(this.xCenter, this.yCenter);\r
+ ctx.lineTo(outerPosition.x, outerPosition.y);\r
+ ctx.stroke();\r
+ ctx.closePath();\r
+ }\r
+ // Extra 3px out for some label spacing\r
+ var pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);\r
+\r
+ var pointLabelFontColor = helpers.getValueOrDefault(this.options.pointLabels.fontColor, globalDefaults.defaultFontColor);\r
+ var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, globalDefaults.defaultFontSize);\r
+ var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, globalDefaults.defaultFontStyle);\r
+ var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, globalDefaults.defaultFontFamily);\r
+ var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);\r
+\r
+ ctx.font = pointLabeFont;\r
+ ctx.fillStyle = pointLabelFontColor;\r
+\r
+ var labelsCount = this.pointLabels.length,\r
+ halfLabelsCount = this.pointLabels.length / 2,\r
+ quarterLabelsCount = halfLabelsCount / 2,\r
+ upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),\r
+ exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);\r
+ if (i === 0) {\r
+ ctx.textAlign = 'center';\r
+ } else if (i === halfLabelsCount) {\r
+ ctx.textAlign = 'center';\r
+ } else if (i < halfLabelsCount) {\r
+ ctx.textAlign = 'left';\r
+ } else {\r
+ ctx.textAlign = 'right';\r
+ }\r
+\r
+ // Set the correct text baseline based on outer positioning\r
+ if (exactQuarter) {\r
+ ctx.textBaseline = 'middle';\r
+ } else if (upperHalf) {\r
+ ctx.textBaseline = 'bottom';\r
+ } else {\r
+ ctx.textBaseline = 'top';\r
+ }\r
+\r
+ ctx.fillText(this.pointLabels[i] ? this.pointLabels[i] : '', pointLabelPosition.x, pointLabelPosition.y);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("radialLinear", LinearRadialScale, defaultConfig);\r
+\r
};
},{}],42:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var globalDefaults = Chart.defaults.global;
-
- var defaultConfig = {
- display: true,
-
- //Boolean - Whether to animate scaling the chart from the centre
- animate: true,
- lineArc: false,
- position: "chartArea",
-
- angleLines: {
- display: true,
- color: "rgba(0, 0, 0, 0.1)",
- lineWidth: 1
- },
-
- // label settings
- ticks: {
- //Boolean - Show a backdrop to the scale label
- showLabelBackdrop: true,
-
- //String - The colour of the label backdrop
- backdropColor: "rgba(255,255,255,0.75)",
-
- //Number - The backdrop padding above & below the label in pixels
- backdropPaddingY: 2,
-
- //Number - The backdrop padding to the side of the label in pixels
- backdropPaddingX: 2
- },
-
- pointLabels: {
- //Number - Point label font size in pixels
- fontSize: 10,
-
- //Function - Used to convert point labels
- callback: function(label) {
- return label;
- }
- }
- };
-
- var LinearRadialScale = Chart.LinearScaleBase.extend({
- getValueCount: function() {
- return this.chart.data.labels.length;
- },
- setDimensions: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- // Set the unconstrained dimension before label rotation
- me.width = me.maxWidth;
- me.height = me.maxHeight;
- me.xCenter = Math.round(me.width / 2);
- me.yCenter = Math.round(me.height / 2);
-
- var minSize = helpers.min([me.height, me.width]);
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2);
- },
- determineDataLimits: function() {
- var me = this;
- var chart = me.chart;
- me.min = null;
- me.max = null;
-
-
- helpers.each(chart.data.datasets, function(dataset, datasetIndex) {
- if (chart.isDatasetVisible(datasetIndex)) {
- var meta = chart.getDatasetMeta(datasetIndex);
-
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
-
- // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
- me.handleTickRangeOptions();
- },
- getTickLimit: function() {
- var tickOpts = this.options.ticks;
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));
- },
- convertTicksToLabels: function() {
- var me = this;
- Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me);
-
- // Point labels
- me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me);
- },
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- fit: function() {
- /*
- * Right, this is really confusing and there is a lot of maths going on here
- * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
- *
- * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
- *
- * Solution:
- *
- * We assume the radius of the polygon is half the size of the canvas at first
- * at each index we check if the text overlaps.
- *
- * Where it does, we store that angle and that index.
- *
- * After finding the largest index and angle we calculate how much we need to remove
- * from the shape radius to move the point inwards by that x.
- *
- * We average the left and right distances to get the maximum shape radius that can fit in the box
- * along with labels.
- *
- * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
- * on each side, removing that from the size, halving it and adding the left x protrusion width.
- *
- * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
- * and position it in the most space efficient manner
- *
- * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
- */
-
- var pointLabels = this.options.pointLabels;
- var pointLabelFontSize = helpers.getValueOrDefault(pointLabels.fontSize, globalDefaults.defaultFontSize);
- var pointLabeFontStyle = helpers.getValueOrDefault(pointLabels.fontStyle, globalDefaults.defaultFontStyle);
- var pointLabeFontFamily = helpers.getValueOrDefault(pointLabels.fontFamily, globalDefaults.defaultFontFamily);
- var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
-
- // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
- // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
- var largestPossibleRadius = helpers.min([(this.height / 2 - pointLabelFontSize - 5), this.width / 2]),
- pointPosition,
- i,
- textWidth,
- halfTextWidth,
- furthestRight = this.width,
- furthestRightIndex,
- furthestRightAngle,
- furthestLeft = 0,
- furthestLeftIndex,
- furthestLeftAngle,
- xProtrusionLeft,
- xProtrusionRight,
- radiusReductionRight,
- radiusReductionLeft,
- maxWidthRadius;
- this.ctx.font = pointLabeFont;
-
- for (i = 0; i < this.getValueCount(); i++) {
- // 5px to space the text slightly out - similar to what we do in the draw function.
- pointPosition = this.getPointPosition(i, largestPossibleRadius);
- textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;
- if (i === 0 || i === this.getValueCount() / 2) {
- // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
- // of the radar chart, so text will be aligned centrally, so we'll half it and compare
- // w/left and right text sizes
- halfTextWidth = textWidth / 2;
- if (pointPosition.x + halfTextWidth > furthestRight) {
- furthestRight = pointPosition.x + halfTextWidth;
- furthestRightIndex = i;
- }
- if (pointPosition.x - halfTextWidth < furthestLeft) {
- furthestLeft = pointPosition.x - halfTextWidth;
- furthestLeftIndex = i;
- }
- } else if (i < this.getValueCount() / 2) {
- // Less than half the values means we'll left align the text
- if (pointPosition.x + textWidth > furthestRight) {
- furthestRight = pointPosition.x + textWidth;
- furthestRightIndex = i;
- }
- } else if (i > this.getValueCount() / 2) {
- // More than half the values means we'll right align the text
- if (pointPosition.x - textWidth < furthestLeft) {
- furthestLeft = pointPosition.x - textWidth;
- furthestLeftIndex = i;
- }
- }
- }
-
- xProtrusionLeft = furthestLeft;
- xProtrusionRight = Math.ceil(furthestRight - this.width);
-
- furthestRightAngle = this.getIndexAngle(furthestRightIndex);
- furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
-
- radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI / 2);
- radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI / 2);
-
- // Ensure we actually need to reduce the size of the chart
- radiusReductionRight = (helpers.isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
- radiusReductionLeft = (helpers.isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
-
- this.drawingArea = Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2);
- this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
- },
- setCenterPoint: function(leftMovement, rightMovement) {
- var me = this;
- var maxRight = me.width - rightMovement - me.drawingArea,
- maxLeft = leftMovement + me.drawingArea;
-
- me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left);
- // Always vertically in the centre as the text height doesn't change
- me.yCenter = Math.round((me.height / 2) + me.top);
- },
-
- getIndexAngle: function(index) {
- var angleMultiplier = (Math.PI * 2) / this.getValueCount();
- // Start from the top instead of right, so remove a quarter of the circle
-
- return index * angleMultiplier - (Math.PI / 2);
- },
- getDistanceFromCenterForValue: function(value) {
- var me = this;
-
- if (value === null) {
- return 0; // null always in center
- }
-
- // Take into account half font size + the yPadding of the top value
- var scalingFactor = me.drawingArea / (me.max - me.min);
- if (me.options.reverse) {
- return (me.max - value) * scalingFactor;
- } else {
- return (value - me.min) * scalingFactor;
- }
- },
- getPointPosition: function(index, distanceFromCenter) {
- var me = this;
- var thisAngle = me.getIndexAngle(index);
- return {
- x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter,
- y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter
- };
- },
- getPointPositionForValue: function(index, value) {
- return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
- },
-
- getBasePosition: function() {
- var me = this;
- var min = me.min;
- var max = me.max;
-
- return me.getPointPositionForValue(0,
- me.beginAtZero? 0:
- min < 0 && max < 0? max :
- min > 0 && max > 0? min :
- 0);
- },
-
- draw: function() {
- var me = this;
- var opts = me.options;
- var gridLineOpts = opts.gridLines;
- var tickOpts = opts.ticks;
- var angleLineOpts = opts.angleLines;
- var pointLabelOpts = opts.pointLabels;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- if (opts.display) {
- var ctx = me.ctx;
-
- // Tick Font
- var tickFontSize = getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
-
- helpers.each(me.ticks, function(label, index) {
- // Don't draw a centre value (if it is minimum)
- if (index > 0 || opts.reverse) {
- var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]);
- var yHeight = me.yCenter - yCenterOffset;
-
- // Draw circular lines around the scale
- if (gridLineOpts.display) {
- ctx.strokeStyle = gridLineOpts.color;
- ctx.lineWidth = gridLineOpts.lineWidth;
-
- if (opts.lineArc) {
- // Draw circular arcs between the points
- ctx.beginPath();
- ctx.arc(me.xCenter, me.yCenter, yCenterOffset, 0, Math.PI * 2);
- ctx.closePath();
- ctx.stroke();
- } else {
- // Draw straight lines connecting each index
- ctx.beginPath();
- for (var i = 0; i < me.getValueCount(); i++) {
- var pointPosition = me.getPointPosition(i, yCenterOffset);
- if (i === 0) {
- ctx.moveTo(pointPosition.x, pointPosition.y);
- } else {
- ctx.lineTo(pointPosition.x, pointPosition.y);
- }
- }
- ctx.closePath();
- ctx.stroke();
- }
- }
-
- if (tickOpts.display) {
- var tickFontColor = getValueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor);
- ctx.font = tickLabelFont;
-
- if (tickOpts.showLabelBackdrop) {
- var labelWidth = ctx.measureText(label).width;
- ctx.fillStyle = tickOpts.backdropColor;
- ctx.fillRect(
- me.xCenter - labelWidth / 2 - tickOpts.backdropPaddingX,
- yHeight - tickFontSize / 2 - tickOpts.backdropPaddingY,
- labelWidth + tickOpts.backdropPaddingX * 2,
- tickFontSize + tickOpts.backdropPaddingY * 2
- );
- }
-
- ctx.textAlign = 'center';
- ctx.textBaseline = "middle";
- ctx.fillStyle = tickFontColor;
- ctx.fillText(label, me.xCenter, yHeight);
- }
- }
- });
-
- if (!opts.lineArc) {
- ctx.lineWidth = angleLineOpts.lineWidth;
- ctx.strokeStyle = angleLineOpts.color;
-
- var outerDistance = me.getDistanceFromCenterForValue(opts.reverse ? me.min : me.max);
-
- // Point Label Font
- var pointLabelFontSize = getValueOrDefault(pointLabelOpts.fontSize, globalDefaults.defaultFontSize);
- var pointLabeFontStyle = getValueOrDefault(pointLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
- var pointLabeFontFamily = getValueOrDefault(pointLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
- var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
-
- for (var i = me.getValueCount() - 1; i >= 0; i--) {
- if (angleLineOpts.display) {
- var outerPosition = me.getPointPosition(i, outerDistance);
- ctx.beginPath();
- ctx.moveTo(me.xCenter, me.yCenter);
- ctx.lineTo(outerPosition.x, outerPosition.y);
- ctx.stroke();
- ctx.closePath();
- }
- // Extra 3px out for some label spacing
- var pointLabelPosition = me.getPointPosition(i, outerDistance + 5);
-
- // Keep this in loop since we may support array properties here
- var pointLabelFontColor = getValueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor);
- ctx.font = pointLabeFont;
- ctx.fillStyle = pointLabelFontColor;
-
- var pointLabels = me.pointLabels,
- labelsCount = pointLabels.length,
- halfLabelsCount = pointLabels.length / 2,
- quarterLabelsCount = halfLabelsCount / 2,
- upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
- exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
- if (i === 0) {
- ctx.textAlign = 'center';
- } else if (i === halfLabelsCount) {
- ctx.textAlign = 'center';
- } else if (i < halfLabelsCount) {
- ctx.textAlign = 'left';
- } else {
- ctx.textAlign = 'right';
- }
-
- // Set the correct text baseline based on outer positioning
- if (exactQuarter) {
- ctx.textBaseline = 'middle';
- } else if (upperHalf) {
- ctx.textBaseline = 'bottom';
- } else {
- ctx.textBaseline = 'top';
- }
-
- ctx.fillText(pointLabels[i] ? pointLabels[i] : '', pointLabelPosition.x, pointLabelPosition.y);
- }
- }
- }
- }
- });
- Chart.scaleService.registerScaleType("radialLinear", LinearRadialScale, defaultConfig);
-
-};
-
-},{}],43:[function(require,module,exports){
-/*global window: false */
-"use strict";
-
-var moment = require(6);
-moment = typeof(moment) === 'function' ? moment : window.moment;
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var time = {
- units: [{
- name: 'millisecond',
- steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]
- }, {
- name: 'second',
- steps: [1, 2, 5, 10, 30]
- }, {
- name: 'minute',
- steps: [1, 2, 5, 10, 30]
- }, {
- name: 'hour',
- steps: [1, 2, 3, 6, 12]
- }, {
- name: 'day',
- steps: [1, 2, 5]
- }, {
- name: 'week',
- maxStep: 4
- }, {
- name: 'month',
- maxStep: 3
- }, {
- name: 'quarter',
- maxStep: 4
- }, {
- name: 'year',
- maxStep: false
- }]
- };
-
- var defaultConfig = {
- position: "bottom",
-
- time: {
- parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
- format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/
- unit: false, // false == automatic or override with week, month, year, etc.
- round: false, // none, or override with week, month, year, etc.
- displayFormat: false, // DEPRECATED
- isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/
-
- // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
- displayFormats: {
- 'millisecond': 'h:mm:ss.SSS a', // 11:20:01.123 AM,
- 'second': 'h:mm:ss a', // 11:20:01 AM
- 'minute': 'h:mm:ss a', // 11:20:01 AM
- 'hour': 'MMM D, hA', // Sept 4, 5PM
- 'day': 'll', // Sep 4 2015
- 'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
- 'month': 'MMM YYYY', // Sept 2015
- 'quarter': '[Q]Q - YYYY', // Q3
- 'year': 'YYYY' // 2015
- }
- },
- ticks: {
- autoSkip: false
- }
- };
-
- var TimeScale = Chart.Scale.extend({
- initialize: function() {
- if (!moment) {
- throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');
- }
-
- Chart.Scale.prototype.initialize.call(this);
- },
- getLabelMoment: function(datasetIndex, index) {
- return this.labelMoments[datasetIndex][index];
- },
- getMomentStartOf: function(tick) {
- var me = this;
- if (me.options.time.unit === 'week' && me.options.time.isoWeekday !== false) {
- return tick.clone().startOf('isoWeek').isoWeekday(me.options.time.isoWeekday);
- } else {
- return tick.clone().startOf(me.tickUnit);
- }
- },
- determineDataLimits: function() {
- var me = this;
- me.labelMoments = [];
-
- // Only parse these once. If the dataset does not have data as x,y pairs, we will use
- // these
- var scaleLabelMoments = [];
- if (me.chart.data.labels && me.chart.data.labels.length > 0) {
- helpers.each(me.chart.data.labels, function(label, index) {
- var labelMoment = me.parseTime(label);
-
- if (labelMoment.isValid()) {
- if (me.options.time.round) {
- labelMoment.startOf(me.options.time.round);
- }
- scaleLabelMoments.push(labelMoment);
- }
- }, me);
-
- me.firstTick = moment.min.call(me, scaleLabelMoments);
- me.lastTick = moment.max.call(me, scaleLabelMoments);
- } else {
- me.firstTick = null;
- me.lastTick = null;
- }
-
- helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
- var momentsForDataset = [];
- var datasetVisible = me.chart.isDatasetVisible(datasetIndex);
-
- if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {
- helpers.each(dataset.data, function(value, index) {
- var labelMoment = me.parseTime(me.getRightValue(value));
-
- if (labelMoment.isValid()) {
- if (me.options.time.round) {
- labelMoment.startOf(me.options.time.round);
- }
- momentsForDataset.push(labelMoment);
-
- if (datasetVisible) {
- // May have gone outside the scale ranges, make sure we keep the first and last ticks updated
- me.firstTick = me.firstTick !== null ? moment.min(me.firstTick, labelMoment) : labelMoment;
- me.lastTick = me.lastTick !== null ? moment.max(me.lastTick, labelMoment) : labelMoment;
- }
- }
- }, me);
- } else {
- // We have no labels. Use the ones from the scale
- momentsForDataset = scaleLabelMoments;
- }
-
- me.labelMoments.push(momentsForDataset);
- }, me);
-
- // Set these after we've done all the data
- if (me.options.time.min) {
- me.firstTick = me.parseTime(me.options.time.min);
- }
-
- if (me.options.time.max) {
- me.lastTick = me.parseTime(me.options.time.max);
- }
-
- // We will modify these, so clone for later
- me.firstTick = (me.firstTick || moment()).clone();
- me.lastTick = (me.lastTick || moment()).clone();
- },
- buildTicks: function(index) {
- var me = this;
-
- me.ctx.save();
- var tickFontSize = helpers.getValueOrDefault(me.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(me.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(me.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- me.ctx.font = tickLabelFont;
-
- me.ticks = [];
- me.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step
- me.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc)
-
- // Set unit override if applicable
- if (me.options.time.unit) {
- me.tickUnit = me.options.time.unit || 'day';
- me.displayFormat = me.options.time.displayFormats[me.tickUnit];
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, 1);
- } else {
- // Determine the smallest needed unit of the time
- var innerWidth = me.isHorizontal() ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
-
- // Crude approximation of what the label length might be
- var tempFirstLabel = me.tickFormatFunction(me.firstTick, 0, []);
- var tickLabelWidth = me.ctx.measureText(tempFirstLabel).width;
- var cosRotation = Math.cos(helpers.toRadians(me.options.ticks.maxRotation));
- var sinRotation = Math.sin(helpers.toRadians(me.options.ticks.maxRotation));
- tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
- var labelCapacity = innerWidth / (tickLabelWidth);
-
- // Start as small as possible
- me.tickUnit = 'millisecond';
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- me.displayFormat = me.options.time.displayFormats[me.tickUnit];
-
- var unitDefinitionIndex = 0;
- var unitDefinition = time.units[unitDefinitionIndex];
-
- // While we aren't ideal and we don't have units left
- while (unitDefinitionIndex < time.units.length) {
- // Can we scale this unit. If `false` we can scale infinitely
- me.unitScale = 1;
-
- if (helpers.isArray(unitDefinition.steps) && Math.ceil(me.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) {
- // Use one of the prefedined steps
- for (var idx = 0; idx < unitDefinition.steps.length; ++idx) {
- if (unitDefinition.steps[idx] >= Math.ceil(me.scaleSizeInUnits / labelCapacity)) {
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, unitDefinition.steps[idx]);
- break;
- }
- }
-
- break;
- } else if ((unitDefinition.maxStep === false) || (Math.ceil(me.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) {
- // We have a max step. Scale this unit
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, Math.ceil(me.scaleSizeInUnits / labelCapacity));
- break;
- } else {
- // Move to the next unit up
- ++unitDefinitionIndex;
- unitDefinition = time.units[unitDefinitionIndex];
-
- me.tickUnit = unitDefinition.name;
- var leadingUnitBuffer = me.firstTick.diff(me.getMomentStartOf(me.firstTick), me.tickUnit, true);
- var trailingUnitBuffer = me.getMomentStartOf(me.lastTick.clone().add(1, me.tickUnit)).diff(me.lastTick, me.tickUnit, true);
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer;
- me.displayFormat = me.options.time.displayFormats[unitDefinition.name];
- }
- }
- }
-
- var roundedStart;
-
- // Only round the first tick if we have no hard minimum
- if (!me.options.time.min) {
- me.firstTick = me.getMomentStartOf(me.firstTick);
- roundedStart = me.firstTick;
- } else {
- roundedStart = me.getMomentStartOf(me.firstTick);
- }
-
- // Only round the last tick if we have no hard maximum
- if (!me.options.time.max) {
- var roundedEnd = me.getMomentStartOf(me.lastTick);
- if (roundedEnd.diff(me.lastTick, me.tickUnit, true) !== 0) {
- // Do not use end of because we need me to be in the next time unit
- me.lastTick = me.getMomentStartOf(me.lastTick.add(1, me.tickUnit));
- }
- }
-
- me.smallestLabelSeparation = me.width;
-
- helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
- for (var i = 1; i < me.labelMoments[datasetIndex].length; i++) {
- me.smallestLabelSeparation = Math.min(me.smallestLabelSeparation, me.labelMoments[datasetIndex][i].diff(me.labelMoments[datasetIndex][i - 1], me.tickUnit, true));
- }
- }, me);
-
- // Tick displayFormat override
- if (me.options.time.displayFormat) {
- me.displayFormat = me.options.time.displayFormat;
- }
-
- // first tick. will have been rounded correctly if options.time.min is not specified
- me.ticks.push(me.firstTick.clone());
-
- // For every unit in between the first and last moment, create a moment and add it to the ticks tick
- for (var i = 1; i <= me.scaleSizeInUnits; ++i) {
- var newTick = roundedStart.clone().add(i, me.tickUnit);
-
- // Are we greater than the max time
- if (me.options.time.max && newTick.diff(me.lastTick, me.tickUnit, true) >= 0) {
- break;
- }
-
- if (i % me.unitScale === 0) {
- me.ticks.push(newTick);
- }
- }
-
- // Always show the right tick
- var diff = me.ticks[me.ticks.length - 1].diff(me.lastTick, me.tickUnit);
- if (diff !== 0 || me.scaleSizeInUnits === 0) {
- // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart
- // but the last tick was not rounded.
- if (me.options.time.max) {
- me.ticks.push(me.lastTick.clone());
- me.scaleSizeInUnits = me.lastTick.diff(me.ticks[0], me.tickUnit, true);
- } else {
- me.ticks.push(me.lastTick.clone());
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- }
- }
-
- me.ctx.restore();
- },
- // Get tooltip label
- getLabelForIndex: function(index, datasetIndex) {
- var me = this;
- var label = me.chart.data.labels && index < me.chart.data.labels.length ? me.chart.data.labels[index] : '';
-
- if (typeof me.chart.data.datasets[datasetIndex].data[0] === 'object') {
- label = me.getRightValue(me.chart.data.datasets[datasetIndex].data[index]);
- }
-
- // Format nicely
- if (me.options.time.tooltipFormat) {
- label = me.parseTime(label).format(me.options.time.tooltipFormat);
- }
-
- return label;
- },
- // Function to format an individual tick mark
- tickFormatFunction: function tickFormatFunction(tick, index, ticks) {
- var formattedTick = tick.format(this.displayFormat);
- var tickOpts = this.options.ticks;
- var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);
-
- if (callback) {
- return callback(formattedTick, index, ticks);
- } else {
- return formattedTick;
- }
- },
- convertTicksToLabels: function() {
- var me = this;
- me.tickMoments = me.ticks;
- me.ticks = me.ticks.map(me.tickFormatFunction, me);
- },
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- var labelMoment = value && value.isValid && value.isValid() ? value : me.getLabelMoment(datasetIndex, index);
-
- if (labelMoment) {
- var offset = labelMoment.diff(me.firstTick, me.tickUnit, true);
-
- var decimal = offset / me.scaleSizeInUnits;
-
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueWidth = innerWidth / Math.max(me.ticks.length - 1, 1);
- var valueOffset = (innerWidth * decimal) + me.paddingLeft;
-
- return me.left + Math.round(valueOffset);
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- var valueHeight = innerHeight / Math.max(me.ticks.length - 1, 1);
- var heightOffset = (innerHeight * decimal) + me.paddingTop;
-
- return me.top + Math.round(heightOffset);
- }
- }
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var innerDimension = me.isHorizontal() ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
- var offset = (pixel - (me.isHorizontal() ? me.left + me.paddingLeft : me.top + me.paddingTop)) / innerDimension;
- offset *= me.scaleSizeInUnits;
- return me.firstTick.clone().add(moment.duration(offset, me.tickUnit).asSeconds(), 'seconds');
- },
- parseTime: function(label) {
- var me = this;
- if (typeof me.options.time.parser === 'string') {
- return moment(label, me.options.time.parser);
- }
- if (typeof me.options.time.parser === 'function') {
- return me.options.time.parser(label);
- }
- // Date objects
- if (typeof label.getMonth === 'function' || typeof label === 'number') {
- return moment(label);
- }
- // Moment support
- if (label.isValid && label.isValid()) {
- return label;
- }
- // Custom parsing (return an instance of moment)
- if (typeof me.options.time.format !== 'string' && me.options.time.format.call) {
- console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale");
- return me.options.time.format(label);
- }
- // Moment format parsing
- return moment(label, me.options.time.format);
- }
- });
- Chart.scaleService.registerScaleType("time", TimeScale, defaultConfig);
-
-};
+/*global window: false */\r
+"use strict";\r
+\r
+var moment = require('moment');\r
+moment = typeof(moment) === 'function' ? moment : window.moment;\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var time = {\r
+ units: [{\r
+ name: 'millisecond',\r
+ steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]\r
+ }, {\r
+ name: 'second',\r
+ steps: [1, 2, 5, 10, 30]\r
+ }, {\r
+ name: 'minute',\r
+ steps: [1, 2, 5, 10, 30]\r
+ }, {\r
+ name: 'hour',\r
+ steps: [1, 2, 3, 6, 12]\r
+ }, {\r
+ name: 'day',\r
+ steps: [1, 2, 5]\r
+ }, {\r
+ name: 'week',\r
+ maxStep: 4\r
+ }, {\r
+ name: 'month',\r
+ maxStep: 3\r
+ }, {\r
+ name: 'quarter',\r
+ maxStep: 4\r
+ }, {\r
+ name: 'year',\r
+ maxStep: false\r
+ }]\r
+ };\r
+\r
+ var defaultConfig = {\r
+ position: "bottom",\r
+\r
+ time: {\r
+ parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment\r
+ format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/\r
+ unit: false, // false == automatic or override with week, month, year, etc.\r
+ round: false, // none, or override with week, month, year, etc.\r
+ displayFormat: false, // DEPRECATED\r
+ isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/\r
+\r
+ // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/\r
+ displayFormats: {\r
+ 'millisecond': 'h:mm:ss.SSS a', // 11:20:01.123 AM,\r
+ 'second': 'h:mm:ss a', // 11:20:01 AM\r
+ 'minute': 'h:mm:ss a', // 11:20:01 AM\r
+ 'hour': 'MMM D, hA', // Sept 4, 5PM\r
+ 'day': 'll', // Sep 4 2015\r
+ 'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?\r
+ 'month': 'MMM YYYY', // Sept 2015\r
+ 'quarter': '[Q]Q - YYYY', // Q3\r
+ 'year': 'YYYY' // 2015\r
+ }\r
+ },\r
+ ticks: {\r
+ autoSkip: false\r
+ }\r
+ };\r
+\r
+ var TimeScale = Chart.Scale.extend({\r
+ initialize: function() {\r
+ if (!moment) {\r
+ throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');\r
+ }\r
+\r
+ Chart.Scale.prototype.initialize.call(this);\r
+ },\r
+ getLabelMoment: function(datasetIndex, index) {\r
+ return this.labelMoments[datasetIndex][index];\r
+ },\r
+ getMomentStartOf: function(tick) {\r
+ if (this.options.time.unit === 'week' && this.options.time.isoWeekday !== false) {\r
+ return tick.clone().startOf('isoWeek').isoWeekday(this.options.time.isoWeekday);\r
+ } else {\r
+ return tick.clone().startOf(this.tickUnit);\r
+ }\r
+ },\r
+ determineDataLimits: function() {\r
+ this.labelMoments = [];\r
+\r
+ // Only parse these once. If the dataset does not have data as x,y pairs, we will use\r
+ // these\r
+ var scaleLabelMoments = [];\r
+ if (this.chart.data.labels && this.chart.data.labels.length > 0) {\r
+ helpers.each(this.chart.data.labels, function(label, index) {\r
+ var labelMoment = this.parseTime(label);\r
+\r
+ if (labelMoment.isValid()) {\r
+ if (this.options.time.round) {\r
+ labelMoment.startOf(this.options.time.round);\r
+ }\r
+ scaleLabelMoments.push(labelMoment);\r
+ }\r
+ }, this);\r
+\r
+ this.firstTick = moment.min.call(this, scaleLabelMoments);\r
+ this.lastTick = moment.max.call(this, scaleLabelMoments);\r
+ } else {\r
+ this.firstTick = null;\r
+ this.lastTick = null;\r
+ }\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ var momentsForDataset = [];\r
+ var datasetVisible = this.chart.isDatasetVisible(datasetIndex);\r
+\r
+ if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {\r
+ helpers.each(dataset.data, function(value, index) {\r
+ var labelMoment = this.parseTime(this.getRightValue(value));\r
+\r
+ if (labelMoment.isValid()) {\r
+ if (this.options.time.round) {\r
+ labelMoment.startOf(this.options.time.round);\r
+ }\r
+ momentsForDataset.push(labelMoment);\r
+\r
+ if (datasetVisible) {\r
+ // May have gone outside the scale ranges, make sure we keep the first and last ticks updated\r
+ this.firstTick = this.firstTick !== null ? moment.min(this.firstTick, labelMoment) : labelMoment;\r
+ this.lastTick = this.lastTick !== null ? moment.max(this.lastTick, labelMoment) : labelMoment;\r
+ }\r
+ }\r
+ }, this);\r
+ } else {\r
+ // We have no labels. Use the ones from the scale\r
+ momentsForDataset = scaleLabelMoments;\r
+ }\r
+\r
+ this.labelMoments.push(momentsForDataset);\r
+ }, this);\r
+\r
+ // Set these after we've done all the data\r
+ if (this.options.time.min) {\r
+ this.firstTick = this.parseTime(this.options.time.min);\r
+ }\r
+\r
+ if (this.options.time.max) {\r
+ this.lastTick = this.parseTime(this.options.time.max);\r
+ }\r
+\r
+ // We will modify these, so clone for later\r
+ this.firstTick = (this.firstTick || moment()).clone();\r
+ this.lastTick = (this.lastTick || moment()).clone();\r
+ },\r
+ buildTicks: function(index) {\r
+\r
+ this.ctx.save();\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ this.ctx.font = tickLabelFont;\r
+\r
+ this.ticks = [];\r
+ this.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step\r
+ this.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc)\r
+\r
+ // Set unit override if applicable\r
+ if (this.options.time.unit) {\r
+ this.tickUnit = this.options.time.unit || 'day';\r
+ this.displayFormat = this.options.time.displayFormats[this.tickUnit];\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, 1);\r
+ } else {\r
+ // Determine the smallest needed unit of the time\r
+ var innerWidth = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+\r
+ // Crude approximation of what the label length might be\r
+ var tempFirstLabel = this.tickFormatFunction(this.firstTick, 0, []);\r
+ var tickLabelWidth = this.ctx.measureText(tempFirstLabel).width;\r
+ var cosRotation = Math.cos(helpers.toRadians(this.options.ticks.maxRotation));\r
+ var sinRotation = Math.sin(helpers.toRadians(this.options.ticks.maxRotation));\r
+ tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);\r
+ var labelCapacity = innerWidth / (tickLabelWidth);\r
+\r
+ // Start as small as possible\r
+ this.tickUnit = 'millisecond';\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ this.displayFormat = this.options.time.displayFormats[this.tickUnit];\r
+\r
+ var unitDefinitionIndex = 0;\r
+ var unitDefinition = time.units[unitDefinitionIndex];\r
+\r
+ // While we aren't ideal and we don't have units left\r
+ while (unitDefinitionIndex < time.units.length) {\r
+ // Can we scale this unit. If `false` we can scale infinitely\r
+ this.unitScale = 1;\r
+\r
+ if (helpers.isArray(unitDefinition.steps) && Math.ceil(this.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) {\r
+ // Use one of the prefedined steps\r
+ for (var idx = 0; idx < unitDefinition.steps.length; ++idx) {\r
+ if (unitDefinition.steps[idx] >= Math.ceil(this.scaleSizeInUnits / labelCapacity)) {\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, unitDefinition.steps[idx]);\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+ } else if ((unitDefinition.maxStep === false) || (Math.ceil(this.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) {\r
+ // We have a max step. Scale this unit\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, Math.ceil(this.scaleSizeInUnits / labelCapacity));\r
+ break;\r
+ } else {\r
+ // Move to the next unit up\r
+ ++unitDefinitionIndex;\r
+ unitDefinition = time.units[unitDefinitionIndex];\r
+\r
+ this.tickUnit = unitDefinition.name;\r
+ var leadingUnitBuffer = this.firstTick.diff(this.getMomentStartOf(this.firstTick), this.tickUnit, true);\r
+ var trailingUnitBuffer = this.getMomentStartOf(this.lastTick.clone().add(1, this.tickUnit)).diff(this.lastTick, this.tickUnit, true);\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer;\r
+ this.displayFormat = this.options.time.displayFormats[unitDefinition.name];\r
+ }\r
+ }\r
+ }\r
+\r
+ var roundedStart;\r
+\r
+ // Only round the first tick if we have no hard minimum\r
+ if (!this.options.time.min) {\r
+ this.firstTick = this.getMomentStartOf(this.firstTick);\r
+ roundedStart = this.firstTick;\r
+ } else {\r
+ roundedStart = this.getMomentStartOf(this.firstTick);\r
+ }\r
+\r
+ // Only round the last tick if we have no hard maximum\r
+ if (!this.options.time.max) {\r
+ var roundedEnd = this.getMomentStartOf(this.lastTick);\r
+ if (roundedEnd.diff(this.lastTick, this.tickUnit, true) !== 0) {\r
+ // Do not use end of because we need this to be in the next time unit\r
+ this.lastTick = this.getMomentStartOf(this.lastTick.add(1, this.tickUnit));\r
+ }\r
+ }\r
+\r
+ this.smallestLabelSeparation = this.width;\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ for (var i = 1; i < this.labelMoments[datasetIndex].length; i++) {\r
+ this.smallestLabelSeparation = Math.min(this.smallestLabelSeparation, this.labelMoments[datasetIndex][i].diff(this.labelMoments[datasetIndex][i - 1], this.tickUnit, true));\r
+ }\r
+ }, this);\r
+\r
+ // Tick displayFormat override\r
+ if (this.options.time.displayFormat) {\r
+ this.displayFormat = this.options.time.displayFormat;\r
+ }\r
+\r
+ // first tick. will have been rounded correctly if options.time.min is not specified\r
+ this.ticks.push(this.firstTick.clone());\r
+\r
+ // For every unit in between the first and last moment, create a moment and add it to the ticks tick\r
+ for (var i = 1; i <= this.scaleSizeInUnits; ++i) {\r
+ var newTick = roundedStart.clone().add(i, this.tickUnit);\r
+\r
+ // Are we greater than the max time\r
+ if (this.options.time.max && newTick.diff(this.lastTick, this.tickUnit, true) >= 0) {\r
+ break;\r
+ }\r
+\r
+ if (i % this.unitScale === 0) {\r
+ this.ticks.push(newTick);\r
+ }\r
+ }\r
+\r
+ // Always show the right tick\r
+ var diff = this.ticks[this.ticks.length - 1].diff(this.lastTick, this.tickUnit);\r
+ if (diff !== 0 || this.scaleSizeInUnits === 0) {\r
+ // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart\r
+ // but the last tick was not rounded.\r
+ if (this.options.time.max) {\r
+ this.ticks.push(this.lastTick.clone());\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.ticks[0], this.tickUnit, true);\r
+ } else {\r
+ this.ticks.push(this.lastTick.clone());\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ }\r
+ }\r
+\r
+ this.ctx.restore();\r
+ },\r
+ // Get tooltip label\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ var label = this.chart.data.labels && index < this.chart.data.labels.length ? this.chart.data.labels[index] : '';\r
+\r
+ if (typeof this.chart.data.datasets[datasetIndex].data[0] === 'object') {\r
+ label = this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ }\r
+\r
+ // Format nicely\r
+ if (this.options.time.tooltipFormat) {\r
+ label = this.parseTime(label).format(this.options.time.tooltipFormat);\r
+ }\r
+\r
+ return label;\r
+ },\r
+ // Function to format an individual tick mark\r
+ tickFormatFunction: function tickFormatFunction(tick, index, ticks) {\r
+ var formattedTick = tick.format(this.displayFormat);\r
+ var tickOpts = this.options.ticks;\r
+ var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);\r
+\r
+ if (callback) {\r
+ return callback(formattedTick, index, ticks);\r
+ } else {\r
+ return formattedTick;\r
+ }\r
+ },\r
+ convertTicksToLabels: function() {\r
+ this.tickMoments = this.ticks;\r
+ this.ticks = this.ticks.map(this.tickFormatFunction, this);\r
+ },\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ var labelMoment = value && value.isValid && value.isValid() ? value : this.getLabelMoment(datasetIndex, index);\r
+\r
+ if (labelMoment) {\r
+ var offset = labelMoment.diff(this.firstTick, this.tickUnit, true);\r
+\r
+ var decimal = offset / this.scaleSizeInUnits;\r
+\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueWidth = innerWidth / Math.max(this.ticks.length - 1, 1);\r
+ var valueOffset = (innerWidth * decimal) + this.paddingLeft;\r
+\r
+ return this.left + Math.round(valueOffset);\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueHeight = innerHeight / Math.max(this.ticks.length - 1, 1);\r
+ var heightOffset = (innerHeight * decimal) + this.paddingTop;\r
+\r
+ return this.top + Math.round(heightOffset);\r
+ }\r
+ }\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var innerDimension = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+ var offset = (pixel - (this.isHorizontal() ? this.left + this.paddingLeft : this.top + this.paddingTop)) / innerDimension;\r
+ offset *= this.scaleSizeInUnits;\r
+ return this.firstTick.clone().add(moment.duration(offset, this.tickUnit).asSeconds(), 'seconds');\r
+ },\r
+ parseTime: function(label) {\r
+ if (typeof this.options.time.parser === 'string') {\r
+ return moment(label, this.options.time.parser);\r
+ }\r
+ if (typeof this.options.time.parser === 'function') {\r
+ return this.options.time.parser(label);\r
+ }\r
+ // Date objects\r
+ if (typeof label.getMonth === 'function' || typeof label === 'number') {\r
+ return moment(label);\r
+ }\r
+ // Moment support\r
+ if (label.isValid && label.isValid()) {\r
+ return label;\r
+ }\r
+ // Custom parsing (return an instance of moment)\r
+ if (typeof this.options.time.format !== 'string' && this.options.time.format.call) {\r
+ console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale");\r
+ return this.options.time.format(label);\r
+ }\r
+ // Moment format parsing\r
+ return moment(label, this.options.time.format);\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("time", TimeScale, defaultConfig);\r
+\r
+};\r
-},{"6":6}]},{},[7])(7)
-});
\ No newline at end of file
+},{"moment":6}]},{},[7]);
* Released under the MIT license
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
*/
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Chart=t()}}(function(){var t;return function e(t,n,i){function a(o,s){if(!n[o]){if(!t[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var d=new Error("Cannot find module '"+o+"'");throw d.code="MODULE_NOT_FOUND",d}var u=n[o]={exports:{}};t[o][0].call(u.exports,function(e){var n=t[o][1][e];return a(n?n:e)},u,u.exports,e,t,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)a(i[o]);return a}({1:[function(t,e,n){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/,n=/^#([a-fA-F0-9]{6})$/,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,r=/(\w+)/,o=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(var d=0;d<o.length;d++)o[d]=parseInt(l[d]+l[d],16)}else if(l=t.match(n)){l=l[1];for(var d=0;d<o.length;d++)o[d]=parseInt(l.slice(2*d,2*d+2),16)}else if(l=t.match(i)){for(var d=0;d<o.length;d++)o[d]=parseInt(l[d+1]);s=parseFloat(l[4])}else if(l=t.match(a)){for(var d=0;d<o.length;d++)o[d]=Math.round(2.55*parseFloat(l[d+1]));s=parseFloat(l[4])}else if(l=t.match(r)){if("transparent"==l[1])return[0,0,0,0];if(o=x[l[1]],!o)return}for(var d=0;d<o.length;d++)o[d]=b(o[d],0,255);return s=s||0==s?b(s,0,1):1,o[3]=s,o}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]),a=b(parseInt(n[1]),0,360),r=b(parseFloat(n[2]),0,100),o=b(parseFloat(n[3]),0,100),s=b(isNaN(i)?1:i,0,1);return[a,r,o,s]}}}function r(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,n=t.match(e);if(n){var i=parseFloat(n[4]),a=b(parseInt(n[1]),0,360),r=b(parseFloat(n[2]),0,100),o=b(parseFloat(n[3]),0,100),s=b(isNaN(i)?1:i,0,1);return[a,r,o,s]}}}function o(t){var e=i(t);return e&&e.slice(0,3)}function s(t){var e=a(t);return e&&e.slice(0,3)}function l(t){var e=i(t);return e?e[3]:(e=a(t))?e[3]:(e=r(t))?e[3]:void 0}function d(t){return"#"+y(t[0])+y(t[1])+y(t[2])}function u(t,e){return 1>e||t[3]&&t[3]<1?c(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"}function c(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function h(t,e){if(1>e||t[3]&&t[3]<1)return f(t,e);var n=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+n+"%, "+i+"%, "+a+"%)"}function f(t,e){var n=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgba("+n+"%, "+i+"%, "+a+"%, "+(e||t[3]||1)+")"}function g(t,e){return 1>e||t[3]&&t[3]<1?m(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"}function m(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"}function v(t){return k[t.slice(0,3)]}function b(t,e,n){return Math.min(Math.max(e,t),n)}function y(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var x=t(5);e.exports={getRgba:i,getHsla:a,getRgb:o,getHsl:s,getHwb:r,getAlpha:l,hexString:d,rgbString:u,rgbaString:c,percentString:h,percentaString:f,hslString:g,hslaString:m,hwbString:p,keyword:v};var k={};for(var _ in x)k[x[_]]=_},{5:5}],2:[function(t,e,n){var i=t(4),a=t(1),r=function(t){if(t instanceof r)return t;if(!(this instanceof r))return new r(t);this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;if("string"==typeof t)if(e=a.getRgba(t))this.setValues("rgb",e);else if(e=a.getHsla(t))this.setValues("hsl",e);else{if(!(e=a.getHwb(t)))throw new Error('Unable to parse color from string "'+t+'"');this.setValues("hwb",e)}else if("object"==typeof t)if(e=t,void 0!==e.r||void 0!==e.red)this.setValues("rgb",e);else if(void 0!==e.l||void 0!==e.lightness)this.setValues("hsl",e);else if(void 0!==e.v||void 0!==e.value)this.setValues("hsv",e);else if(void 0!==e.w||void 0!==e.whiteness)this.setValues("hwb",e);else{if(void 0===e.c&&void 0===e.cyan)throw new Error("Unable to parse color from object "+JSON.stringify(t));this.setValues("cmyk",e)}};r.prototype={rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=0>t?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],n=0;n<t.length;n++){var i=t[n]/255;e[n]=.03928>=i?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),n=t.luminosity();return e>n?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb,e=(299*t[0]+587*t[1]+114*t[2])/1e3;return 128>e},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;3>e;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=0>n?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o===-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],e={}.toString.call(t),"[object Array]"===e?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i<t.length;i++)n[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(n.a=e.alpha),n},r.prototype.setValues=function(t,e){var n,a=this.values,r=this.spaces,o=this.maxes,s=1;if("alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(n=0;n<t.length;n++)a[t][n]=e[t.charAt(n)];s=e.a}else if(void 0!==e[r[t][0]]){var l=r[t];for(n=0;n<t.length;n++)a[t][n]=e[l[n]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;var d;for(n=0;n<t.length;n++)d=Math.max(0,Math.min(o[t][n],a[t][n])),a[t][n]=Math.round(d);for(var u in r)u!==t&&(a[u]=i[t][u](a[t]));return!0},r.prototype.setSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n),this)},r.prototype.setChannel=function(t,e,n){var i=this.values[t];return void 0===n?i[e]:n===i[e]?this:(i[e]=n,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=r),e.exports=r},{1:1,4:4}],3:[function(t,e,n){function i(t){var e,n,i,a=t[0]/255,r=t[1]/255,o=t[2]/255,s=Math.min(a,r,o),l=Math.max(a,r,o),d=l-s;return l==s?e=0:a==l?e=(r-o)/d:r==l?e=2+(o-a)/d:o==l&&(e=4+(a-r)/d),e=Math.min(60*e,360),0>e&&(e+=360),i=(s+l)/2,n=l==s?0:.5>=i?d/(l+s):d/(2-l-s),[e,100*n,100*i]}function a(t){var e,n,i,a=t[0],r=t[1],o=t[2],s=Math.min(a,r,o),l=Math.max(a,r,o),d=l-s;return n=0==l?0:d/l*1e3/10,l==s?e=0:a==l?e=(r-o)/d:r==l?e=2+(o-a)/d:o==l&&(e=4+(a-r)/d),e=Math.min(60*e,360),0>e&&(e+=360),i=l/255*1e3/10,[e,n,i]}function o(t){var e=t[0],n=t[1],a=t[2],r=i(t)[0],o=1/255*Math.min(e,Math.min(n,a)),a=1-1/255*Math.max(e,Math.max(n,a));return[r,100*o,100*a]}function s(t){var e,n,i,a,r=t[0]/255,o=t[1]/255,s=t[2]/255;return a=Math.min(1-r,1-o,1-s),e=(1-r-a)/(1-a)||0,n=(1-o-a)/(1-a)||0,i=(1-s-a)/(1-a)||0,[100*e,100*n,100*i,100*a]}function l(t){return Q[JSON.stringify(t)]}function d(t){var e=t[0]/255,n=t[1]/255,i=t[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92;var a=.4124*e+.3576*n+.1805*i,r=.2126*e+.7152*n+.0722*i,o=.0193*e+.1192*n+.9505*i;return[100*a,100*r,100*o]}function u(t){var e,n,i,a=d(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){return B(u(t))}function h(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];n=.5>l?l*(1+s):l+s-l*s,e=2*l-n,a=[0,0,0];for(var d=0;3>d;d++)i=o+1/3*-(d-1),0>i&&i++,i>1&&i--,r=1>6*i?e+6*(n-e)*i:1>2*i?n:2>3*i?e+(n-e)*(2/3-i)*6:e,a[d]=255*r;return a}function f(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=1>=r?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])}function m(t){return o(h(t))}function p(t){return s(h(t))}function v(t){return l(h(t))}function y(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function x(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=1>=n?n:2-n,e=e||0,n/=2,[i,100*e,100*n]}function k(t){return o(y(t))}function _(t){return s(y(t))}function S(t){return l(y(t))}function w(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,d=s+l;switch(d>1&&(s/=d,l/=d),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function M(t){return i(w(t))}function D(t){return a(w(t))}function C(t){return s(w(t))}function T(t){return l(w(t))}function P(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function F(t){return i(P(t))}function A(t){return a(P(t))}function I(t){return o(P(t))}function O(t){return l(P(t))}function R(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+o*-.4986,n=a*-.9689+1.8758*r+.0415*o,i=.0557*a+r*-.204+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e=12.92*e,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n=12.92*n,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i=12.92*i,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function W(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function L(t){return B(W(t))}function V(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return 8>=r?(n=100*r/903.3,a=7.787*(n/100)+16/116):(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=.008856>=e/95.047?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=.008859>=i/108.883?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function B(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),n=360*e/2/Math.PI,0>n&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function Y(t){return R(V(t))}function z(t){var e,n,i,a=t[0],r=t[1],o=t[2];return i=o/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function H(t){return V(z(t))}function N(t){return Y(z(t))}function E(t){return X[t]}function U(t){return i(E(t))}function j(t){return a(E(t))}function G(t){return o(E(t))}function q(t){return s(E(t))}function Z(t){return u(E(t))}function J(t){return d(E(t))}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:d,rgb2lab:u,rgb2lch:c,hsl2rgb:h,hsl2hsv:f,hsl2hwb:m,hsl2cmyk:p,hsl2keyword:v,hsv2rgb:y,hsv2hsl:x,hsv2hwb:k,hsv2cmyk:_,hsv2keyword:S,hwb2rgb:w,hwb2hsl:M,hwb2hsv:D,hwb2cmyk:C,hwb2keyword:T,cmyk2rgb:P,cmyk2hsl:F,cmyk2hsv:A,cmyk2hwb:I,cmyk2keyword:O,keyword2rgb:E,keyword2hsl:U,keyword2hsv:j,keyword2hwb:G,keyword2cmyk:q,keyword2lab:Z,keyword2xyz:J,xyz2rgb:R,xyz2lab:W,xyz2lch:L,lab2xyz:V,lab2rgb:Y,lab2lch:B,lch2lab:z,lch2xyz:H,lch2rgb:N};var X={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},Q={};for(var $ in X)Q[JSON.stringify(X[$])]=$},{}],4:[function(t,e,n){var i=t(3),a=function(){return new d};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];a[s]=a[s]||{},a[s][l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a<n.length;a++)n[a]=Math.round(n[a]);return n}}(r)}var d=function(){this.convs={}};d.prototype.routeSpace=function(t,e){var n=e[0];return void 0===n?this.getValues(t):("number"==typeof n&&(n=Array.prototype.slice.call(e)),this.setValues(t,n))},d.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},d.prototype.getValues=function(t){var e=this.convs[t];if(!e){var n=this.space,i=this.convs[n];e=a[n][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){d.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{3:3}],5:[function(t,e,n){e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(e,n,i){!function(e,a){"object"==typeof i&&"undefined"!=typeof n?n.exports=a():"function"==typeof t&&t.amd?t(a):e.moment=a()}(this,function(){"use strict";function t(){return li.apply(null,arguments)}function i(t){li=t}function a(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function r(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function o(t,e){var n,i=[];for(n=0;n<t.length;++n)i.push(e(t[n],n));return i}function s(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function l(t,e){for(var n in e)s(e,n)&&(t[n]=e[n]);return s(e,"toString")&&(t.toString=e.toString),s(e,"valueOf")&&(t.valueOf=e.valueOf),t}function d(t,e,n,i){return Vt(t,e,n,i,!0).utc()}function u(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function c(t){return null==t._pf&&(t._pf=u()),t._pf}function h(t){if(null==t._isValid){var e=c(t),n=di.call(e.parsedDateParts,function(t){return null!=t});t._isValid=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&n),t._strict&&(t._isValid=t._isValid&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour)}return t._isValid}function f(t){var e=d(NaN);return null!=t?l(c(e),t):c(e).userInvalidated=!0,e}function g(t){return void 0===t}function m(t,e){var n,i,a;if(g(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),g(e._i)||(t._i=e._i),g(e._f)||(t._f=e._f),g(e._l)||(t._l=e._l),g(e._strict)||(t._strict=e._strict),g(e._tzm)||(t._tzm=e._tzm),g(e._isUTC)||(t._isUTC=e._isUTC),g(e._offset)||(t._offset=e._offset),g(e._pf)||(t._pf=c(e)),g(e._locale)||(t._locale=e._locale),ui.length>0)for(n in ui)i=ui[n],a=e[i],g(a)||(t[i]=a);return t}function p(e){m(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),ci===!1&&(ci=!0,t.updateOffset(this),ci=!1)}function v(t){return t instanceof p||null!=t&&null!=t._isAMomentObject}function b(t){return 0>t?Math.ceil(t):Math.floor(t)}function y(t){var e=+t,n=0;return 0!==e&&isFinite(e)&&(n=b(e)),n}function x(t,e,n){var i,a=Math.min(t.length,e.length),r=Math.abs(t.length-e.length),o=0;for(i=0;a>i;i++)(n&&t[i]!==e[i]||!n&&y(t[i])!==y(e[i]))&&o++;return o+r}function k(e){t.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function _(e,n){var i=!0;return l(function(){return null!=t.deprecationHandler&&t.deprecationHandler(null,e),i&&(k(e+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),i=!1),n.apply(this,arguments)},n)}function S(e,n){null!=t.deprecationHandler&&t.deprecationHandler(e,n),hi[e]||(k(n),hi[e]=!0)}function w(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function M(t){return"[object Object]"===Object.prototype.toString.call(t)}function D(t){var e,n;for(n in t)e=t[n],w(e)?this[n]=e:this["_"+n]=e;this._config=t,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function C(t,e){var n,i=l({},t);for(n in e)s(e,n)&&(M(t[n])&&M(e[n])?(i[n]={},l(i[n],t[n]),l(i[n],e[n])):null!=e[n]?i[n]=e[n]:delete i[n]);return i}function T(t){null!=t&&this.set(t)}function P(t){return t?t.toLowerCase().replace("_","-"):t}function F(t){for(var e,n,i,a,r=0;r<t.length;){for(a=P(t[r]).split("-"),e=a.length,n=P(t[r+1]),n=n?n.split("-"):null;e>0;){if(i=A(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&x(a,n,!0)>=e-1)break;e--}r++}return null}function A(t){var i=null;if(!pi[t]&&"undefined"!=typeof n&&n&&n.exports)try{i=gi._abbr,e("./locale/"+t),I(i)}catch(a){}return pi[t]}function I(t,e){var n;return t&&(n=g(e)?W(t):O(t,e),n&&(gi=n)),gi._abbr}function O(t,e){return null!==e?(e.abbr=t,null!=pi[t]?(S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),e=C(pi[t]._config,e)):null!=e.parentLocale&&(null!=pi[e.parentLocale]?e=C(pi[e.parentLocale]._config,e):S("parentLocaleUndefined","specified parentLocale is not defined yet")),pi[t]=new T(e),I(t),pi[t]):(delete pi[t],null)}function R(t,e){if(null!=e){var n;null!=pi[t]&&(e=C(pi[t]._config,e)),n=new T(e),n.parentLocale=pi[t],pi[t]=n,I(t)}else null!=pi[t]&&(null!=pi[t].parentLocale?pi[t]=pi[t].parentLocale:null!=pi[t]&&delete pi[t]);return pi[t]}function W(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return gi;if(!a(t)){if(e=A(t))return e;t=[t]}return F(t)}function L(){return fi(pi)}function V(t,e){var n=t.toLowerCase();vi[n]=vi[n+"s"]=vi[e]=t}function B(t){return"string"==typeof t?vi[t]||vi[t.toLowerCase()]:void 0}function Y(t){var e,n,i={};for(n in t)s(t,n)&&(e=B(n),e&&(i[e]=t[n]));return i}function z(e,n){return function(i){return null!=i?(N(this,e,i),t.updateOffset(this,n),this):H(this,e)}}function H(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function N(t,e,n){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](n)}function E(t,e){var n;if("object"==typeof t)for(n in t)this.set(n,t[n]);else if(t=B(t),w(this[t]))return this[t](e);return this}function U(t,e,n){var i=""+Math.abs(t),a=e-i.length,r=t>=0;return(r?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function j(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(ki[t]=a),e&&(ki[e[0]]=function(){return U(a.apply(this,arguments),e[1],e[2])}),n&&(ki[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function G(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function q(t){var e,n,i=t.match(bi);for(e=0,n=i.length;n>e;e++)ki[i[e]]?i[e]=ki[i[e]]:i[e]=G(i[e]);return function(e){var a,r="";for(a=0;n>a;a++)r+=i[a]instanceof Function?i[a].call(e,t):i[a];return r}}function Z(t,e){return t.isValid()?(e=J(e,t.localeData()),xi[e]=xi[e]||q(e),xi[e](t)):t.localeData().invalidDate()}function J(t,e){function n(t){return e.longDateFormat(t)||t}var i=5;for(yi.lastIndex=0;i>=0&&yi.test(t);)t=t.replace(yi,n),yi.lastIndex=0,i-=1;return t}function X(t,e,n){Yi[t]=w(e)?e:function(t,i){return t&&n?n:e}}function Q(t,e){return s(Yi,t)?Yi[t](e._strict,e._locale):new RegExp($(t))}function $(t){return K(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function K(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tt(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),"number"==typeof e&&(i=function(t,n){n[e]=y(t)}),n=0;n<t.length;n++)zi[t[n]]=i}function et(t,e){tt(t,function(t,n,i,a){i._w=i._w||{},e(t,i._w,i,a)})}function nt(t,e,n){null!=e&&s(zi,t)&&zi[t](e,n._a,n,t)}function it(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function at(t,e){return a(this._months)?this._months[t.month()]:this._months[Xi.test(e)?"format":"standalone"][t.month()]}function rt(t,e){return a(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Xi.test(e)?"format":"standalone"][t.month()]}function ot(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],i=0;12>i;++i)r=d([2e3,i]),this._shortMonthsParse[i]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[i]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===e?(a=mi.call(this._shortMonthsParse,o),-1!==a?a:null):(a=mi.call(this._longMonthsParse,o),-1!==a?a:null):"MMM"===e?(a=mi.call(this._shortMonthsParse,o),-1!==a?a:(a=mi.call(this._longMonthsParse,o),-1!==a?a:null)):(a=mi.call(this._longMonthsParse,o),-1!==a?a:(a=mi.call(this._shortMonthsParse,o),-1!==a?a:null))}function st(t,e,n){var i,a,r;if(this._monthsParseExact)return ot.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;12>i;i++){if(a=d([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}}function lt(t,e){var n;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=y(e);else if(e=t.localeData().monthsParse(e),"number"!=typeof e)return t;return n=Math.min(t.date(),it(t.year(),e)),
-t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,n),t}function dt(e){return null!=e?(lt(this,e),t.updateOffset(this,!0),this):H(this,"Month")}function ut(){return it(this.year(),this.month())}function ct(t){return this._monthsParseExact?(s(this,"_monthsRegex")||ft.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex}function ht(t){return this._monthsParseExact?(s(this,"_monthsRegex")||ft.call(this),t?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex}function ft(){function t(t,e){return e.length-t.length}var e,n,i=[],a=[],r=[];for(e=0;12>e;e++)n=d([2e3,e]),i.push(this.monthsShort(n,"")),a.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(i.sort(t),a.sort(t),r.sort(t),e=0;12>e;e++)i[e]=K(i[e]),a[e]=K(a[e]),r[e]=K(r[e]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+i.join("|")+")","i")}function gt(t){var e,n=t._a;return n&&-2===c(t).overflow&&(e=n[Ni]<0||n[Ni]>11?Ni:n[Ei]<1||n[Ei]>it(n[Hi],n[Ni])?Ei:n[Ui]<0||n[Ui]>24||24===n[Ui]&&(0!==n[ji]||0!==n[Gi]||0!==n[qi])?Ui:n[ji]<0||n[ji]>59?ji:n[Gi]<0||n[Gi]>59?Gi:n[qi]<0||n[qi]>999?qi:-1,c(t)._overflowDayOfYear&&(Hi>e||e>Ei)&&(e=Ei),c(t)._overflowWeeks&&-1===e&&(e=Zi),c(t)._overflowWeekday&&-1===e&&(e=Ji),c(t).overflow=e),t}function mt(t){var e,n,i,a,r,o,s=t._i,l=ea.exec(s)||na.exec(s);if(l){for(c(t).iso=!0,e=0,n=aa.length;n>e;e++)if(aa[e][1].exec(l[1])){a=aa[e][0],i=aa[e][2]!==!1;break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,n=ra.length;n>e;e++)if(ra[e][1].exec(l[3])){r=(l[2]||" ")+ra[e][0];break}if(null==r)return void(t._isValid=!1)}if(!i&&null!=r)return void(t._isValid=!1);if(l[4]){if(!ia.exec(l[4]))return void(t._isValid=!1);o="Z"}t._f=a+(r||"")+(o||""),Ft(t)}else t._isValid=!1}function pt(e){var n=oa.exec(e._i);return null!==n?void(e._d=new Date(+n[1])):(mt(e),void(e._isValid===!1&&(delete e._isValid,t.createFromInputFallback(e))))}function vt(t,e,n,i,a,r,o){var s=new Date(t,e,n,i,a,r,o);return 100>t&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function bt(t){var e=new Date(Date.UTC.apply(null,arguments));return 100>t&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function yt(t){return xt(t)?366:365}function xt(t){return t%4===0&&t%100!==0||t%400===0}function kt(){return xt(this.year())}function _t(t,e,n){var i=7+e-n,a=(7+bt(t,0,i).getUTCDay()-e)%7;return-a+i-1}function St(t,e,n,i,a){var r,o,s=(7+n-i)%7,l=_t(t,i,a),d=1+7*(e-1)+s+l;return 0>=d?(r=t-1,o=yt(r)+d):d>yt(t)?(r=t+1,o=d-yt(t)):(r=t,o=d),{year:r,dayOfYear:o}}function wt(t,e,n){var i,a,r=_t(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return 1>o?(a=t.year()-1,i=o+Mt(a,e,n)):o>Mt(t.year(),e,n)?(i=o-Mt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function Mt(t,e,n){var i=_t(t,e,n),a=_t(t+1,e,n);return(yt(t)-i+a)/7}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(e){var n=new Date(t.now());return e._useUTC?[n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate()]:[n.getFullYear(),n.getMonth(),n.getDate()]}function Tt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[Ei]&&null==t._a[Ni]&&Pt(t),t._dayOfYear&&(a=Dt(t._a[Hi],i[Hi]),t._dayOfYear>yt(a)&&(c(t)._overflowDayOfYear=!0),n=bt(a,0,t._dayOfYear),t._a[Ni]=n.getUTCMonth(),t._a[Ei]=n.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;7>e;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Ui]&&0===t._a[ji]&&0===t._a[Gi]&&0===t._a[qi]&&(t._nextDay=!0,t._a[Ui]=0),t._d=(t._useUTC?bt:vt).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Ui]=24)}}function Pt(t){var e,n,i,a,r,o,s,l;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(r=1,o=4,n=Dt(e.GG,t._a[Hi],wt(Bt(),1,4).year),i=Dt(e.W,1),a=Dt(e.E,1),(1>a||a>7)&&(l=!0)):(r=t._locale._week.dow,o=t._locale._week.doy,n=Dt(e.gg,t._a[Hi],wt(Bt(),r,o).year),i=Dt(e.w,1),null!=e.d?(a=e.d,(0>a||a>6)&&(l=!0)):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r),1>i||i>Mt(n,r,o)?c(t)._overflowWeeks=!0:null!=l?c(t)._overflowWeekday=!0:(s=St(n,i,a,r,o),t._a[Hi]=s.year,t._dayOfYear=s.dayOfYear)}function Ft(e){if(e._f===t.ISO_8601)return void mt(e);e._a=[],c(e).empty=!0;var n,i,a,r,o,s=""+e._i,l=s.length,d=0;for(a=J(e._f,e._locale).match(bi)||[],n=0;n<a.length;n++)r=a[n],i=(s.match(Q(r,e))||[])[0],i&&(o=s.substr(0,s.indexOf(i)),o.length>0&&c(e).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),d+=i.length),ki[r]?(i?c(e).empty=!1:c(e).unusedTokens.push(r),nt(r,i,e)):e._strict&&!i&&c(e).unusedTokens.push(r);c(e).charsLeftOver=l-d,s.length>0&&c(e).unusedInput.push(s),c(e).bigHour===!0&&e._a[Ui]<=12&&e._a[Ui]>0&&(c(e).bigHour=void 0),c(e).parsedDateParts=e._a.slice(0),c(e).meridiem=e._meridiem,e._a[Ui]=At(e._locale,e._a[Ui],e._meridiem),Tt(e),gt(e)}function At(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?(i=t.isPM(n),i&&12>e&&(e+=12),i||12!==e||(e=0),e):e}function It(t){var e,n,i,a,r;if(0===t._f.length)return c(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)r=0,e=m({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],Ft(e),h(e)&&(r+=c(e).charsLeftOver,r+=10*c(e).unusedTokens.length,c(e).score=r,(null==i||i>r)&&(i=r,n=e));l(t,n||e)}function Ot(t){if(!t._d){var e=Y(t._i);t._a=o([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),Tt(t)}}function Rt(t){var e=new p(gt(Wt(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Wt(t){var e=t._i,n=t._f;return t._locale=t._locale||W(t._l),null===e||void 0===n&&""===e?f({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),v(e)?new p(gt(e)):(a(n)?It(t):n?Ft(t):r(e)?t._d=e:Lt(t),h(t)||(t._d=null),t))}function Lt(e){var n=e._i;void 0===n?e._d=new Date(t.now()):r(n)?e._d=new Date(n.valueOf()):"string"==typeof n?pt(e):a(n)?(e._a=o(n.slice(0),function(t){return parseInt(t,10)}),Tt(e)):"object"==typeof n?Ot(e):"number"==typeof n?e._d=new Date(n):t.createFromInputFallback(e)}function Vt(t,e,n,i,a){var r={};return"boolean"==typeof n&&(i=n,n=void 0),r._isAMomentObject=!0,r._useUTC=r._isUTC=a,r._l=n,r._i=t,r._f=e,r._strict=i,Rt(r)}function Bt(t,e,n,i){return Vt(t,e,n,i,!1)}function Yt(t,e){var n,i;if(1===e.length&&a(e[0])&&(e=e[0]),!e.length)return Bt();for(n=e[0],i=1;i<e.length;++i)(!e[i].isValid()||e[i][t](n))&&(n=e[i]);return n}function zt(){var t=[].slice.call(arguments,0);return Yt("isBefore",t)}function Ht(){var t=[].slice.call(arguments,0);return Yt("isAfter",t)}function Nt(t){var e=Y(t),n=e.year||0,i=e.quarter||0,a=e.month||0,r=e.week||0,o=e.day||0,s=e.hour||0,l=e.minute||0,d=e.second||0,u=e.millisecond||0;this._milliseconds=+u+1e3*d+6e4*l+1e3*s*60*60,this._days=+o+7*r,this._months=+a+3*i+12*n,this._data={},this._locale=W(),this._bubble()}function Et(t){return t instanceof Nt}function Ut(t,e){j(t,0,0,function(){var t=this.utcOffset(),n="+";return 0>t&&(t=-t,n="-"),n+U(~~(t/60),2)+e+U(~~t%60,2)})}function jt(t,e){var n=(e||"").match(t)||[],i=n[n.length-1]||[],a=(i+"").match(ca)||["-",0,0],r=+(60*a[1])+y(a[2]);return"+"===a[0]?r:-r}function Gt(e,n){var i,a;return n._isUTC?(i=n.clone(),a=(v(e)||r(e)?e.valueOf():Bt(e).valueOf())-i.valueOf(),i._d.setTime(i._d.valueOf()+a),t.updateOffset(i,!1),i):Bt(e).local()}function qt(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Zt(e,n){var i,a=this._offset||0;return this.isValid()?null!=e?("string"==typeof e?e=jt(Li,e):Math.abs(e)<16&&(e=60*e),!this._isUTC&&n&&(i=qt(this)),this._offset=e,this._isUTC=!0,null!=i&&this.add(i,"m"),a!==e&&(!n||this._changeInProgress?ce(this,re(e-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,t.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?a:qt(this):null!=e?this:NaN}function Jt(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}function Xt(t){return this.utcOffset(0,t)}function Qt(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(qt(this),"m")),this}function $t(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(jt(Wi,this._i)),this}function Kt(t){return this.isValid()?(t=t?Bt(t).utcOffset():0,(this.utcOffset()-t)%60===0):!1}function te(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function ee(){if(!g(this._isDSTShifted))return this._isDSTShifted;var t={};if(m(t,this),t=Wt(t),t._a){var e=t._isUTC?d(t._a):Bt(t._a);this._isDSTShifted=this.isValid()&&x(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function ne(){return this.isValid()?!this._isUTC:!1}function ie(){return this.isValid()?this._isUTC:!1}function ae(){return this.isValid()?this._isUTC&&0===this._offset:!1}function re(t,e){var n,i,a,r=t,o=null;return Et(t)?r={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(r={},e?r[e]=t:r.milliseconds=t):(o=ha.exec(t))?(n="-"===o[1]?-1:1,r={y:0,d:y(o[Ei])*n,h:y(o[Ui])*n,m:y(o[ji])*n,s:y(o[Gi])*n,ms:y(o[qi])*n}):(o=fa.exec(t))?(n="-"===o[1]?-1:1,r={y:oe(o[2],n),M:oe(o[3],n),w:oe(o[4],n),d:oe(o[5],n),h:oe(o[6],n),m:oe(o[7],n),s:oe(o[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(a=le(Bt(r.from),Bt(r.to)),r={},r.ms=a.milliseconds,r.M=a.months),i=new Nt(r),Et(t)&&s(t,"_locale")&&(i._locale=t._locale),i}function oe(t,e){var n=t&&parseFloat(t.replace(",","."));return(isNaN(n)?0:n)*e}function se(t,e){var n={milliseconds:0,months:0};return n.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(n.months,"M").isAfter(e)&&--n.months,n.milliseconds=+e-+t.clone().add(n.months,"M"),n}function le(t,e){var n;return t.isValid()&&e.isValid()?(e=Gt(e,t),t.isBefore(e)?n=se(t,e):(n=se(e,t),n.milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function de(t){return 0>t?-1*Math.round(-1*t):Math.round(t)}function ue(t,e){return function(n,i){var a,r;return null===i||isNaN(+i)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period)."),r=n,n=i,i=r),n="string"==typeof n?+n:n,a=re(n,i),ce(this,a,t),this}}function ce(e,n,i,a){var r=n._milliseconds,o=de(n._days),s=de(n._months);e.isValid()&&(a=null==a?!0:a,r&&e._d.setTime(e._d.valueOf()+r*i),o&&N(e,"Date",H(e,"Date")+o*i),s&<(e,H(e,"Month")+s*i),a&&t.updateOffset(e,o||s))}function he(t,e){var n=t||Bt(),i=Gt(n,this).startOf("day"),a=this.diff(i,"days",!0),r=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse",o=e&&(w(e[r])?e[r]():e[r]);return this.format(o||this.localeData().calendar(r,this,Bt(n)))}function fe(){return new p(this)}function ge(t,e){var n=v(t)?t:Bt(t);return this.isValid()&&n.isValid()?(e=B(g(e)?"millisecond":e),"millisecond"===e?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(e).valueOf()):!1}function me(t,e){var n=v(t)?t:Bt(t);return this.isValid()&&n.isValid()?(e=B(g(e)?"millisecond":e),"millisecond"===e?this.valueOf()<n.valueOf():this.clone().endOf(e).valueOf()<n.valueOf()):!1}function pe(t,e,n,i){return i=i||"()",("("===i[0]?this.isAfter(t,n):!this.isBefore(t,n))&&(")"===i[1]?this.isBefore(e,n):!this.isAfter(e,n))}function ve(t,e){var n,i=v(t)?t:Bt(t);return this.isValid()&&i.isValid()?(e=B(e||"millisecond"),"millisecond"===e?this.valueOf()===i.valueOf():(n=i.valueOf(),this.clone().startOf(e).valueOf()<=n&&n<=this.clone().endOf(e).valueOf())):!1}function be(t,e){return this.isSame(t,e)||this.isAfter(t,e)}function ye(t,e){return this.isSame(t,e)||this.isBefore(t,e)}function xe(t,e,n){var i,a,r,o;return this.isValid()?(i=Gt(t,this),i.isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),e=B(e),"year"===e||"month"===e||"quarter"===e?(o=ke(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:b(o)):NaN):NaN}function ke(t,e){var n,i,a=12*(e.year()-t.year())+(e.month()-t.month()),r=t.clone().add(a,"months");return 0>e-r?(n=t.clone().add(a-1,"months"),i=(e-r)/(r-n)):(n=t.clone().add(a+1,"months"),i=(e-r)/(n-r)),-(a+i)||0}function _e(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function Se(){var t=this.clone().utc();return 0<t.year()&&t.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():Z(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):Z(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function we(e){e||(e=this.isUtc()?t.defaultFormatUtc:t.defaultFormat);var n=Z(this,e);return this.localeData().postformat(n)}function Me(t,e){return this.isValid()&&(v(t)&&t.isValid()||Bt(t).isValid())?re({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function De(t){return this.from(Bt(),t)}function Ce(t,e){return this.isValid()&&(v(t)&&t.isValid()||Bt(t).isValid())?re({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function Te(t){return this.to(Bt(),t)}function Pe(t){var e;return void 0===t?this._locale._abbr:(e=W(t),null!=e&&(this._locale=e),this)}function Fe(){return this._locale}function Ae(t){switch(t=B(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this}function Ie(t){return t=B(t),void 0===t||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))}function Oe(){return this._d.valueOf()-6e4*(this._offset||0)}function Re(){return Math.floor(this.valueOf()/1e3)}function We(){return this._offset?new Date(this.valueOf()):this._d}function Le(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function Ve(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Be(){return this.isValid()?this.toISOString():null}function Ye(){return h(this)}function ze(){return l({},c(this))}function He(){return c(this).overflow}function Ne(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Ee(t,e){j(0,[t,t.length],0,e)}function Ue(t){return Ze.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function je(t){return Ze.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)}function Ge(){return Mt(this.year(),1,4)}function qe(){var t=this.localeData()._week;return Mt(this.year(),t.dow,t.doy)}function Ze(t,e,n,i,a){var r;return null==t?wt(this,i,a).year:(r=Mt(t,i,a),e>r&&(e=r),Je.call(this,t,e,n,i,a))}function Je(t,e,n,i,a){var r=St(t,e,n,i,a),o=bt(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function Xe(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}function Qe(t){return wt(t,this._week.dow,this._week.doy).week}function $e(){return this._week.dow}function Ke(){return this._week.doy}function tn(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function en(t){var e=wt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function nn(t,e){return"string"!=typeof t?t:isNaN(t)?(t=e.weekdaysParse(t),"number"==typeof t?t:null):parseInt(t,10)}function an(t,e){return a(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]}function rn(t){return this._weekdaysShort[t.day()]}function on(t){return this._weekdaysMin[t.day()]}function sn(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;7>i;++i)r=d([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?(a=mi.call(this._weekdaysParse,o),-1!==a?a:null):"ddd"===e?(a=mi.call(this._shortWeekdaysParse,o),-1!==a?a:null):(a=mi.call(this._minWeekdaysParse,o),-1!==a?a:null):"dddd"===e?(a=mi.call(this._weekdaysParse,o),-1!==a?a:(a=mi.call(this._shortWeekdaysParse,o),-1!==a?a:(a=mi.call(this._minWeekdaysParse,o),-1!==a?a:null))):"ddd"===e?(a=mi.call(this._shortWeekdaysParse,o),-1!==a?a:(a=mi.call(this._weekdaysParse,o),-1!==a?a:(a=mi.call(this._minWeekdaysParse,o),-1!==a?a:null))):(a=mi.call(this._minWeekdaysParse,o),-1!==a?a:(a=mi.call(this._weekdaysParse,o),-1!==a?a:(a=mi.call(this._shortWeekdaysParse,o),-1!==a?a:null)))}function ln(t,e,n){var i,a,r;if(this._weekdaysParseExact)return sn.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;7>i;i++){if(a=d([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}}function dn(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=nn(t,this.localeData()),this.add(t-e,"d")):e}function un(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function cn(t){return this.isValid()?null==t?this.day()||7:this.day(this.day()%7?t:t-7):null!=t?this:NaN}function hn(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||mn.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex}function fn(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||mn.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}function gn(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||mn.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}function mn(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;7>e;e++)n=d([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;7>e;e++)s[e]=K(s[e]),l[e]=K(l[e]),u[e]=K(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function pn(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}function vn(){return this.hours()%12||12}function bn(){return this.hours()||24}function yn(t,e){j(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function xn(t,e){return e._meridiemParse}function kn(t){return"p"===(t+"").toLowerCase().charAt(0)}function _n(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"}function Sn(t,e){e[qi]=y(1e3*("0."+t))}function wn(){return this._isUTC?"UTC":""}function Mn(){return this._isUTC?"Coordinated Universal Time":""}function Dn(t){return Bt(1e3*t)}function Cn(){return Bt.apply(null,arguments).parseZone()}function Tn(t,e,n){var i=this._calendar[t];return w(i)?i.call(e,n):i}function Pn(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])}function Fn(){return this._invalidDate}function An(t){return this._ordinal.replace("%d",t)}function In(t){return t}function On(t,e,n,i){var a=this._relativeTime[n];return w(a)?a(t,e,n,i):a.replace(/%d/i,t)}function Rn(t,e){var n=this._relativeTime[t>0?"future":"past"];return w(n)?n(e):n.replace(/%s/i,e)}function Wn(t,e,n,i){var a=W(),r=d().set(i,e);return a[n](r,t)}function Ln(t,e,n){if("number"==typeof t&&(e=t,t=void 0),t=t||"",null!=e)return Wn(t,e,n,"month");var i,a=[];for(i=0;12>i;i++)a[i]=Wn(t,i,n,"month");return a}function Vn(t,e,n,i){"boolean"==typeof t?("number"==typeof e&&(n=e,e=void 0),e=e||""):(e=t,n=e,t=!1,"number"==typeof e&&(n=e,e=void 0),e=e||"");var a=W(),r=t?a._week.dow:0;if(null!=n)return Wn(e,(n+r)%7,i,"day");var o,s=[];for(o=0;7>o;o++)s[o]=Wn(e,(o+r)%7,i,"day");return s}function Bn(t,e){return Ln(t,e,"months")}function Yn(t,e){return Ln(t,e,"monthsShort")}function zn(t,e,n){return Vn(t,e,n,"weekdays")}function Hn(t,e,n){return Vn(t,e,n,"weekdaysShort")}function Nn(t,e,n){return Vn(t,e,n,"weekdaysMin")}function En(){var t=this._data;return this._milliseconds=za(this._milliseconds),this._days=za(this._days),this._months=za(this._months),t.milliseconds=za(t.milliseconds),t.seconds=za(t.seconds),t.minutes=za(t.minutes),t.hours=za(t.hours),t.months=za(t.months),t.years=za(t.years),this}function Un(t,e,n,i){var a=re(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function jn(t,e){return Un(this,t,e,1)}function Gn(t,e){return Un(this,t,e,-1)}function qn(t){return 0>t?Math.floor(t):Math.ceil(t)}function Zn(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||0>=r&&0>=o&&0>=s||(r+=864e5*qn(Xn(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=b(r/1e3),l.seconds=t%60,e=b(t/60),l.minutes=e%60,n=b(e/60),l.hours=n%24,o+=b(n/24),a=b(Jn(o)),s+=a,o-=qn(Xn(a)),i=b(s/12),s%=12,l.days=o,l.months=s,l.years=i,this}function Jn(t){return 4800*t/146097}function Xn(t){return 146097*t/4800}function Qn(t){var e,n,i=this._milliseconds;if(t=B(t),"month"===t||"year"===t)return e=this._days+i/864e5,n=this._months+Jn(e),"month"===t?n:n/12;switch(e=this._days+Math.round(Xn(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}}function $n(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*y(this._months/12)}function Kn(t){return function(){return this.as(t)}}function ti(t){return t=B(t),this[t+"s"]()}function ei(t){return function(){return this._data[t]}}function ni(){return b(this.days()/7)}function ii(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ai(t,e,n){var i=re(t).abs(),a=nr(i.as("s")),r=nr(i.as("m")),o=nr(i.as("h")),s=nr(i.as("d")),l=nr(i.as("M")),d=nr(i.as("y")),u=a<ir.s&&["s",a]||1>=r&&["m"]||r<ir.m&&["mm",r]||1>=o&&["h"]||o<ir.h&&["hh",o]||1>=s&&["d"]||s<ir.d&&["dd",s]||1>=l&&["M"]||l<ir.M&&["MM",l]||1>=d&&["y"]||["yy",d];return u[2]=e,u[3]=+t>0,u[4]=n,ii.apply(null,u)}function ri(t,e){return void 0===ir[t]?!1:void 0===e?ir[t]:(ir[t]=e,!0)}function oi(t){var e=this.localeData(),n=ai(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)}function si(){var t,e,n,i=ar(this._milliseconds)/1e3,a=ar(this._days),r=ar(this._months);t=b(i/60),e=b(t/60),i%=60,t%=60,n=b(r/12),r%=12;var o=n,s=r,l=a,d=e,u=t,c=i,h=this.asSeconds();return h?(0>h?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(d||u||c?"T":"")+(d?d+"H":"")+(u?u+"M":"")+(c?c+"S":""):"P0D"}var li,di;di=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;n>i;i++)if(i in e&&t.call(this,e[i],i,e))return!0;return!1};var ui=t.momentProperties=[],ci=!1,hi={};t.suppressDeprecationWarnings=!1,t.deprecationHandler=null;var fi;fi=Object.keys?Object.keys:function(t){var e,n=[];for(e in t)s(t,e)&&n.push(e);return n};var gi,mi,pi={},vi={},bi=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,yi=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,xi={},ki={},_i=/\d/,Si=/\d\d/,wi=/\d{3}/,Mi=/\d{4}/,Di=/[+-]?\d{6}/,Ci=/\d\d?/,Ti=/\d\d\d\d?/,Pi=/\d\d\d\d\d\d?/,Fi=/\d{1,3}/,Ai=/\d{1,4}/,Ii=/[+-]?\d{1,6}/,Oi=/\d+/,Ri=/[+-]?\d+/,Wi=/Z|[+-]\d\d:?\d\d/gi,Li=/Z|[+-]\d\d(?::?\d\d)?/gi,Vi=/[+-]?\d+(\.\d{1,3})?/,Bi=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Yi={},zi={},Hi=0,Ni=1,Ei=2,Ui=3,ji=4,Gi=5,qi=6,Zi=7,Ji=8;mi=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},j("M",["MM",2],"Mo",function(){return this.month()+1}),j("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),j("MMMM",0,0,function(t){return this.localeData().months(this,t)}),V("month","M"),X("M",Ci),X("MM",Ci,Si),X("MMM",function(t,e){return e.monthsShortRegex(t)}),X("MMMM",function(t,e){return e.monthsRegex(t)}),tt(["M","MM"],function(t,e){e[Ni]=y(t)-1}),tt(["MMM","MMMM"],function(t,e,n,i){var a=n._locale.monthsParse(t,i,n._strict);null!=a?e[Ni]=a:c(n).invalidMonth=t});var Xi=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Qi="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),$i="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Ki=Bi,ta=Bi,ea=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,na=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ia=/Z|[+-]\d\d(?::?\d\d)?/,aa=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],ra=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],oa=/^\/?Date\((\-?\d+)/i;t.createFromInputFallback=_("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),j("Y",0,0,function(){var t=this.year();return 9999>=t?""+t:"+"+t}),j(0,["YY",2],0,function(){return this.year()%100}),j(0,["YYYY",4],0,"year"),j(0,["YYYYY",5],0,"year"),j(0,["YYYYYY",6,!0],0,"year"),V("year","y"),X("Y",Ri),X("YY",Ci,Si),X("YYYY",Ai,Mi),X("YYYYY",Ii,Di),X("YYYYYY",Ii,Di),tt(["YYYYY","YYYYYY"],Hi),tt("YYYY",function(e,n){n[Hi]=2===e.length?t.parseTwoDigitYear(e):y(e)}),tt("YY",function(e,n){n[Hi]=t.parseTwoDigitYear(e)}),tt("Y",function(t,e){e[Hi]=parseInt(t,10)}),t.parseTwoDigitYear=function(t){return y(t)+(y(t)>68?1900:2e3)};var sa=z("FullYear",!0);t.ISO_8601=function(){};var la=_("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var t=Bt.apply(null,arguments);return this.isValid()&&t.isValid()?this>t?this:t:f()}),da=_("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var t=Bt.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:f()}),ua=function(){return Date.now?Date.now():+new Date};Ut("Z",":"),Ut("ZZ",""),X("Z",Li),X("ZZ",Li),tt(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=jt(Li,t)});var ca=/([\+\-]|\d\d)/gi;t.updateOffset=function(){};var ha=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,fa=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;re.fn=Nt.prototype;var ga=ue(1,"add"),ma=ue(-1,"subtract");t.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",t.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var pa=_("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});j(0,["gg",2],0,function(){return this.weekYear()%100}),j(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ee("gggg","weekYear"),Ee("ggggg","weekYear"),Ee("GGGG","isoWeekYear"),Ee("GGGGG","isoWeekYear"),V("weekYear","gg"),V("isoWeekYear","GG"),X("G",Ri),X("g",Ri),X("GG",Ci,Si),X("gg",Ci,Si),X("GGGG",Ai,Mi),X("gggg",Ai,Mi),X("GGGGG",Ii,Di),X("ggggg",Ii,Di),et(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=y(t)}),et(["gg","GG"],function(e,n,i,a){n[a]=t.parseTwoDigitYear(e)}),j("Q",0,"Qo","quarter"),V("quarter","Q"),X("Q",_i),tt("Q",function(t,e){e[Ni]=3*(y(t)-1)}),j("w",["ww",2],"wo","week"),j("W",["WW",2],"Wo","isoWeek"),V("week","w"),V("isoWeek","W"),X("w",Ci),X("ww",Ci,Si),X("W",Ci),X("WW",Ci,Si),et(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=y(t)});var va={dow:0,doy:6};j("D",["DD",2],"Do","date"),V("date","D"),X("D",Ci),X("DD",Ci,Si),X("Do",function(t,e){return t?e._ordinalParse:e._ordinalParseLenient}),tt(["D","DD"],Ei),tt("Do",function(t,e){e[Ei]=y(t.match(Ci)[0],10)});var ba=z("Date",!0);j("d",0,"do","day"),j("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),j("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),j("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),j("e",0,0,"weekday"),j("E",0,0,"isoWeekday"),V("day","d"),V("weekday","e"),V("isoWeekday","E"),X("d",Ci),X("e",Ci),X("E",Ci),X("dd",function(t,e){return e.weekdaysMinRegex(t)}),X("ddd",function(t,e){return e.weekdaysShortRegex(t)}),X("dddd",function(t,e){return e.weekdaysRegex(t)}),et(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:c(n).invalidWeekday=t}),et(["d","e","E"],function(t,e,n,i){e[i]=y(t)});var ya="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),xa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),ka="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),_a=Bi,Sa=Bi,wa=Bi;j("DDD",["DDDD",3],"DDDo","dayOfYear"),V("dayOfYear","DDD"),X("DDD",Fi),X("DDDD",wi),tt(["DDD","DDDD"],function(t,e,n){n._dayOfYear=y(t)}),j("H",["HH",2],0,"hour"),j("h",["hh",2],0,vn),j("k",["kk",2],0,bn),j("hmm",0,0,function(){return""+vn.apply(this)+U(this.minutes(),2)}),j("hmmss",0,0,function(){return""+vn.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),j("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),j("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),yn("a",!0),yn("A",!1),V("hour","h"),X("a",xn),X("A",xn),X("H",Ci),X("h",Ci),X("HH",Ci,Si),X("hh",Ci,Si),X("hmm",Ti),X("hmmss",Pi),X("Hmm",Ti),X("Hmmss",Pi),tt(["H","HH"],Ui),tt(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),tt(["h","hh"],function(t,e,n){e[Ui]=y(t),c(n).bigHour=!0}),tt("hmm",function(t,e,n){var i=t.length-2;e[Ui]=y(t.substr(0,i)),e[ji]=y(t.substr(i)),
-c(n).bigHour=!0}),tt("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[Ui]=y(t.substr(0,i)),e[ji]=y(t.substr(i,2)),e[Gi]=y(t.substr(a)),c(n).bigHour=!0}),tt("Hmm",function(t,e,n){var i=t.length-2;e[Ui]=y(t.substr(0,i)),e[ji]=y(t.substr(i))}),tt("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[Ui]=y(t.substr(0,i)),e[ji]=y(t.substr(i,2)),e[Gi]=y(t.substr(a))});var Ma=/[ap]\.?m?\.?/i,Da=z("Hours",!0);j("m",["mm",2],0,"minute"),V("minute","m"),X("m",Ci),X("mm",Ci,Si),tt(["m","mm"],ji);var Ca=z("Minutes",!1);j("s",["ss",2],0,"second"),V("second","s"),X("s",Ci),X("ss",Ci,Si),tt(["s","ss"],Gi);var Ta=z("Seconds",!1);j("S",0,0,function(){return~~(this.millisecond()/100)}),j(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),j(0,["SSS",3],0,"millisecond"),j(0,["SSSS",4],0,function(){return 10*this.millisecond()}),j(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),j(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),j(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),j(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),j(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),V("millisecond","ms"),X("S",Fi,_i),X("SS",Fi,Si),X("SSS",Fi,wi);var Pa;for(Pa="SSSS";Pa.length<=9;Pa+="S")X(Pa,Oi);for(Pa="S";Pa.length<=9;Pa+="S")tt(Pa,Sn);var Fa=z("Milliseconds",!1);j("z",0,0,"zoneAbbr"),j("zz",0,0,"zoneName");var Aa=p.prototype;Aa.add=ga,Aa.calendar=he,Aa.clone=fe,Aa.diff=xe,Aa.endOf=Ie,Aa.format=we,Aa.from=Me,Aa.fromNow=De,Aa.to=Ce,Aa.toNow=Te,Aa.get=E,Aa.invalidAt=He,Aa.isAfter=ge,Aa.isBefore=me,Aa.isBetween=pe,Aa.isSame=ve,Aa.isSameOrAfter=be,Aa.isSameOrBefore=ye,Aa.isValid=Ye,Aa.lang=pa,Aa.locale=Pe,Aa.localeData=Fe,Aa.max=da,Aa.min=la,Aa.parsingFlags=ze,Aa.set=E,Aa.startOf=Ae,Aa.subtract=ma,Aa.toArray=Le,Aa.toObject=Ve,Aa.toDate=We,Aa.toISOString=Se,Aa.toJSON=Be,Aa.toString=_e,Aa.unix=Re,Aa.valueOf=Oe,Aa.creationData=Ne,Aa.year=sa,Aa.isLeapYear=kt,Aa.weekYear=Ue,Aa.isoWeekYear=je,Aa.quarter=Aa.quarters=Xe,Aa.month=dt,Aa.daysInMonth=ut,Aa.week=Aa.weeks=tn,Aa.isoWeek=Aa.isoWeeks=en,Aa.weeksInYear=qe,Aa.isoWeeksInYear=Ge,Aa.date=ba,Aa.day=Aa.days=dn,Aa.weekday=un,Aa.isoWeekday=cn,Aa.dayOfYear=pn,Aa.hour=Aa.hours=Da,Aa.minute=Aa.minutes=Ca,Aa.second=Aa.seconds=Ta,Aa.millisecond=Aa.milliseconds=Fa,Aa.utcOffset=Zt,Aa.utc=Xt,Aa.local=Qt,Aa.parseZone=$t,Aa.hasAlignedHourOffset=Kt,Aa.isDST=te,Aa.isDSTShifted=ee,Aa.isLocal=ne,Aa.isUtcOffset=ie,Aa.isUtc=ae,Aa.isUTC=ae,Aa.zoneAbbr=wn,Aa.zoneName=Mn,Aa.dates=_("dates accessor is deprecated. Use date instead.",ba),Aa.months=_("months accessor is deprecated. Use month instead",dt),Aa.years=_("years accessor is deprecated. Use year instead",sa),Aa.zone=_("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Jt);var Ia=Aa,Oa={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ra={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Wa="Invalid date",La="%d",Va=/\d{1,2}/,Ba={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Ya=T.prototype;Ya._calendar=Oa,Ya.calendar=Tn,Ya._longDateFormat=Ra,Ya.longDateFormat=Pn,Ya._invalidDate=Wa,Ya.invalidDate=Fn,Ya._ordinal=La,Ya.ordinal=An,Ya._ordinalParse=Va,Ya.preparse=In,Ya.postformat=In,Ya._relativeTime=Ba,Ya.relativeTime=On,Ya.pastFuture=Rn,Ya.set=D,Ya.months=at,Ya._months=Qi,Ya.monthsShort=rt,Ya._monthsShort=$i,Ya.monthsParse=st,Ya._monthsRegex=ta,Ya.monthsRegex=ht,Ya._monthsShortRegex=Ki,Ya.monthsShortRegex=ct,Ya.week=Qe,Ya._week=va,Ya.firstDayOfYear=Ke,Ya.firstDayOfWeek=$e,Ya.weekdays=an,Ya._weekdays=ya,Ya.weekdaysMin=on,Ya._weekdaysMin=ka,Ya.weekdaysShort=rn,Ya._weekdaysShort=xa,Ya.weekdaysParse=ln,Ya._weekdaysRegex=_a,Ya.weekdaysRegex=hn,Ya._weekdaysShortRegex=Sa,Ya.weekdaysShortRegex=fn,Ya._weekdaysMinRegex=wa,Ya.weekdaysMinRegex=gn,Ya.isPM=kn,Ya._meridiemParse=Ma,Ya.meridiem=_n,I("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,n=1===y(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+n}}),t.lang=_("moment.lang is deprecated. Use moment.locale instead.",I),t.langData=_("moment.langData is deprecated. Use moment.localeData instead.",W);var za=Math.abs,Ha=Kn("ms"),Na=Kn("s"),Ea=Kn("m"),Ua=Kn("h"),ja=Kn("d"),Ga=Kn("w"),qa=Kn("M"),Za=Kn("y"),Ja=ei("milliseconds"),Xa=ei("seconds"),Qa=ei("minutes"),$a=ei("hours"),Ka=ei("days"),tr=ei("months"),er=ei("years"),nr=Math.round,ir={s:45,m:45,h:22,d:26,M:11},ar=Math.abs,rr=Nt.prototype;rr.abs=En,rr.add=jn,rr.subtract=Gn,rr.as=Qn,rr.asMilliseconds=Ha,rr.asSeconds=Na,rr.asMinutes=Ea,rr.asHours=Ua,rr.asDays=ja,rr.asWeeks=Ga,rr.asMonths=qa,rr.asYears=Za,rr.valueOf=$n,rr._bubble=Zn,rr.get=ti,rr.milliseconds=Ja,rr.seconds=Xa,rr.minutes=Qa,rr.hours=$a,rr.days=Ka,rr.weeks=ni,rr.months=tr,rr.years=er,rr.humanize=oi,rr.toISOString=si,rr.toString=si,rr.toJSON=si,rr.locale=Pe,rr.localeData=Fe,rr.toIsoString=_("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",si),rr.lang=pa,j("X",0,0,"unix"),j("x",0,0,"valueOf"),X("x",Ri),X("X",Vi),tt("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),tt("x",function(t,e,n){n._d=new Date(y(t))}),t.version="2.13.0",i(Bt),t.fn=Ia,t.min=zt,t.max=Ht,t.now=ua,t.utc=d,t.unix=Dn,t.months=Bn,t.isDate=r,t.locale=I,t.invalid=f,t.duration=re,t.isMoment=v,t.weekdays=zn,t.parseZone=Cn,t.localeData=W,t.isDuration=Et,t.monthsShort=Yn,t.weekdaysMin=Nn,t.defineLocale=O,t.updateLocale=R,t.locales=L,t.weekdaysShort=Hn,t.normalizeUnits=B,t.relativeTimeThreshold=ri,t.prototype=Ia;var or=t;return or})},{}],7:[function(t,e,n){var i=t(26)();t(25)(i),t(24)(i),t(21)(i),t(22)(i),t(23)(i),t(27)(i),t(31)(i),t(29)(i),t(30)(i),t(32)(i),t(28)(i),t(33)(i),t(34)(i),t(35)(i),t(36)(i),t(37)(i),t(40)(i),t(38)(i),t(39)(i),t(41)(i),t(42)(i),t(43)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i),window.Chart=e.exports=i},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,37:37,38:38,39:39,40:40,41:41,42:42,43:43,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.options=t.helpers.configMerge({aspectRatio:1},n.options),n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){var e={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){return"("+t.xLabel+", "+t.yLabel+")"}}}};t.defaults.scatter=e,t.controllers.scatter=t.controllers.line,t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(e,n){t.DatasetController.prototype.initialize.call(this,e,n),this.getMeta().bar=!0},getBarCount:function(){var t=this,n=0;return e.each(t.chart.data.datasets,function(e,i){var a=t.chart.getDatasetMeta(i);a.bar&&t.chart.isDatasetVisible(i)&&++n},t),n},update:function(t){var n=this;e.each(n.getMeta().data,function(e,i){n.updateElement(e,i,t)},n)},updateElement:function(t,n,i){var a=this,r=a.getMeta(),o=a.getScaleForId(r.xAxisID),s=a.getScaleForId(r.yAxisID),l=s.getBasePixel(),d=a.chart.options.elements.rectangle,u=t.custom||{},c=a.getDataset();e.extend(t,{_xScale:o,_yScale:s,_datasetIndex:a.index,_index:n,_model:{x:a.calculateBarX(n,a.index),y:i?l:a.calculateBarY(n,a.index),label:a.chart.data.labels[n],datasetLabel:c.label,base:i?l:a.calculateBarBase(a.index,n),width:a.calculateBarWidth(n),backgroundColor:u.backgroundColor?u.backgroundColor:e.getValueAtIndexOrDefault(c.backgroundColor,n,d.backgroundColor),borderSkipped:u.borderSkipped?u.borderSkipped:d.borderSkipped,borderColor:u.borderColor?u.borderColor:e.getValueAtIndexOrDefault(c.borderColor,n,d.borderColor),borderWidth:u.borderWidth?u.borderWidth:e.getValueAtIndexOrDefault(c.borderWidth,n,d.borderWidth)}}),t.pivot()},calculateBarBase:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.yAxisID),r=0;if(a.options.stacked){var o=n.chart,s=o.data.datasets,l=s[t].data[e];if(0>l)for(var d=0;t>d;d++){var u=s[d],c=o.getDatasetMeta(d);c.bar&&c.yAxisID===a.id&&o.isDatasetVisible(d)&&(r+=u.data[e]<0?u.data[e]:0)}else for(var h=0;t>h;h++){var f=s[h],g=o.getDatasetMeta(h);g.bar&&g.yAxisID===a.id&&o.isDatasetVisible(h)&&(r+=f.data[e]>0?f.data[e]:0)}return a.getPixelForValue(r)}return a.getBasePixel()},getRuler:function(t){var e,n=this,i=n.getMeta(),a=n.getScaleForId(i.xAxisID),r=n.getBarCount();e="category"===a.options.type?a.getPixelForTick(t+1)-a.getPixelForTick(t):a.width/a.ticks.length;var o=e*a.options.categoryPercentage,s=(e-e*a.options.categoryPercentage)/2,l=o/r;if(a.ticks.length!==n.chart.data.labels.length){var d=a.ticks.length/n.chart.data.labels.length;l*=d}var u=l*a.options.barPercentage,c=l-l*a.options.barPercentage;return{datasetCount:r,tickWidth:e,categoryWidth:o,categorySpacing:s,fullBarWidth:l,barWidth:u,barSpacing:c}},calculateBarWidth:function(t){var e=this.getScaleForId(this.getMeta().xAxisID),n=this.getRuler(t);return e.options.stacked?n.categoryWidth:n.barWidth},getBarIndex:function(t){var e,n,i=0;for(n=0;t>n;++n)e=this.chart.getDatasetMeta(n),e.bar&&this.chart.isDatasetVisible(n)&&++i;return i},calculateBarX:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.xAxisID),r=n.getBarIndex(e),o=n.getRuler(t),s=a.getPixelForValue(null,t,e,n.chart.isCombo);return s-=n.chart.isCombo?o.tickWidth/2:0,a.options.stacked?s+o.categoryWidth/2+o.categorySpacing:s+o.barWidth/2+o.categorySpacing+o.barWidth*r+o.barSpacing/2+o.barSpacing*r},calculateBarY:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.yAxisID),r=n.getDataset().data[t];if(a.options.stacked){for(var o=0,s=0,l=0;e>l;l++){var d=n.chart.data.datasets[l],u=n.chart.getDatasetMeta(l);u.bar&&u.yAxisID===a.id&&n.chart.isDatasetVisible(l)&&(d.data[t]<0?s+=d.data[t]||0:o+=d.data[t]||0)}return 0>r?a.getPixelForValue(s+r):a.getPixelForValue(o+r)}return a.getPixelForValue(r)},draw:function(t){var n=this,i=t||1;e.each(n.getMeta().data,function(t,e){var a=n.getDataset().data[e];null===a||void 0===a||isNaN(a)||t.transition(i).draw()},n)},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model;r.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.hoverBackgroundColor,i,e.getHoverColor(r.backgroundColor)),r.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(n.hoverBorderColor,i,e.getHoverColor(r.borderColor)),r.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(n.hoverBorderWidth,i,r.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model,o=this.chart.options.elements.rectangle;r.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(n.backgroundColor,i,o.backgroundColor),r.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(n.borderColor,i,o.borderColor),r.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(n.borderWidth,i,o.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(n=e.labels[t[0].index])),n},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({updateElement:function(t,n,i,a){var r=this,o=r.getMeta(),s=r.getScaleForId(o.xAxisID),l=r.getScaleForId(o.yAxisID),d=s.getBasePixel(),u=t.custom||{},c=r.getDataset(),h=r.chart.options.elements.rectangle;e.extend(t,{_xScale:s,_yScale:l,_datasetIndex:r.index,_index:n,_model:{x:i?d:r.calculateBarX(n,r.index),y:r.calculateBarY(n,r.index),label:r.chart.data.labels[n],datasetLabel:c.label,base:i?d:r.calculateBarBase(r.index,n),height:r.calculateBarHeight(n),backgroundColor:u.backgroundColor?u.backgroundColor:e.getValueAtIndexOrDefault(c.backgroundColor,n,h.backgroundColor),borderSkipped:u.borderSkipped?u.borderSkipped:h.borderSkipped,borderColor:u.borderColor?u.borderColor:e.getValueAtIndexOrDefault(c.borderColor,n,h.borderColor),borderWidth:u.borderWidth?u.borderWidth:e.getValueAtIndexOrDefault(c.borderWidth,n,h.borderWidth)},draw:function(){function t(t){return l[(u+t)%4]}var e=this._chart.ctx,n=this._view,i=n.height/2,a=n.y-i,r=n.y+i,o=n.base-(n.base-n.x),s=n.borderWidth/2;n.borderWidth&&(a+=s,r-=s,o+=s),e.beginPath(),e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,e.lineWidth=n.borderWidth;var l=[[n.base,r],[n.base,a],[o,a],[o,r]],d=["bottom","left","top","right"],u=d.indexOf(n.borderSkipped,0);-1===u&&(u=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),n.borderWidth&&e.stroke()},inRange:function(t,e){var n=this._view,i=!1;return n&&(i=n.x<n.base?e>=n.y-n.height/2&&e<=n.y+n.height/2&&t>=n.x&&t<=n.base:e>=n.y-n.height/2&&e<=n.y+n.height/2&&t>=n.base&&t<=n.x),i}}),t.pivot()},calculateBarBase:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.xAxisID),r=0;if(a.options.stacked){var o=n.chart.data.datasets[t].data[e];if(0>o)for(var s=0;t>s;s++){var l=n.chart.data.datasets[s],d=n.chart.getDatasetMeta(s);d.bar&&d.xAxisID===a.id&&n.chart.isDatasetVisible(s)&&(r+=l.data[e]<0?l.data[e]:0)}else for(var u=0;t>u;u++){var c=n.chart.data.datasets[u],h=n.chart.getDatasetMeta(u);h.bar&&h.xAxisID===a.id&&n.chart.isDatasetVisible(u)&&(r+=c.data[e]>0?c.data[e]:0)}return a.getPixelForValue(r)}return a.getBasePixel()},getRuler:function(t){var e,n=this,i=n.getMeta(),a=n.getScaleForId(i.yAxisID),r=n.getBarCount();e="category"===a.options.type?a.getPixelForTick(t+1)-a.getPixelForTick(t):a.width/a.ticks.length;var o=e*a.options.categoryPercentage,s=(e-e*a.options.categoryPercentage)/2,l=o/r;if(a.ticks.length!==n.chart.data.labels.length){var d=a.ticks.length/n.chart.data.labels.length;l*=d}var u=l*a.options.barPercentage,c=l-l*a.options.barPercentage;return{datasetCount:r,tickHeight:e,categoryHeight:o,categorySpacing:s,fullBarHeight:l,barHeight:u,barSpacing:c}},calculateBarHeight:function(t){var e=this,n=e.getScaleForId(e.getMeta().yAxisID),i=e.getRuler(t);return n.options.stacked?i.categoryHeight:i.barHeight},calculateBarX:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.xAxisID),r=n.getDataset().data[t];if(a.options.stacked){for(var o=0,s=0,l=0;e>l;l++){var d=n.chart.data.datasets[l],u=n.chart.getDatasetMeta(l);u.bar&&u.xAxisID===a.id&&n.chart.isDatasetVisible(l)&&(d.data[t]<0?s+=d.data[t]||0:o+=d.data[t]||0)}return 0>r?a.getPixelForValue(s+r):a.getPixelForValue(o+r)}return a.getPixelForValue(r)},calculateBarY:function(t,e){var n=this,i=n.getMeta(),a=n.getScaleForId(i.yAxisID),r=n.getBarIndex(e),o=n.getRuler(t),s=a.getPixelForValue(null,t,e,n.chart.isCombo);return s-=n.chart.isCombo?o.tickHeight/2:0,a.options.stacked?s+o.categoryHeight/2+o.categorySpacing:s+o.barHeight/2+o.categorySpacing+o.barHeight*r+o.barSpacing/2+o.barSpacing*r}})}},{}],16:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){var n=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return n+": ("+i.x+", "+i.y+", "+i.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var n=this,i=n.getMeta(),a=i.data;e.each(a,function(e,i){n.updateElement(e,i,t)})},updateElement:function(n,i,a){var r=this,o=r.getMeta(),s=r.getScaleForId(o.xAxisID),l=r.getScaleForId(o.yAxisID),d=n.custom||{},u=r.getDataset(),c=u.data[i],h=r.chart.options.elements.point,f=r.index;e.extend(n,{_xScale:s,_yScale:l,_datasetIndex:f,_index:i,_model:{x:a?s.getPixelForDecimal(.5):s.getPixelForValue(c,i,f,r.chart.isCombo),y:a?l.getBasePixel():l.getPixelForValue(c,i,f),radius:a?0:d.radius?d.radius:r.getRadius(c),hitRadius:d.hitRadius?d.hitRadius:e.getValueAtIndexOrDefault(u.hitRadius,i,h.hitRadius)}}),t.DatasetController.prototype.removeHoverStyle.call(r,n,h);var g=n._model;g.skip=d.skip?d.skip:isNaN(g.x)||isNaN(g.y),n.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(n){var i=this;t.DatasetController.prototype.setHoverStyle.call(i,n);var a=i.chart.data.datasets[n._datasetIndex],r=n._index,o=n.custom||{},s=n._model;s.radius=o.hoverRadius?o.hoverRadius:e.getValueAtIndexOrDefault(a.hoverRadius,r,i.chart.options.elements.point.hoverRadius)+i.getRadius(a.data[r])},removeHoverStyle:function(e){var n=this;t.DatasetController.prototype.removeHoverStyle.call(n,e,n.chart.options.elements.point);var i=n.chart.data.datasets[e._datasetIndex].data[e._index],a=e.custom||{},r=e._model;r.radius=a.radius?a.radius:n.getRadius(i)}})}},{}],17:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults;n.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'"></span>'),a[r]&&e.push(a[r]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var r=t.getDatasetMeta(0),o=n.datasets[0],s=r.data[a],l=s.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=l.backgroundColor?l.backgroundColor:d(o.backgroundColor,a,u.backgroundColor),h=l.borderColor?l.borderColor:d(o.borderColor,a,u.borderColor),f=l.borderWidth?l.borderWidth:d(o.borderWidth,a,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(o.data[a])||r.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;i>n;++n)a=o.getDatasetMeta(n),a.data[r].hidden=!a.data[r].hidden;o.update()}},cutoutPercentage:50,rotation:Math.PI*-.5,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+e.datasets[t.datasetIndex].data[t.index]}}}},n.pie=e.clone(n.doughnut),e.extend(n.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,n=0;t>n;++n)this.chart.isDatasetVisible(n)&&++e;return e},update:function(t){var n=this,i=n.chart,a=i.chartArea,r=i.options,o=r.elements.arc,s=a.right-a.left-o.borderWidth,l=a.bottom-a.top-o.borderWidth,d=Math.min(s,l),u={x:0,y:0},c=n.getMeta(),h=r.cutoutPercentage,f=r.circumference;if(f<2*Math.PI){var g=r.rotation%(2*Math.PI);g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0);var m=g+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},b=0>=g&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,y=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,k=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,_=h/100,S={x:x?-1:Math.min(p.x*(p.x<0?1:_),v.x*(v.x<0?1:_)),y:k?-1:Math.min(p.y*(p.y<0?1:_),v.y*(v.y<0?1:_))},w={x:b?1:Math.max(p.x*(p.x>0?1:_),v.x*(v.x>0?1:_)),y:y?1:Math.max(p.y*(p.y>0?1:_),v.y*(v.y>0?1:_))},M={width:.5*(w.x-S.x),height:.5*(w.y-S.y)};d=Math.min(s/M.width,l/M.height),u={x:(w.x+S.x)*-.5,y:(w.y+S.y)*-.5}}i.outerRadius=Math.max(d/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=u.x*i.outerRadius,i.offsetY=u.y*i.outerRadius,c.total=n.calculateTotal(),n.outerRadius=i.outerRadius-i.radiusLength*n.getRingIndex(n.index),n.innerRadius=n.outerRadius-i.radiusLength,e.each(c.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){var a=this,r=a.chart,o=r.chartArea,s=r.options,l=s.animation,d=(s.elements.arc,(o.left+o.right)/2),u=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=a.getDataset(),g=i&&l.animateRotate?0:t.hidden?0:a.calculateCircumference(f.data[n])*(s.circumference/(2*Math.PI)),m=i&&l.animateScale?0:a.innerRadius,p=i&&l.animateScale?0:a.outerRadius,v=(t.custom||{},e.getValueAtIndexOrDefault);e.extend(t,{_datasetIndex:a.index,_index:n,_model:{x:d+r.offsetX,y:u+r.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,n,r.data.labels[n])}});var b=t._model;this.removeHoverStyle(t),i&&l.animateRotate||(0===n?b.startAngle=s.rotation:b.startAngle=a.getMeta().data[n-1]._model.endAngle,b.endAngle=b.startAngle+b.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,n=this.getDataset(),i=this.getMeta(),a=0;return e.each(i.data,function(e,i){t=n.data[i],isNaN(t)||e.hidden||(a+=Math.abs(t))}),a},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0}})}},{}],18:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return n.getValueOrDefault(t.showLine,e.showLines)}var n=t.helpers;t.defaults.line={showLines:!0,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,addElementAndReset:function(n){var i=this,a=i.chart.options,r=i.getMeta();t.DatasetController.prototype.addElementAndReset.call(i,n),e(i.getDataset(),a)&&0!==r.dataset._model.tension&&i.updateBezierControlPoints()},update:function(t){var i,a,r,o=this,s=o.getMeta(),l=s.dataset,d=s.data||[],u=o.chart.options,c=u.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,u);for(g&&(r=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=d,l._model={spanGaps:f.spanGaps?f.spanGaps:!1,tension:r.tension?r.tension:n.getValueOrDefault(f.lineTension,c.tension),backgroundColor:r.backgroundColor?r.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:f.borderWidth||c.borderWidth,borderColor:r.borderColor?r.borderColor:f.borderColor||c.borderColor,borderCapStyle:r.borderCapStyle?r.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:r.borderDash?r.borderDash:f.borderDash||c.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:r.fill?r.fill:void 0!==f.fill?f.fill:c.fill,scaleTop:h.top,scaleBottom:h.bottom,scaleZero:h.getBasePixel()},l.pivot()),i=0,a=d.length;a>i;++i)o.updateElement(d[i],i,t);for(g&&0!==l._model.tension&&o.updateBezierControlPoints(),i=0,a=d.length;a>i;++i)d[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,a=this.getDataset(),r=t.custom||{};return r.backgroundColor?i=r.backgroundColor:a.pointBackgroundColor?i=n.getValueAtIndexOrDefault(a.pointBackgroundColor,e,i):a.backgroundColor&&(i=a.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,a=this.getDataset(),r=t.custom||{};return r.borderColor?i=r.borderColor:a.pointBorderColor?i=n.getValueAtIndexOrDefault(a.pointBorderColor,e,i):a.borderColor&&(i=a.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,a=this.getDataset(),r=t.custom||{};return r.borderWidth?i=r.borderWidth:a.pointBorderWidth?i=n.getValueAtIndexOrDefault(a.pointBorderWidth,e,i):a.borderWidth&&(i=a.borderWidth),i},updateElement:function(t,e,i){var a,r,o=this,s=o.getMeta(),l=t.custom||{},d=o.getDataset(),u=o.index,c=d.data[e],h=o.getScaleForId(s.yAxisID),f=o.getScaleForId(s.xAxisID),g=o.chart.options.elements.point;void 0!==d.radius&&void 0===d.pointRadius&&(d.pointRadius=d.radius),void 0!==d.hitRadius&&void 0===d.pointHitRadius&&(d.pointHitRadius=d.hitRadius),a=f.getPixelForValue(c,e,u,o.chart.isCombo),r=i?h.getBasePixel():o.calculatePointY(c,e,u,o.chart.isCombo),t._xScale=f,t._yScale=h,t._datasetIndex=u,t._index=e,t._model={x:a,y:r,skip:l.skip||isNaN(a)||isNaN(r),radius:l.radius||n.getValueAtIndexOrDefault(d.pointRadius,e,g.radius),pointStyle:l.pointStyle||n.getValueAtIndexOrDefault(d.pointStyle,e,g.pointStyle),backgroundColor:o.getPointBackgroundColor(t,e),borderColor:o.getPointBorderColor(t,e),borderWidth:o.getPointBorderWidth(t,e),tension:s.dataset._model?s.dataset._model.tension:0,hitRadius:l.hitRadius||n.getValueAtIndexOrDefault(d.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,n,i){var a,r,o,s=this,l=s.chart,d=s.getMeta(),u=s.getScaleForId(d.yAxisID),c=0,h=0;if(u.options.stacked){for(a=0;n>a;a++)r=l.data.datasets[a],o=l.getDatasetMeta(a),"line"===o.type&&l.isDatasetVisible(a)&&(r.data[e]<0?h+=r.data[e]||0:c+=r.data[e]||0);return 0>t?u.getPixelForValue(h+t):u.getPixelForValue(c+t)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,i,a,r,o=this.getMeta(),s=this.chart.chartArea,l=o.data||[];for(t=0,e=l.length;e>t;++t)i=l[t],a=i._model,r=n.splineCurve(n.previousItem(l,t)._model,a,n.nextItem(l,t)._model,o.dataset._model.tension),a.controlPointPreviousX=Math.max(Math.min(r.previous.x,s.right),s.left),a.controlPointPreviousY=Math.max(Math.min(r.previous.y,s.bottom),s.top),a.controlPointNextX=Math.max(Math.min(r.next.x,s.right),s.left),a.controlPointNextY=Math.max(Math.min(r.next.y,s.bottom),s.top)},draw:function(t){var n,i,a=this,r=a.getMeta(),o=r.data||[],s=t||1;for(n=0,i=o.length;i>n;++n)o[n].transition(s);for(e(a.getDataset(),a.chart.options)&&r.dataset.transition(s).draw(),n=0,i=o.length;i>n;++n)o[n].draw()},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=t._model;r.radius=a.hoverRadius||n.getValueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),r.backgroundColor=a.hoverBackgroundColor||n.getValueAtIndexOrDefault(e.pointHoverBackgroundColor,i,n.getHoverColor(r.backgroundColor)),r.borderColor=a.hoverBorderColor||n.getValueAtIndexOrDefault(e.pointHoverBorderColor,i,n.getHoverColor(r.borderColor)),r.borderWidth=a.hoverBorderWidth||n.getValueAtIndexOrDefault(e.pointHoverBorderWidth,i,r.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],a=t._index,r=t.custom||{},o=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),o.radius=r.radius||n.getValueAtIndexOrDefault(i.pointRadius,a,e.chart.options.elements.point.radius),o.backgroundColor=e.getPointBackgroundColor(t,a),o.borderColor=e.getPointBorderColor(t,a),o.borderWidth=e.getPointBorderWidth(t,a)}})}},{}],19:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",lineArc:!0},animation:{animateRotate:!0,animateScale:!0},aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r<i[0].data.length;++r)e.push('<li><span style="background-color:'+i[0].backgroundColor[r]+'">'),a[r]&&e.push(a[r]),e.push("</span></li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var n=t.data;return n.labels.length&&n.datasets.length?n.labels.map(function(i,a){var r=t.getDatasetMeta(0),o=n.datasets[0],s=r.data[a],l=s.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=l.backgroundColor?l.backgroundColor:d(o.backgroundColor,a,u.backgroundColor),h=l.borderColor?l.borderColor:d(o.borderColor,a,u.borderColor),f=l.borderWidth?l.borderWidth:d(o.borderWidth,a,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(o.data[a])||r.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;i>n;++n)a=o.getDatasetMeta(n),a.data[r].hidden=!a.data[r].hidden;o.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var n=this,i=n.chart,a=i.chartArea,r=n.getMeta(),o=i.options,s=o.elements.arc,l=Math.min(a.right-a.left,a.bottom-a.top);i.outerRadius=Math.max((l-s.borderWidth/2)/2,0),i.innerRadius=Math.max(o.cutoutPercentage?i.outerRadius/100*o.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),n.outerRadius=i.outerRadius-i.radiusLength*n.index,n.innerRadius=n.outerRadius-i.radiusLength,r.count=n.countVisibleElements(),e.each(r.data,function(e,i){n.updateElement(e,i,t)})},updateElement:function(t,n,i){for(var a=this,r=a.chart,o=r.chartArea,s=a.getDataset(),l=r.options,d=l.animation,u=(l.elements.arc,t.custom||{},r.scale),c=e.getValueAtIndexOrDefault,h=r.data.labels,f=a.calculateCircumference(s.data[n]),g=(o.left+o.right)/2,m=(o.top+o.bottom)/2,p=0,v=a.getMeta(),b=0;n>b;++b)isNaN(s.data[b])||v.data[b].hidden||++p;var y=-.5*Math.PI,x=t.hidden?0:u.getDistanceFromCenterForValue(s.data[n]),k=y+f*p,_=k+(t.hidden?0:f),S=d.animateScale?0:u.getDistanceFromCenterForValue(s.data[n]);e.extend(t,{_datasetIndex:a.index,_index:n,_scale:u,_model:{x:g,y:m,innerRadius:0,outerRadius:i?S:x,startAngle:i&&d.animateRotate?y:k,endAngle:i&&d.animateRotate?y:_,label:c(h,n,h[n])}}),a.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),n=this.getMeta(),i=0;return e.each(n.data,function(e,n){isNaN(t.data[n])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,addElementAndReset:function(e){t.DatasetController.prototype.addElementAndReset.call(this,e),this.updateBezierControlPoints()},update:function(t){var n=this,i=n.getMeta(),a=i.dataset,r=i.data,o=a.custom||{},s=n.getDataset(),l=n.chart.options.elements.line,d=n.chart.scale;
-void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),e.extend(i.dataset,{_datasetIndex:n.index,_children:r,_loop:!0,_model:{tension:o.tension?o.tension:e.getValueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle,scaleTop:d.top,scaleBottom:d.bottom,scaleZero:d.getBasePosition()}}),i.dataset.pivot(),e.each(r,function(e,i){n.updateElement(e,i,t)},n),n.updateBezierControlPoints()},updateElement:function(t,n,i){var a=this,r=t.custom||{},o=a.getDataset(),s=a.chart.scale,l=a.chart.options.elements.point,d=s.getPointPositionForValue(n,o.data[n]);e.extend(t,{_datasetIndex:a.index,_index:n,_scale:s,_model:{x:i?s.xCenter:d.x,y:i?s.yCenter:d.y,tension:r.tension?r.tension:e.getValueOrDefault(o.tension,a.chart.options.elements.line.tension),radius:r.radius?r.radius:e.getValueAtIndexOrDefault(o.pointRadius,n,l.radius),backgroundColor:r.backgroundColor?r.backgroundColor:e.getValueAtIndexOrDefault(o.pointBackgroundColor,n,l.backgroundColor),borderColor:r.borderColor?r.borderColor:e.getValueAtIndexOrDefault(o.pointBorderColor,n,l.borderColor),borderWidth:r.borderWidth?r.borderWidth:e.getValueAtIndexOrDefault(o.pointBorderWidth,n,l.borderWidth),pointStyle:r.pointStyle?r.pointStyle:e.getValueAtIndexOrDefault(o.pointStyle,n,l.pointStyle),hitRadius:r.hitRadius?r.hitRadius:e.getValueAtIndexOrDefault(o.hitRadius,n,l.hitRadius)}}),t._model.skip=r.skip?r.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,n=this.getMeta();e.each(n.data,function(i,a){var r=i._model,o=e.splineCurve(e.previousItem(n.data,a,!0)._model,r,e.nextItem(n.data,a,!0)._model,r.tension);r.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),r.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),r.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),r.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),i.pivot()})},draw:function(t){var n=this.getMeta(),i=t||1;e.each(n.data,function(t,e){t.transition(i)}),n.dataset.transition(i).draw(),e.each(n.data,function(t){t.draw()})},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,r=t._model;r.radius=i.hoverRadius?i.hoverRadius:e.getValueAtIndexOrDefault(n.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),r.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:e.getValueAtIndexOrDefault(n.pointHoverBackgroundColor,a,e.getHoverColor(r.backgroundColor)),r.borderColor=i.hoverBorderColor?i.hoverBorderColor:e.getValueAtIndexOrDefault(n.pointHoverBorderColor,a,e.getHoverColor(r.borderColor)),r.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:e.getValueAtIndexOrDefault(n.pointHoverBorderWidth,a,r.borderWidth)},removeHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},a=t._index,r=t._model,o=this.chart.options.elements.point;r.radius=i.radius?i.radius:e.getValueAtIndexOrDefault(n.radius,a,o.radius),r.backgroundColor=i.backgroundColor?i.backgroundColor:e.getValueAtIndexOrDefault(n.pointBackgroundColor,a,o.backgroundColor),r.borderColor=i.borderColor?i.borderColor:e.getValueAtIndexOrDefault(n.pointBorderColor,a,o.borderColor),r.borderWidth=i.borderWidth?i.borderWidth:e.getValueAtIndexOrDefault(n.pointBorderWidth,a,o.borderWidth)}})}},{}],21:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({currentStep:null,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a=this;i||(t.animating=!0);for(var r=0;r<a.animations.length;++r)if(a.animations[r].chartInstance===t)return void(a.animations[r].animationObject=e);a.animations.push({chartInstance:t,animationObject:e}),1===a.animations.length&&a.requestAnimationFrame()},cancelAnimation:function(t){var n=e.findIndex(this.animations,function(e){return e.chartInstance===t});-1!==n&&(this.animations.splice(n,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),n=0;t.dropFrames>1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1);for(var i=0;i<t.animations.length;)null===t.animations[i].animationObject.currentStep&&(t.animations[i].animationObject.currentStep=0),t.animations[i].animationObject.currentStep+=1+n,t.animations[i].animationObject.currentStep>t.animations[i].animationObject.numSteps&&(t.animations[i].animationObject.currentStep=t.animations[i].animationObject.numSteps),t.animations[i].animationObject.render(t.animations[i].chartInstance,t.animations[i].animationObject),t.animations[i].animationObject.onAnimationProgress&&t.animations[i].animationObject.onAnimationProgress.call&&t.animations[i].animationObject.onAnimationProgress.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].animationObject.currentStep===t.animations[i].animationObject.numSteps?(t.animations[i].animationObject.onAnimationComplete&&t.animations[i].animationObject.onAnimationComplete.call&&t.animations[i].animationObject.onAnimationComplete.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].chartInstance.animating=!1,t.animations.splice(i,1)):++i;var a=Date.now(),r=(a-e)/t.frameDuration;t.dropFrames+=r,t.animations.length>0&&t.requestAnimationFrame()}}}},{}],22:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.types={},t.instances={},t.controllers={},t.Controller=function(n){return this.chart=n,this.config=n.config,this.options=this.config.options=e.configMerge(t.defaults.global,t.defaults[this.config.type],this.config.options||{}),this.id=e.uid(),Object.defineProperty(this,"data",{get:function(){return this.config.data}}),t.instances[this.id]=this,this.options.responsive&&this.resize(!0),this.initialize(),this},e.extend(t.Controller.prototype,{initialize:function(){var e=this;return t.pluginService.notifyPlugins("beforeInit",[e]),e.bindEvents(),e.ensureScalesHaveIDs(),e.buildOrUpdateControllers(),e.buildScales(),e.updateLayout(),e.resetElements(),e.initToolTip(),e.update(),t.pluginService.notifyPlugins("afterInit",[e]),e},clear:function(){return e.clear(this.chart),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(n){var i=this,a=i.chart,r=a.canvas,o=e.getMaximumWidth(r),s=a.aspectRatio,l=i.options.maintainAspectRatio&&isNaN(s)===!1&&isFinite(s)&&0!==s?o/s:e.getMaximumHeight(r),d=a.width!==o||a.height!==l;if(!d)return i;r.width=a.width=o,r.height=a.height=l,e.retinaScale(a);var u={width:o,height:l};return t.pluginService.notifyPlugins("resize",[i,u]),i.options.onResize&&i.options.onResize(i,u),n||(i.stop(),i.update(i.options.responsiveAnimationDuration)),i},ensureScalesHaveIDs:function(){var t=this.options,n=t.scales||{},i=t.scale;e.each(n.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),e.each(n.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildScales:function(){var n=this,i=n.options,a=n.scales={},r=[];i.scales&&(r=r.concat((i.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category"}}),(i.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear"}}))),i.scale&&r.push({options:i.scale,dtype:"radialLinear",isDefault:!0}),e.each(r,function(i,r){var o=i.options,s=e.getValueOrDefault(o.type,i.dtype),l=t.scaleService.getScaleConstructor(s);if(l){var d=new l({id:o.id,options:o,ctx:n.chart.ctx,chart:n});a[d.id]=d,i.isDefault&&(n.scale=d)}}),t.scaleService.addScalesToLayout(this)},updateLayout:function(){t.layoutService.update(this,this.chart.width,this.chart.height)},buildOrUpdateControllers:function(){var n=this,i=[],a=[];if(e.each(n.data.datasets,function(e,r){var o=n.getDatasetMeta(r);o.type||(o.type=e.type||n.config.type),i.push(o.type),o.controller?o.controller.updateIndex(r):(o.controller=new t.controllers[o.type](n,r),a.push(o.controller))},n),i.length>1)for(var r=1;r<i.length;r++)if(i[r]!==i[r-1]){n.isCombo=!0;break}return a},resetElements:function(){var t=this;e.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},update:function(n,i){var a=this;t.pluginService.notifyPlugins("beforeUpdate",[a]),a.tooltip._data=a.data;var r=a.buildOrUpdateControllers();e.each(a.data.datasets,function(t,e){a.getDatasetMeta(e).controller.buildOrUpdateElements()},a),t.layoutService.update(a,a.chart.width,a.chart.height),t.pluginService.notifyPlugins("afterScaleUpdate",[a]),e.each(r,function(t){t.reset()}),e.each(a.data.datasets,function(t,e){a.getDatasetMeta(e).controller.update()},a),t.pluginService.notifyPlugins("afterUpdate",[a]),a.render(n,i)},render:function(n,i){var a=this;t.pluginService.notifyPlugins("beforeRender",[a]);var r=a.options.animation;if(r&&("undefined"!=typeof n&&0!==n||"undefined"==typeof n&&0!==r.duration)){var o=new t.Animation;o.numSteps=(n||r.duration)/16.66,o.easing=r.easing,o.render=function(t,n){var i=e.easingEffects[n.easing],a=n.currentStep/n.numSteps,r=i(a);t.draw(r,a,n.currentStep)},o.onAnimationProgress=r.onProgress,o.onAnimationComplete=r.onComplete,t.animationService.addAnimation(a,o,n,i)}else a.draw(),r&&r.onComplete&&r.onComplete.call&&r.onComplete.call(a);return a},draw:function(n){var i=this,a=n||1;i.clear(),t.pluginService.notifyPlugins("beforeDraw",[i,a]),e.each(i.boxes,function(t){t.draw(i.chartArea)},i),i.scale&&i.scale.draw(),t.pluginService.notifyPlugins("beforeDatasetDraw",[i,a]),e.each(i.data.datasets,function(t,e){i.isDatasetVisible(e)&&i.getDatasetMeta(e).controller.draw(n)},i,!0),t.pluginService.notifyPlugins("afterDatasetDraw",[i,a]),i.tooltip.transition(a).draw(),t.pluginService.notifyPlugins("afterDraw",[i,a])},getElementAtEvent:function(t){var n=this,i=e.getRelativePosition(t,n.chart),a=[];return e.each(n.data.datasets,function(t,r){if(n.isDatasetVisible(r)){var o=n.getDatasetMeta(r);e.each(o.data,function(t,e){return t.inRange(i.x,i.y)?(a.push(t),a):void 0})}}),a},getElementsAtEvent:function(t){var n=this,i=e.getRelativePosition(t,n.chart),a=[],r=function(){if(n.data.datasets)for(var t=0;t<n.data.datasets.length;t++){var e=n.getDatasetMeta(t);if(n.isDatasetVisible(t))for(var a=0;a<e.data.length;a++)if(e.data[a].inRange(i.x,i.y))return e.data[a]}}.call(n);return r?(e.each(n.data.datasets,function(t,e){if(n.isDatasetVisible(e)){var i=n.getDatasetMeta(e);a.push(i.data[r._index])}},n),a):a},getElementsAtEventForMode:function(t,e){var n=this;switch(e){case"single":return n.getElementAtEvent(t);case"label":return n.getElementsAtEvent(t);case"dataset":return n.getDatasetAtEvent(t);default:return t}},getDatasetAtEvent:function(t){var e=this.getElementAtEvent(t);return e.length>0&&(e=this.getDatasetMeta(e[0]._datasetIndex).data),e},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;n>e;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){var n=this;n.stop(),n.clear(),e.unbindEvents(n,n.events),e.removeResizeListener(n.chart.canvas.parentNode);var i=n.chart.canvas;i.width=n.chart.width,i.height=n.chart.height,void 0!==n.chart.originalDevicePixelRatio&&n.chart.ctx.scale(1/n.chart.originalDevicePixelRatio,1/n.chart.originalDevicePixelRatio),i.style.width=n.chart.originalCanvasStyleWidth,i.style.height=n.chart.originalCanvasStyleHeight,t.pluginService.notifyPlugins("destroy",[n]),delete t.instances[n.id]},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e.chart,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this;e.bindEvents(t,t.options.events,function(e){t.eventHandler(e)})},updateHoverStyle:function(t,e,n){var i,a,r,o=n?"setHoverStyle":"removeHoverStyle";switch(e){case"single":t=[t[0]];break;case"label":case"dataset":break;default:return}for(a=0,r=t.length;r>a;++a)i=t[a],i&&this.getDatasetMeta(i._datasetIndex).controller[o](i)},eventHandler:function(t){var n=this,i=n.tooltip,a=n.options||{},r=a.hover,o=a.tooltips;return n.lastActive=n.lastActive||[],n.lastTooltipActive=n.lastTooltipActive||[],"mouseout"===t.type?(n.active=[],n.tooltipActive=[]):(n.active=n.getElementsAtEventForMode(t,r.mode),n.tooltipActive=n.getElementsAtEventForMode(t,o.mode)),r.onHover&&r.onHover.call(n,n.active),("mouseup"===t.type||"click"===t.type)&&(a.onClick&&a.onClick.call(n,t,n.active),n.legend&&n.legend.handleEvent&&n.legend.handleEvent(t)),n.lastActive.length&&n.updateHoverStyle(n.lastActive,r.mode,!1),n.active.length&&r.mode&&n.updateHoverStyle(n.active,r.mode,!0),(o.enabled||o.custom)&&(i.initialize(),i._active=n.tooltipActive,i.update(!0)),i.pivot(),n.animating||e.arrayEquals(n.active,n.lastActive)&&e.arrayEquals(n.tooltipActive,n.lastTooltipActive)||(n.stop(),(o.enabled||o.custom)&&i.update(!0),n.render(r.animationDuration,!0)),n.lastActive=n.active,n.lastTooltipActive=n.tooltipActive,n}})}},{}],23:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=e.noop;t.DatasetController=function(t,e){this.initialize.call(this,t,e)},e.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;e>t;++t)r[t]=r[t]||n.createMetaData(i,t);i.dataset=i.dataset||n.createMetaDataset()},addElementAndReset:function(t){var e=this,n=e.createMetaData(t);e.getMeta().data.splice(t,0,n),e.updateElement(n,t,!0)},buildOrUpdateElements:function(){var t=this.getMeta(),e=t.data,n=this.getDataset().data.length,i=e.length;if(i>n)e.splice(n,i-n);else if(n>i)for(var a=i;n>a;++a)this.addElementAndReset(a)},update:n,draw:function(t){var n=t||1;e.each(this.getMeta().data,function(t,e){t.transition(n).draw()})},removeHoverStyle:function(t,n){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,r=t.custom||{},o=e.getValueAtIndexOrDefault,s=(e.color,t._model);s.backgroundColor=r.backgroundColor?r.backgroundColor:o(i.backgroundColor,a,n.backgroundColor),s.borderColor=r.borderColor?r.borderColor:o(i.borderColor,a,n.borderColor),s.borderWidth=r.borderWidth?r.borderWidth:o(i.borderWidth,a,n.borderWidth)},setHoverStyle:function(t){var n=this.chart.data.datasets[t._datasetIndex],i=t._index,a=t.custom||{},r=e.getValueAtIndexOrDefault,o=(e.color,e.getHoverColor),s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:r(n.hoverBackgroundColor,i,o(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:r(n.hoverBorderColor,i,o(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:r(n.hoverBorderWidth,i,s.borderWidth)}}),t.DatasetController.extend=e.inherits}},{}],24:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.elements={},t.Element=function(t){e.extend(this,t),this.initialize.apply(this,arguments)},e.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=e.clone(t._model)),t._start=e.clone(t._view),t},transition:function(t){var n=this;return n._view||(n._view=e.clone(n._model)),1===t?(n._view=n._model,n._start=null,n):(n._start||n.pivot(),e.each(n._model,function(i,a){if("_"===a[0]);else if(n._view.hasOwnProperty(a))if(i===n._view[a]);else if("string"==typeof i)try{var r=e.color(n._model[a]).mix(e.color(n._start[a]),t);n._view[a]=r.rgbString()}catch(o){n._view[a]=i}else if("number"==typeof i){var s=void 0!==n._start[a]&&isNaN(n._start[a])===!1?n._start[a]:0;n._view[a]=(n._model[a]-s)*t+s}else n._view[a]=i;else"number"!=typeof i||isNaN(n._view[a])?n._view[a]=i:n._view[a]=i*t},n),n)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return e.isNumber(this._model.x)&&e.isNumber(this._model.y)}}),t.Element.extend=e.inherits}},{}],25:[function(t,e,n){"use strict";var i=t(2);e.exports=function(t){function e(t,e,n){var i;return"string"==typeof t?(i=parseInt(t,10),-1!=t.indexOf("%")&&(i=i/100*e.parentNode[n])):i=t,i}function n(t){return void 0!==t&&null!==t&&"none"!==t}function a(t,i,a){var r=document.defaultView,o=t.parentNode,s=r.getComputedStyle(t)[i],l=r.getComputedStyle(o)[i],d=n(s),u=n(l),c=Number.POSITIVE_INFINITY;return d||u?Math.min(d?e(s,t,a):c,u?e(l,o,a):c):"none"}var r=t.helpers={};r.each=function(t,e,n,i){var a,o;if(r.isArray(t))if(o=t.length,i)for(a=o-1;a>=0;a--)e.call(n,t[a],a);else for(a=0;o>a;a++)e.call(n,t[a],a);else if("object"==typeof t){var s=Object.keys(t);for(o=s.length,a=0;o>a;a++)e.call(n,t[s[a]],s[a])}},r.clone=function(t){var e={};return r.each(t,function(t,n){r.isArray(t)?e[n]=t.slice(0):"object"==typeof t&&null!==t?e[n]=r.clone(t):e[n]=t}),e},r.extend=function(t){for(var e=arguments.length,n=[],i=1;e>i;i++)n.push(arguments[i]);return r.each(n,function(e){r.each(e,function(e,n){t[n]=e})}),t},r.configMerge=function(e){var n=r.clone(e);return r.each(Array.prototype.slice.call(arguments,1),function(e){r.each(e,function(e,i){if("scales"===i)n[i]=r.scaleMerge(n.hasOwnProperty(i)?n[i]:{},e);else if("scale"===i)n[i]=r.configMerge(n.hasOwnProperty(i)?n[i]:{},t.scaleService.getScaleDefaults(e.type),e);else if(n.hasOwnProperty(i)&&r.isArray(n[i])&&r.isArray(e)){var a=n[i];r.each(e,function(t,e){e<a.length?"object"==typeof a[e]&&null!==a[e]&&"object"==typeof t&&null!==t?a[e]=r.configMerge(a[e],t):a[e]=t:a.push(t)})}else n.hasOwnProperty(i)&&"object"==typeof n[i]&&null!==n[i]&&"object"==typeof e?n[i]=r.configMerge(n[i],e):n[i]=e})}),n},r.extendDeep=function(t){function e(t){return r.each(arguments,function(n){n!==t&&r.each(n,function(n,i){t[i]&&t[i].constructor&&t[i].constructor===Object?e(t[i],n):t[i]=n})}),t}return e.apply(this,arguments)},r.scaleMerge=function(e,n){var i=r.clone(e);return r.each(n,function(e,n){"xAxes"===n||"yAxes"===n?i.hasOwnProperty(n)?r.each(e,function(e,a){var o=r.getValueOrDefault(e.type,"xAxes"===n?"category":"linear"),s=t.scaleService.getScaleDefaults(o);a>=i[n].length||!i[n][a].type?i[n].push(r.configMerge(s,e)):e.type&&e.type!==i[n][a].type?i[n][a]=r.configMerge(i[n][a],s,e):i[n][a]=r.configMerge(i[n][a],e)}):(i[n]=[],r.each(e,function(e){var a=r.getValueOrDefault(e.type,"xAxes"===n?"category":"linear");i[n].push(r.configMerge(t.scaleService.getScaleDefaults(a),e))})):i.hasOwnProperty(n)&&"object"==typeof i[n]&&null!==i[n]&&"object"==typeof e?i[n]=r.configMerge(i[n],e):i[n]=e}),i},r.getValueAtIndexOrDefault=function(t,e,n){return void 0===t||null===t?n:r.isArray(t)?e<t.length?t[e]:n:t},r.getValueOrDefault=function(t,e){return void 0===t?e:t},r.indexOf=function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var n=0;n<t.length;n++)if(t[n]===e)return n;return-1},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=function(t,e,n){var i=-1;if(Array.prototype.findIndex)i=t.findIndex(e,n);else for(var a=0;a<t.length;++a)if(n=void 0!==n?n:t,e.call(n,t[a],a,t)){i=a;break}return i},r.findNextWhere=function(t,e,n){(void 0===n||null===n)&&(n=-1);for(var i=n+1;i<t.length;i++){var a=t[i];if(e(a))return a}},r.findPreviousWhere=function(t,e,n){(void 0===n||null===n)&&(n=t.length);for(var i=n-1;i>=0;i--){var a=t[i];if(e(a))return a}},r.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n},r.noop=function(){},r.uid=function(){var t=0;return function(){return t++}}(),r.warn=function(t){console&&"function"==typeof console.warn&&console.warn(t)},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)<n},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=function(t){return Math.sign?Math.sign(t):(t=+t,0===t||isNaN(t)?t:t>0?1:-1)},r.log10=function(t){return Math.log10?Math.log10(t):Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.aliasPixel=function(t){return t%2===0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),d=s/(s+l),u=l/(s+l);d=isNaN(d)?0:d,u=isNaN(u)?0:u;var c=i*d,h=i*u;return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.nextItem=function(t,e,n){return n?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?0>=e?t[t.length-1]:t[e-1]:0>=e?t[0]:t[e-1]},r.niceNum=function(t,e){var n,i=Math.floor(r.log10(t)),a=t/Math.pow(10,i);return n=e?1.5>a?1:3>a?2:7>a?5:10:1>=a?1:2>=a?2:5>=a?5:10,n*Math.pow(10,i)};var o=r.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===(t/=1)?1:(n||(n=.3),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2===(t/=.5)?1:(n||(n=1*(.3*1.5)),i<Math.abs(1)?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),1>t?-.5*(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)):i*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-o.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*o.easeInBounce(2*t):.5*o.easeOutBounce(2*t-1)+.5}};r.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),r.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var d=parseFloat(r.getStyle(o,"padding-left")),u=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-d-c,g=s.bottom-s.top-u-h;return n=Math.round((n-s.left-d)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-u)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.addEvent=function(t,e,n){t.addEventListener?t.addEventListener(e,n):t.attachEvent?t.attachEvent("on"+e,n):t["on"+e]=n},r.removeEvent=function(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent?t.detachEvent("on"+e,n):t["on"+e]=r.noop},r.bindEvents=function(t,e,n){var i=t.events=t.events||{};r.each(e,function(e){i[e]=function(){n.apply(t,arguments)},r.addEvent(t.chart.canvas,e,i[e])})},r.unbindEvents=function(t,e){var n=t.chart.canvas;r.each(e,function(t,e){r.removeEvent(n,e,t)})},r.getConstraintWidth=function(t){return a(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return a(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode,n=parseInt(r.getStyle(e,"padding-left"))+parseInt(r.getStyle(e,"padding-right")),i=e.clientWidth-n,a=r.getConstraintWidth(t);return isNaN(a)?i:Math.min(i,a)},r.getMaximumHeight=function(t){var e=t.parentNode,n=parseInt(r.getStyle(e,"padding-top"))+parseInt(r.getStyle(e,"padding-bottom")),i=e.clientHeight-n,a=r.getConstraintHeight(t);return isNaN(a)?i:Math.min(i,a)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t){var e=t.ctx,n=t.canvas,i=n.width,a=n.height,r=t.currentDevicePixelRatio=window.devicePixelRatio||1;1!==r&&(n.height=a*r,n.width=i*r,e.scale(r,r),t.originalDevicePixelRatio=t.originalDevicePixelRatio||r),n.style.width=i+"px",n.style.height=a+"px"},r.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){i=i||{};var a=i.data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&r.isArray(e)!==!0?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var d=0;l>d;d++)delete a[o[d]];o.splice(0,l)}return s},r.measureText=function(t,e,n,i,a){var r=e[a];return r||(r=e[a]=t.measureText(a).width,n.push(a)),r>i&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.drawRoundedRectangle=function(t,e,n,i,a,r){t.beginPath(),t.moveTo(e+r,n),t.lineTo(e+i-r,n),t.quadraticCurveTo(e+i,n,e+i,n+r),t.lineTo(e+i,n+a-r),t.quadraticCurveTo(e+i,n+a,e+i-r,n+a),t.lineTo(e+r,n+a),t.quadraticCurveTo(e,n+a,e,n+a-r),t.lineTo(e,n+r),t.quadraticCurveTo(e,n,e+r,n),t.closePath()},r.color=function(e){return i?i(e instanceof CanvasGradient?t.defaults.global.defaultColor:e):(console.log("Color.js not found!"),e)},r.addResizeListener=function(t,e){var n=document.createElement("iframe"),i="chartjs-hidden-iframe";n.classlist?n.classlist.add(i):n.setAttribute("class",i);var a=n.style;a.width="100%",a.display="block",a.border=0,a.height=0,a.margin=0,a.position="absolute",a.left=0,a.right=0,a.top=0,a.bottom=0,t.insertBefore(n,t.firstChild),(n.contentWindow||n).onresize=function(){e&&e()}},r.removeResizeListener=function(t){var e=t.querySelector(".chartjs-hidden-iframe");e&&e.parentNode.removeChild(e)},r.isArray=function(t){return Array.isArray?Array.isArray(t):"[object Array]"===Object.prototype.toString.call(t)},r.arrayEquals=function(t,e){var n,i,a,o;if(!t||!e||t.length!=e.length)return!1;for(n=0,i=t.length;i>n;++n)if(a=t[n],o=e[n],a instanceof Array&&o instanceof Array){if(!r.arrayEquals(a,o))return!1}else if(a!=o)return!1;return!0},r.callCallback=function(t,e,n){t&&"function"==typeof t.call&&t.apply(n,e)},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2}],26:[function(t,e,n){"use strict";e.exports=function(){var t=function(e,n){var i=this,a=t.helpers;return i.config=n,e.length&&e[0].getContext&&(e=e[0]),e.getContext&&(e=e.getContext("2d")),i.ctx=e,i.canvas=e.canvas,e.canvas.style.display=e.canvas.style.display||"block",i.width=e.canvas.width||parseInt(a.getStyle(e.canvas,"width"),10)||a.getMaximumWidth(e.canvas),i.height=e.canvas.height||parseInt(a.getStyle(e.canvas,"height"),10)||a.getMaximumHeight(e.canvas),i.aspectRatio=i.width/i.height,(isNaN(i.aspectRatio)||isFinite(i.aspectRatio)===!1)&&(i.aspectRatio=void 0!==n.aspectRatio?n.aspectRatio:2),i.originalCanvasStyleWidth=e.canvas.style.width,i.originalCanvasStyleHeight=e.canvas.style.height,a.retinaScale(i),n&&(i.controller=new t.Controller(i)),a.addResizeListener(e.canvas.parentNode,function(){i.controller&&i.controller.config.options.responsive&&i.controller.resize()}),i.controller?i.controller:i};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"single",animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var n=0;n<t.data.datasets.length;n++)e.push('<li><span style="background-color:'+t.data.datasets[n].backgroundColor+'"></span>'),
-t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t.Chart=t,t}},{}],27:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),t.boxes.push(e)},removeBox:function(t,e){t.boxes&&t.boxes.splice(t.boxes.indexOf(e),1)},update:function(t,n,i){function a(t){var e,n=t.isHorizontal();n?(e=t.update(t.options.fullWidth?m:k,x),_-=e.height):(e=t.update(y,b),k-=e.width),S.push({horizontal:n,minSize:e,box:t})}function r(t){var n=e.findNextWhere(S,function(e){return e.box===t});if(n)if(t.isHorizontal()){var i={left:w,right:M,top:0,bottom:0};t.update(t.options.fullWidth?m:k,p/2,i)}else t.update(n.minSize.width,_)}function o(t){var n=e.findNextWhere(S,function(e){return e.box===t}),i={left:0,right:0,top:D,bottom:C};n&&t.update(n.minSize.width,_,i)}function s(t){t.isHorizontal()?(t.left=t.options.fullWidth?l:w,t.right=t.options.fullWidth?n-l:w+k,t.top=A,t.bottom=A+t.height,A=t.bottom):(t.left=F,t.right=F+t.width,t.top=D,t.bottom=D+_,F=t.right)}if(t){var l=0,d=0,u=e.where(t.boxes,function(t){return"left"===t.options.position}),c=e.where(t.boxes,function(t){return"right"===t.options.position}),h=e.where(t.boxes,function(t){return"top"===t.options.position}),f=e.where(t.boxes,function(t){return"bottom"===t.options.position}),g=e.where(t.boxes,function(t){return"chartArea"===t.options.position});h.sort(function(t,e){return(e.options.fullWidth?1:0)-(t.options.fullWidth?1:0)}),f.sort(function(t,e){return(t.options.fullWidth?1:0)-(e.options.fullWidth?1:0)});var m=n-2*l,p=i-2*d,v=m/2,b=p/2,y=(n-v)/(u.length+c.length),x=(i-b)/(h.length+f.length),k=m,_=p,S=[];e.each(u.concat(c,h,f),a);var w=l,M=l,D=d,C=d;e.each(u.concat(c),r),e.each(u,function(t){w+=t.width}),e.each(c,function(t){M+=t.width}),e.each(h.concat(f),r),e.each(h,function(t){D+=t.height}),e.each(f,function(t){C+=t.height}),e.each(u.concat(c),o),w=l,M=l,D=d,C=d,e.each(u,function(t){w+=t.width}),e.each(c,function(t){M+=t.width}),e.each(h,function(t){D+=t.height}),e.each(f,function(t){C+=t.height});var T=i-D-C,P=n-w-M;(P!==k||T!==_)&&(e.each(u,function(t){t.height=T}),e.each(c,function(t){t.height=T}),e.each(h,function(t){t.options.fullWidth||(t.width=P)}),e.each(f,function(t){t.options.fullWidth||(t.width=P)}),_=T,k=P);var F=l,A=d;e.each(u.concat(h),s),F+=k,A+=_,e.each(c,s),e.each(f,s),t.chartArea={left:w,top:D,right:w+k,bottom:D+_},e.each(g,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(k,_)})}}}}},{}],28:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=e.noop;t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},labels:{boxWidth:40,padding:10,generateLabels:function(t){var n=t.data;return e.isArray(n.datasets)?n.datasets.map(function(n,i){return{text:n.label,fillStyle:e.isArray(n.backgroundColor)?n.backgroundColor[0]:n.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:n.borderCapStyle,lineDash:n.borderDash,lineDashOffset:n.borderDashOffset,lineJoin:n.borderJoinStyle,lineWidth:n.borderWidth,strokeStyle:n.borderColor,datasetIndex:i}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){e.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:n,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:n,beforeSetDimensions:n,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:n,beforeBuildLabels:n,buildLabels:function(){var t=this;t.legendItems=t.options.labels.generateLabels.call(t,t.chart),t.options.reverse&&t.legendItems.reverse()},afterBuildLabels:n,beforeFit:n,fit:function(){var n=this,i=n.options,a=i.labels,r=i.display,o=n.ctx,s=t.defaults.global,l=e.getValueOrDefault,d=l(a.fontSize,s.defaultFontSize),u=l(a.fontStyle,s.defaultFontStyle),c=l(a.fontFamily,s.defaultFontFamily),h=e.fontString(d,u,c),f=n.legendHitBoxes=[],g=n.minSize,m=n.isHorizontal();if(m?(g.width=n.maxWidth,g.height=r?10:0):(g.width=r?10:0,g.height=n.maxHeight),r&&m){var p=n.lineWidths=[0],v=n.legendItems.length?d+a.padding:0;o.textAlign="left",o.textBaseline="top",o.font=h,e.each(n.legendItems,function(t,e){var i=a.boxWidth+d/2+o.measureText(t.text).width;p[p.length-1]+i+a.padding>=n.width&&(v+=d+a.padding,p[p.length]=n.left),f[e]={left:0,top:0,width:i,height:d},p[p.length-1]+=i+a.padding},n),g.height+=v}n.width=g.width,n.height=g.height},afterFit:n,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var n=this,i=n.options,a=i.labels,r=t.defaults.global,o=r.elements.line,s=n.width,l=n.lineWidths;if(i.display){var d=n.ctx,u={x:n.left+(s-l[0])/2,y:n.top+a.padding,line:0},c=e.getValueOrDefault,h=c(a.fontColor,r.defaultFontColor),f=c(a.fontSize,r.defaultFontSize),g=c(a.fontStyle,r.defaultFontStyle),m=c(a.fontFamily,r.defaultFontFamily),p=e.fontString(f,g,m);if(n.isHorizontal()){d.textAlign="left",d.textBaseline="top",d.lineWidth=.5,d.strokeStyle=h,d.fillStyle=h,d.font=p;var v=a.boxWidth,b=n.legendHitBoxes;e.each(n.legendItems,function(t,e){var i=d.measureText(t.text).width,h=v+f/2+i,g=u.x,m=u.y;g+h>=s&&(m=u.y+=f+a.padding,u.line++,g=u.x=n.left+(s-l[u.line])/2),d.save(),d.fillStyle=c(t.fillStyle,r.defaultColor),d.lineCap=c(t.lineCap,o.borderCapStyle),d.lineDashOffset=c(t.lineDashOffset,o.borderDashOffset),d.lineJoin=c(t.lineJoin,o.borderJoinStyle),d.lineWidth=c(t.lineWidth,o.borderWidth),d.strokeStyle=c(t.strokeStyle,r.defaultColor),d.setLineDash&&d.setLineDash(c(t.lineDash,o.borderDash)),d.strokeRect(g,m,v,f),d.fillRect(g,m,v,f),d.restore(),b[e].left=g,b[e].top=m,d.fillText(t.text,v+f/2+g,m),t.hidden&&(d.beginPath(),d.lineWidth=2,d.moveTo(v+f/2+g,m+f/2),d.lineTo(v+f/2+g+i,m+f/2),d.stroke()),u.x+=h+a.padding},n)}}},handleEvent:function(t){var n=this,i=e.getRelativePosition(t,n.chart.chart),a=i.x,r=i.y,o=n.options;if(a>=n.left&&a<=n.right&&r>=n.top&&r<=n.bottom)for(var s=n.legendHitBoxes,l=0;l<s.length;++l){var d=s[l];if(a>=d.left&&a<=d.left+d.width&&r>=d.top&&r<=d.top+d.height){o.onClick&&o.onClick.call(n,t,n.legendItems[l]);break}}}}),t.pluginService.register({beforeInit:function(e){var n=e.options,i=n.legend;i&&(e.legend=new t.Legend({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.legend))}})}},{}],29:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.plugins=[],t.pluginService={register:function(e){var n=t.plugins;-1===n.indexOf(e)&&n.push(e)},remove:function(e){var n=t.plugins,i=n.indexOf(e);-1!==i&&n.splice(i,1)},notifyPlugins:function(n,i,a){e.each(t.plugins,function(t){t[n]&&"function"==typeof t[n]&&t[n].apply(a,i)},a)}};var n=e.noop;t.PluginBase=t.Element.extend({beforeInit:n,afterInit:n,beforeUpdate:n,afterUpdate:n,beforeDraw:n,afterDraw:n,destroy:n})}},{}],30:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",offsetGridLines:!1},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:10,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:function(t){return e.isArray(t)?t:""+t}}},t.Scale=t.Element.extend({beforeUpdate:function(){e.callCallback(this.options.beforeUpdate,[this])},update:function(t,n,i){var a=this;return a.beforeUpdate(),a.maxWidth=t,a.maxHeight=n,a.margins=e.extend({left:0,right:0,top:0,bottom:0},i),a.beforeSetDimensions(),a.setDimensions(),a.afterSetDimensions(),a.beforeDataLimits(),a.determineDataLimits(),a.afterDataLimits(),a.beforeBuildTicks(),a.buildTicks(),a.afterBuildTicks(),a.beforeTickToLabelConversion(),a.convertTicksToLabels(),a.afterTickToLabelConversion(),a.beforeCalculateTickRotation(),a.calculateTickRotation(),a.afterCalculateTickRotation(),a.beforeFit(),a.fit(),a.afterFit(),a.afterUpdate(),a.minSize},afterUpdate:function(){e.callCallback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){e.callCallback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){e.callCallback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){e.callCallback(this.options.beforeDataLimits,[this])},determineDataLimits:e.noop,afterDataLimits:function(){e.callCallback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){e.callCallback(this.options.beforeBuildTicks,[this])},buildTicks:e.noop,afterBuildTicks:function(){e.callCallback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){e.callCallback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this;t.ticks=t.ticks.map(function(e,n,i){return t.options.ticks.userCallback?t.options.ticks.userCallback(e,n,i):t.options.ticks.callback(e,n,i)},t)},afterTickToLabelConversion:function(){e.callCallback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){e.callCallback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var n=this,i=n.ctx,a=t.defaults.global,r=n.options.ticks,o=e.getValueOrDefault(r.fontSize,a.defaultFontSize),s=e.getValueOrDefault(r.fontStyle,a.defaultFontStyle),l=e.getValueOrDefault(r.fontFamily,a.defaultFontFamily),d=e.fontString(o,s,l);i.font=d;var u,c=i.measureText(n.ticks[0]).width,h=i.measureText(n.ticks[n.ticks.length-1]).width;if(n.labelRotation=r.minRotation||0,n.paddingRight=0,n.paddingLeft=0,n.options.display&&n.isHorizontal()){n.paddingRight=h/2+3,n.paddingLeft=c/2+3,n.longestTextCache||(n.longestTextCache={});for(var f,g,m=e.longestText(i,d,n.ticks,n.longestTextCache),p=m,v=n.getPixelForTick(1)-n.getPixelForTick(0)-6;p>v&&n.labelRotation<r.maxRotation;){if(f=Math.cos(e.toRadians(n.labelRotation)),g=Math.sin(e.toRadians(n.labelRotation)),u=f*c,u+o/2>n.yLabelWidth&&(n.paddingLeft=u+o/2),n.paddingRight=o/2,g*m>n.maxHeight){n.labelRotation--;break}n.labelRotation++,p=f*m}}n.margins&&(n.paddingLeft=Math.max(n.paddingLeft-n.margins.left,0),n.paddingRight=Math.max(n.paddingRight-n.margins.right,0))},afterCalculateTickRotation:function(){e.callCallback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){e.callCallback(this.options.beforeFit,[this])},fit:function(){var n=this,i=n.minSize={width:0,height:0},a=n.options,r=t.defaults.global,o=a.ticks,s=a.scaleLabel,l=a.display,d=n.isHorizontal(),u=e.getValueOrDefault(o.fontSize,r.defaultFontSize),c=e.getValueOrDefault(o.fontStyle,r.defaultFontStyle),h=e.getValueOrDefault(o.fontFamily,r.defaultFontFamily),f=e.fontString(u,c,h),g=e.getValueOrDefault(s.fontSize,r.defaultFontSize),m=e.getValueOrDefault(s.fontStyle,r.defaultFontStyle),p=e.getValueOrDefault(s.fontFamily,r.defaultFontFamily),v=(e.fontString(g,m,p),a.gridLines.tickMarkLength);if(d?i.width=n.isFullWidth()?n.maxWidth-n.margins.left-n.margins.right:n.maxWidth:i.width=l?v:0,d?i.height=l?v:0:i.height=n.maxHeight,s.display&&l&&(d?i.height+=1.5*g:i.width+=1.5*g),o.display&&l){n.longestTextCache||(n.longestTextCache={});var b=e.longestText(n.ctx,f,n.ticks,n.longestTextCache),y=e.numberOfLabelLines(n.ticks),x=.5*u;if(d){n.longestLabelWidth=b;var k=Math.sin(e.toRadians(n.labelRotation))*n.longestLabelWidth+u*y+x*y;i.height=Math.min(n.maxHeight,i.height+k),n.ctx.font=f;var _=n.ctx.measureText(n.ticks[0]).width,S=n.ctx.measureText(n.ticks[n.ticks.length-1]).width,w=Math.cos(e.toRadians(n.labelRotation)),M=Math.sin(e.toRadians(n.labelRotation));n.paddingLeft=0!==n.labelRotation?w*_+3:_/2+3,n.paddingRight=0!==n.labelRotation?M*(u/2)+3:S/2+3}else{var D=n.maxWidth-i.width,C=o.mirror;C?b=0:b+=n.options.ticks.padding,D>b?i.width+=b:i.width=n.maxWidth,n.paddingTop=u/2,n.paddingBottom=u/2}}n.margins&&(n.paddingLeft=Math.max(n.paddingLeft-n.margins.left,0),n.paddingTop=Math.max(n.paddingTop-n.margins.top,0),n.paddingRight=Math.max(n.paddingRight-n.margins.right,0),n.paddingBottom=Math.max(n.paddingBottom-n.margins.bottom,0)),n.width=i.width,n.height=i.height},afterFit:function(){e.callCallback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function n(t){return null===t||"undefined"==typeof t?NaN:"number"==typeof t&&isNaN(t)?NaN:"object"==typeof t?t instanceof Date||t.isValid?t:n(this.isHorizontal()?t.x:t.y):t},getLabelForIndex:e.noop,getPixelForValue:e.noop,getValueForPixel:e.noop,getPixelForTick:function(t,e){var n=this;if(n.isHorizontal()){var i=n.width-(n.paddingLeft+n.paddingRight),a=i/Math.max(n.ticks.length-(n.options.gridLines.offsetGridLines?0:1),1),r=a*t+n.paddingLeft;e&&(r+=a/2);var o=n.left+Math.round(r);return o+=n.isFullWidth()?n.margins.left:0}var s=n.height-(n.paddingTop+n.paddingBottom);return n.top+t*(s/(n.ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=e.width-(e.paddingLeft+e.paddingRight),i=n*t+e.paddingLeft,a=e.left+Math.round(i);return a+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){var t=this,e=t.min,n=t.max;return t.getPixelForValue(t.beginAtZero?0:0>e&&0>n?n:e>0&&n>0?e:0)},draw:function(n){var i=this,a=i.options;if(a.display){var r,o,s,l,d,u=i.ctx,c=t.defaults.global,h=a.ticks,f=a.gridLines,g=a.scaleLabel,m=0!==i.labelRotation,p=h.autoSkip;h.maxTicksLimit&&(d=h.maxTicksLimit);var v=e.getValueOrDefault(h.fontColor,c.defaultFontColor),b=e.getValueOrDefault(h.fontSize,c.defaultFontSize),y=e.getValueOrDefault(h.fontStyle,c.defaultFontStyle),x=e.getValueOrDefault(h.fontFamily,c.defaultFontFamily),k=e.fontString(b,y,x),_=f.tickMarkLength,S=e.getValueOrDefault(g.fontColor,c.defaultFontColor),w=e.getValueOrDefault(g.fontSize,c.defaultFontSize),M=e.getValueOrDefault(g.fontStyle,c.defaultFontStyle),D=e.getValueOrDefault(g.fontFamily,c.defaultFontFamily),C=e.fontString(w,M,D),T=e.toRadians(i.labelRotation),P=Math.cos(T),F=(Math.sin(T),i.longestLabelWidth*P);if(u.fillStyle=v,i.isHorizontal()){r=!0;var A="bottom"===a.position?i.top:i.bottom-_,I="bottom"===a.position?i.top+_:i.bottom;if(o=!1,m&&(F/=2),(F+h.autoSkipPadding)*i.ticks.length>i.width-(i.paddingLeft+i.paddingRight)&&(o=1+Math.floor((F+h.autoSkipPadding)*i.ticks.length/(i.width-(i.paddingLeft+i.paddingRight)))),d&&i.ticks.length>d)for(;!o||i.ticks.length/(o||1)>d;)o||(o=1),o+=1;p||(o=!1),e.each(i.ticks,function(t,s){var l=i.ticks.length===s+1,d=o>1&&s%o>0||s%o===0&&s+o>=i.ticks.length;if((!d||l)&&void 0!==t&&null!==t){var c=i.getPixelForTick(s),g=i.getPixelForTick(s,f.offsetGridLines);if(f.display&&(s===("undefined"!=typeof i.zeroLineIndex?i.zeroLineIndex:0)?(u.lineWidth=f.zeroLineWidth,u.strokeStyle=f.zeroLineColor,r=!0):r&&(u.lineWidth=f.lineWidth,u.strokeStyle=f.color,r=!1),c+=e.aliasPixel(u.lineWidth),u.beginPath(),f.drawTicks&&(u.moveTo(c,A),u.lineTo(c,I)),f.drawOnChartArea&&(u.moveTo(c,n.top),u.lineTo(c,n.bottom)),u.stroke()),h.display){if(u.save(),u.translate(g+h.labelOffset,m?i.top+12:"top"===a.position?i.bottom-_:i.top+_),u.rotate(-1*T),u.font=k,u.textAlign=m?"right":"center",u.textBaseline=m?"middle":"top"===a.position?"bottom":"top",e.isArray(t))for(var p=0,v=0;p<t.length;++p)u.fillText(""+t[p],0,v),v+=1.5*b;else u.fillText(t,0,0);u.restore()}}},i),g.display&&(u.textAlign="center",u.textBaseline="middle",u.fillStyle=S,u.font=C,s=i.left+(i.right-i.left)/2,l="bottom"===a.position?i.bottom-w/2:i.top+w/2,u.fillText(g.labelString,s,l))}else{r=!0;var O="right"===a.position?i.left:i.right-5,R="right"===a.position?i.left+5:i.right;if(e.each(i.ticks,function(t,o){if(void 0!==t&&null!==t){var s=i.getPixelForTick(o);if(f.display&&(o===("undefined"!=typeof i.zeroLineIndex?i.zeroLineIndex:0)?(u.lineWidth=f.zeroLineWidth,u.strokeStyle=f.zeroLineColor,r=!0):r&&(u.lineWidth=f.lineWidth,u.strokeStyle=f.color,r=!1),s+=e.aliasPixel(u.lineWidth),u.beginPath(),f.drawTicks&&(u.moveTo(O,s),u.lineTo(R,s)),f.drawOnChartArea&&(u.moveTo(n.left,s),u.lineTo(n.right,s)),u.stroke()),h.display){var l,d=i.getPixelForTick(o,f.offsetGridLines);u.save(),"left"===a.position?h.mirror?(l=i.right+h.padding,u.textAlign="left"):(l=i.right-h.padding,u.textAlign="right"):h.mirror?(l=i.left-h.padding,u.textAlign="right"):(l=i.left+h.padding,u.textAlign="left"),u.translate(l,d+h.labelOffset),u.rotate(-1*T),u.font=k,u.textBaseline="middle",u.fillText(t,0,0),u.restore()}}},i),g.display){s="left"===a.position?i.left+w/2:i.right-w/2,l=i.top+(i.bottom-i.top)/2;var W="left"===a.position?-.5*Math.PI:.5*Math.PI;u.save(),u.translate(s,l),u.rotate(W),u.textAlign="center",u.fillStyle=S,u.font=C,u.textBaseline="middle",u.fillText(g.labelString,0,0),u.restore()}}if(f.drawBorder){u.lineWidth=f.lineWidth,u.strokeStyle=f.color;var L=i.left,V=i.right,B=i.top,Y=i.bottom,z=e.aliasPixel(u.lineWidth);i.isHorizontal()?(B=Y="top"===a.position?i.bottom:i.top,B+=z,Y+=z):(L=V="left"===a.position?i.right:i.left,L+=z,V+=z),u.beginPath(),u.moveTo(L,B),u.lineTo(V,Y),u.stroke()}}}})}},{}],31:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,n,i){this.constructors[t]=n,this.defaults[t]=e.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(n){return this.defaults.hasOwnProperty(n)?e.scaleMerge(t.defaults.scale,this.defaults[n]):{}},updateScaleDefaults:function(t,n){var i=this.defaults;i.hasOwnProperty(t)&&(i[t]=e.extend(i[t],n))},addScalesToLayout:function(n){e.each(n.scales,function(e){t.layoutService.addBox(n,e)})}}}},{}],32:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.title={display:!1,position:"top",fullWidth:!0,fontStyle:"bold",padding:10,text:""};var n=e.noop;t.Title=t.Element.extend({initialize:function(n){var i=this;e.extend(i,n),i.options=e.configMerge(t.defaults.global.title,n.options),i.legendHitBoxes=[]},beforeUpdate:function(){var n=this.chart.options;n&&n.title&&(this.options=e.configMerge(t.defaults.global.title,n.title))},update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:n,beforeSetDimensions:n,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:n,beforeBuildLabels:n,buildLabels:n,afterBuildLabels:n,beforeFit:n,fit:function(){var n=this,i=(n.ctx,e.getValueOrDefault),a=n.options,r=t.defaults.global,o=a.display,s=i(a.fontSize,r.defaultFontSize),l=n.minSize;n.isHorizontal()?(l.width=n.maxWidth,l.height=o?s+2*a.padding:0):(l.width=o?s+2*a.padding:0,l.height=n.maxHeight),n.width=l.width,n.height=l.height},afterFit:n,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var n=this,i=n.ctx,a=e.getValueOrDefault,r=n.options,o=t.defaults.global;if(r.display){var s,l,d=a(r.fontSize,o.defaultFontSize),u=a(r.fontStyle,o.defaultFontStyle),c=a(r.fontFamily,o.defaultFontFamily),h=e.fontString(d,u,c),f=0,g=n.top,m=n.left,p=n.bottom,v=n.right;i.fillStyle=a(r.fontColor,o.defaultFontColor),i.font=h,n.isHorizontal()?(s=m+(v-m)/2,l=g+(p-g)/2):(s="left"===r.position?m+d/2:v-d/2,l=g+(p-g)/2,f=Math.PI*("left"===r.position?-.5:.5)),i.save(),i.translate(s,l),i.rotate(f),i.textAlign="center",i.textBaseline="middle",i.fillText(r.text,0,0),i.restore()}}}),t.pluginService.register({beforeInit:function(e){var n=e.options,i=n.title;i&&(e.titleBlock=new t.Title({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.titleBlock))}})}},{}],33:[function(t,e,n){"use strict";e.exports=function(t){function e(t,e){return e&&(a.isArray(e)?t=t.concat(e):t.push(e)),t}function n(t){if(!t.length)return!1;var e,n,i=[],a=[];for(e=0,n=t.length;n>e;++e){var r=t[e];if(r&&r.hasValue()){var o=r.tooltipPosition();i.push(o.x),a.push(o.y)}}var s=0,l=0;for(e=0,n-i.length;n>e;++e)s+=i[e],l+=a[e];return{x:Math.round(s/i.length),y:Math.round(l/i.length)}}function i(t){var e=t._xScale,n=t._yScale||t._scale,i=t._index,a=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,a):"",yLabel:n?n.getLabelForIndex(i,a):"",index:i,datasetIndex:a}}var a=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"single",backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleColor:"#fff",titleAlign:"left",bodySpacing:2,bodyColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,yAlign:"center",xAlign:"center",caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",callbacks:{beforeTitle:a.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.index<a&&(n=i[r.index])}return n},afterTitle:a.noop,beforeBody:a.noop,beforeLabel:a.noop,label:function(t,e){var n=e.datasets[t.datasetIndex].label||"";return n+": "+t.yLabel},labelColor:function(t,e){var n=e.getDatasetMeta(t.datasetIndex),i=n.data[t.index],a=i._view;return{borderColor:a.borderColor,backgroundColor:a.backgroundColor}},afterLabel:a.noop,afterBody:a.noop,beforeFooter:a.noop,footer:a.noop,afterFooter:a.noop}},t.Tooltip=t.Element.extend({initialize:function(){var e=this,n=t.defaults.global,i=e._options,r=a.getValueOrDefault;a.extend(e,{_model:{xPadding:i.xPadding,yPadding:i.yPadding,xAlign:i.yAlign,yAlign:i.xAlign,bodyColor:i.bodyColor,_bodyFontFamily:r(i.bodyFontFamily,n.defaultFontFamily),_bodyFontStyle:r(i.bodyFontStyle,n.defaultFontStyle),_bodyAlign:i.bodyAlign,bodyFontSize:r(i.bodyFontSize,n.defaultFontSize),bodySpacing:i.bodySpacing,titleColor:i.titleColor,_titleFontFamily:r(i.titleFontFamily,n.defaultFontFamily),_titleFontStyle:r(i.titleFontStyle,n.defaultFontStyle),titleFontSize:r(i.titleFontSize,n.defaultFontSize),_titleAlign:i.titleAlign,titleSpacing:i.titleSpacing,titleMarginBottom:i.titleMarginBottom,footerColor:i.footerColor,_footerFontFamily:r(i.footerFontFamily,n.defaultFontFamily),_footerFontStyle:r(i.footerFontStyle,n.defaultFontStyle),footerFontSize:r(i.footerFontSize,n.defaultFontSize),_footerAlign:i.footerAlign,footerSpacing:i.footerSpacing,footerMarginTop:i.footerMarginTop,caretSize:i.caretSize,cornerRadius:i.cornerRadius,backgroundColor:i.backgroundColor,opacity:0,legendColorBackground:i.multiKeyBackground}})},getTitle:function(){var t=this,n=t._options,i=n.callbacks,a=i.beforeTitle.apply(t,arguments),r=i.title.apply(t,arguments),o=i.afterTitle.apply(t,arguments),s=[];return s=e(s,a),s=e(s,r),s=e(s,o)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return a.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,n){var i=this,r=i._options.callbacks,o=[];return a.each(t,function(t){var a={before:[],lines:[],after:[]};e(a.before,r.beforeLabel.call(i,t,n)),e(a.lines,r.label.call(i,t,n)),e(a.after,r.afterLabel.call(i,t,n)),o.push(a)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return a.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,n=t._options.callbacks,i=n.beforeFooter.apply(t,arguments),a=n.footer.apply(t,arguments),r=n.afterFooter.apply(t,arguments),o=[];return o=e(o,i),o=e(o,a),o=e(o,r)},update:function(t){var e,r,o=this,s=o._options,l=o._model,d=o._active,u=o._data,c=o._chartInstance;if(d.length){l.opacity=1;var h=[],f=n(d),g=[];for(e=0,r=d.length;r>e;++e)g.push(i(d[e]));s.itemSort&&(g=g.sort(s.itemSort)),d.length>1&&a.each(g,function(t){h.push(s.callbacks.labelColor.call(o,t,c))}),a.extend(l,{title:o.getTitle(g,u),beforeBody:o.getBeforeBody(g,u),body:o.getBody(g,u),afterBody:o.getAfterBody(g,u),footer:o.getFooter(g,u),x:Math.round(f.x),y:Math.round(f.y),caretPadding:a.getValueOrDefault(f.padding,2),labelColors:h});var m=o.getTooltipSize(l);o.determineAlignment(m),a.extend(l,o.getBackgroundPoint(l,m))}else o._model.opacity=0;return t&&s.custom&&s.custom.call(o,l),o},getTooltipSize:function(t){var e=this._chart.ctx,n={height:2*t.yPadding,width:0},i=t.body,r=i.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);r+=t.beforeBody.length+t.afterBody.length;var o=t.title.length,s=t.footer.length,l=t.titleFontSize,d=t.bodyFontSize,u=t.footerFontSize;n.height+=o*l,n.height+=(o-1)*t.titleSpacing,n.height+=o?t.titleMarginBottom:0,n.height+=r*d,n.height+=r?(r-1)*t.bodySpacing:0,n.height+=s?t.footerMarginTop:0,n.height+=s*u,n.height+=s?(s-1)*t.footerSpacing:0;var c=0,h=function(t){n.width=Math.max(n.width,e.measureText(t).width+c)};return e.font=a.fontString(l,t._titleFontStyle,t._titleFontFamily),a.each(t.title,h),e.font=a.fontString(d,t._bodyFontStyle,t._bodyFontFamily),a.each(t.beforeBody.concat(t.afterBody),h),c=i.length>1?d+2:0,a.each(i,function(t){a.each(t.before,h),a.each(t.lines,h),a.each(t.after,h)}),c=0,e.font=a.fontString(u,t._footerFontStyle,t._footerFontFamily),a.each(t.footer,h),n.width+=2*t.xPadding,n},determineAlignment:function(t){var e=this,n=e._model,i=e._chart,a=e._chartInstance.chartArea;n.y<t.height?n.yAlign="top":n.y>i.height-t.height&&(n.yAlign="bottom");var r,o,s,l,d,u=(a.left+a.right)/2,c=(a.top+a.bottom)/2;"center"===n.yAlign?(r=function(t){return u>=t},o=function(t){return t>u}):(r=function(e){return e<=t.width/2},o=function(e){return e>=i.width-t.width/2}),s=function(e){return e+t.width>i.width},l=function(e){return e-t.width<0},d=function(t){return c>=t?"top":"bottom"},r(n.x)?(n.xAlign="left",s(n.x)&&(n.xAlign="center",n.yAlign=d(n.y))):o(n.x)&&(n.xAlign="right",l(n.x)&&(n.xAlign="center",n.yAlign=d(n.y)))},getBackgroundPoint:function(t,e){var n={x:t.x,y:t.y},i=t.caretSize,a=t.caretPadding,r=t.cornerRadius,o=t.xAlign,s=t.yAlign,l=i+a,d=r+a;return"right"===o?n.x-=e.width:"center"===o&&(n.x-=e.width/2),"top"===s?n.y+=l:"bottom"===s?n.y-=e.height+l:n.y-=e.height/2,"center"===s?"left"===o?n.x+=l:"right"===o&&(n.x-=l):"left"===o?n.x-=d:"right"===o&&(n.x+=d),n},drawCaret:function(t,e,n,i){var r,o,s,l,d,u,c=this._view,h=this._chart.ctx,f=c.caretSize,g=c.cornerRadius,m=c.xAlign,p=c.yAlign,v=t.x,b=t.y,y=e.width,x=e.height;"center"===p?("left"===m?(r=v,o=r-f,s=r):(r=v+y,o=r+f,s=r),d=b+x/2,l=d-f,u=d+f):("left"===m?(r=v+g,o=r+f,s=o+f):"right"===m?(r=v+y-g,o=r-f,s=o-f):(o=v+y/2,r=o-f,s=o+f),"top"===p?(l=b,d=l-f,u=l):(l=b+x,d=l+f,u=l));var k=a.color(c.backgroundColor);h.fillStyle=k.alpha(n*k.alpha()).rgbString(),h.beginPath(),h.moveTo(r,l),h.lineTo(o,d),h.lineTo(s,u),h.closePath(),h.fill()},drawTitle:function(t,e,n,i){var r=e.title;if(r.length){n.textAlign=e._titleAlign,n.textBaseline="top";var o=e.titleFontSize,s=e.titleSpacing,l=a.color(e.titleColor);n.fillStyle=l.alpha(i*l.alpha()).rgbString(),n.font=a.fontString(o,e._titleFontStyle,e._titleFontFamily);var d,u;for(d=0,u=r.length;u>d;++d)n.fillText(r[d],t.x,t.y),t.y+=o+s,d+1===r.length&&(t.y+=e.titleMarginBottom-s)}},drawBody:function(t,e,n,i){var r=e.bodyFontSize,o=e.bodySpacing,s=e.body;n.textAlign=e._bodyAlign,n.textBaseline="top";var l=a.color(e.bodyColor),d=l.alpha(i*l.alpha()).rgbString();n.fillStyle=d,n.font=a.fontString(r,e._bodyFontStyle,e._bodyFontFamily);var u=0,c=function(e){n.fillText(e,t.x+u,t.y),t.y+=r+o};a.each(e.beforeBody,c);var h=s.length>1;u=h?r+2:0,a.each(s,function(o,s){a.each(o.before,c),a.each(o.lines,function(o){h&&(n.fillStyle=a.color(e.legendColorBackground).alpha(i).rgbaString(),n.fillRect(t.x,t.y,r,r),n.strokeStyle=a.color(e.labelColors[s].borderColor).alpha(i).rgbaString(),n.strokeRect(t.x,t.y,r,r),n.fillStyle=a.color(e.labelColors[s].backgroundColor).alpha(i).rgbaString(),n.fillRect(t.x+1,t.y+1,r-2,r-2),n.fillStyle=d),c(o)}),a.each(o.after,c)}),u=0,a.each(e.afterBody,c),t.y-=o},drawFooter:function(t,e,n,i){var r=e.footer;if(r.length){t.y+=e.footerMarginTop,n.textAlign=e._footerAlign,n.textBaseline="top";var o=a.color(e.footerColor);n.fillStyle=o.alpha(i*o.alpha()).rgbString(),n.font=a.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),a.each(r,function(i){n.fillText(i,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing})}},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n=this.getTooltipSize(e),i={x:e.x,y:e.y},r=Math.abs(e.opacity<.001)?0:e.opacity;if(this._options.enabled){var o=a.color(e.backgroundColor);t.fillStyle=o.alpha(r*o.alpha()).rgbString(),a.drawRoundedRectangle(t,i.x,i.y,n.width,n.height,e.cornerRadius),t.fill(),this.drawCaret(i,n,r,e.caretPadding),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,r),this.drawBody(i,e,t,r),this.drawFooter(i,e,t,r)}}}})}},{}],34:[function(t,e,n){"use strict";e.exports=function(t,e){var n=t.helpers,i=t.defaults.global;i.elements.arc={backgroundColor:i.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2):!1},inRange:function(t,e){var i=this._view;if(i){for(var a=n.getAngleFromPoint(i,{x:t,y:e}),r=a.angle,o=a.distance,s=i.startAngle,l=i.endAngle;s>l;)l+=2*Math.PI;for(;r>l;)r-=2*Math.PI;for(;s>r;)r+=2*Math.PI;var d=r>=s&&l>=r,u=o>=i.innerRadius&&o<=i.outerRadius;return d&&u}return!1},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],35:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:n.defaultColor,borderWidth:3,borderColor:n.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",fill:!0},t.elements.Line=t.Element.extend({lineToNextPoint:function(t,e,n,i,a){var r=this,o=r._chart.ctx,s=r._view?r._view.spanGaps:!1;e._view.skip&&!s?i.call(r,t,e,n):t._view.skip&&!s?a.call(r,t,e,n):0===e._view.tension?o.lineTo(e._view.x,e._view.y):o.bezierCurveTo(t._view.controlPointNextX,t._view.controlPointNextY,e._view.controlPointPreviousX,e._view.controlPointPreviousY,e._view.x,e._view.y)},draw:function(){function t(t){o._view.skip||s._view.skip?t&&r.lineTo(i._view.scaleZero.x,i._view.scaleZero.y):r.bezierCurveTo(s._view.controlPointNextX,s._view.controlPointNextY,o._view.controlPointPreviousX,o._view.controlPointPreviousY,o._view.x,o._view.y)}var i=this,a=i._view,r=i._chart.ctx,o=i._children[0],s=i._children[i._children.length-1];r.save(),i._children.length>0&&a.fill&&(r.beginPath(),e.each(i._children,function(t,n){var o=e.previousItem(i._children,n),s=e.nextItem(i._children,n);0===n?(i._loop?r.moveTo(a.scaleZero.x,a.scaleZero.y):r.moveTo(t._view.x,a.scaleZero),t._view.skip?i._loop||r.moveTo(s._view.x,i._view.scaleZero):r.lineTo(t._view.x,t._view.y)):i.lineToNextPoint(o,t,s,function(t,e,n){
-i._loop?r.lineTo(i._view.scaleZero.x,i._view.scaleZero.y):(r.lineTo(t._view.x,i._view.scaleZero),r.moveTo(n._view.x,i._view.scaleZero))},function(t,e){r.lineTo(e._view.x,e._view.y)})},i),i._loop?t(!0):(r.lineTo(i._children[i._children.length-1]._view.x,a.scaleZero),r.lineTo(i._children[0]._view.x,a.scaleZero)),r.fillStyle=a.backgroundColor||n.defaultColor,r.closePath(),r.fill());var l=n.elements.line;r.lineCap=a.borderCapStyle||l.borderCapStyle,r.setLineDash&&r.setLineDash(a.borderDash||l.borderDash),r.lineDashOffset=a.borderDashOffset||l.borderDashOffset,r.lineJoin=a.borderJoinStyle||l.borderJoinStyle,r.lineWidth=a.borderWidth||l.borderWidth,r.strokeStyle=a.borderColor||n.defaultColor,r.beginPath(),e.each(i._children,function(t,n){var a=e.previousItem(i._children,n),o=e.nextItem(i._children,n);0===n?r.moveTo(t._view.x,t._view.y):i.lineToNextPoint(a,t,o,function(t,e,n){r.moveTo(n._view.x,n._view.y)},function(t,e){r.moveTo(e._view.x,e._view.y)})},i),i._loop&&i._children.length>0&&t(),r.stroke(),r.restore()}})}},{}],36:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global,i=n.defaultColor;n.elements.point={radius:3,pointStyle:"circle",backgroundColor:i,borderWidth:1,borderColor:i,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var n=this._view;return n?Math.pow(t-n.x,2)+Math.pow(e-n.y,2)<Math.pow(n.hitRadius+n.radius,2):!1},inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2):!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(){var t,a,r,o,s,l,d=this._view,u=this._chart.ctx,c=d.pointStyle,h=d.radius,f=d.x,g=d.y;if(!d.skip){if("object"==typeof c&&(t=c.toString(),"[object HTMLImageElement]"===t||"[object HTMLCanvasElement]"===t))return void u.drawImage(c,f-c.width/2,g-c.height/2);if(!(isNaN(h)||0>=h)){switch(u.strokeStyle=d.borderColor||i,u.lineWidth=e.getValueOrDefault(d.borderWidth,n.elements.point.borderWidth),u.fillStyle=d.backgroundColor||i,c){default:u.beginPath(),u.arc(f,g,h,0,2*Math.PI),u.closePath(),u.fill();break;case"triangle":u.beginPath(),a=3*h/Math.sqrt(3),s=a*Math.sqrt(3)/2,u.moveTo(f-a/2,g+s/3),u.lineTo(f+a/2,g+s/3),u.lineTo(f,g-2*s/3),u.closePath(),u.fill();break;case"rect":l=1/Math.SQRT2*h,u.fillRect(f-l,g-l,2*l,2*l),u.strokeRect(f-l,g-l,2*l,2*l);break;case"rectRot":l=1/Math.SQRT2*h,u.beginPath(),u.moveTo(f-l,g),u.lineTo(f,g+l),u.lineTo(f+l,g),u.lineTo(f,g-l),u.closePath(),u.fill();break;case"cross":u.beginPath(),u.moveTo(f,g+h),u.lineTo(f,g-h),u.moveTo(f-h,g),u.lineTo(f+h,g),u.closePath();break;case"crossRot":u.beginPath(),r=Math.cos(Math.PI/4)*h,o=Math.sin(Math.PI/4)*h,u.moveTo(f-r,g-o),u.lineTo(f+r,g+o),u.moveTo(f-r,g+o),u.lineTo(f+r,g-o),u.closePath();break;case"star":u.beginPath(),u.moveTo(f,g+h),u.lineTo(f,g-h),u.moveTo(f-h,g),u.lineTo(f+h,g),r=Math.cos(Math.PI/4)*h,o=Math.sin(Math.PI/4)*h,u.moveTo(f-r,g-o),u.lineTo(f+r,g+o),u.moveTo(f-r,g+o),u.lineTo(f+r,g-o),u.closePath();break;case"line":u.beginPath(),u.moveTo(f-h,g),u.lineTo(f+h,g),u.closePath();break;case"dash":u.beginPath(),u.moveTo(f,g),u.lineTo(f+h,g),u.closePath()}u.stroke()}}}})}},{}],37:[function(t,e,n){"use strict";e.exports=function(t){var e=(t.helpers,t.defaults.global);e.elements.rectangle={backgroundColor:e.defaultColor,borderWidth:0,borderColor:e.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return l[(u+t)%4]}var e=this._chart.ctx,n=this._view,i=n.width/2,a=n.x-i,r=n.x+i,o=n.base-(n.base-n.y),s=n.borderWidth/2;n.borderWidth&&(a+=s,r-=s,o+=s),e.beginPath(),e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,e.lineWidth=n.borderWidth;var l=[[a,n.base],[a,o],[r,o],[r,n.base]],d=["bottom","left","top","right"],u=d.indexOf(n.borderSkipped,0);-1===u&&(u=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),n.borderWidth&&e.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=this._view;return n?n.y<n.base?t>=n.x-n.width/2&&t<=n.x+n.width/2&&e>=n.y&&e<=n.base:t>=n.x-n.width/2&&t<=n.x+n.width/2&&e>=n.base&&e<=n.y:!1},inLabelRange:function(t){var e=this._view;return e?t>=e.x-e.width/2&&t<=e.x+e.width/2:!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],38:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"bottom"},i=t.Scale.extend({determineDataLimits:function(){var t=this;t.minIndex=0,t.maxIndex=t.chart.data.labels.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.chart.data.labels,t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.chart.data.labels,t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=t.chart.data.labels[t.minIndex],t.max=t.chart.data.labels[t.maxIndex]},buildTicks:function(t){var e=this;e.ticks=0===e.minIndex&&e.maxIndex===e.chart.data.labels.length-1?e.chart.data.labels:e.chart.data.labels.slice(e.minIndex,e.maxIndex+1)},getLabelForIndex:function(t,e){return this.ticks[t]},getPixelForValue:function(t,e,n,i){var a=this,r=Math.max(a.maxIndex+1-a.minIndex-(a.options.gridLines.offsetGridLines?0:1),1);if(a.isHorizontal()){var o=a.width-(a.paddingLeft+a.paddingRight),s=o/r,l=s*(e-a.minIndex)+a.paddingLeft;return a.options.gridLines.offsetGridLines&&i&&(l+=s/2),a.left+Math.round(l)}var d=a.height-(a.paddingTop+a.paddingBottom),u=d/r,c=u*(e-a.minIndex)+a.paddingTop;return a.options.gridLines.offsetGridLines&&i&&(c+=u/2),a.top+Math.round(c)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e,n=this,i=Math.max(n.ticks.length-(n.options.gridLines.offsetGridLines?0:1),1),a=n.isHorizontal(),r=a?n.width-(n.paddingLeft+n.paddingRight):n.height-(n.paddingTop+n.paddingBottom),o=r/i;return n.options.gridLines.offsetGridLines&&(t-=o/2),t-=a?n.paddingLeft:n.paddingTop,e=0>=t?0:Math.round(t/o)}});t.scaleService.registerScaleType("category",i,n)}},{}],39:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:function(t,n,i){var a=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=e.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o}}},i=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return s?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=(i.ticks,n.chart),r=a.data,o=r.datasets,s=n.isHorizontal();if(n.min=null,n.max=null,i.stacked){var l={},d=!1,u=!1;e.each(o,function(r,o){var s=a.getDatasetMeta(o);void 0===l[s.type]&&(l[s.type]={positiveValues:[],negativeValues:[]});var c=l[s.type].positiveValues,h=l[s.type].negativeValues;a.isDatasetVisible(o)&&t(s)&&e.each(r.data,function(t,e){var a=+n.getRightValue(t);isNaN(a)||s.data[e].hidden||(c[e]=c[e]||0,h[e]=h[e]||0,i.relativePoints?c[e]=100:0>a?(u=!0,h[e]+=a):(d=!0,c[e]+=a))})}),e.each(l,function(t){var i=t.positiveValues.concat(t.negativeValues),a=e.min(i),r=e.max(i);n.min=null===n.min?a:Math.min(n.min,a),n.max=null===n.max?r:Math.max(n.max,r)})}else e.each(o,function(i,r){var o=a.getDatasetMeta(r);a.isDatasetVisible(r)&&t(o)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||o.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i))})});this.handleTickRangeOptions()},getTickLimit:function(){var n,i=this,a=i.options.ticks;if(i.isHorizontal())n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.width/50));else{var r=e.getValueOrDefault(a.fontSize,t.defaults.global.defaultFontSize);n=Math.min(a.maxTicksLimit?a.maxTicksLimit:11,Math.ceil(i.height/(2*r)))}return n},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t,e,n,i){var a,r,o=this,s=o.paddingLeft,l=o.paddingBottom,d=o.start,u=+o.getRightValue(t),c=o.end-d;return o.isHorizontal()?(r=o.width-(s+o.paddingRight),a=o.left+r/c*(u-d),Math.round(a+s)):(r=o.height-(o.paddingTop+l),a=o.bottom-l-r/c*(u-d),Math.round(a))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=e.paddingLeft,a=e.paddingBottom,r=n?e.width-(i+e.paddingRight):e.height-(e.paddingTop+a),o=(n?t-e.left-i:e.bottom-a-t)/r;return e.start+(e.end-e.start)*o},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticksAsNumbers[t],null,null,e)}});t.scaleService.registerScaleType("linear",i,n)}},{}],40:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=e.noop;t.LinearScaleBase=t.Scale.extend({handleTickRangeOptions:function(){var t=this,n=t.options,i=n.ticks;if(i.beginAtZero){var a=e.sign(t.min),r=e.sign(t.max);0>a&&0>r?t.max=0:a>0&&r>0&&(t.min=0)}void 0!==i.min?t.min=i.min:void 0!==i.suggestedMin&&(t.min=Math.min(t.min,i.suggestedMin)),void 0!==i.max?t.max=i.max:void 0!==i.suggestedMax&&(t.max=Math.max(t.max,i.suggestedMax)),t.min===t.max&&(t.max++,i.beginAtZero||t.min--)},getTickLimit:n,handleDirectionalChanges:n,buildTicks:function(){var t=this,n=t.options,i=n.ticks,a=e.getValueOrDefault,r=(t.isHorizontal(),t.ticks=[]),o=t.getTickLimit();o=Math.max(2,o);var s,l=i.fixedStepSize&&i.fixedStepSize>0||i.stepSize&&i.stepSize>0;if(l)s=a(i.fixedStepSize,i.stepSize);else{var d=e.niceNum(t.max-t.min,!1);s=e.niceNum(d/(o-1),!0)}var u=Math.floor(t.min/s)*s,c=Math.ceil(t.max/s)*s,h=(c-u)/s;h=e.almostEquals(h,Math.round(h),s/1e3)?Math.round(h):Math.ceil(h),r.push(void 0!==i.min?i.min:u);for(var f=1;h>f;++f)r.push(u+f*s);r.push(void 0!==i.max?i.max:c),t.handleDirectionalChanges(),t.max=e.max(r),t.min=e.min(r),i.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{}],41:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n={position:"left",ticks:{callback:function(t,n,i){var a=t/Math.pow(10,Math.floor(e.log10(t)));return 1===a||2===a||5===a||0===n||n===i.length-1?t.toExponential():""}}},i=t.Scale.extend({determineDataLimits:function(){function t(t){return d?t.xAxisID===n.id:t.yAxisID===n.id}var n=this,i=n.options,a=i.ticks,r=n.chart,o=r.data,s=o.datasets,l=e.getValueOrDefault,d=n.isHorizontal();if(n.min=null,n.max=null,i.stacked){var u={};e.each(s,function(a,o){var s=r.getDatasetMeta(o);r.isDatasetVisible(o)&&t(s)&&(void 0===u[s.type]&&(u[s.type]=[]),e.each(a.data,function(t,e){var a=u[s.type],r=+n.getRightValue(t);isNaN(r)||s.data[e].hidden||(a[e]=a[e]||0,i.relativePoints?a[e]=100:a[e]+=r)}))}),e.each(u,function(t){var i=e.min(t),a=e.max(t);n.min=null===n.min?i:Math.min(n.min,i),n.max=null===n.max?a:Math.max(n.max,a)})}else e.each(s,function(i,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&e.each(i.data,function(t,e){var i=+n.getRightValue(t);isNaN(i)||o.data[e].hidden||(null===n.min?n.min=i:i<n.min&&(n.min=i),null===n.max?n.max=i:i>n.max&&(n.max=i))})});n.min=l(a.min,n.min),n.max=l(a.max,n.max),n.min===n.max&&(0!==n.min&&null!==n.min?(n.min=Math.pow(10,Math.floor(e.log10(n.min))-1),n.max=Math.pow(10,Math.floor(e.log10(n.max))+1)):(n.min=1,n.max=10))},buildTicks:function(){for(var t=this,n=t.options,i=n.ticks,a=e.getValueOrDefault,r=t.ticks=[],o=a(i.min,Math.pow(10,Math.floor(e.log10(t.min))));o<t.max;){r.push(o);var s=Math.floor(e.log10(o)),l=Math.floor(o/Math.pow(10,s))+1;10===l&&(l=1,++s),o=l*Math.pow(10,s)}var d=a(i.max,o);r.push(d),t.isHorizontal()||r.reverse(),t.max=e.max(r),t.min=e.min(r),i.reverse?(r.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickValues[t],null,null,e)},getPixelForValue:function(t,n,i,a){var r,o,s=this,l=s.start,d=+s.getRightValue(t),u=e.log10(s.end)-e.log10(l),c=s.paddingTop,h=s.paddingBottom,f=s.paddingLeft;return s.isHorizontal()?0===d?o=s.left+f:(r=s.width-(f+s.paddingRight),o=s.left+r/u*(e.log10(d)-e.log10(l)),o+=f):0===d?o=s.top+c:(r=s.height-(c+h),o=s.bottom-h-r/u*(e.log10(d)-e.log10(l))),o},getValueForPixel:function(t){var n,i,a=this,r=e.log10(a.end)-e.log10(a.start);return a.isHorizontal()?(i=a.width-(a.paddingLeft+a.paddingRight),n=a.start*Math.pow(10,(t-a.left-a.paddingLeft)*r/i)):(i=a.height-(a.paddingTop+a.paddingBottom),n=Math.pow(10,(a.bottom-a.paddingBottom-t)*r/i)/a.start),n}});t.scaleService.registerScaleType("logarithmic",i,n)}},{}],42:[function(t,e,n){"use strict";e.exports=function(t){var e=t.helpers,n=t.defaults.global,i={display:!0,animate:!0,lineArc:!1,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2},pointLabels:{fontSize:10,callback:function(t){return t}}},a=t.LinearScaleBase.extend({getValueCount:function(){return this.chart.data.labels.length},setDimensions:function(){var t=this,i=t.options,a=i.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var r=e.min([t.height,t.width]),o=e.getValueOrDefault(a.fontSize,n.defaultFontSize);t.drawingArea=i.display?r/2-(o/2+a.backdropPaddingY):r/2},determineDataLimits:function(){var t=this,n=t.chart;t.min=null,t.max=null,e.each(n.data.datasets,function(i,a){if(n.isDatasetVisible(a)){var r=n.getDatasetMeta(a);e.each(i.data,function(e,n){var i=+t.getRightValue(e);isNaN(i)||r.data[n].hidden||(null===t.min?t.min=i:i<t.min&&(t.min=i),null===t.max?t.max=i:i>t.max&&(t.max=i))})}}),t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,i=e.getValueOrDefault(t.fontSize,n.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*i)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,i,a,r,o,s,l,d,u,c,h,f,g=this.options.pointLabels,m=e.getValueOrDefault(g.fontSize,n.defaultFontSize),p=e.getValueOrDefault(g.fontStyle,n.defaultFontStyle),v=e.getValueOrDefault(g.fontFamily,n.defaultFontFamily),b=e.fontString(m,p,v),y=e.min([this.height/2-m-5,this.width/2]),x=this.width,k=0;for(this.ctx.font=b,i=0;i<this.getValueCount();i++)t=this.getPointPosition(i,y),a=this.ctx.measureText(this.pointLabels[i]?this.pointLabels[i]:"").width+5,0===i||i===this.getValueCount()/2?(r=a/2,t.x+r>x&&(x=t.x+r,o=i),t.x-r<k&&(k=t.x-r,l=i)):i<this.getValueCount()/2?t.x+a>x&&(x=t.x+a,o=i):i>this.getValueCount()/2&&t.x-a<k&&(k=t.x-a,l=i);u=k,c=Math.ceil(x-this.width),s=this.getIndexAngle(o),d=this.getIndexAngle(l),h=c/Math.sin(s+Math.PI/2),f=u/Math.sin(d+Math.PI/2),h=e.isNumber(h)?h:0,f=e.isNumber(f)?f:0,this.drawingArea=Math.round(y-(f+h)/2),this.setCenterPoint(f,h)},setCenterPoint:function(t,e){var n=this,i=n.width-e-n.drawingArea,a=t+n.drawingArea;n.xCenter=Math.round((a+i)/2+n.left),n.yCenter=Math.round(n.height/2+n.top)},getIndexAngle:function(t){var e=2*Math.PI/this.getValueCount();return t*e-Math.PI/2},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var n=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this,i=n.getIndexAngle(t);return{x:Math.round(Math.cos(i)*e)+n.xCenter,y:Math.round(Math.sin(i)*e)+n.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,n=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:0>e&&0>n?n:e>0&&n>0?e:0)},draw:function(){var t=this,i=t.options,a=i.gridLines,r=i.ticks,o=i.angleLines,s=i.pointLabels,l=e.getValueOrDefault;if(i.display){var d=t.ctx,u=l(r.fontSize,n.defaultFontSize),c=l(r.fontStyle,n.defaultFontStyle),h=l(r.fontFamily,n.defaultFontFamily),f=e.fontString(u,c,h);if(e.each(t.ticks,function(e,o){if(o>0||i.reverse){var s=t.getDistanceFromCenterForValue(t.ticksAsNumbers[o]),c=t.yCenter-s;if(a.display)if(d.strokeStyle=a.color,d.lineWidth=a.lineWidth,i.lineArc)d.beginPath(),d.arc(t.xCenter,t.yCenter,s,0,2*Math.PI),d.closePath(),d.stroke();else{d.beginPath();for(var h=0;h<t.getValueCount();h++){var g=t.getPointPosition(h,s);0===h?d.moveTo(g.x,g.y):d.lineTo(g.x,g.y)}d.closePath(),d.stroke()}if(r.display){var m=l(r.fontColor,n.defaultFontColor);if(d.font=f,r.showLabelBackdrop){var p=d.measureText(e).width;d.fillStyle=r.backdropColor,d.fillRect(t.xCenter-p/2-r.backdropPaddingX,c-u/2-r.backdropPaddingY,p+2*r.backdropPaddingX,u+2*r.backdropPaddingY)}d.textAlign="center",d.textBaseline="middle",d.fillStyle=m,d.fillText(e,t.xCenter,c)}}}),!i.lineArc){d.lineWidth=o.lineWidth,d.strokeStyle=o.color;for(var g=t.getDistanceFromCenterForValue(i.reverse?t.min:t.max),m=l(s.fontSize,n.defaultFontSize),p=l(s.fontStyle,n.defaultFontStyle),v=l(s.fontFamily,n.defaultFontFamily),b=e.fontString(m,p,v),y=t.getValueCount()-1;y>=0;y--){if(o.display){var x=t.getPointPosition(y,g);d.beginPath(),d.moveTo(t.xCenter,t.yCenter),d.lineTo(x.x,x.y),d.stroke(),d.closePath()}var k=t.getPointPosition(y,g+5),_=l(s.fontColor,n.defaultFontColor);d.font=b,d.fillStyle=_;var S=t.pointLabels,w=S.length,M=S.length/2,D=M/2,C=D>y||y>w-D,T=y===D||y===w-D;0===y?d.textAlign="center":y===M?d.textAlign="center":M>y?d.textAlign="left":d.textAlign="right",T?d.textBaseline="middle":C?d.textBaseline="bottom":d.textBaseline="top",d.fillText(S[y]?S[y]:"",k.x,k.y)}}}}});t.scaleService.registerScaleType("radialLinear",a,i)}},{}],43:[function(t,e,n){"use strict";var i=t(6);i="function"==typeof i?i:window.moment,e.exports=function(t){var e=t.helpers,n={units:[{name:"millisecond",steps:[1,2,5,10,20,50,100,250,500]},{name:"second",steps:[1,2,5,10,30]},{name:"minute",steps:[1,2,5,10,30]},{name:"hour",steps:[1,2,3,6,12]},{name:"day",steps:[1,2,5]},{name:"week",maxStep:4},{name:"month",maxStep:3},{name:"quarter",maxStep:4},{name:"year",maxStep:!1}]},a={position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}},r=t.Scale.extend({initialize:function(){if(!i)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");t.Scale.prototype.initialize.call(this)},getLabelMoment:function(t,e){return this.labelMoments[t][e]},getMomentStartOf:function(t){var e=this;return"week"===e.options.time.unit&&e.options.time.isoWeekday!==!1?t.clone().startOf("isoWeek").isoWeekday(e.options.time.isoWeekday):t.clone().startOf(e.tickUnit)},determineDataLimits:function(){var t=this;t.labelMoments=[];var n=[];t.chart.data.labels&&t.chart.data.labels.length>0?(e.each(t.chart.data.labels,function(e,i){var a=t.parseTime(e);a.isValid()&&(t.options.time.round&&a.startOf(t.options.time.round),n.push(a))},t),t.firstTick=i.min.call(t,n),t.lastTick=i.max.call(t,n)):(t.firstTick=null,t.lastTick=null),e.each(t.chart.data.datasets,function(a,r){var o=[],s=t.chart.isDatasetVisible(r);"object"==typeof a.data[0]&&null!==a.data[0]?e.each(a.data,function(e,n){var a=t.parseTime(t.getRightValue(e));a.isValid()&&(t.options.time.round&&a.startOf(t.options.time.round),o.push(a),s&&(t.firstTick=null!==t.firstTick?i.min(t.firstTick,a):a,t.lastTick=null!==t.lastTick?i.max(t.lastTick,a):a))},t):o=n,t.labelMoments.push(o)},t),t.options.time.min&&(t.firstTick=t.parseTime(t.options.time.min)),t.options.time.max&&(t.lastTick=t.parseTime(t.options.time.max)),t.firstTick=(t.firstTick||i()).clone(),t.lastTick=(t.lastTick||i()).clone()},buildTicks:function(i){var a=this;a.ctx.save();var r=e.getValueOrDefault(a.options.ticks.fontSize,t.defaults.global.defaultFontSize),o=e.getValueOrDefault(a.options.ticks.fontStyle,t.defaults.global.defaultFontStyle),s=e.getValueOrDefault(a.options.ticks.fontFamily,t.defaults.global.defaultFontFamily),l=e.fontString(r,o,s);if(a.ctx.font=l,a.ticks=[],a.unitScale=1,a.scaleSizeInUnits=0,a.options.time.unit)a.tickUnit=a.options.time.unit||"day",a.displayFormat=a.options.time.displayFormats[a.tickUnit],a.scaleSizeInUnits=a.lastTick.diff(a.firstTick,a.tickUnit,!0),a.unitScale=e.getValueOrDefault(a.options.time.unitStepSize,1);else{var d=a.isHorizontal()?a.width-(a.paddingLeft+a.paddingRight):a.height-(a.paddingTop+a.paddingBottom),u=a.tickFormatFunction(a.firstTick,0,[]),c=a.ctx.measureText(u).width,h=Math.cos(e.toRadians(a.options.ticks.maxRotation)),f=Math.sin(e.toRadians(a.options.ticks.maxRotation));c=c*h+r*f;var g=d/c;a.tickUnit="millisecond",a.scaleSizeInUnits=a.lastTick.diff(a.firstTick,a.tickUnit,!0),a.displayFormat=a.options.time.displayFormats[a.tickUnit];for(var m=0,p=n.units[m];m<n.units.length;){if(a.unitScale=1,e.isArray(p.steps)&&Math.ceil(a.scaleSizeInUnits/g)<e.max(p.steps)){for(var v=0;v<p.steps.length;++v)if(p.steps[v]>=Math.ceil(a.scaleSizeInUnits/g)){a.unitScale=e.getValueOrDefault(a.options.time.unitStepSize,p.steps[v]);break}break}if(p.maxStep===!1||Math.ceil(a.scaleSizeInUnits/g)<p.maxStep){a.unitScale=e.getValueOrDefault(a.options.time.unitStepSize,Math.ceil(a.scaleSizeInUnits/g));break}++m,p=n.units[m],a.tickUnit=p.name;var b=a.firstTick.diff(a.getMomentStartOf(a.firstTick),a.tickUnit,!0),y=a.getMomentStartOf(a.lastTick.clone().add(1,a.tickUnit)).diff(a.lastTick,a.tickUnit,!0);a.scaleSizeInUnits=a.lastTick.diff(a.firstTick,a.tickUnit,!0)+b+y,a.displayFormat=a.options.time.displayFormats[p.name]}}var x;if(a.options.time.min?x=a.getMomentStartOf(a.firstTick):(a.firstTick=a.getMomentStartOf(a.firstTick),x=a.firstTick),!a.options.time.max){var k=a.getMomentStartOf(a.lastTick);0!==k.diff(a.lastTick,a.tickUnit,!0)&&(a.lastTick=a.getMomentStartOf(a.lastTick.add(1,a.tickUnit)))}a.smallestLabelSeparation=a.width,e.each(a.chart.data.datasets,function(t,e){for(var n=1;n<a.labelMoments[e].length;n++)a.smallestLabelSeparation=Math.min(a.smallestLabelSeparation,a.labelMoments[e][n].diff(a.labelMoments[e][n-1],a.tickUnit,!0))},a),a.options.time.displayFormat&&(a.displayFormat=a.options.time.displayFormat),a.ticks.push(a.firstTick.clone());for(var _=1;_<=a.scaleSizeInUnits;++_){var S=x.clone().add(_,a.tickUnit);if(a.options.time.max&&S.diff(a.lastTick,a.tickUnit,!0)>=0)break;_%a.unitScale===0&&a.ticks.push(S)}var w=a.ticks[a.ticks.length-1].diff(a.lastTick,a.tickUnit);(0!==w||0===a.scaleSizeInUnits)&&(a.options.time.max?(a.ticks.push(a.lastTick.clone()),a.scaleSizeInUnits=a.lastTick.diff(a.ticks[0],a.tickUnit,!0)):(a.ticks.push(a.lastTick.clone()),a.scaleSizeInUnits=a.lastTick.diff(a.firstTick,a.tickUnit,!0))),a.ctx.restore()},getLabelForIndex:function(t,e){var n=this,i=n.chart.data.labels&&t<n.chart.data.labels.length?n.chart.data.labels[t]:"";return"object"==typeof n.chart.data.datasets[e].data[0]&&(i=n.getRightValue(n.chart.data.datasets[e].data[t])),n.options.time.tooltipFormat&&(i=n.parseTime(i).format(n.options.time.tooltipFormat)),i},tickFormatFunction:function(t,n,i){var a=t.format(this.displayFormat),r=this.options.ticks,o=e.getValueOrDefault(r.callback,r.userCallback);return o?o(a,n,i):a},convertTicksToLabels:function(){var t=this;t.tickMoments=t.ticks,t.ticks=t.ticks.map(t.tickFormatFunction,t)},getPixelForValue:function(t,e,n,i){var a=this,r=t&&t.isValid&&t.isValid()?t:a.getLabelMoment(n,e);if(r){var o=r.diff(a.firstTick,a.tickUnit,!0),s=o/a.scaleSizeInUnits;if(a.isHorizontal()){var l=a.width-(a.paddingLeft+a.paddingRight),d=(l/Math.max(a.ticks.length-1,1),l*s+a.paddingLeft);return a.left+Math.round(d)}var u=a.height-(a.paddingTop+a.paddingBottom),c=(u/Math.max(a.ticks.length-1,1),u*s+a.paddingTop);return a.top+Math.round(c)}},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickMoments[t],null,null,e)},getValueForPixel:function(t){var e=this,n=e.isHorizontal()?e.width-(e.paddingLeft+e.paddingRight):e.height-(e.paddingTop+e.paddingBottom),a=(t-(e.isHorizontal()?e.left+e.paddingLeft:e.top+e.paddingTop))/n;return a*=e.scaleSizeInUnits,e.firstTick.clone().add(i.duration(a,e.tickUnit).asSeconds(),"seconds")},parseTime:function(t){var e=this;return"string"==typeof e.options.time.parser?i(t,e.options.time.parser):"function"==typeof e.options.time.parser?e.options.time.parser(t):"function"==typeof t.getMonth||"number"==typeof t?i(t):t.isValid&&t.isValid()?t:"string"!=typeof e.options.time.format&&e.options.time.format.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale"),e.options.time.format(t)):i(t,e.options.time.format)}});t.scaleService.registerScaleType("time",r,a)}},{6:6}]},{},[7])(7)});
\ No newline at end of file
+!function t(e,i,n){function a(r,s){if(!i[r]){if(!e[r]){var l="function"==typeof require&&require;if(!s&&l)return l(r,!0);if(o)return o(r,!0);var h=new Error("Cannot find module '"+r+"'");throw h.code="MODULE_NOT_FOUND",h}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return a(i?i:t)},d,d.exports,t,e,i,n)}return i[r].exports}for(var o="function"==typeof require&&require,r=0;r<n.length;r++)a(n[r]);return a}({1:[function(t,e,i){function n(t){if(t){var e=/^#([a-fA-F0-9]{3})$/,i=/^#([a-fA-F0-9]{6})$/,n=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,a=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,o=/(\w+)/,r=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(var h=0;h<r.length;h++)r[h]=parseInt(l[h]+l[h],16)}else if(l=t.match(i)){l=l[1];for(var h=0;h<r.length;h++)r[h]=parseInt(l.slice(2*h,2*h+2),16)}else if(l=t.match(n)){for(var h=0;h<r.length;h++)r[h]=parseInt(l[h+1]);s=parseFloat(l[4])}else if(l=t.match(a)){for(var h=0;h<r.length;h++)r[h]=Math.round(2.55*parseFloat(l[h+1]));s=parseFloat(l[4])}else if(l=t.match(o)){if("transparent"==l[1])return[0,0,0,0];if(r=x[l[1]],!r)return}for(var h=0;h<r.length;h++)r[h]=v(r[h],0,255);return s=s||0==s?v(s,0,1):1,r[3]=s,r}}function a(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,i=t.match(e);if(i){var n=parseFloat(i[4]),a=v(parseInt(i[1]),0,360),o=v(parseFloat(i[2]),0,100),r=v(parseFloat(i[3]),0,100),s=v(isNaN(n)?1:n,0,1);return[a,o,r,s]}}}function o(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,i=t.match(e);if(i){var n=parseFloat(i[4]),a=v(parseInt(i[1]),0,360),o=v(parseFloat(i[2]),0,100),r=v(parseFloat(i[3]),0,100),s=v(isNaN(n)?1:n,0,1);return[a,o,r,s]}}}function r(t){var e=n(t);return e&&e.slice(0,3)}function s(t){var e=a(t);return e&&e.slice(0,3)}function l(t){var e=n(t);return e?e[3]:(e=a(t))?e[3]:(e=o(t))?e[3]:void 0}function h(t){return"#"+y(t[0])+y(t[1])+y(t[2])}function d(t,e){return 1>e||t[3]&&t[3]<1?u(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"}function u(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function c(t,e){if(1>e||t[3]&&t[3]<1)return f(t,e);var i=Math.round(t[0]/255*100),n=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+i+"%, "+n+"%, "+a+"%)"}function f(t,e){var i=Math.round(t[0]/255*100),n=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgba("+i+"%, "+n+"%, "+a+"%, "+(e||t[3]||1)+")"}function g(t,e){return 1>e||t[3]&&t[3]<1?m(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"}function m(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"}function b(t){return k[t.slice(0,3)]}function v(t,e,i){return Math.min(Math.max(e,t),i)}function y(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var x=t("color-name");e.exports={getRgba:n,getHsla:a,getRgb:r,getHsl:s,getHwb:o,getAlpha:l,hexString:h,rgbString:d,rgbaString:u,percentString:c,percentaString:f,hslString:g,hslaString:m,hwbString:p,keyword:b};var k={};for(var _ in x)k[x[_]]=_},{"color-name":5}],2:[function(t,e,i){var n=t("color-convert"),a=t("chartjs-color-string"),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;if("string"==typeof t)if(e=a.getRgba(t))this.setValues("rgb",e);else if(e=a.getHsla(t))this.setValues("hsl",e);else{if(!(e=a.getHwb(t)))throw new Error('Unable to parse color from string "'+t+'"');this.setValues("hwb",e)}else if("object"==typeof t)if(e=t,void 0!==e.r||void 0!==e.red)this.setValues("rgb",e);else if(void 0!==e.l||void 0!==e.lightness)this.setValues("hsl",e);else if(void 0!==e.v||void 0!==e.value)this.setValues("hsv",e);else if(void 0!==e.w||void 0!==e.whiteness)this.setValues("hwb",e);else{if(void 0===e.c&&void 0===e.cyan)throw new Error("Unable to parse color from object "+JSON.stringify(t));this.setValues("cmyk",e)}};o.prototype={rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=0>t?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return a.hexString(this.values.rgb)},rgbString:function(){return a.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return a.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return a.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return a.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return a.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return a.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return a.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],i=0;i<t.length;i++){var n=t[i]/255;e[i]=.03928>=n?n/12.92:Math.pow((n+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),i=t.luminosity();return e>i?(e+.05)/(i+.05):(i+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb,e=(299*t[0]+587*t[1]+114*t[2])/1e3;return 128>e},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;3>e;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,i=(e[0]+t)%360;return e[0]=0>i?360+i:i,this.setValues("hsl",e),this},mix:function(t,e){var i=this,n=t,a=void 0===e?.5:e,o=2*a-1,r=i.alpha()-n.alpha(),s=((o*r===-1?o:(o+r)/(1+o*r))+1)/2,l=1-s;return this.rgb(s*i.red()+l*n.red(),s*i.green()+l*n.green(),s*i.blue()+l*n.blue()).alpha(i.alpha()*a+n.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,i=new o,n=this.values,a=i.values;for(var r in n)n.hasOwnProperty(r)&&(t=n[r],e={}.toString.call(t),"[object Array]"===e?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return i}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,i={},n=0;n<t.length;n++)i[t.charAt(n)]=e[t][n];return 1!==e.alpha&&(i.a=e.alpha),i},o.prototype.setValues=function(t,e){var i,a=this.values,o=this.spaces,r=this.maxes,s=1;if("alpha"===t)s=e;else if(e.length)a[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(i=0;i<t.length;i++)a[t][i]=e[t.charAt(i)];s=e.a}else if(void 0!==e[o[t][0]]){var l=o[t];for(i=0;i<t.length;i++)a[t][i]=e[l[i]];s=e.alpha}if(a.alpha=Math.max(0,Math.min(1,void 0===s?a.alpha:s)),"alpha"===t)return!1;var h;for(i=0;i<t.length;i++)h=Math.max(0,Math.min(r[t][i],a[t][i])),a[t][i]=Math.round(h);for(var d in o)d!==t&&(a[d]=n[t][d](a[t]));return!0},o.prototype.setSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i),this)},o.prototype.setChannel=function(t,e,i){var n=this.values[t];return void 0===i?n[e]:i===n[e]?this:(n[e]=i,this.setValues(t,n),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{"chartjs-color-string":1,"color-convert":4}],3:[function(t,e,i){function n(t){var e,i,n,a=t[0]/255,o=t[1]/255,r=t[2]/255,s=Math.min(a,o,r),l=Math.max(a,o,r),h=l-s;return l==s?e=0:a==l?e=(o-r)/h:o==l?e=2+(r-a)/h:r==l&&(e=4+(a-o)/h),e=Math.min(60*e,360),0>e&&(e+=360),n=(s+l)/2,i=l==s?0:.5>=n?h/(l+s):h/(2-l-s),[e,100*i,100*n]}function a(t){var e,i,n,a=t[0],o=t[1],r=t[2],s=Math.min(a,o,r),l=Math.max(a,o,r),h=l-s;return i=0==l?0:h/l*1e3/10,l==s?e=0:a==l?e=(o-r)/h:o==l?e=2+(r-a)/h:r==l&&(e=4+(a-o)/h),e=Math.min(60*e,360),0>e&&(e+=360),n=l/255*1e3/10,[e,i,n]}function o(t){var e=t[0],i=t[1],a=t[2],o=n(t)[0],r=1/255*Math.min(e,Math.min(i,a)),a=1-1/255*Math.max(e,Math.max(i,a));return[o,100*r,100*a]}function s(t){var e,i,n,a,o=t[0]/255,r=t[1]/255,s=t[2]/255;return a=Math.min(1-o,1-r,1-s),e=(1-o-a)/(1-a)||0,i=(1-r-a)/(1-a)||0,n=(1-s-a)/(1-a)||0,[100*e,100*i,100*n,100*a]}function l(t){return Q[JSON.stringify(t)]}function h(t){var e=t[0]/255,i=t[1]/255,n=t[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92;var a=.4124*e+.3576*i+.1805*n,o=.2126*e+.7152*i+.0722*n,r=.0193*e+.1192*i+.9505*n;return[100*a,100*o,100*r]}function d(t){var e,i,n,a=h(t),o=a[0],r=a[1],s=a[2];return o/=95.047,r/=100,s/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*r-16,i=500*(o-r),n=200*(r-s),[e,i,n]}function u(t){return B(d(t))}function c(t){var e,i,n,a,o,r=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return o=255*l,[o,o,o];i=.5>l?l*(1+s):l+s-l*s,e=2*l-i,a=[0,0,0];for(var h=0;3>h;h++)n=r+1/3*-(h-1),0>n&&n++,n>1&&n--,o=1>6*n?e+6*(i-e)*n:1>2*n?i:2>3*n?e+(i-e)*(2/3-n)*6:e,a[h]=255*o;return a}function f(t){var e,i,n=t[0],a=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,a*=1>=o?o:2-o,i=(o+a)/2,e=2*a/(o+a),[n,100*e,100*i])}function m(t){return o(c(t))}function p(t){return s(c(t))}function v(t){return l(c(t))}function y(t){var e=t[0]/60,i=t[1]/100,n=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),r=255*n*(1-i),s=255*n*(1-i*o),l=255*n*(1-i*(1-o)),n=255*n;switch(a){case 0:return[n,l,r];case 1:return[s,n,r];case 2:return[r,n,l];case 3:return[r,s,n];case 4:return[l,r,n];case 5:return[n,r,s]}}function x(t){var e,i,n=t[0],a=t[1]/100,o=t[2]/100;return i=(2-a)*o,e=a*o,e/=1>=i?i:2-i,e=e||0,i/=2,[n,100*e,100*i]}function k(t){return o(y(t))}function _(t){return s(y(t))}function S(t){return l(y(t))}function w(t){var e,i,n,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,h=s+l;switch(h>1&&(s/=h,l/=h),e=Math.floor(6*o),i=1-l,n=6*o-e,0!=(1&e)&&(n=1-n),a=s+n*(i-s),e){default:case 6:case 0:r=i,g=a,b=s;break;case 1:r=a,g=i,b=s;break;case 2:r=s,g=i,b=a;break;case 3:r=s,g=a,b=i;break;case 4:r=a,g=s,b=i;break;case 5:r=i,g=s,b=a}return[255*r,255*g,255*b]}function M(t){return n(w(t))}function C(t){return a(w(t))}function D(t){return s(w(t))}function T(t){return l(w(t))}function P(t){var e,i,n,a=t[0]/100,o=t[1]/100,r=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),[255*e,255*i,255*n]}function A(t){return n(P(t))}function F(t){return a(P(t))}function I(t){return o(P(t))}function O(t){return l(P(t))}function R(t){var e,i,n,a=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*a+-1.5372*o+r*-.4986,i=a*-.9689+1.8758*o+.0415*r,n=.0557*a+o*-.204+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e=12.92*e,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i=12.92*i,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n=12.92*n,e=Math.min(Math.max(0,e),1),i=Math.min(Math.max(0,i),1),n=Math.min(Math.max(0,n),1),[255*e,255*i,255*n]}function W(t){var e,i,n,a=t[0],o=t[1],r=t[2];return a/=95.047,o/=100,r/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,i=500*(a-o),n=200*(o-r),[e,i,n]}function V(t){return B(W(t))}function L(t){var e,i,n,a,o=t[0],r=t[1],s=t[2];return 8>=o?(i=100*o/903.3,a=7.787*(i/100)+16/116):(i=100*Math.pow((o+16)/116,3),a=Math.pow(i/100,1/3)),e=.008856>=e/95.047?e=95.047*(r/500+a-16/116)/7.787:95.047*Math.pow(r/500+a,3),n=.008859>=n/108.883?n=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,i,n]}function B(t){var e,i,n,a=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),i=360*e/2/Math.PI,0>i&&(i+=360),n=Math.sqrt(o*o+r*r),[a,n,i]}function z(t){return R(L(t))}function Y(t){var e,i,n,a=t[0],o=t[1],r=t[2];return n=r/360*2*Math.PI,e=o*Math.cos(n),i=o*Math.sin(n),[a,e,i]}function H(t){return L(Y(t))}function N(t){return z(Y(t))}function E(t){return X[t]}function U(t){return n(E(t))}function j(t){return a(E(t))}function G(t){return o(E(t))}function q(t){return s(E(t))}function Z(t){return d(E(t))}function J(t){return h(E(t))}e.exports={rgb2hsl:n,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:h,rgb2lab:d,rgb2lch:u,hsl2rgb:c,hsl2hsv:f,hsl2hwb:m,hsl2cmyk:p,hsl2keyword:v,hsv2rgb:y,hsv2hsl:x,hsv2hwb:k,hsv2cmyk:_,hsv2keyword:S,hwb2rgb:w,hwb2hsl:M,hwb2hsv:C,hwb2cmyk:D,hwb2keyword:T,cmyk2rgb:P,cmyk2hsl:A,cmyk2hsv:F,cmyk2hwb:I,cmyk2keyword:O,keyword2rgb:E,keyword2hsl:U,keyword2hsv:j,keyword2hwb:G,keyword2cmyk:q,keyword2lab:Z,keyword2xyz:J,xyz2rgb:R,xyz2lab:W,xyz2lch:V,lab2xyz:L,lab2rgb:z,lab2lch:B,lch2lab:Y,lch2xyz:H,lch2rgb:N};var X={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},Q={};for(var $ in X)Q[JSON.stringify(X[$])]=$},{}],4:[function(t,e,i){var n=t("./conversions"),a=function(){return new h};for(var o in n){a[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),n[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),s=r[1],l=r[2];a[s]=a[s]||{},a[s][l]=a[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var i=n[t](e);if("string"==typeof i||void 0===i)return i;for(var a=0;a<i.length;a++)i[a]=Math.round(i[a]);return i}}(o)}var h=function(){this.convs={}};h.prototype.routeSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i))},h.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},h.prototype.getValues=function(t){var e=this.convs[t];if(!e){var i=this.space,n=this.convs[i];e=a[i][t](n),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){h.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=a},{"./conversions":3}],5:[function(t,e,i){e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],6:[function(t,e,i){!function(t,n){"object"==typeof i&&"undefined"!=typeof e?e.exports=n():"function"==typeof define&&define.amd?define(n):t.moment=n()}(this,function(){"use strict";function i(){return ln.apply(null,arguments)}function n(t){ln=t}function a(t){return t instanceof Array||"[object Array]"===Object.prototype.toString.call(t)}function o(t){return t instanceof Date||"[object Date]"===Object.prototype.toString.call(t)}function r(t,e){var i,n=[];for(i=0;i<t.length;++i)n.push(e(t[i],i));return n}function s(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function l(t,e){for(var i in e)s(e,i)&&(t[i]=e[i]);return s(e,"toString")&&(t.toString=e.toString),s(e,"valueOf")&&(t.valueOf=e.valueOf),t}function h(t,e,i,n){return Lt(t,e,i,n,!0).utc()}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function u(t){return null==t._pf&&(t._pf=d()),t._pf}function c(t){if(null==t._isValid){var e=u(t),i=hn.call(e.parsedDateParts,function(t){return null!=t});t._isValid=!isNaN(t._d.getTime())&&e.overflow<0&&!e.empty&&!e.invalidMonth&&!e.invalidWeekday&&!e.nullInput&&!e.invalidFormat&&!e.userInvalidated&&(!e.meridiem||e.meridiem&&i),t._strict&&(t._isValid=t._isValid&&0===e.charsLeftOver&&0===e.unusedTokens.length&&void 0===e.bigHour)}return t._isValid}function f(t){var e=h(NaN);return null!=t?l(u(e),t):u(e).userInvalidated=!0,e}function g(t){return void 0===t}function m(t,e){var i,n,a;if(g(e._isAMomentObject)||(t._isAMomentObject=e._isAMomentObject),g(e._i)||(t._i=e._i),g(e._f)||(t._f=e._f),g(e._l)||(t._l=e._l),g(e._strict)||(t._strict=e._strict),g(e._tzm)||(t._tzm=e._tzm),g(e._isUTC)||(t._isUTC=e._isUTC),g(e._offset)||(t._offset=e._offset),g(e._pf)||(t._pf=u(e)),g(e._locale)||(t._locale=e._locale),dn.length>0)for(i in dn)n=dn[i],a=e[n],g(a)||(t[n]=a);return t}function p(t){m(this,t),this._d=new Date(null!=t._d?t._d.getTime():NaN),un===!1&&(un=!0,i.updateOffset(this),un=!1)}function b(t){return t instanceof p||null!=t&&null!=t._isAMomentObject}function v(t){return 0>t?Math.ceil(t):Math.floor(t)}function y(t){var e=+t,i=0;return 0!==e&&isFinite(e)&&(i=v(e)),i}function x(t,e,i){var n,a=Math.min(t.length,e.length),o=Math.abs(t.length-e.length),r=0;for(n=0;a>n;n++)(i&&t[n]!==e[n]||!i&&y(t[n])!==y(e[n]))&&r++;return r+o}function k(t){i.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+t)}function _(t,e){var n=!0;return l(function(){return null!=i.deprecationHandler&&i.deprecationHandler(null,t),n&&(k(t+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),n=!1),e.apply(this,arguments)},e)}function S(t,e){null!=i.deprecationHandler&&i.deprecationHandler(t,e),cn[t]||(k(e),cn[t]=!0)}function w(t){return t instanceof Function||"[object Function]"===Object.prototype.toString.call(t)}function M(t){return"[object Object]"===Object.prototype.toString.call(t)}function C(t){var e,i;for(i in t)e=t[i],w(e)?this[i]=e:this["_"+i]=e;this._config=t,this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function D(t,e){var i,n=l({},t);for(i in e)s(e,i)&&(M(t[i])&&M(e[i])?(n[i]={},l(n[i],t[i]),l(n[i],e[i])):null!=e[i]?n[i]=e[i]:delete n[i]);return n}function T(t){null!=t&&this.set(t)}function P(t){return t?t.toLowerCase().replace("_","-"):t}function A(t){for(var e,i,n,a,o=0;o<t.length;){for(a=P(t[o]).split("-"),e=a.length,i=P(t[o+1]),i=i?i.split("-"):null;e>0;){if(n=F(a.slice(0,e).join("-")))return n;if(i&&i.length>=e&&x(a,i,!0)>=e-1)break;e--}o++}return null}function F(i){var n=null;if(!pn[i]&&"undefined"!=typeof e&&e&&e.exports)try{n=gn._abbr,t("./locale/"+i),I(n)}catch(a){}return pn[i]}function I(t,e){var i;return t&&(i=g(e)?W(t):O(t,e),i&&(gn=i)),gn._abbr}function O(t,e){return null!==e?(e.abbr=t,null!=pn[t]?(S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale"),e=D(pn[t]._config,e)):null!=e.parentLocale&&(null!=pn[e.parentLocale]?e=D(pn[e.parentLocale]._config,e):S("parentLocaleUndefined","specified parentLocale is not defined yet")),pn[t]=new T(e),I(t),pn[t]):(delete pn[t],null)}function R(t,e){if(null!=e){var i;null!=pn[t]&&(e=D(pn[t]._config,e)),i=new T(e),i.parentLocale=pn[t],pn[t]=i,I(t)}else null!=pn[t]&&(null!=pn[t].parentLocale?pn[t]=pn[t].parentLocale:null!=pn[t]&&delete pn[t]);return pn[t]}function W(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return gn;if(!a(t)){if(e=F(t))return e;t=[t]}return A(t)}function V(){return fn(pn)}function L(t,e){var i=t.toLowerCase();bn[i]=bn[i+"s"]=bn[e]=t}function B(t){return"string"==typeof t?bn[t]||bn[t.toLowerCase()]:void 0}function z(t){var e,i,n={};for(i in t)s(t,i)&&(e=B(i),e&&(n[e]=t[i]));return n}function Y(t,e){return function(n){return null!=n?(N(this,t,n),i.updateOffset(this,e),this):H(this,t)}}function H(t,e){return t.isValid()?t._d["get"+(t._isUTC?"UTC":"")+e]():NaN}function N(t,e,i){t.isValid()&&t._d["set"+(t._isUTC?"UTC":"")+e](i)}function E(t,e){var i;if("object"==typeof t)for(i in t)this.set(i,t[i]);else if(t=B(t),w(this[t]))return this[t](e);return this}function U(t,e,i){var n=""+Math.abs(t),a=e-n.length,o=t>=0;return(o?i?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+n}function j(t,e,i,n){var a=n;"string"==typeof n&&(a=function(){return this[n]()}),t&&(kn[t]=a),e&&(kn[e[0]]=function(){return U(a.apply(this,arguments),e[1],e[2])}),i&&(kn[i]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function G(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function q(t){var e,i,n=t.match(vn);for(e=0,i=n.length;i>e;e++)kn[n[e]]?n[e]=kn[n[e]]:n[e]=G(n[e]);return function(e){var a,o="";for(a=0;i>a;a++)o+=n[a]instanceof Function?n[a].call(e,t):n[a];return o}}function Z(t,e){return t.isValid()?(e=J(e,t.localeData()),xn[e]=xn[e]||q(e),xn[e](t)):t.localeData().invalidDate()}function J(t,e){function i(t){return e.longDateFormat(t)||t}var n=5;for(yn.lastIndex=0;n>=0&&yn.test(t);)t=t.replace(yn,i),yn.lastIndex=0,n-=1;return t}function X(t,e,i){zn[t]=w(e)?e:function(t,n){return t&&i?i:e}}function Q(t,e){return s(zn,t)?zn[t](e._strict,e._locale):new RegExp($(t))}function $(t){return K(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,i,n,a){return e||i||n||a}))}function K(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function tt(t,e){var i,n=e;for("string"==typeof t&&(t=[t]),"number"==typeof e&&(n=function(t,i){i[e]=y(t)}),i=0;i<t.length;i++)Yn[t[i]]=n}function et(t,e){tt(t,function(t,i,n,a){n._w=n._w||{},e(t,n._w,n,a)})}function it(t,e,i){null!=e&&s(Yn,t)&&Yn[t](e,i._a,i,t)}function nt(t,e){return new Date(Date.UTC(t,e+1,0)).getUTCDate()}function at(t,e){return a(this._months)?this._months[t.month()]:this._months[Xn.test(e)?"format":"standalone"][t.month()]}function ot(t,e){return a(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[Xn.test(e)?"format":"standalone"][t.month()]}function rt(t,e,i){var n,a,o,r=t.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],n=0;12>n;++n)o=h([2e3,n]),this._shortMonthsParse[n]=this.monthsShort(o,"").toLocaleLowerCase(),this._longMonthsParse[n]=this.months(o,"").toLocaleLowerCase();return i?"MMM"===e?(a=mn.call(this._shortMonthsParse,r),-1!==a?a:null):(a=mn.call(this._longMonthsParse,r),-1!==a?a:null):"MMM"===e?(a=mn.call(this._shortMonthsParse,r),-1!==a?a:(a=mn.call(this._longMonthsParse,r),-1!==a?a:null)):(a=mn.call(this._longMonthsParse,r),-1!==a?a:(a=mn.call(this._shortMonthsParse,r),-1!==a?a:null))}function st(t,e,i){var n,a,o;if(this._monthsParseExact)return rt.call(this,t,e,i);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),n=0;12>n;n++){if(a=h([2e3,n]),i&&!this._longMonthsParse[n]&&(this._longMonthsParse[n]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[n]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),i||this._monthsParse[n]||(o="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[n]=new RegExp(o.replace(".",""),"i")),i&&"MMMM"===e&&this._longMonthsParse[n].test(t))return n;if(i&&"MMM"===e&&this._shortMonthsParse[n].test(t))return n;if(!i&&this._monthsParse[n].test(t))return n}}function lt(t,e){var i;if(!t.isValid())return t;if("string"==typeof e)if(/^\d+$/.test(e))e=y(e);else if(e=t.localeData().monthsParse(e),"number"!=typeof e)return t;return i=Math.min(t.date(),nt(t.year(),e)),t._d["set"+(t._isUTC?"UTC":"")+"Month"](e,i),t}function ht(t){return null!=t?(lt(this,t),i.updateOffset(this,!0),this):H(this,"Month")}function dt(){
+return nt(this.year(),this.month())}function ut(t){return this._monthsParseExact?(s(this,"_monthsRegex")||ft.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex}function ct(t){return this._monthsParseExact?(s(this,"_monthsRegex")||ft.call(this),t?this._monthsStrictRegex:this._monthsRegex):this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex}function ft(){function t(t,e){return e.length-t.length}var e,i,n=[],a=[],o=[];for(e=0;12>e;e++)i=h([2e3,e]),n.push(this.monthsShort(i,"")),a.push(this.months(i,"")),o.push(this.months(i,"")),o.push(this.monthsShort(i,""));for(n.sort(t),a.sort(t),o.sort(t),e=0;12>e;e++)n[e]=K(n[e]),a[e]=K(a[e]),o[e]=K(o[e]);this._monthsRegex=new RegExp("^("+o.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+n.join("|")+")","i")}function gt(t){var e,i=t._a;return i&&-2===u(t).overflow&&(e=i[Nn]<0||i[Nn]>11?Nn:i[En]<1||i[En]>nt(i[Hn],i[Nn])?En:i[Un]<0||i[Un]>24||24===i[Un]&&(0!==i[jn]||0!==i[Gn]||0!==i[qn])?Un:i[jn]<0||i[jn]>59?jn:i[Gn]<0||i[Gn]>59?Gn:i[qn]<0||i[qn]>999?qn:-1,u(t)._overflowDayOfYear&&(Hn>e||e>En)&&(e=En),u(t)._overflowWeeks&&-1===e&&(e=Zn),u(t)._overflowWeekday&&-1===e&&(e=Jn),u(t).overflow=e),t}function mt(t){var e,i,n,a,o,r,s=t._i,l=ea.exec(s)||ia.exec(s);if(l){for(u(t).iso=!0,e=0,i=aa.length;i>e;e++)if(aa[e][1].exec(l[1])){a=aa[e][0],n=aa[e][2]!==!1;break}if(null==a)return void(t._isValid=!1);if(l[3]){for(e=0,i=oa.length;i>e;e++)if(oa[e][1].exec(l[3])){o=(l[2]||" ")+oa[e][0];break}if(null==o)return void(t._isValid=!1)}if(!n&&null!=o)return void(t._isValid=!1);if(l[4]){if(!na.exec(l[4]))return void(t._isValid=!1);r="Z"}t._f=a+(o||"")+(r||""),At(t)}else t._isValid=!1}function pt(t){var e=ra.exec(t._i);return null!==e?void(t._d=new Date(+e[1])):(mt(t),void(t._isValid===!1&&(delete t._isValid,i.createFromInputFallback(t))))}function bt(t,e,i,n,a,o,r){var s=new Date(t,e,i,n,a,o,r);return 100>t&&t>=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function vt(t){var e=new Date(Date.UTC.apply(null,arguments));return 100>t&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function yt(t){return xt(t)?366:365}function xt(t){return t%4===0&&t%100!==0||t%400===0}function kt(){return xt(this.year())}function _t(t,e,i){var n=7+e-i,a=(7+vt(t,0,n).getUTCDay()-e)%7;return-a+n-1}function St(t,e,i,n,a){var o,r,s=(7+i-n)%7,l=_t(t,n,a),h=1+7*(e-1)+s+l;return 0>=h?(o=t-1,r=yt(o)+h):h>yt(t)?(o=t+1,r=h-yt(t)):(o=t,r=h),{year:o,dayOfYear:r}}function wt(t,e,i){var n,a,o=_t(t.year(),e,i),r=Math.floor((t.dayOfYear()-o-1)/7)+1;return 1>r?(a=t.year()-1,n=r+Mt(a,e,i)):r>Mt(t.year(),e,i)?(n=r-Mt(t.year(),e,i),a=t.year()+1):(a=t.year(),n=r),{week:n,year:a}}function Mt(t,e,i){var n=_t(t,e,i),a=_t(t+1,e,i);return(yt(t)-n+a)/7}function Ct(t,e,i){return null!=t?t:null!=e?e:i}function Dt(t){var e=new Date(i.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Tt(t){var e,i,n,a,o=[];if(!t._d){for(n=Dt(t),t._w&&null==t._a[En]&&null==t._a[Nn]&&Pt(t),t._dayOfYear&&(a=Ct(t._a[Hn],n[Hn]),t._dayOfYear>yt(a)&&(u(t)._overflowDayOfYear=!0),i=vt(a,0,t._dayOfYear),t._a[Nn]=i.getUTCMonth(),t._a[En]=i.getUTCDate()),e=0;3>e&&null==t._a[e];++e)t._a[e]=o[e]=n[e];for(;7>e;e++)t._a[e]=o[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[Un]&&0===t._a[jn]&&0===t._a[Gn]&&0===t._a[qn]&&(t._nextDay=!0,t._a[Un]=0),t._d=(t._useUTC?vt:bt).apply(null,o),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[Un]=24)}}function Pt(t){var e,i,n,a,o,r,s,l;e=t._w,null!=e.GG||null!=e.W||null!=e.E?(o=1,r=4,i=Ct(e.GG,t._a[Hn],wt(Bt(),1,4).year),n=Ct(e.W,1),a=Ct(e.E,1),(1>a||a>7)&&(l=!0)):(o=t._locale._week.dow,r=t._locale._week.doy,i=Ct(e.gg,t._a[Hn],wt(Bt(),o,r).year),n=Ct(e.w,1),null!=e.d?(a=e.d,(0>a||a>6)&&(l=!0)):null!=e.e?(a=e.e+o,(e.e<0||e.e>6)&&(l=!0)):a=o),1>n||n>Mt(i,o,r)?u(t)._overflowWeeks=!0:null!=l?u(t)._overflowWeekday=!0:(s=St(i,n,a,o,r),t._a[Hn]=s.year,t._dayOfYear=s.dayOfYear)}function At(t){if(t._f===i.ISO_8601)return void mt(t);t._a=[],u(t).empty=!0;var e,n,a,o,r,s=""+t._i,l=s.length,h=0;for(a=J(t._f,t._locale).match(vn)||[],e=0;e<a.length;e++)o=a[e],n=(s.match(Q(o,t))||[])[0],n&&(r=s.substr(0,s.indexOf(n)),r.length>0&&u(t).unusedInput.push(r),s=s.slice(s.indexOf(n)+n.length),h+=n.length),kn[o]?(n?u(t).empty=!1:u(t).unusedTokens.push(o),it(o,n,t)):t._strict&&!n&&u(t).unusedTokens.push(o);u(t).charsLeftOver=l-h,s.length>0&&u(t).unusedInput.push(s),u(t).bigHour===!0&&t._a[Un]<=12&&t._a[Un]>0&&(u(t).bigHour=void 0),u(t).parsedDateParts=t._a.slice(0),u(t).meridiem=t._meridiem,t._a[Un]=Ft(t._locale,t._a[Un],t._meridiem),Tt(t),gt(t)}function Ft(t,e,i){var n;return null==i?e:null!=t.meridiemHour?t.meridiemHour(e,i):null!=t.isPM?(n=t.isPM(i),n&&12>e&&(e+=12),n||12!==e||(e=0),e):e}function It(t){var e,i,n,a,o;if(0===t._f.length)return u(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;a<t._f.length;a++)o=0,e=m({},t),null!=t._useUTC&&(e._useUTC=t._useUTC),e._f=t._f[a],At(e),c(e)&&(o+=u(e).charsLeftOver,o+=10*u(e).unusedTokens.length,u(e).score=o,(null==n||n>o)&&(n=o,i=e));l(t,i||e)}function Ot(t){if(!t._d){var e=z(t._i);t._a=r([e.year,e.month,e.day||e.date,e.hour,e.minute,e.second,e.millisecond],function(t){return t&&parseInt(t,10)}),Tt(t)}}function Rt(t){var e=new p(gt(Wt(t)));return e._nextDay&&(e.add(1,"d"),e._nextDay=void 0),e}function Wt(t){var e=t._i,i=t._f;return t._locale=t._locale||W(t._l),null===e||void 0===i&&""===e?f({nullInput:!0}):("string"==typeof e&&(t._i=e=t._locale.preparse(e)),b(e)?new p(gt(e)):(a(i)?It(t):i?At(t):o(e)?t._d=e:Vt(t),c(t)||(t._d=null),t))}function Vt(t){var e=t._i;void 0===e?t._d=new Date(i.now()):o(e)?t._d=new Date(e.valueOf()):"string"==typeof e?pt(t):a(e)?(t._a=r(e.slice(0),function(t){return parseInt(t,10)}),Tt(t)):"object"==typeof e?Ot(t):"number"==typeof e?t._d=new Date(e):i.createFromInputFallback(t)}function Lt(t,e,i,n,a){var o={};return"boolean"==typeof i&&(n=i,i=void 0),o._isAMomentObject=!0,o._useUTC=o._isUTC=a,o._l=i,o._i=t,o._f=e,o._strict=n,Rt(o)}function Bt(t,e,i,n){return Lt(t,e,i,n,!1)}function zt(t,e){var i,n;if(1===e.length&&a(e[0])&&(e=e[0]),!e.length)return Bt();for(i=e[0],n=1;n<e.length;++n)(!e[n].isValid()||e[n][t](i))&&(i=e[n]);return i}function Yt(){var t=[].slice.call(arguments,0);return zt("isBefore",t)}function Ht(){var t=[].slice.call(arguments,0);return zt("isAfter",t)}function Nt(t){var e=z(t),i=e.year||0,n=e.quarter||0,a=e.month||0,o=e.week||0,r=e.day||0,s=e.hour||0,l=e.minute||0,h=e.second||0,d=e.millisecond||0;this._milliseconds=+d+1e3*h+6e4*l+1e3*s*60*60,this._days=+r+7*o,this._months=+a+3*n+12*i,this._data={},this._locale=W(),this._bubble()}function Et(t){return t instanceof Nt}function Ut(t,e){j(t,0,0,function(){var t=this.utcOffset(),i="+";return 0>t&&(t=-t,i="-"),i+U(~~(t/60),2)+e+U(~~t%60,2)})}function jt(t,e){var i=(e||"").match(t)||[],n=i[i.length-1]||[],a=(n+"").match(ua)||["-",0,0],o=+(60*a[1])+y(a[2]);return"+"===a[0]?o:-o}function Gt(t,e){var n,a;return e._isUTC?(n=e.clone(),a=(b(t)||o(t)?t.valueOf():Bt(t).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+a),i.updateOffset(n,!1),n):Bt(t).local()}function qt(t){return 15*-Math.round(t._d.getTimezoneOffset()/15)}function Zt(t,e){var n,a=this._offset||0;return this.isValid()?null!=t?("string"==typeof t?t=jt(Vn,t):Math.abs(t)<16&&(t=60*t),!this._isUTC&&e&&(n=qt(this)),this._offset=t,this._isUTC=!0,null!=n&&this.add(n,"m"),a!==t&&(!e||this._changeInProgress?ue(this,oe(t-a,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,i.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?a:qt(this):null!=t?this:NaN}function Jt(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}function Xt(t){return this.utcOffset(0,t)}function Qt(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(qt(this),"m")),this}function $t(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(jt(Wn,this._i)),this}function Kt(t){return this.isValid()?(t=t?Bt(t).utcOffset():0,(this.utcOffset()-t)%60===0):!1}function te(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function ee(){if(!g(this._isDSTShifted))return this._isDSTShifted;var t={};if(m(t,this),t=Wt(t),t._a){var e=t._isUTC?h(t._a):Bt(t._a);this._isDSTShifted=this.isValid()&&x(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function ie(){return this.isValid()?!this._isUTC:!1}function ne(){return this.isValid()?this._isUTC:!1}function ae(){return this.isValid()?this._isUTC&&0===this._offset:!1}function oe(t,e){var i,n,a,o=t,r=null;return Et(t)?o={ms:t._milliseconds,d:t._days,M:t._months}:"number"==typeof t?(o={},e?o[e]=t:o.milliseconds=t):(r=ca.exec(t))?(i="-"===r[1]?-1:1,o={y:0,d:y(r[En])*i,h:y(r[Un])*i,m:y(r[jn])*i,s:y(r[Gn])*i,ms:y(r[qn])*i}):(r=fa.exec(t))?(i="-"===r[1]?-1:1,o={y:re(r[2],i),M:re(r[3],i),w:re(r[4],i),d:re(r[5],i),h:re(r[6],i),m:re(r[7],i),s:re(r[8],i)}):null==o?o={}:"object"==typeof o&&("from"in o||"to"in o)&&(a=le(Bt(o.from),Bt(o.to)),o={},o.ms=a.milliseconds,o.M=a.months),n=new Nt(o),Et(t)&&s(t,"_locale")&&(n._locale=t._locale),n}function re(t,e){var i=t&&parseFloat(t.replace(",","."));return(isNaN(i)?0:i)*e}function se(t,e){var i={milliseconds:0,months:0};return i.months=e.month()-t.month()+12*(e.year()-t.year()),t.clone().add(i.months,"M").isAfter(e)&&--i.months,i.milliseconds=+e-+t.clone().add(i.months,"M"),i}function le(t,e){var i;return t.isValid()&&e.isValid()?(e=Gt(e,t),t.isBefore(e)?i=se(t,e):(i=se(e,t),i.milliseconds=-i.milliseconds,i.months=-i.months),i):{milliseconds:0,months:0}}function he(t){return 0>t?-1*Math.round(-1*t):Math.round(t)}function de(t,e){return function(i,n){var a,o;return null===n||isNaN(+n)||(S(e,"moment()."+e+"(period, number) is deprecated. Please use moment()."+e+"(number, period)."),o=i,i=n,n=o),i="string"==typeof i?+i:i,a=oe(i,n),ue(this,a,t),this}}function ue(t,e,n,a){var o=e._milliseconds,r=he(e._days),s=he(e._months);t.isValid()&&(a=null==a?!0:a,o&&t._d.setTime(t._d.valueOf()+o*n),r&&N(t,"Date",H(t,"Date")+r*n),s&<(t,H(t,"Month")+s*n),a&&i.updateOffset(t,r||s))}function ce(t,e){var i=t||Bt(),n=Gt(i,this).startOf("day"),a=this.diff(n,"days",!0),o=-6>a?"sameElse":-1>a?"lastWeek":0>a?"lastDay":1>a?"sameDay":2>a?"nextDay":7>a?"nextWeek":"sameElse",r=e&&(w(e[o])?e[o]():e[o]);return this.format(r||this.localeData().calendar(o,this,Bt(i)))}function fe(){return new p(this)}function ge(t,e){var i=b(t)?t:Bt(t);return this.isValid()&&i.isValid()?(e=B(g(e)?"millisecond":e),"millisecond"===e?this.valueOf()>i.valueOf():i.valueOf()<this.clone().startOf(e).valueOf()):!1}function me(t,e){var i=b(t)?t:Bt(t);return this.isValid()&&i.isValid()?(e=B(g(e)?"millisecond":e),"millisecond"===e?this.valueOf()<i.valueOf():this.clone().endOf(e).valueOf()<i.valueOf()):!1}function pe(t,e,i,n){return n=n||"()",("("===n[0]?this.isAfter(t,i):!this.isBefore(t,i))&&(")"===n[1]?this.isBefore(e,i):!this.isAfter(e,i))}function be(t,e){var i,n=b(t)?t:Bt(t);return this.isValid()&&n.isValid()?(e=B(e||"millisecond"),"millisecond"===e?this.valueOf()===n.valueOf():(i=n.valueOf(),this.clone().startOf(e).valueOf()<=i&&i<=this.clone().endOf(e).valueOf())):!1}function ve(t,e){return this.isSame(t,e)||this.isAfter(t,e)}function ye(t,e){return this.isSame(t,e)||this.isBefore(t,e)}function xe(t,e,i){var n,a,o,r;return this.isValid()?(n=Gt(t,this),n.isValid()?(a=6e4*(n.utcOffset()-this.utcOffset()),e=B(e),"year"===e||"month"===e||"quarter"===e?(r=ke(this,n),"quarter"===e?r/=3:"year"===e&&(r/=12)):(o=this-n,r="second"===e?o/1e3:"minute"===e?o/6e4:"hour"===e?o/36e5:"day"===e?(o-a)/864e5:"week"===e?(o-a)/6048e5:o),i?r:v(r)):NaN):NaN}function ke(t,e){var i,n,a=12*(e.year()-t.year())+(e.month()-t.month()),o=t.clone().add(a,"months");return 0>e-o?(i=t.clone().add(a-1,"months"),n=(e-o)/(o-i)):(i=t.clone().add(a+1,"months"),n=(e-o)/(i-o)),-(a+n)||0}function _e(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function Se(){var t=this.clone().utc();return 0<t.year()&&t.year()<=9999?w(Date.prototype.toISOString)?this.toDate().toISOString():Z(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):Z(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function we(t){t||(t=this.isUtc()?i.defaultFormatUtc:i.defaultFormat);var e=Z(this,t);return this.localeData().postformat(e)}function Me(t,e){return this.isValid()&&(b(t)&&t.isValid()||Bt(t).isValid())?oe({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function Ce(t){return this.from(Bt(),t)}function De(t,e){return this.isValid()&&(b(t)&&t.isValid()||Bt(t).isValid())?oe({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()}function Te(t){return this.to(Bt(),t)}function Pe(t){var e;return void 0===t?this._locale._abbr:(e=W(t),null!=e&&(this._locale=e),this)}function Ae(){return this._locale}function Fe(t){switch(t=B(t)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":case"date":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===t&&this.weekday(0),"isoWeek"===t&&this.isoWeekday(1),"quarter"===t&&this.month(3*Math.floor(this.month()/3)),this}function Ie(t){return t=B(t),void 0===t||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))}function Oe(){return this._d.valueOf()-6e4*(this._offset||0)}function Re(){return Math.floor(this.valueOf()/1e3)}function We(){return this._offset?new Date(this.valueOf()):this._d}function Ve(){var t=this;return[t.year(),t.month(),t.date(),t.hour(),t.minute(),t.second(),t.millisecond()]}function Le(){var t=this;return{years:t.year(),months:t.month(),date:t.date(),hours:t.hours(),minutes:t.minutes(),seconds:t.seconds(),milliseconds:t.milliseconds()}}function Be(){return this.isValid()?this.toISOString():null}function ze(){return c(this)}function Ye(){return l({},u(this))}function He(){return u(this).overflow}function Ne(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Ee(t,e){j(0,[t,t.length],0,e)}function Ue(t){return Ze.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function je(t){return Ze.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)}function Ge(){return Mt(this.year(),1,4)}function qe(){var t=this.localeData()._week;return Mt(this.year(),t.dow,t.doy)}function Ze(t,e,i,n,a){var o;return null==t?wt(this,n,a).year:(o=Mt(t,n,a),e>o&&(e=o),Je.call(this,t,e,i,n,a))}function Je(t,e,i,n,a){var o=St(t,e,i,n,a),r=vt(o.year,0,o.dayOfYear);return this.year(r.getUTCFullYear()),this.month(r.getUTCMonth()),this.date(r.getUTCDate()),this}function Xe(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)}function Qe(t){return wt(t,this._week.dow,this._week.doy).week}function $e(){return this._week.dow}function Ke(){return this._week.doy}function ti(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")}function ei(t){var e=wt(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")}function ii(t,e){return"string"!=typeof t?t:isNaN(t)?(t=e.weekdaysParse(t),"number"==typeof t?t:null):parseInt(t,10)}function ni(t,e){return a(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]}function ai(t){return this._weekdaysShort[t.day()]}function oi(t){return this._weekdaysMin[t.day()]}function ri(t,e,i){var n,a,o,r=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],n=0;7>n;++n)o=h([2e3,1]).day(n),this._minWeekdaysParse[n]=this.weekdaysMin(o,"").toLocaleLowerCase(),this._shortWeekdaysParse[n]=this.weekdaysShort(o,"").toLocaleLowerCase(),this._weekdaysParse[n]=this.weekdays(o,"").toLocaleLowerCase();return i?"dddd"===e?(a=mn.call(this._weekdaysParse,r),-1!==a?a:null):"ddd"===e?(a=mn.call(this._shortWeekdaysParse,r),-1!==a?a:null):(a=mn.call(this._minWeekdaysParse,r),-1!==a?a:null):"dddd"===e?(a=mn.call(this._weekdaysParse,r),-1!==a?a:(a=mn.call(this._shortWeekdaysParse,r),-1!==a?a:(a=mn.call(this._minWeekdaysParse,r),-1!==a?a:null))):"ddd"===e?(a=mn.call(this._shortWeekdaysParse,r),-1!==a?a:(a=mn.call(this._weekdaysParse,r),-1!==a?a:(a=mn.call(this._minWeekdaysParse,r),-1!==a?a:null))):(a=mn.call(this._minWeekdaysParse,r),-1!==a?a:(a=mn.call(this._weekdaysParse,r),-1!==a?a:(a=mn.call(this._shortWeekdaysParse,r),-1!==a?a:null)))}function si(t,e,i){var n,a,o;if(this._weekdaysParseExact)return ri.call(this,t,e,i);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),n=0;7>n;n++){if(a=h([2e3,1]).day(n),i&&!this._fullWeekdaysParse[n]&&(this._fullWeekdaysParse[n]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[n]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[n]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[n]||(o="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[n]=new RegExp(o.replace(".",""),"i")),i&&"dddd"===e&&this._fullWeekdaysParse[n].test(t))return n;if(i&&"ddd"===e&&this._shortWeekdaysParse[n].test(t))return n;if(i&&"dd"===e&&this._minWeekdaysParse[n].test(t))return n;if(!i&&this._weekdaysParse[n].test(t))return n}}function li(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ii(t,this.localeData()),this.add(t-e,"d")):e}function hi(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")}function di(t){return this.isValid()?null==t?this.day()||7:this.day(this.day()%7?t:t-7):null!=t?this:NaN}function ui(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||gi.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex}function ci(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||gi.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex}function fi(t){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||gi.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex}function gi(){function t(t,e){return e.length-t.length}var e,i,n,a,o,r=[],s=[],l=[],d=[];for(e=0;7>e;e++)i=h([2e3,1]).day(e),n=this.weekdaysMin(i,""),a=this.weekdaysShort(i,""),o=this.weekdays(i,""),r.push(n),s.push(a),l.push(o),d.push(n),d.push(a),d.push(o);for(r.sort(t),s.sort(t),l.sort(t),d.sort(t),e=0;7>e;e++)s[e]=K(s[e]),l[e]=K(l[e]),d[e]=K(d[e]);this._weekdaysRegex=new RegExp("^("+d.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+r.join("|")+")","i")}function mi(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")}function pi(){return this.hours()%12||12}function bi(){return this.hours()||24}function vi(t,e){j(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function yi(t,e){return e._meridiemParse}function xi(t){return"p"===(t+"").toLowerCase().charAt(0)}function ki(t,e,i){return t>11?i?"pm":"PM":i?"am":"AM"}function _i(t,e){e[qn]=y(1e3*("0."+t))}function Si(){return this._isUTC?"UTC":""}function wi(){return this._isUTC?"Coordinated Universal Time":""}function Mi(t){return Bt(1e3*t)}function Ci(){return Bt.apply(null,arguments).parseZone()}function Di(t,e,i){var n=this._calendar[t];return w(n)?n.call(e,i):n}function Ti(t){var e=this._longDateFormat[t],i=this._longDateFormat[t.toUpperCase()];return e||!i?e:(this._longDateFormat[t]=i.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])}function Pi(){return this._invalidDate}function Ai(t){return this._ordinal.replace("%d",t)}function Fi(t){return t}function Ii(t,e,i,n){var a=this._relativeTime[i];return w(a)?a(t,e,i,n):a.replace(/%d/i,t)}function Oi(t,e){var i=this._relativeTime[t>0?"future":"past"];return w(i)?i(e):i.replace(/%s/i,e)}function Ri(t,e,i,n){var a=W(),o=h().set(n,e);return a[i](o,t)}function Wi(t,e,i){if("number"==typeof t&&(e=t,t=void 0),t=t||"",null!=e)return Ri(t,e,i,"month");var n,a=[];for(n=0;12>n;n++)a[n]=Ri(t,n,i,"month");return a}function Vi(t,e,i,n){"boolean"==typeof t?("number"==typeof e&&(i=e,e=void 0),e=e||""):(e=t,i=e,t=!1,"number"==typeof e&&(i=e,e=void 0),e=e||"");var a=W(),o=t?a._week.dow:0;if(null!=i)return Ri(e,(i+o)%7,n,"day");var r,s=[];for(r=0;7>r;r++)s[r]=Ri(e,(r+o)%7,n,"day");return s}function Li(t,e){return Wi(t,e,"months")}function Bi(t,e){return Wi(t,e,"monthsShort")}function zi(t,e,i){return Vi(t,e,i,"weekdays")}function Yi(t,e,i){return Vi(t,e,i,"weekdaysShort")}function Hi(t,e,i){return Vi(t,e,i,"weekdaysMin")}function Ni(){var t=this._data;return this._milliseconds=Ya(this._milliseconds),this._days=Ya(this._days),this._months=Ya(this._months),t.milliseconds=Ya(t.milliseconds),t.seconds=Ya(t.seconds),t.minutes=Ya(t.minutes),t.hours=Ya(t.hours),t.months=Ya(t.months),t.years=Ya(t.years),this}function Ei(t,e,i,n){var a=oe(e,i);return t._milliseconds+=n*a._milliseconds,t._days+=n*a._days,t._months+=n*a._months,t._bubble()}function Ui(t,e){return Ei(this,t,e,1)}function ji(t,e){return Ei(this,t,e,-1)}function Gi(t){return 0>t?Math.floor(t):Math.ceil(t)}function qi(){var t,e,i,n,a,o=this._milliseconds,r=this._days,s=this._months,l=this._data;return o>=0&&r>=0&&s>=0||0>=o&&0>=r&&0>=s||(o+=864e5*Gi(Ji(s)+r),r=0,s=0),l.milliseconds=o%1e3,t=v(o/1e3),l.seconds=t%60,e=v(t/60),l.minutes=e%60,i=v(e/60),l.hours=i%24,r+=v(i/24),a=v(Zi(r)),s+=a,r-=Gi(Ji(a)),n=v(s/12),s%=12,l.days=r,l.months=s,l.years=n,this}function Zi(t){return 4800*t/146097}function Ji(t){return 146097*t/4800}function Xi(t){var e,i,n=this._milliseconds;if(t=B(t),"month"===t||"year"===t)return e=this._days+n/864e5,i=this._months+Zi(e),"month"===t?i:i/12;switch(e=this._days+Math.round(Ji(this._months)),t){case"week":return e/7+n/6048e5;case"day":return e+n/864e5;case"hour":return 24*e+n/36e5;case"minute":return 1440*e+n/6e4;case"second":return 86400*e+n/1e3;case"millisecond":return Math.floor(864e5*e)+n;default:throw new Error("Unknown unit "+t)}}function Qi(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*y(this._months/12)}function $i(t){return function(){return this.as(t)}}function Ki(t){return t=B(t),this[t+"s"]()}function tn(t){return function(){return this._data[t]}}function en(){return v(this.days()/7)}function nn(t,e,i,n,a){return a.relativeTime(e||1,!!i,t,n)}function an(t,e,i){var n=oe(t).abs(),a=io(n.as("s")),o=io(n.as("m")),r=io(n.as("h")),s=io(n.as("d")),l=io(n.as("M")),h=io(n.as("y")),d=a<no.s&&["s",a]||1>=o&&["m"]||o<no.m&&["mm",o]||1>=r&&["h"]||r<no.h&&["hh",r]||1>=s&&["d"]||s<no.d&&["dd",s]||1>=l&&["M"]||l<no.M&&["MM",l]||1>=h&&["y"]||["yy",h];return d[2]=e,d[3]=+t>0,d[4]=i,nn.apply(null,d)}function on(t,e){return void 0===no[t]?!1:void 0===e?no[t]:(no[t]=e,!0)}function rn(t){var e=this.localeData(),i=an(this,!t,e);return t&&(i=e.pastFuture(+this,i)),e.postformat(i)}function sn(){var t,e,i,n=ao(this._milliseconds)/1e3,a=ao(this._days),o=ao(this._months);t=v(n/60),e=v(t/60),n%=60,t%=60,i=v(o/12),o%=12;var r=i,s=o,l=a,h=e,d=t,u=n,c=this.asSeconds();return c?(0>c?"-":"")+"P"+(r?r+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(h||d||u?"T":"")+(h?h+"H":"")+(d?d+"M":"")+(u?u+"S":""):"P0D"}var ln,hn;hn=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),i=e.length>>>0,n=0;i>n;n++)if(n in e&&t.call(this,e[n],n,e))return!0;return!1};var dn=i.momentProperties=[],un=!1,cn={};i.suppressDeprecationWarnings=!1,i.deprecationHandler=null;var fn;fn=Object.keys?Object.keys:function(t){var e,i=[];for(e in t)s(t,e)&&i.push(e);return i};var gn,mn,pn={},bn={},vn=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,yn=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,xn={},kn={},_n=/\d/,Sn=/\d\d/,wn=/\d{3}/,Mn=/\d{4}/,Cn=/[+-]?\d{6}/,Dn=/\d\d?/,Tn=/\d\d\d\d?/,Pn=/\d\d\d\d\d\d?/,An=/\d{1,3}/,Fn=/\d{1,4}/,In=/[+-]?\d{1,6}/,On=/\d+/,Rn=/[+-]?\d+/,Wn=/Z|[+-]\d\d:?\d\d/gi,Vn=/Z|[+-]\d\d(?::?\d\d)?/gi,Ln=/[+-]?\d+(\.\d{1,3})?/,Bn=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,zn={},Yn={},Hn=0,Nn=1,En=2,Un=3,jn=4,Gn=5,qn=6,Zn=7,Jn=8;mn=Array.prototype.indexOf?Array.prototype.indexOf:function(t){var e;for(e=0;e<this.length;++e)if(this[e]===t)return e;return-1},j("M",["MM",2],"Mo",function(){return this.month()+1}),j("MMM",0,0,function(t){return this.localeData().monthsShort(this,t)}),j("MMMM",0,0,function(t){return this.localeData().months(this,t)}),L("month","M"),X("M",Dn),X("MM",Dn,Sn),X("MMM",function(t,e){return e.monthsShortRegex(t)}),X("MMMM",function(t,e){return e.monthsRegex(t)}),tt(["M","MM"],function(t,e){e[Nn]=y(t)-1}),tt(["MMM","MMMM"],function(t,e,i,n){var a=i._locale.monthsParse(t,n,i._strict);null!=a?e[Nn]=a:u(i).invalidMonth=t});var Xn=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,Qn="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),$n="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),Kn=Bn,ta=Bn,ea=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ia=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,na=/Z|[+-]\d\d(?::?\d\d)?/,aa=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],oa=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],ra=/^\/?Date\((\-?\d+)/i;i.createFromInputFallback=_("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),j("Y",0,0,function(){var t=this.year();return 9999>=t?""+t:"+"+t}),j(0,["YY",2],0,function(){return this.year()%100}),j(0,["YYYY",4],0,"year"),j(0,["YYYYY",5],0,"year"),j(0,["YYYYYY",6,!0],0,"year"),L("year","y"),X("Y",Rn),X("YY",Dn,Sn),X("YYYY",Fn,Mn),X("YYYYY",In,Cn),X("YYYYYY",In,Cn),tt(["YYYYY","YYYYYY"],Hn),tt("YYYY",function(t,e){e[Hn]=2===t.length?i.parseTwoDigitYear(t):y(t)}),tt("YY",function(t,e){e[Hn]=i.parseTwoDigitYear(t)}),tt("Y",function(t,e){e[Hn]=parseInt(t,10)}),i.parseTwoDigitYear=function(t){return y(t)+(y(t)>68?1900:2e3)};var sa=Y("FullYear",!0);i.ISO_8601=function(){};var la=_("moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var t=Bt.apply(null,arguments);return this.isValid()&&t.isValid()?this>t?this:t:f()}),ha=_("moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var t=Bt.apply(null,arguments);return this.isValid()&&t.isValid()?t>this?this:t:f()}),da=function(){return Date.now?Date.now():+new Date};Ut("Z",":"),Ut("ZZ",""),X("Z",Vn),X("ZZ",Vn),tt(["Z","ZZ"],function(t,e,i){i._useUTC=!0,i._tzm=jt(Vn,t)});var ua=/([\+\-]|\d\d)/gi;i.updateOffset=function(){};var ca=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,fa=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;oe.fn=Nt.prototype;var ga=de(1,"add"),ma=de(-1,"subtract");i.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",i.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var pa=_("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});j(0,["gg",2],0,function(){return this.weekYear()%100}),j(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ee("gggg","weekYear"),Ee("ggggg","weekYear"),Ee("GGGG","isoWeekYear"),Ee("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),X("G",Rn),X("g",Rn),X("GG",Dn,Sn),X("gg",Dn,Sn),X("GGGG",Fn,Mn),X("gggg",Fn,Mn),X("GGGGG",In,Cn),X("ggggg",In,Cn),et(["gggg","ggggg","GGGG","GGGGG"],function(t,e,i,n){e[n.substr(0,2)]=y(t)}),et(["gg","GG"],function(t,e,n,a){e[a]=i.parseTwoDigitYear(t)}),j("Q",0,"Qo","quarter"),L("quarter","Q"),X("Q",_n),tt("Q",function(t,e){e[Nn]=3*(y(t)-1)}),j("w",["ww",2],"wo","week"),j("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),X("w",Dn),X("ww",Dn,Sn),X("W",Dn),X("WW",Dn,Sn),et(["w","ww","W","WW"],function(t,e,i,n){e[n.substr(0,1)]=y(t)});var ba={dow:0,doy:6};j("D",["DD",2],"Do","date"),L("date","D"),X("D",Dn),X("DD",Dn,Sn),X("Do",function(t,e){return t?e._ordinalParse:e._ordinalParseLenient}),tt(["D","DD"],En),tt("Do",function(t,e){e[En]=y(t.match(Dn)[0],10)});var va=Y("Date",!0);j("d",0,"do","day"),j("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),j("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),j("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),j("e",0,0,"weekday"),j("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),X("d",Dn),X("e",Dn),X("E",Dn),X("dd",function(t,e){return e.weekdaysMinRegex(t)}),X("ddd",function(t,e){return e.weekdaysShortRegex(t)}),X("dddd",function(t,e){return e.weekdaysRegex(t)}),et(["dd","ddd","dddd"],function(t,e,i,n){var a=i._locale.weekdaysParse(t,n,i._strict);null!=a?e.d=a:u(i).invalidWeekday=t}),et(["d","e","E"],function(t,e,i,n){e[n]=y(t)});var ya="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),xa="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),ka="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),_a=Bn,Sa=Bn,wa=Bn;j("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),X("DDD",An),X("DDDD",wn),tt(["DDD","DDDD"],function(t,e,i){i._dayOfYear=y(t)}),j("H",["HH",2],0,"hour"),j("h",["hh",2],0,pi),j("k",["kk",2],0,bi),j("hmm",0,0,function(){return""+pi.apply(this)+U(this.minutes(),2)}),j("hmmss",0,0,function(){return""+pi.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),j("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),j("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),vi("a",!0),vi("A",!1),L("hour","h"),X("a",yi),X("A",yi),X("H",Dn),X("h",Dn),X("HH",Dn,Sn),X("hh",Dn,Sn),X("hmm",Tn),X("hmmss",Pn),X("Hmm",Tn),X("Hmmss",Pn),tt(["H","HH"],Un),tt(["a","A"],function(t,e,i){i._isPm=i._locale.isPM(t),i._meridiem=t}),tt(["h","hh"],function(t,e,i){e[Un]=y(t),u(i).bigHour=!0}),tt("hmm",function(t,e,i){var n=t.length-2;e[Un]=y(t.substr(0,n)),e[jn]=y(t.substr(n)),u(i).bigHour=!0}),tt("hmmss",function(t,e,i){var n=t.length-4,a=t.length-2;e[Un]=y(t.substr(0,n)),e[jn]=y(t.substr(n,2)),e[Gn]=y(t.substr(a)),
+u(i).bigHour=!0}),tt("Hmm",function(t,e,i){var n=t.length-2;e[Un]=y(t.substr(0,n)),e[jn]=y(t.substr(n))}),tt("Hmmss",function(t,e,i){var n=t.length-4,a=t.length-2;e[Un]=y(t.substr(0,n)),e[jn]=y(t.substr(n,2)),e[Gn]=y(t.substr(a))});var Ma=/[ap]\.?m?\.?/i,Ca=Y("Hours",!0);j("m",["mm",2],0,"minute"),L("minute","m"),X("m",Dn),X("mm",Dn,Sn),tt(["m","mm"],jn);var Da=Y("Minutes",!1);j("s",["ss",2],0,"second"),L("second","s"),X("s",Dn),X("ss",Dn,Sn),tt(["s","ss"],Gn);var Ta=Y("Seconds",!1);j("S",0,0,function(){return~~(this.millisecond()/100)}),j(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),j(0,["SSS",3],0,"millisecond"),j(0,["SSSS",4],0,function(){return 10*this.millisecond()}),j(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),j(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),j(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),j(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),j(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),L("millisecond","ms"),X("S",An,_n),X("SS",An,Sn),X("SSS",An,wn);var Pa;for(Pa="SSSS";Pa.length<=9;Pa+="S")X(Pa,On);for(Pa="S";Pa.length<=9;Pa+="S")tt(Pa,_i);var Aa=Y("Milliseconds",!1);j("z",0,0,"zoneAbbr"),j("zz",0,0,"zoneName");var Fa=p.prototype;Fa.add=ga,Fa.calendar=ce,Fa.clone=fe,Fa.diff=xe,Fa.endOf=Ie,Fa.format=we,Fa.from=Me,Fa.fromNow=Ce,Fa.to=De,Fa.toNow=Te,Fa.get=E,Fa.invalidAt=He,Fa.isAfter=ge,Fa.isBefore=me,Fa.isBetween=pe,Fa.isSame=be,Fa.isSameOrAfter=ve,Fa.isSameOrBefore=ye,Fa.isValid=ze,Fa.lang=pa,Fa.locale=Pe,Fa.localeData=Ae,Fa.max=ha,Fa.min=la,Fa.parsingFlags=Ye,Fa.set=E,Fa.startOf=Fe,Fa.subtract=ma,Fa.toArray=Ve,Fa.toObject=Le,Fa.toDate=We,Fa.toISOString=Se,Fa.toJSON=Be,Fa.toString=_e,Fa.unix=Re,Fa.valueOf=Oe,Fa.creationData=Ne,Fa.year=sa,Fa.isLeapYear=kt,Fa.weekYear=Ue,Fa.isoWeekYear=je,Fa.quarter=Fa.quarters=Xe,Fa.month=ht,Fa.daysInMonth=dt,Fa.week=Fa.weeks=ti,Fa.isoWeek=Fa.isoWeeks=ei,Fa.weeksInYear=qe,Fa.isoWeeksInYear=Ge,Fa.date=va,Fa.day=Fa.days=li,Fa.weekday=hi,Fa.isoWeekday=di,Fa.dayOfYear=mi,Fa.hour=Fa.hours=Ca,Fa.minute=Fa.minutes=Da,Fa.second=Fa.seconds=Ta,Fa.millisecond=Fa.milliseconds=Aa,Fa.utcOffset=Zt,Fa.utc=Xt,Fa.local=Qt,Fa.parseZone=$t,Fa.hasAlignedHourOffset=Kt,Fa.isDST=te,Fa.isDSTShifted=ee,Fa.isLocal=ie,Fa.isUtcOffset=ne,Fa.isUtc=ae,Fa.isUTC=ae,Fa.zoneAbbr=Si,Fa.zoneName=wi,Fa.dates=_("dates accessor is deprecated. Use date instead.",va),Fa.months=_("months accessor is deprecated. Use month instead",ht),Fa.years=_("years accessor is deprecated. Use year instead",sa),Fa.zone=_("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Jt);var Ia=Fa,Oa={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ra={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Wa="Invalid date",Va="%d",La=/\d{1,2}/,Ba={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},za=T.prototype;za._calendar=Oa,za.calendar=Di,za._longDateFormat=Ra,za.longDateFormat=Ti,za._invalidDate=Wa,za.invalidDate=Pi,za._ordinal=Va,za.ordinal=Ai,za._ordinalParse=La,za.preparse=Fi,za.postformat=Fi,za._relativeTime=Ba,za.relativeTime=Ii,za.pastFuture=Oi,za.set=C,za.months=at,za._months=Qn,za.monthsShort=ot,za._monthsShort=$n,za.monthsParse=st,za._monthsRegex=ta,za.monthsRegex=ct,za._monthsShortRegex=Kn,za.monthsShortRegex=ut,za.week=Qe,za._week=ba,za.firstDayOfYear=Ke,za.firstDayOfWeek=$e,za.weekdays=ni,za._weekdays=ya,za.weekdaysMin=oi,za._weekdaysMin=ka,za.weekdaysShort=ai,za._weekdaysShort=xa,za.weekdaysParse=si,za._weekdaysRegex=_a,za.weekdaysRegex=ui,za._weekdaysShortRegex=Sa,za.weekdaysShortRegex=ci,za._weekdaysMinRegex=wa,za.weekdaysMinRegex=fi,za.isPM=xi,za._meridiemParse=Ma,za.meridiem=ki,I("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10,i=1===y(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th";return t+i}}),i.lang=_("moment.lang is deprecated. Use moment.locale instead.",I),i.langData=_("moment.langData is deprecated. Use moment.localeData instead.",W);var Ya=Math.abs,Ha=$i("ms"),Na=$i("s"),Ea=$i("m"),Ua=$i("h"),ja=$i("d"),Ga=$i("w"),qa=$i("M"),Za=$i("y"),Ja=tn("milliseconds"),Xa=tn("seconds"),Qa=tn("minutes"),$a=tn("hours"),Ka=tn("days"),to=tn("months"),eo=tn("years"),io=Math.round,no={s:45,m:45,h:22,d:26,M:11},ao=Math.abs,oo=Nt.prototype;oo.abs=Ni,oo.add=Ui,oo.subtract=ji,oo.as=Xi,oo.asMilliseconds=Ha,oo.asSeconds=Na,oo.asMinutes=Ea,oo.asHours=Ua,oo.asDays=ja,oo.asWeeks=Ga,oo.asMonths=qa,oo.asYears=Za,oo.valueOf=Qi,oo._bubble=qi,oo.get=Ki,oo.milliseconds=Ja,oo.seconds=Xa,oo.minutes=Qa,oo.hours=$a,oo.days=Ka,oo.weeks=en,oo.months=to,oo.years=eo,oo.humanize=rn,oo.toISOString=sn,oo.toString=sn,oo.toJSON=sn,oo.locale=Pe,oo.localeData=Ae,oo.toIsoString=_("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",sn),oo.lang=pa,j("X",0,0,"unix"),j("x",0,0,"valueOf"),X("x",Rn),X("X",Ln),tt("X",function(t,e,i){i._d=new Date(1e3*parseFloat(t,10))}),tt("x",function(t,e,i){i._d=new Date(y(t))}),i.version="2.13.0",n(Bt),i.fn=Ia,i.min=Yt,i.max=Ht,i.now=da,i.utc=h,i.unix=Mi,i.months=Li,i.isDate=o,i.locale=I,i.invalid=f,i.duration=oe,i.isMoment=b,i.weekdays=zi,i.parseZone=Ci,i.localeData=W,i.isDuration=Et,i.monthsShort=Bi,i.weekdaysMin=Hi,i.defineLocale=O,i.updateLocale=R,i.locales=V,i.weekdaysShort=Yi,i.normalizeUnits=B,i.relativeTimeThreshold=on,i.prototype=Ia;var ro=i;return ro})},{}],7:[function(t,e,i){var n=t("./core/core.js")();t("./core/core.helpers")(n),t("./core/core.element")(n),t("./core/core.animation")(n),t("./core/core.controller")(n),t("./core/core.datasetController")(n),t("./core/core.layoutService")(n),t("./core/core.legend")(n),t("./core/core.plugin.js")(n),t("./core/core.scale")(n),t("./core/core.scaleService")(n),t("./core/core.title")(n),t("./core/core.tooltip")(n),t("./elements/element.arc")(n),t("./elements/element.line")(n),t("./elements/element.point")(n),t("./elements/element.rectangle")(n),t("./scales/scale.category")(n),t("./scales/scale.linear")(n),t("./scales/scale.logarithmic")(n),t("./scales/scale.radialLinear")(n),t("./scales/scale.time")(n),t("./controllers/controller.bar")(n),t("./controllers/controller.bubble")(n),t("./controllers/controller.doughnut")(n),t("./controllers/controller.line")(n),t("./controllers/controller.polarArea")(n),t("./controllers/controller.radar")(n),t("./charts/Chart.Bar")(n),t("./charts/Chart.Bubble")(n),t("./charts/Chart.Doughnut")(n),t("./charts/Chart.Line")(n),t("./charts/Chart.PolarArea")(n),t("./charts/Chart.Radar")(n),t("./charts/Chart.Scatter")(n),window.Chart=e.exports=n},{"./charts/Chart.Bar":8,"./charts/Chart.Bubble":9,"./charts/Chart.Doughnut":10,"./charts/Chart.Line":11,"./charts/Chart.PolarArea":12,"./charts/Chart.Radar":13,"./charts/Chart.Scatter":14,"./controllers/controller.bar":15,"./controllers/controller.bubble":16,"./controllers/controller.doughnut":17,"./controllers/controller.line":18,"./controllers/controller.polarArea":19,"./controllers/controller.radar":20,"./core/core.animation":21,"./core/core.controller":22,"./core/core.datasetController":23,"./core/core.element":24,"./core/core.helpers":25,"./core/core.js":26,"./core/core.layoutService":27,"./core/core.legend":28,"./core/core.plugin.js":29,"./core/core.scale":30,"./core/core.scaleService":31,"./core/core.title":32,"./core/core.tooltip":33,"./elements/element.arc":34,"./elements/element.line":35,"./elements/element.point":36,"./elements/element.rectangle":37,"./scales/scale.category":38,"./scales/scale.linear":39,"./scales/scale.logarithmic":40,"./scales/scale.radialLinear":41,"./scales/scale.time":42}],8:[function(t,e,i){"use strict";e.exports=function(t){t.Bar=function(e,i){return i.type="bar",new t(e,i)}}},{}],9:[function(t,e,i){"use strict";e.exports=function(t){t.Bubble=function(e,i){return i.type="bubble",new t(e,i)}}},{}],10:[function(t,e,i){"use strict";e.exports=function(t){t.Doughnut=function(e,i){return i.type="doughnut",new t(e,i)}}},{}],11:[function(t,e,i){"use strict";e.exports=function(t){t.Line=function(e,i){return i.type="line",new t(e,i)}}},{}],12:[function(t,e,i){"use strict";e.exports=function(t){t.PolarArea=function(e,i){return i.type="polarArea",new t(e,i)}}},{}],13:[function(t,e,i){"use strict";e.exports=function(t){t.Radar=function(e,i){return i.options=t.helpers.configMerge({aspectRatio:1},i.options),i.type="radar",new t(e,i)}}},{}],14:[function(t,e,i){"use strict";e.exports=function(t){var e={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){return"("+t.xLabel+", "+t.yLabel+")"}}}};t.defaults.scatter=e,t.controllers.scatter=t.controllers.line,t.Scatter=function(e,i){return i.type="scatter",new t(e,i)}}},{}],15:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(e,i){t.DatasetController.prototype.initialize.call(this,e,i),this.getMeta().bar=!0},getBarCount:function(){var t=0;return e.each(this.chart.data.datasets,function(e,i){var n=this.chart.getDatasetMeta(i);n.bar&&this.chart.isDatasetVisible(i)&&++t},this),t},update:function(t){e.each(this.getMeta().data,function(e,i){this.updateElement(e,i,t)},this)},updateElement:function(t,i,n){var a=this.getMeta(),o=this.getScaleForId(a.xAxisID),r=this.getScaleForId(a.yAxisID),s=r.getBasePixel(),l=this.chart.options.elements.rectangle,h=t.custom||{},d=this.getDataset();e.extend(t,{_xScale:o,_yScale:r,_datasetIndex:this.index,_index:i,_model:{x:this.calculateBarX(i,this.index),y:n?s:this.calculateBarY(i,this.index),label:this.chart.data.labels[i],datasetLabel:d.label,base:n?s:this.calculateBarBase(this.index,i),width:this.calculateBarWidth(i),backgroundColor:h.backgroundColor?h.backgroundColor:e.getValueAtIndexOrDefault(d.backgroundColor,i,l.backgroundColor),borderSkipped:h.borderSkipped?h.borderSkipped:l.borderSkipped,borderColor:h.borderColor?h.borderColor:e.getValueAtIndexOrDefault(d.borderColor,i,l.borderColor),borderWidth:h.borderWidth?h.borderWidth:e.getValueAtIndexOrDefault(d.borderWidth,i,l.borderWidth)}}),t.pivot()},calculateBarBase:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.yAxisID),a=0;if(n.options.stacked){var o=this.chart,r=o.data.datasets,s=r[t].data[e];if(0>s)for(var l=0;t>l;l++){var h=r[l],d=o.getDatasetMeta(l);d.bar&&d.yAxisID===n.id&&o.isDatasetVisible(l)&&(a+=h.data[e]<0?h.data[e]:0)}else for(var u=0;t>u;u++){var c=r[u],f=o.getDatasetMeta(u);f.bar&&f.yAxisID===n.id&&o.isDatasetVisible(u)&&(a+=c.data[e]>0?c.data[e]:0)}return n.getPixelForValue(a)}return n.getBasePixel()},getRuler:function(t){var e,i=this.getMeta(),n=this.getScaleForId(i.xAxisID),a=this.getBarCount();e="category"===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var o=e*n.options.categoryPercentage,r=(e-e*n.options.categoryPercentage)/2,s=o/a;if(n.ticks.length!==this.chart.data.labels.length){var l=n.ticks.length/this.chart.data.labels.length;s*=l}var h=s*n.options.barPercentage,d=s-s*n.options.barPercentage;return{datasetCount:a,tickWidth:e,categoryWidth:o,categorySpacing:r,fullBarWidth:s,barWidth:h,barSpacing:d}},calculateBarWidth:function(t){var e=this.getScaleForId(this.getMeta().xAxisID),i=this.getRuler(t);return e.options.stacked?i.categoryWidth:i.barWidth},getBarIndex:function(t){var e,i,n=0;for(i=0;t>i;++i)e=this.chart.getDatasetMeta(i),e.bar&&this.chart.isDatasetVisible(i)&&++n;return n},calculateBarX:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.xAxisID),a=this.getBarIndex(e),o=this.getRuler(t),r=n.getPixelForValue(null,t,e,this.chart.isCombo);return r-=this.chart.isCombo?o.tickWidth/2:0,n.options.stacked?r+o.categoryWidth/2+o.categorySpacing:r+o.barWidth/2+o.categorySpacing+o.barWidth*a+o.barSpacing/2+o.barSpacing*a},calculateBarY:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.yAxisID),a=this.getDataset().data[t];if(n.options.stacked){for(var o=0,r=0,s=0;e>s;s++){var l=this.chart.data.datasets[s],h=this.chart.getDatasetMeta(s);h.bar&&h.yAxisID===n.id&&this.chart.isDatasetVisible(s)&&(l.data[t]<0?r+=l.data[t]||0:o+=l.data[t]||0)}return 0>a?n.getPixelForValue(r+a):n.getPixelForValue(o+a)}return n.getPixelForValue(a)},draw:function(t){var i=t||1;e.each(this.getMeta().data,function(t,e){var n=this.getDataset().data[e];null===n||void 0===n||isNaN(n)||t.transition(i).draw()},this)},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=t._model;o.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.hoverBackgroundColor,n,e.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(i.hoverBorderColor,n,e.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(i.hoverBorderWidth,n,o.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=t._model,r=this.chart.options.elements.rectangle;o.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(i.backgroundColor,n,r.backgroundColor),o.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(i.borderColor,n,r.borderColor),o.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(i.borderWidth,n,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var i="";return t.length>0&&(t[0].yLabel?i=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({updateElement:function(t,i,n,a){var o=this.getMeta(),r=this.getScaleForId(o.xAxisID),s=this.getScaleForId(o.yAxisID),l=r.getBasePixel(),h=t.custom||{},d=this.getDataset(),u=this.chart.options.elements.rectangle;e.extend(t,{_xScale:r,_yScale:s,_datasetIndex:this.index,_index:i,_model:{x:n?l:this.calculateBarX(i,this.index),y:this.calculateBarY(i,this.index),label:this.chart.data.labels[i],datasetLabel:d.label,base:n?l:this.calculateBarBase(this.index,i),height:this.calculateBarHeight(i),backgroundColor:h.backgroundColor?h.backgroundColor:e.getValueAtIndexOrDefault(d.backgroundColor,i,u.backgroundColor),borderSkipped:h.borderSkipped?h.borderSkipped:u.borderSkipped,borderColor:h.borderColor?h.borderColor:e.getValueAtIndexOrDefault(d.borderColor,i,u.borderColor),borderWidth:h.borderWidth?h.borderWidth:e.getValueAtIndexOrDefault(d.borderWidth,i,u.borderWidth)},draw:function(){function t(t){return l[(d+t)%4]}var e=this._chart.ctx,i=this._view,n=i.height/2,a=i.y-n,o=i.y+n,r=i.base-(i.base-i.x),s=i.borderWidth/2;i.borderWidth&&(a+=s,o-=s,r+=s),e.beginPath(),e.fillStyle=i.backgroundColor,e.strokeStyle=i.borderColor,e.lineWidth=i.borderWidth;var l=[[i.base,o],[i.base,a],[r,a],[r,o]],h=["bottom","left","top","right"],d=h.indexOf(i.borderSkipped,0);-1===d&&(d=0),e.moveTo.apply(e,t(0));for(var u=1;4>u;u++)e.lineTo.apply(e,t(u));e.fill(),i.borderWidth&&e.stroke()},inRange:function(t,e){var i=this._view,n=!1;return i&&(n=i.x<i.base?e>=i.y-i.height/2&&e<=i.y+i.height/2&&t>=i.x&&t<=i.base:e>=i.y-i.height/2&&e<=i.y+i.height/2&&t>=i.base&&t<=i.x),n}}),t.pivot()},calculateBarBase:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.xAxisID),a=0;if(n.options.stacked){var o=this.chart.data.datasets[t].data[e];if(0>o)for(var r=0;t>r;r++){var s=this.chart.data.datasets[r],l=this.chart.getDatasetMeta(r);l.bar&&l.xAxisID===n.id&&this.chart.isDatasetVisible(r)&&(a+=s.data[e]<0?s.data[e]:0)}else for(var h=0;t>h;h++){var d=this.chart.data.datasets[h],u=this.chart.getDatasetMeta(h);u.bar&&u.xAxisID===n.id&&this.chart.isDatasetVisible(h)&&(a+=d.data[e]>0?d.data[e]:0)}return n.getPixelForValue(a)}return n.getBasePixel()},getRuler:function(t){var e,i=this.getMeta(),n=this.getScaleForId(i.yAxisID),a=this.getBarCount();e="category"===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var o=e*n.options.categoryPercentage,r=(e-e*n.options.categoryPercentage)/2,s=o/a;if(n.ticks.length!==this.chart.data.labels.length){var l=n.ticks.length/this.chart.data.labels.length;s*=l}var h=s*n.options.barPercentage,d=s-s*n.options.barPercentage;return{datasetCount:a,tickHeight:e,categoryHeight:o,categorySpacing:r,fullBarHeight:s,barHeight:h,barSpacing:d}},calculateBarHeight:function(t){var e=this.getScaleForId(this.getMeta().yAxisID),i=this.getRuler(t);return e.options.stacked?i.categoryHeight:i.barHeight},calculateBarX:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.xAxisID),a=this.getDataset().data[t];if(n.options.stacked){for(var o=0,r=0,s=0;e>s;s++){var l=this.chart.data.datasets[s],h=this.chart.getDatasetMeta(s);h.bar&&h.xAxisID===n.id&&this.chart.isDatasetVisible(s)&&(l.data[t]<0?r+=l.data[t]||0:o+=l.data[t]||0)}return 0>a?n.getPixelForValue(r+a):n.getPixelForValue(o+a)}return n.getPixelForValue(a)},calculateBarY:function(t,e){var i=this.getMeta(),n=this.getScaleForId(i.yAxisID),a=this.getBarIndex(e),o=this.getRuler(t),r=n.getPixelForValue(null,t,e,this.chart.isCombo);return r-=this.chart.isCombo?o.tickHeight/2:0,n.options.stacked?r+o.categoryHeight/2+o.categorySpacing:r+o.barHeight/2+o.categorySpacing+o.barHeight*a+o.barSpacing/2+o.barSpacing*a}})}},{}],16:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"",n=e.datasets[t.datasetIndex].data[t.index];return i+": ("+n.x+", "+n.y+", "+n.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var i=this.getMeta(),n=i.data;e.each(n,function(e,i){this.updateElement(e,i,t)},this)},updateElement:function(t,i,n){var a=this.getMeta(),o=this.getScaleForId(a.xAxisID),r=this.getScaleForId(a.yAxisID),s=t.custom||{},l=this.getDataset(),h=l.data[i],d=this.chart.options.elements.point;e.extend(t,{_xScale:o,_yScale:r,_datasetIndex:this.index,_index:i,_model:{x:n?o.getPixelForDecimal(.5):o.getPixelForValue(h,i,this.index,this.chart.isCombo),y:n?r.getBasePixel():r.getPixelForValue(h,i,this.index),radius:n?0:s.radius?s.radius:this.getRadius(h),backgroundColor:s.backgroundColor?s.backgroundColor:e.getValueAtIndexOrDefault(l.backgroundColor,i,d.backgroundColor),borderColor:s.borderColor?s.borderColor:e.getValueAtIndexOrDefault(l.borderColor,i,d.borderColor),borderWidth:s.borderWidth?s.borderWidth:e.getValueAtIndexOrDefault(l.borderWidth,i,d.borderWidth),hitRadius:s.hitRadius?s.hitRadius:e.getValueAtIndexOrDefault(l.hitRadius,i,d.hitRadius)}});var u=t._model;u.skip=s.skip?s.skip:isNaN(u.x)||isNaN(u.y),t.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=t._model;o.radius=a.hoverRadius?a.hoverRadius:e.getValueAtIndexOrDefault(i.hoverRadius,n,this.chart.options.elements.point.hoverRadius)+this.getRadius(this.getDataset().data[t._index]),o.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.hoverBackgroundColor,n,e.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(i.hoverBorderColor,n,e.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(i.hoverBorderWidth,n,o.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=t._model,r=this.chart.options.elements.point;o.radius=a.radius?a.radius:this.getRadius(i.data[t._index]),o.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(i.backgroundColor,n,r.backgroundColor),o.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(i.borderColor,n,r.borderColor),o.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(i.borderWidth,n,r.borderWidth)}})}},{}],17:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults;i.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'"></span>'),a[o]&&e.push(a[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var i=t.data;return i.labels.length&&i.datasets.length?i.labels.map(function(n,a){var o=t.getDatasetMeta(0),r=i.datasets[0],s=o.data[a],l=s.custom||{},h=e.getValueAtIndexOrDefault,d=t.options.elements.arc,u=l.backgroundColor?l.backgroundColor:h(r.backgroundColor,a,d.backgroundColor),c=l.borderColor?l.borderColor:h(r.borderColor,a,d.borderColor),f=l.borderWidth?l.borderWidth:h(r.borderWidth,a,d.borderWidth);return{text:n,fillStyle:u,strokeStyle:c,lineWidth:f,hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;n>i;++i)a=r.getDatasetMeta(i),a.data[o].hidden=!a.data[o].hidden;r.update()}},cutoutPercentage:50,rotation:Math.PI*-.5,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+e.datasets[t.datasetIndex].data[t.index]}}}},i.pie=e.clone(i.doughnut),e.extend(i.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,i=0;t>i;++i)this.chart.isDatasetVisible(i)&&++e;return e},update:function(t){var i=this,n=i.chart,a=n.chartArea,o=n.options,r=o.elements.arc,s=a.right-a.left-r.borderWidth,l=a.bottom-a.top-r.borderWidth,h=Math.min(s,l),d={x:0,y:0},u=i.getMeta(),c=o.cutoutPercentage,f=o.circumference;if(f<2*Math.PI){var g=o.rotation%(2*Math.PI);g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0);var m=g+f,p={x:Math.cos(g),y:Math.sin(g)},b={x:Math.cos(m),y:Math.sin(m)},v=0>=g&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,y=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,k=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,_=c/100,S={x:x?-1:Math.min(p.x*(p.x<0?1:_),b.x*(b.x<0?1:_)),y:k?-1:Math.min(p.y*(p.y<0?1:_),b.y*(b.y<0?1:_))},w={x:v?1:Math.max(p.x*(p.x>0?1:_),b.x*(b.x>0?1:_)),y:y?1:Math.max(p.y*(p.y>0?1:_),b.y*(b.y>0?1:_))},M={width:.5*(w.x-S.x),height:.5*(w.y-S.y)};h=Math.min(s/M.width,l/M.height),d={x:(w.x+S.x)*-.5,y:(w.y+S.y)*-.5}}n.outerRadius=Math.max(h/2,0),n.innerRadius=Math.max(c?n.outerRadius/100*c:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,u.total=i.calculateTotal(),i.outerRadius=n.outerRadius-n.radiusLength*i.getRingIndex(i.index),i.innerRadius=i.outerRadius-n.radiusLength,e.each(u.data,function(e,n){i.updateElement(e,n,t)})},updateElement:function(t,i,n){var a=this,o=a.chart,r=o.chartArea,s=o.options,l=s.animation,h=s.elements.arc,d=(r.left+r.right)/2,u=(r.top+r.bottom)/2,c=s.rotation,f=s.rotation,g=a.getDataset(),m=n&&l.animateRotate?0:t.hidden?0:a.calculateCircumference(g.data[i])*(s.circumference/(2*Math.PI)),p=n&&l.animateScale?0:a.innerRadius,b=n&&l.animateScale?0:a.outerRadius,v=t.custom||{},y=e.getValueAtIndexOrDefault;e.extend(t,{_datasetIndex:a.index,_index:i,_model:{x:d+o.offsetX,y:u+o.offsetY,startAngle:c,endAngle:f,circumference:m,outerRadius:b,innerRadius:p,label:y(g.label,i,o.data.labels[i])}});var x=t._model;x.backgroundColor=v.backgroundColor?v.backgroundColor:y(g.backgroundColor,i,h.backgroundColor),x.hoverBackgroundColor=v.hoverBackgroundColor?v.hoverBackgroundColor:y(g.hoverBackgroundColor,i,h.hoverBackgroundColor),x.borderWidth=v.borderWidth?v.borderWidth:y(g.borderWidth,i,h.borderWidth),x.borderColor=v.borderColor?v.borderColor:y(g.borderColor,i,h.borderColor),n&&l.animateRotate||(0===i?x.startAngle=s.rotation:x.startAngle=a.getMeta().data[i-1]._model.endAngle,x.endAngle=x.startAngle+x.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,i=this.getDataset(),n=this.getMeta(),a=0;return e.each(n.data,function(e,n){t=i.data[n],isNaN(t)||e.hidden||(a+=Math.abs(t))}),a},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0}})}},{}],18:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.line={showLines:!0,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,addElementAndReset:function(e){var i=this,n=i.chart.options;t.DatasetController.prototype.addElementAndReset.call(i,e),n.showLines&&0!==n.elements.line.tension&&i.updateBezierControlPoints()},update:function(t){var i,n,a,o,r=this,s=r.getMeta(),l=s.dataset,h=s.data||[],d=r.chart.options,u=d.elements.line,c=r.getScaleForId(s.yAxisID);for(d.showLines&&(a=r.getDataset(),o=l.custom||{},void 0!==a.tension&&void 0===a.lineTension&&(a.lineTension=a.tension),l._scale=c,l._datasetIndex=r.index,l._children=h,l._model={tension:o.tension?o.tension:e.getValueOrDefault(a.lineTension,u.tension),backgroundColor:o.backgroundColor?o.backgroundColor:a.backgroundColor||u.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:a.borderWidth||u.borderWidth,borderColor:o.borderColor?o.borderColor:a.borderColor||u.borderColor,borderCapStyle:o.borderCapStyle?o.borderCapStyle:a.borderCapStyle||u.borderCapStyle,borderDash:o.borderDash?o.borderDash:a.borderDash||u.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:a.borderDashOffset||u.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:a.borderJoinStyle||u.borderJoinStyle,fill:o.fill?o.fill:void 0!==a.fill?a.fill:u.fill,scaleTop:c.top,scaleBottom:c.bottom,scaleZero:c.getBasePixel()},l.pivot()),i=0,n=h.length;n>i;++i)r.updateElement(h[i],i,t);d.showLines&&0!==u.tension&&r.updateBezierControlPoints()},getPointBackgroundColor:function(t,i){var n=this.chart.options.elements.point.backgroundColor,a=this.getDataset(),o=t.custom||{};return o.backgroundColor?n=o.backgroundColor:a.pointBackgroundColor?n=e.getValueAtIndexOrDefault(a.pointBackgroundColor,i,n):a.backgroundColor&&(n=a.backgroundColor),n},getPointBorderColor:function(t,i){var n=this.chart.options.elements.point.borderColor,a=this.getDataset(),o=t.custom||{};return o.borderColor?n=o.borderColor:a.pointBorderColor?n=e.getValueAtIndexOrDefault(a.pointBorderColor,i,n):a.borderColor&&(n=a.borderColor),n},getPointBorderWidth:function(t,i){var n=this.chart.options.elements.point.borderWidth,a=this.getDataset(),o=t.custom||{};return o.borderWidth?n=o.borderWidth:a.pointBorderWidth?n=e.getValueAtIndexOrDefault(a.pointBorderWidth,i,n):a.borderWidth&&(n=a.borderWidth),n},updateElement:function(t,i,n){var a,o,r=this,s=r.getMeta(),l=t.custom||{},h=r.getDataset(),d=r.index,u=h.data[i],c=r.getScaleForId(s.yAxisID),f=r.getScaleForId(s.xAxisID),g=r.chart.options.elements.point;void 0!==h.radius&&void 0===h.pointRadius&&(h.pointRadius=h.radius),void 0!==h.hitRadius&&void 0===h.pointHitRadius&&(h.pointHitRadius=h.hitRadius),a=f.getPixelForValue(u,i,d,r.chart.isCombo),o=n?c.getBasePixel():r.calculatePointY(u,i,d,r.chart.isCombo),t._xScale=f,t._yScale=c,t._datasetIndex=d,t._index=i,t._model={x:a,y:o,skip:l.skip||isNaN(a)||isNaN(o),radius:l.radius||e.getValueAtIndexOrDefault(h.pointRadius,i,g.radius),pointStyle:l.pointStyle||e.getValueAtIndexOrDefault(h.pointStyle,i,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,i),borderColor:r.getPointBorderColor(t,i),borderWidth:r.getPointBorderWidth(t,i),tension:s.dataset._model?s.dataset._model.tension:0,hitRadius:l.hitRadius||e.getValueAtIndexOrDefault(h.pointHitRadius,i,g.hitRadius)}},calculatePointY:function(t,e,i,n){var a,o,r,s=this,l=s.chart,h=s.getMeta(),d=s.getScaleForId(h.yAxisID),u=0,c=0;if(d.options.stacked){for(a=0;i>a;a++)o=l.data.datasets[a],r=l.getDatasetMeta(a),"line"===r.type&&l.isDatasetVisible(a)&&(o.data[e]<0?c+=o.data[e]||0:u+=o.data[e]||0);return 0>t?d.getPixelForValue(c+t):d.getPixelForValue(u+t)}return d.getPixelForValue(t)},updateBezierControlPoints:function(){var t,i,n,a,o,r=this.getMeta(),s=this.chart.chartArea,l=r.data||[];for(t=0,i=l.length;i>t;++t)n=l[t],a=n._model,o=e.splineCurve(e.previousItem(l,t)._model,a,e.nextItem(l,t)._model,r.dataset._model.tension),a.controlPointPreviousX=Math.max(Math.min(o.previous.x,s.right),s.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,s.bottom),s.top),a.controlPointNextX=Math.max(Math.min(o.next.x,s.right),s.left),a.controlPointNextY=Math.max(Math.min(o.next.y,s.bottom),s.top),n.pivot()},draw:function(t){var e,i,n=this.getMeta(),a=n.data||[],o=t||1;for(e=0,i=a.length;i>e;++e)a[e].transition(o);for(this.chart.options.showLines&&n.dataset.transition(o).draw(),e=0,i=a.length;i>e;++e)a[e].draw()},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=t._model;o.radius=a.hoverRadius||e.getValueAtIndexOrDefault(i.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),o.backgroundColor=a.hoverBackgroundColor||e.getValueAtIndexOrDefault(i.pointHoverBackgroundColor,n,e.getHoverColor(o.backgroundColor)),o.borderColor=a.hoverBorderColor||e.getValueAtIndexOrDefault(i.pointHoverBorderColor,n,e.getHoverColor(o.borderColor)),o.borderWidth=a.hoverBorderWidth||e.getValueAtIndexOrDefault(i.pointHoverBorderWidth,n,o.borderWidth)},removeHoverStyle:function(t){var i=this,n=i.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=t._model;void 0!==n.radius&&void 0===n.pointRadius&&(n.pointRadius=n.radius),r.radius=o.radius||e.getValueAtIndexOrDefault(n.pointRadius,a,i.chart.options.elements.point.radius),r.backgroundColor=i.getPointBackgroundColor(t,a),r.borderColor=i.getPointBorderColor(t,a),r.borderWidth=i.getPointBorderWidth(t,a)}})}},{}],19:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",lineArc:!0},animation:{animateRotate:!0,animateScale:!0},aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,n=i.datasets,a=i.labels;if(n.length)for(var o=0;o<n[0].data.length;++o)e.push('<li><span style="background-color:'+n[0].backgroundColor[o]+'">'),a[o]&&e.push(a[o]),e.push("</span></li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var i=t.data;return i.labels.length&&i.datasets.length?i.labels.map(function(n,a){var o=t.getDatasetMeta(0),r=i.datasets[0],s=o.data[a],l=s.custom||{},h=e.getValueAtIndexOrDefault,d=t.options.elements.arc,u=l.backgroundColor?l.backgroundColor:h(r.backgroundColor,a,d.backgroundColor),c=l.borderColor?l.borderColor:h(r.borderColor,a,d.borderColor),f=l.borderWidth?l.borderWidth:h(r.borderWidth,a,d.borderWidth);
+return{text:n,fillStyle:u,strokeStyle:c,lineWidth:f,hidden:isNaN(r.data[a])||o.data[a].hidden,index:a}}):[]}},onClick:function(t,e){var i,n,a,o=e.index,r=this.chart;for(i=0,n=(r.data.datasets||[]).length;n>i;++i)a=r.getDatasetMeta(i),a.data[o].hidden=!a.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var i=this,n=i.chart,a=n.chartArea,o=this.getMeta(),r=n.options,s=r.elements.arc,l=Math.min(a.right-a.left,a.bottom-a.top);n.outerRadius=Math.max((l-s.borderWidth/2)/2,0),n.innerRadius=Math.max(r.cutoutPercentage?n.outerRadius/100*r.cutoutPercentage:1,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),i.outerRadius=n.outerRadius-n.radiusLength*i.index,i.innerRadius=i.outerRadius-n.radiusLength,o.count=i.countVisibleElements(),e.each(o.data,function(e,n){i.updateElement(e,n,t)})},updateElement:function(t,i,n){for(var a=this,o=a.chart,r=o.chartArea,s=a.getDataset(),l=o.options,h=l.animation,d=l.elements.arc,u=t.custom||{},c=o.scale,f=e.getValueAtIndexOrDefault,g=o.data.labels,m=a.calculateCircumference(s.data[i]),p=(r.left+r.right)/2,b=(r.top+r.bottom)/2,v=0,y=a.getMeta(),x=0;i>x;++x)isNaN(s.data[x])||y.data[x].hidden||++v;var k=t.hidden?0:c.getDistanceFromCenterForValue(s.data[i]),_=-.5*Math.PI+m*v,S=_+(t.hidden?0:m),w={x:p,y:b,innerRadius:0,outerRadius:h.animateScale?0:c.getDistanceFromCenterForValue(s.data[i]),startAngle:h.animateRotate?Math.PI*-.5:_,endAngle:h.animateRotate?Math.PI*-.5:S,backgroundColor:u.backgroundColor?u.backgroundColor:f(s.backgroundColor,i,d.backgroundColor),borderWidth:u.borderWidth?u.borderWidth:f(s.borderWidth,i,d.borderWidth),borderColor:u.borderColor?u.borderColor:f(s.borderColor,i,d.borderColor),label:f(g,i,g[i])};e.extend(t,{_datasetIndex:a.index,_index:i,_scale:c,_model:n?w:{x:p,y:b,innerRadius:0,outerRadius:k,startAngle:_,endAngle:S,backgroundColor:u.backgroundColor?u.backgroundColor:f(s.backgroundColor,i,d.backgroundColor),borderWidth:u.borderWidth?u.borderWidth:f(s.borderWidth,i,d.borderWidth),borderColor:u.borderColor?u.borderColor:f(s.borderColor,i,d.borderColor),label:f(g,i,g[i])}}),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),i=this.getMeta(),n=0;return e.each(i.data,function(e,i){isNaN(t.data[i])||e.hidden||n++}),n},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,addElementAndReset:function(e){t.DatasetController.prototype.addElementAndReset.call(this,e),this.updateBezierControlPoints()},update:function(t){var i=this.getMeta(),n=i.dataset,a=i.data,o=n.custom||{},r=this.getDataset(),s=this.chart.options.elements.line,l=this.chart.scale;void 0!==r.tension&&void 0===r.lineTension&&(r.lineTension=r.tension),e.extend(i.dataset,{_datasetIndex:this.index,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:e.getValueOrDefault(r.lineTension,s.tension),backgroundColor:o.backgroundColor?o.backgroundColor:r.backgroundColor||s.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:r.borderWidth||s.borderWidth,borderColor:o.borderColor?o.borderColor:r.borderColor||s.borderColor,fill:o.fill?o.fill:void 0!==r.fill?r.fill:s.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:r.borderCapStyle||s.borderCapStyle,borderDash:o.borderDash?o.borderDash:r.borderDash||s.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:r.borderDashOffset||s.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:r.borderJoinStyle||s.borderJoinStyle,scaleTop:l.top,scaleBottom:l.bottom,scaleZero:l.getBasePosition()}}),i.dataset.pivot(),e.each(a,function(e,i){this.updateElement(e,i,t)},this),this.updateBezierControlPoints()},updateElement:function(t,i,n){var a=t.custom||{},o=this.getDataset(),r=this.chart.scale,s=this.chart.options.elements.point,l=r.getPointPositionForValue(i,o.data[i]);e.extend(t,{_datasetIndex:this.index,_index:i,_scale:r,_model:{x:n?r.xCenter:l.x,y:n?r.yCenter:l.y,tension:a.tension?a.tension:e.getValueOrDefault(o.tension,this.chart.options.elements.line.tension),radius:a.radius?a.radius:e.getValueAtIndexOrDefault(o.pointRadius,i,s.radius),backgroundColor:a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(o.pointBackgroundColor,i,s.backgroundColor),borderColor:a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(o.pointBorderColor,i,s.borderColor),borderWidth:a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(o.pointBorderWidth,i,s.borderWidth),pointStyle:a.pointStyle?a.pointStyle:e.getValueAtIndexOrDefault(o.pointStyle,i,s.pointStyle),hitRadius:a.hitRadius?a.hitRadius:e.getValueAtIndexOrDefault(o.hitRadius,i,s.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,i=this.getMeta();e.each(i.data,function(n,a){var o=n._model,r=e.splineCurve(e.previousItem(i.data,a,!0)._model,o,e.nextItem(i.data,a,!0)._model,o.tension);o.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),o.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),o.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),o.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),n.pivot()},this)},draw:function(t){var i=this.getMeta(),n=t||1;e.each(i.data,function(t,e){t.transition(n)}),i.dataset.transition(n).draw(),e.each(i.data,function(t){t.draw()})},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},a=t._index,o=t._model;o.radius=n.hoverRadius?n.hoverRadius:e.getValueAtIndexOrDefault(i.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),o.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.pointHoverBackgroundColor,a,e.getHoverColor(o.backgroundColor)),o.borderColor=n.hoverBorderColor?n.hoverBorderColor:e.getValueAtIndexOrDefault(i.pointHoverBorderColor,a,e.getHoverColor(o.borderColor)),o.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:e.getValueAtIndexOrDefault(i.pointHoverBorderWidth,a,o.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},a=t._index,o=t._model,r=this.chart.options.elements.point;o.radius=n.radius?n.radius:e.getValueAtIndexOrDefault(i.radius,a,r.radius),o.backgroundColor=n.backgroundColor?n.backgroundColor:e.getValueAtIndexOrDefault(i.pointBackgroundColor,a,r.backgroundColor),o.borderColor=n.borderColor?n.borderColor:e.getValueAtIndexOrDefault(i.pointBorderColor,a,r.borderColor),o.borderWidth=n.borderWidth?n.borderWidth:e.getValueAtIndexOrDefault(i.pointBorderWidth,a,r.borderWidth)}})}},{}],21:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({currentStep:null,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,i,n){n||(t.animating=!0);for(var a=0;a<this.animations.length;++a)if(this.animations[a].chartInstance===t)return void(this.animations[a].animationObject=e);this.animations.push({chartInstance:t,animationObject:e}),1===this.animations.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var i=e.findIndex(this.animations,function(e){return e.chartInstance===t});-1!==i&&(this.animations.splice(i,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=Date.now(),e=0;this.dropFrames>1&&(e=Math.floor(this.dropFrames),this.dropFrames=this.dropFrames%1);for(var i=0;i<this.animations.length;)null===this.animations[i].animationObject.currentStep&&(this.animations[i].animationObject.currentStep=0),this.animations[i].animationObject.currentStep+=1+e,this.animations[i].animationObject.currentStep>this.animations[i].animationObject.numSteps&&(this.animations[i].animationObject.currentStep=this.animations[i].animationObject.numSteps),this.animations[i].animationObject.render(this.animations[i].chartInstance,this.animations[i].animationObject),this.animations[i].animationObject.onAnimationProgress&&this.animations[i].animationObject.onAnimationProgress.call&&this.animations[i].animationObject.onAnimationProgress.call(this.animations[i].chartInstance,this.animations[i]),this.animations[i].animationObject.currentStep===this.animations[i].animationObject.numSteps?(this.animations[i].animationObject.onAnimationComplete&&this.animations[i].animationObject.onAnimationComplete.call&&this.animations[i].animationObject.onAnimationComplete.call(this.animations[i].chartInstance,this.animations[i]),this.animations[i].chartInstance.animating=!1,this.animations.splice(i,1)):++i;var n=Date.now(),a=(n-t)/this.frameDuration;this.dropFrames+=a,this.animations.length>0&&this.requestAnimationFrame()}}}},{}],22:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.types={},t.instances={},t.controllers={},t.Controller=function(i){return this.chart=i,this.config=i.config,this.options=this.config.options=e.configMerge(t.defaults.global,t.defaults[this.config.type],this.config.options||{}),this.id=e.uid(),Object.defineProperty(this,"data",{get:function(){return this.config.data}}),t.instances[this.id]=this,this.options.responsive&&this.resize(!0),this.initialize(),this},e.extend(t.Controller.prototype,{initialize:function(){return t.pluginService.notifyPlugins("beforeInit",[this]),this.bindEvents(),this.ensureScalesHaveIDs(),this.buildOrUpdateControllers(),this.buildScales(),this.buildSurroundingItems(),this.updateLayout(),this.resetElements(),this.initToolTip(),this.update(),t.pluginService.notifyPlugins("afterInit",[this]),this},clear:function(){return e.clear(this.chart),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var i=this.chart.canvas,n=e.getMaximumWidth(this.chart.canvas),a=this.options.maintainAspectRatio&&isNaN(this.chart.aspectRatio)===!1&&isFinite(this.chart.aspectRatio)&&0!==this.chart.aspectRatio?n/this.chart.aspectRatio:e.getMaximumHeight(this.chart.canvas),o=this.chart.width!==n||this.chart.height!==a;return o?(i.width=this.chart.width=n,i.height=this.chart.height=a,e.retinaScale(this.chart),t||(this.stop(),this.update(this.options.responsiveAnimationDuration)),this):this},ensureScalesHaveIDs:function(){var t=this.options,i=t.scales||{},n=t.scale;e.each(i.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),e.each(i.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var i=this,n=i.options,a=i.scales={},o=[];n.scales&&(o=o.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear"}}))),n.scale&&o.push({options:n.scale,dtype:"radialLinear",isDefault:!0}),e.each(o,function(n,o){var r=n.options,s=e.getValueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(s);if(l){var h=new l({id:r.id,options:r,ctx:i.chart.ctx,chart:i});a[h.id]=h,n.isDefault&&(i.scale=h)}}),t.scaleService.addScalesToLayout(this)},buildSurroundingItems:function(){this.options.title&&(this.titleBlock=new t.Title({ctx:this.chart.ctx,options:this.options.title,chart:this}),t.layoutService.addBox(this,this.titleBlock)),this.options.legend&&(this.legend=new t.Legend({ctx:this.chart.ctx,options:this.options.legend,chart:this}),t.layoutService.addBox(this,this.legend))},updateLayout:function(){t.layoutService.update(this,this.chart.width,this.chart.height)},buildOrUpdateControllers:function(){var i=[],n=[];if(e.each(this.data.datasets,function(e,a){var o=this.getDatasetMeta(a);o.type||(o.type=e.type||this.config.type),i.push(o.type),o.controller?o.controller.updateIndex(a):(o.controller=new t.controllers[o.type](this,a),n.push(o.controller))},this),i.length>1)for(var a=1;a<i.length;a++)if(i[a]!==i[a-1]){this.isCombo=!0;break}return n},resetElements:function(){e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.reset()},this)},update:function(i,n){t.pluginService.notifyPlugins("beforeUpdate",[this]),this.tooltip._data=this.data;var a=this.buildOrUpdateControllers();e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.buildOrUpdateElements()},this),t.layoutService.update(this,this.chart.width,this.chart.height),t.pluginService.notifyPlugins("afterScaleUpdate",[this]),e.each(a,function(t){t.reset()}),e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.update()},this),t.pluginService.notifyPlugins("afterUpdate",[this]),this.render(i,n)},render:function(i,n){t.pluginService.notifyPlugins("beforeRender",[this]);var a=this.options.animation;if(a&&("undefined"!=typeof i&&0!==i||"undefined"==typeof i&&0!==a.duration)){var o=new t.Animation;o.numSteps=(i||a.duration)/16.66,o.easing=a.easing,o.render=function(t,i){var n=e.easingEffects[i.easing],a=i.currentStep/i.numSteps,o=n(a);t.draw(o,a,i.currentStep)},o.onAnimationProgress=a.onProgress,o.onAnimationComplete=a.onComplete,t.animationService.addAnimation(this,o,i,n)}else this.draw(),a&&a.onComplete&&a.onComplete.call&&a.onComplete.call(this);return this},draw:function(i){var n=i||1;this.clear(),t.pluginService.notifyPlugins("beforeDraw",[this,n]),e.each(this.boxes,function(t){t.draw(this.chartArea)},this),this.scale&&this.scale.draw();var a=this.chart.ctx;a.save(),a.beginPath(),a.rect(this.chartArea.left,this.chartArea.top,this.chartArea.right-this.chartArea.left,this.chartArea.bottom-this.chartArea.top),a.clip(),e.each(this.data.datasets,function(t,e){this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.draw(i)},this,!0),a.restore(),this.tooltip.transition(n).draw(),t.pluginService.notifyPlugins("afterDraw",[this,n])},getElementAtEvent:function(t){var i=e.getRelativePosition(t,this.chart),n=[];return e.each(this.data.datasets,function(t,a){if(this.isDatasetVisible(a)){var o=this.getDatasetMeta(a);e.each(o.data,function(t,e){return t.inRange(i.x,i.y)?(n.push(t),n):void 0})}},this),n},getElementsAtEvent:function(t){var i=e.getRelativePosition(t,this.chart),n=[],a=function(){if(this.data.datasets)for(var t=0;t<this.data.datasets.length;t++){var e=this.getDatasetMeta(t);if(this.isDatasetVisible(t))for(var n=0;n<e.data.length;n++)if(e.data[n].inRange(i.x,i.y))return e.data[n]}}.call(this);return a?(e.each(this.data.datasets,function(t,e){if(this.isDatasetVisible(e)){var i=this.getDatasetMeta(e);n.push(i.data[a._index])}},this),n):n},getElementsAtEventForMode:function(t,e){var i=this;switch(e){case"single":return i.getElementAtEvent(t);case"label":return i.getElementsAtEvent(t);case"dataset":return i.getDatasetAtEvent(t);default:return t}},getDatasetAtEvent:function(t){var e=this.getElementAtEvent(t);return e.length>0&&(e=this.getDatasetMeta(e[0]._datasetIndex).data),e},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var i=e._meta[this.id];return i||(i=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,i=this.data.datasets.length;i>e;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){this.clear(),e.unbindEvents(this,this.events),e.removeResizeListener(this.chart.canvas.parentNode);var i=this.chart.canvas;i.width=this.chart.width,i.height=this.chart.height,void 0!==this.chart.originalDevicePixelRatio&&this.chart.ctx.scale(1/this.chart.originalDevicePixelRatio,1/this.chart.originalDevicePixelRatio),i.style.width=this.chart.originalCanvasStyleWidth,i.style.height=this.chart.originalCanvasStyleHeight,t.pluginService.notifyPlugins("destroy",[this]),delete t.instances[this.id]},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)},initToolTip:function(){this.tooltip=new t.Tooltip({_chart:this.chart,_chartInstance:this,_data:this.data,_options:this.options},this)},bindEvents:function(){e.bindEvents(this,this.options.events,function(t){this.eventHandler(t)})},updateHoverStyle:function(t,e,i){var n,a,o,r=i?"setHoverStyle":"removeHoverStyle";switch(e){case"single":t=[t[0]];break;case"label":case"dataset":break;default:return}for(a=0,o=t.length;o>a;++a)n=t[a],n&&this.getDatasetMeta(n._datasetIndex).controller[r](n)},eventHandler:function(t){var i=this,n=i.tooltip,a=i.options||{},o=a.hover,r=a.tooltips;return i.lastActive=i.lastActive||[],i.lastTooltipActive=i.lastTooltipActive||[],"mouseout"===t.type?(i.active=[],i.tooltipActive=[]):(i.active=i.getElementsAtEventForMode(t,o.mode),i.tooltipActive=i.getElementsAtEventForMode(t,r.mode)),o.onHover&&o.onHover.call(i,i.active),("mouseup"===t.type||"click"===t.type)&&(a.onClick&&a.onClick.call(i,t,i.active),i.legend&&i.legend.handleEvent&&i.legend.handleEvent(t)),i.lastActive.length&&i.updateHoverStyle(i.lastActive,o.mode,!1),i.active.length&&o.mode&&i.updateHoverStyle(i.active,o.mode,!0),(r.enabled||r.custom)&&(n.initialize(),n._active=i.tooltipActive,n.update(!0)),n.pivot(),i.animating||e.arrayEquals(i.active,i.lastActive)&&e.arrayEquals(i.tooltipActive,i.lastTooltipActive)||(i.stop(),(r.enabled||r.custom)&&n.update(!0),i.render(o.animationDuration,!0)),i.lastActive=i.active,i.lastTooltipActive=i.tooltipActive,i}})}},{}],23:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=e.noop;t.DatasetController=function(t,e){this.initialize.call(this,t,e)},e.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this.getMeta(),e=this.getDataset();null===t.xAxisID&&(t.xAxisID=e.xAxisID||this.chart.options.scales.xAxes[0].id),null===t.yAxisID&&(t.yAxisID=e.yAxisID||this.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,i=e.dataElementType;return i&&new i({_chart:e.chart.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,i=this,n=i.getMeta(),a=i.getDataset().data||[],o=n.data;for(t=0,e=a.length;e>t;++t)o[t]=o[t]||i.createMetaData(n,t);n.dataset=n.dataset||i.createMetaDataset()},addElementAndReset:function(t){var e=this,i=e.createMetaData(t);e.getMeta().data.splice(t,0,i),e.updateElement(i,t,!0)},buildOrUpdateElements:function(){var t=this.getMeta(),e=t.data,i=this.getDataset().data.length,n=e.length;if(n>i)e.splice(i,n-i);else if(i>n)for(var a=n;i>a;++a)this.addElementAndReset(a)},update:i,draw:function(t){var i=t||1;e.each(this.getMeta().data,function(t,e){t.transition(i).draw()})},removeHoverStyle:function(t,i){var n=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},r=e.getValueAtIndexOrDefault,s=(e.color,t._model);s.backgroundColor=o.backgroundColor?o.backgroundColor:r(n.backgroundColor,a,i.backgroundColor),s.borderColor=o.borderColor?o.borderColor:r(n.borderColor,a,i.borderColor),s.borderWidth=o.borderWidth?o.borderWidth:r(n.borderWidth,a,i.borderWidth)},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,a=t.custom||{},o=e.getValueAtIndexOrDefault,r=(e.color,e.getHoverColor),s=t._model;s.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:o(i.hoverBackgroundColor,n,r(s.backgroundColor)),s.borderColor=a.hoverBorderColor?a.hoverBorderColor:o(i.hoverBorderColor,n,r(s.borderColor)),s.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:o(i.hoverBorderWidth,n,s.borderWidth)}}),t.DatasetController.extend=e.inherits}},{}],24:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.elements={},t.Element=function(t){e.extend(this,t),this.initialize.apply(this,arguments)},e.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){return this._view||(this._view=e.clone(this._model)),this._start=e.clone(this._view),this},transition:function(t){return this._view||(this._view=e.clone(this._model)),1===t?(this._view=this._model,this._start=null,this):(this._start||this.pivot(),e.each(this._model,function(i,n){if("_"===n[0]);else if(this._view.hasOwnProperty(n))if(i===this._view[n]);else if("string"==typeof i)try{var a=e.color(this._model[n]).mix(e.color(this._start[n]),t);this._view[n]=a.rgbString()}catch(o){this._view[n]=i}else if("number"==typeof i){var r=void 0!==this._start[n]&&isNaN(this._start[n])===!1?this._start[n]:0;this._view[n]=(this._model[n]-r)*t+r}else this._view[n]=i;else"number"!=typeof i||isNaN(this._view[n])?this._view[n]=i:this._view[n]=i*t},this),this)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return e.isNumber(this._model.x)&&e.isNumber(this._model.y)}}),t.Element.extend=e.inherits}},{}],25:[function(t,e,i){"use strict";var n=t("chartjs-color");e.exports=function(t){function e(t,e,i){var n;return"string"==typeof t?(n=parseInt(t,10),-1!=t.indexOf("%")&&(n=n/100*e.parentNode[i])):n=t,n}function i(t){return void 0!==t&&null!==t&&"none"!==t}function a(t,n,a){var o=document.defaultView,r=t.parentNode,s=o.getComputedStyle(t)[n],l=o.getComputedStyle(r)[n],h=i(s),d=i(l),u=Number.POSITIVE_INFINITY;return h||d?Math.min(h?e(s,t,a):u,d?e(l,r,a):u):"none"}var o=t.helpers={};o.each=function(t,e,i,n){var a,r;if(o.isArray(t))if(r=t.length,n)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;r>a;a++)e.call(i,t[a],a);else if("object"==typeof t){var s=Object.keys(t);for(r=s.length,a=0;r>a;a++)e.call(i,t[s[a]],s[a])}},o.clone=function(t){var e={};return o.each(t,function(t,i){o.isArray(t)?e[i]=t.slice(0):"object"==typeof t&&null!==t?e[i]=o.clone(t):e[i]=t}),e},o.extend=function(t){for(var e=arguments.length,i=[],n=1;e>n;n++)i.push(arguments[n]);return o.each(i,function(e){o.each(e,function(e,i){t[i]=e})}),t},o.configMerge=function(e){var i=o.clone(e);return o.each(Array.prototype.slice.call(arguments,1),function(e){o.each(e,function(e,n){if("scales"===n)i[n]=o.scaleMerge(i.hasOwnProperty(n)?i[n]:{},e);else if("scale"===n)i[n]=o.configMerge(i.hasOwnProperty(n)?i[n]:{},t.scaleService.getScaleDefaults(e.type),e);else if(i.hasOwnProperty(n)&&o.isArray(i[n])&&o.isArray(e)){var a=i[n];o.each(e,function(t,e){e<a.length?"object"==typeof a[e]&&null!==a[e]&&"object"==typeof t&&null!==t?a[e]=o.configMerge(a[e],t):a[e]=t:a.push(t)})}else i.hasOwnProperty(n)&&"object"==typeof i[n]&&null!==i[n]&&"object"==typeof e?i[n]=o.configMerge(i[n],e):i[n]=e})}),i},o.extendDeep=function(t){function e(t){return o.each(arguments,function(i){i!==t&&o.each(i,function(i,n){t[n]&&t[n].constructor&&t[n].constructor===Object?e(t[n],i):t[n]=i})}),t}return e.apply(this,arguments)},o.scaleMerge=function(e,i){var n=o.clone(e);return o.each(i,function(e,i){"xAxes"===i||"yAxes"===i?n.hasOwnProperty(i)?o.each(e,function(e,a){var r=o.getValueOrDefault(e.type,"xAxes"===i?"category":"linear"),s=t.scaleService.getScaleDefaults(r);a>=n[i].length||!n[i][a].type?n[i].push(o.configMerge(s,e)):e.type&&e.type!==n[i][a].type?n[i][a]=o.configMerge(n[i][a],s,e):n[i][a]=o.configMerge(n[i][a],e)}):(n[i]=[],o.each(e,function(e){var a=o.getValueOrDefault(e.type,"xAxes"===i?"category":"linear");n[i].push(o.configMerge(t.scaleService.getScaleDefaults(a),e))})):n.hasOwnProperty(i)&&"object"==typeof n[i]&&null!==n[i]&&"object"==typeof e?n[i]=o.configMerge(n[i],e):n[i]=e}),n},o.getValueAtIndexOrDefault=function(t,e,i){return void 0===t||null===t?i:o.isArray(t)?e<t.length?t[e]:i:t},o.getValueOrDefault=function(t,e){return void 0===t?e:t},o.indexOf=function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var i=[];return o.each(t,function(t){e(t)&&i.push(t)}),i},o.findIndex=function(t,e,i){var n=-1;if(Array.prototype.findIndex)n=t.findIndex(e,i);else for(var a=0;a<t.length;++a)if(i=void 0!==i?i:t,e.call(i,t[a],a,t)){n=a;break}return n},o.findNextWhere=function(t,e,i){(void 0===i||null===i)&&(i=-1);for(var n=i+1;n<t.length;n++){var a=t[n];if(e(a))return a}},o.findPreviousWhere=function(t,e,i){(void 0===i||null===i)&&(i=t.length);for(var n=i-1;n>=0;n--){var a=t[n];if(e(a))return a}},o.inherits=function(t){var e=this,i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},n=function(){this.constructor=i};return n.prototype=e.prototype,i.prototype=new n,i.extend=o.inherits,t&&o.extend(i.prototype,t),i.__super__=e.prototype,i},o.noop=function(){},o.uid=function(){var t=0;return function(){return t++}}(),o.warn=function(t){console&&"function"==typeof console.warn&&console.warn(t)},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,i){return Math.abs(t-e)<i},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=function(t){return Math.sign?Math.sign(t):(t=+t,0===t||isNaN(t)?t:t>0?1:-1)},o.log10=function(t){return Math.log10?Math.log10(t):Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var i=e.x-t.x,n=e.y-t.y,a=Math.sqrt(i*i+n*n),o=Math.atan2(n,i);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:a}},o.aliasPixel=function(t){return t%2===0?0:.5},o.splineCurve=function(t,e,i,n){var a=t.skip?e:t,o=e,r=i.skip?e:i,s=Math.sqrt(Math.pow(o.x-a.x,2)+Math.pow(o.y-a.y,2)),l=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),h=s/(s+l),d=l/(s+l);h=isNaN(h)?0:h,d=isNaN(d)?0:d;var u=n*h,c=n*d;return{previous:{x:o.x-u*(r.x-a.x),y:o.y-u*(r.y-a.y)},next:{x:o.x+c*(r.x-a.x),y:o.y+c*(r.y-a.y)}}},o.nextItem=function(t,e,i){return i?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,i){return i?0>=e?t[t.length-1]:t[e-1]:0>=e?t[0]:t[e-1]},o.niceNum=function(t,e){var i,n=Math.floor(o.log10(t)),a=t/Math.pow(10,n);return i=e?1.5>a?1:3>a?2:7>a?5:10:1>=a?1:2>=a?2:5>=a?5:10,i*Math.pow(10,n)};var r=o.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===(t/=1)?1:(i||(i=.3),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),-(n*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)))},easeOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:1===(t/=1)?1:(i||(i=.3),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),n*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/i)+1)},easeInOutElastic:function(t){var e=1.70158,i=0,n=1;return 0===t?0:2===(t/=.5)?1:(i||(i=1*(.3*1.5)),n<Math.abs(1)?(n=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/n),1>t?-.5*(n*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)):n*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};o.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),o.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),o.getRelativePosition=function(t,e){var i,n,a=t.originalEvent||t,r=t.currentTarget||t.srcElement,s=r.getBoundingClientRect(),l=a.touches;l&&l.length>0?(i=l[0].clientX,n=l[0].clientY):(i=a.clientX,n=a.clientY);var h=parseFloat(o.getStyle(r,"padding-left")),d=parseFloat(o.getStyle(r,"padding-top")),u=parseFloat(o.getStyle(r,"padding-right")),c=parseFloat(o.getStyle(r,"padding-bottom")),f=s.right-s.left-h-u,g=s.bottom-s.top-d-c;return i=Math.round((i-s.left-h)/f*r.width/e.currentDevicePixelRatio),n=Math.round((n-s.top-d)/g*r.height/e.currentDevicePixelRatio),{x:i,y:n}},o.addEvent=function(t,e,i){t.addEventListener?t.addEventListener(e,i):t.attachEvent?t.attachEvent("on"+e,i):t["on"+e]=i},o.removeEvent=function(t,e,i){t.removeEventListener?t.removeEventListener(e,i,!1):t.detachEvent?t.detachEvent("on"+e,i):t["on"+e]=o.noop},o.bindEvents=function(t,e,i){var n=t.events=t.events||{};o.each(e,function(e){n[e]=function(){i.apply(t,arguments)},o.addEvent(t.chart.canvas,e,n[e])})},o.unbindEvents=function(t,e){var i=t.chart.canvas;o.each(e,function(t,e){o.removeEvent(i,e,t)})},o.getConstraintWidth=function(t){return a(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return a(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode,i=parseInt(o.getStyle(e,"padding-left"))+parseInt(o.getStyle(e,"padding-right")),n=e.clientWidth-i,a=o.getConstraintWidth(t);return isNaN(a)?n:Math.min(n,a)},o.getMaximumHeight=function(t){var e=t.parentNode,i=parseInt(o.getStyle(e,"padding-top"))+parseInt(o.getStyle(e,"padding-bottom")),n=e.clientHeight-i,a=o.getConstraintHeight(t);return isNaN(a)?n:Math.min(n,a)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e);
+},o.retinaScale=function(t){var e=t.ctx,i=t.canvas,n=i.width,a=i.height,o=t.currentDevicePixelRatio=window.devicePixelRatio||1;1!==o&&(i.height=a*o,i.width=n*o,e.scale(o,o),t.originalDevicePixelRatio=t.originalDevicePixelRatio||o),i.style.width=n+"px",i.style.height=a+"px"},o.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},o.fontString=function(t,e,i){return e+" "+t+"px "+i},o.longestText=function(t,e,i,n){n=n||{};var a=n.data=n.data||{},r=n.garbageCollect=n.garbageCollect||[];n.font!==e&&(a=n.data={},r=n.garbageCollect=[],n.font=e),t.font=e;var s=0;o.each(i,function(e){if(void 0!==e&&null!==e){var i=a[e];i||(i=a[e]=t.measureText(e).width,r.push(e)),i>s&&(s=i)}});var l=r.length/2;if(l>i.length){for(var h=0;l>h;h++)delete a[r[h]];r.splice(0,l)}return s},o.drawRoundedRectangle=function(t,e,i,n,a,o){t.beginPath(),t.moveTo(e+o,i),t.lineTo(e+n-o,i),t.quadraticCurveTo(e+n,i,e+n,i+o),t.lineTo(e+n,i+a-o),t.quadraticCurveTo(e+n,i+a,e+n-o,i+a),t.lineTo(e+o,i+a),t.quadraticCurveTo(e,i+a,e,i+a-o),t.lineTo(e,i+o),t.quadraticCurveTo(e,i,e+o,i),t.closePath()},o.color=function(e){return n?n(e instanceof CanvasGradient?t.defaults.global.defaultColor:e):(console.log("Color.js not found!"),e)},o.addResizeListener=function(t,e){var i=document.createElement("iframe"),n="chartjs-hidden-iframe";i.classlist?i.classlist.add(n):i.setAttribute("class",n);var a=i.style;a.width="100%",a.display="block",a.border=0,a.height=0,a.margin=0,a.position="absolute",a.left=0,a.right=0,a.top=0,a.bottom=0,t.insertBefore(i,t.firstChild),(i.contentWindow||i).onresize=function(){e&&e()}},o.removeResizeListener=function(t){var e=t.querySelector(".chartjs-hidden-iframe");e&&e.parentNode.removeChild(e)},o.isArray=function(t){return Array.isArray?Array.isArray(t):"[object Array]"===Object.prototype.toString.call(t)},o.arrayEquals=function(t,e){var i,n,a,r;if(!t||!e||t.length!=e.length)return!1;for(i=0,n=t.length;n>i;++i)if(a=t[i],r=e[i],a instanceof Array&&r instanceof Array){if(!o.arrayEquals(a,r))return!1}else if(a!=r)return!1;return!0},o.pushAllIfDefined=function(t,e){"undefined"!=typeof t&&(o.isArray(t)?e.push.apply(e,t):e.push(t))},o.callCallback=function(t,e,i){t&&"function"==typeof t.call&&t.apply(i,e)},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{"chartjs-color":2}],26:[function(t,e,i){"use strict";e.exports=function(){var t=function(e,i){this.config=i,e.length&&e[0].getContext&&(e=e[0]),e.getContext&&(e=e.getContext("2d")),this.ctx=e,this.canvas=e.canvas,this.width=e.canvas.width||parseInt(t.helpers.getStyle(e.canvas,"width"))||t.helpers.getMaximumWidth(e.canvas),this.height=e.canvas.height||parseInt(t.helpers.getStyle(e.canvas,"height"))||t.helpers.getMaximumHeight(e.canvas),this.aspectRatio=this.width/this.height,(isNaN(this.aspectRatio)||isFinite(this.aspectRatio)===!1)&&(this.aspectRatio=void 0!==i.aspectRatio?i.aspectRatio:2),this.originalCanvasStyleWidth=e.canvas.style.width,this.originalCanvasStyleHeight=e.canvas.style.height,t.helpers.retinaScale(this),i&&(this.controller=new t.Controller(this));var n=this;return t.helpers.addResizeListener(e.canvas.parentNode,function(){n.controller&&n.controller.config.options.responsive&&n.controller.resize()}),this.controller?this.controller:this};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"single",animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var i=0;i<t.data.datasets.length;i++)e.push('<li><span style="background-color:'+t.data.datasets[i].backgroundColor+'"></span>'),t.data.datasets[i].label&&e.push(t.data.datasets[i].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t}},{}],27:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),t.boxes.push(e)},removeBox:function(t,e){t.boxes&&t.boxes.splice(t.boxes.indexOf(e),1)},update:function(t,i,n){function a(t){var e,i=t.isHorizontal();i?(e=t.update(t.options.fullWidth?m:k,x),_-=e.height):(e=t.update(y,v),k-=e.width),S.push({horizontal:i,minSize:e,box:t})}function o(t){var i=e.findNextWhere(S,function(e){return e.box===t});if(i)if(t.isHorizontal()){var n={left:w,right:M,top:0,bottom:0};t.update(t.options.fullWidth?m:k,p/2,n)}else t.update(i.minSize.width,_)}function r(t){var i=e.findNextWhere(S,function(e){return e.box===t}),n={left:0,right:0,top:C,bottom:D};i&&t.update(i.minSize.width,_,n)}function s(t){t.isHorizontal()?(t.left=t.options.fullWidth?l:w,t.right=t.options.fullWidth?i-l:w+k,t.top=F,t.bottom=F+t.height,F=t.bottom):(t.left=A,t.right=A+t.width,t.top=C,t.bottom=C+_,A=t.right)}if(t){var l=0,h=0,d=e.where(t.boxes,function(t){return"left"===t.options.position}),u=e.where(t.boxes,function(t){return"right"===t.options.position}),c=e.where(t.boxes,function(t){return"top"===t.options.position}),f=e.where(t.boxes,function(t){return"bottom"===t.options.position}),g=e.where(t.boxes,function(t){return"chartArea"===t.options.position});c.sort(function(t,e){return(e.options.fullWidth?1:0)-(t.options.fullWidth?1:0)}),f.sort(function(t,e){return(t.options.fullWidth?1:0)-(e.options.fullWidth?1:0)});var m=i-2*l,p=n-2*h,b=m/2,v=p/2,y=(i-b)/(d.length+u.length),x=(n-v)/(c.length+f.length),k=m,_=p,S=[];e.each(d.concat(u,c,f),a);var w=l,M=l,C=h,D=h;e.each(d.concat(u),o),e.each(d,function(t){w+=t.width}),e.each(u,function(t){M+=t.width}),e.each(c.concat(f),o),e.each(c,function(t){C+=t.height}),e.each(f,function(t){D+=t.height}),e.each(d.concat(u),r),w=l,M=l,C=h,D=h,e.each(d,function(t){w+=t.width}),e.each(u,function(t){M+=t.width}),e.each(c,function(t){C+=t.height}),e.each(f,function(t){D+=t.height});var T=n-C-D,P=i-w-M;(P!==k||T!==_)&&(e.each(d,function(t){t.height=T}),e.each(u,function(t){t.height=T}),e.each(c,function(t){t.options.fullWidth||(t.width=P)}),e.each(f,function(t){t.options.fullWidth||(t.width=P)}),_=T,k=P);var A=l,F=h;e.each(d.concat(c),s),A+=k,F+=_,e.each(u,s),e.each(f,s),t.chartArea={left:w,top:C,right:w+k,bottom:C+_},e.each(g,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(k,_)})}}}}},{}],28:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=e.noop;t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,onClick:function(t,e){var i=e.datasetIndex,n=this.chart,a=n.getDatasetMeta(i);a.hidden=null===a.hidden?!n.data.datasets[i].hidden:null,n.update()},labels:{boxWidth:40,padding:10,generateLabels:function(t){var i=t.data;return e.isArray(i.datasets)?i.datasets.map(function(e,i){return{text:e.label,fillStyle:e.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,datasetIndex:i}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){e.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:i,update:function(t,e,i){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this.margins=i,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeBuildLabels(),this.buildLabels(),this.afterBuildLabels(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:i,beforeSetDimensions:i,setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0,this.minSize={width:0,height:0}},afterSetDimensions:i,beforeBuildLabels:i,buildLabels:function(){this.legendItems=this.options.labels.generateLabels.call(this,this.chart),this.options.reverse&&this.legendItems.reverse()},afterBuildLabels:i,beforeFit:i,fit:function(){var i=this.options,n=i.labels,a=i.display,o=this.ctx,r=t.defaults.global,s=e.getValueOrDefault,l=s(n.fontSize,r.defaultFontSize),h=s(n.fontStyle,r.defaultFontStyle),d=s(n.fontFamily,r.defaultFontFamily),u=e.fontString(l,h,d),c=this.legendHitBoxes=[],f=this.minSize,g=this.isHorizontal();if(g?(f.width=this.maxWidth,f.height=a?10:0):(f.width=a?10:0,f.height=this.maxHeight),a&&g){var m=this.lineWidths=[0],p=this.legendItems.length?l+n.padding:0;o.textAlign="left",o.textBaseline="top",o.font=u,e.each(this.legendItems,function(t,e){var i=n.boxWidth+l/2+o.measureText(t.text).width;m[m.length-1]+i+n.padding>=this.width&&(p+=l+n.padding,m[m.length]=this.left),c[e]={left:0,top:0,width:i,height:l},m[m.length-1]+=i+n.padding},this),f.height+=p}this.width=f.width,this.height=f.height},afterFit:i,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var i=this.options,n=i.labels,a=t.defaults.global,o=a.elements.line,r=this.width,s=this.lineWidths;if(i.display){var l=this.ctx,h={x:this.left+(r-s[0])/2,y:this.top+n.padding,line:0},d=e.getValueOrDefault,u=d(n.fontColor,a.defaultFontColor),c=d(n.fontSize,a.defaultFontSize),f=d(n.fontStyle,a.defaultFontStyle),g=d(n.fontFamily,a.defaultFontFamily),m=e.fontString(c,f,g);if(this.isHorizontal()){l.textAlign="left",l.textBaseline="top",l.lineWidth=.5,l.strokeStyle=u,l.fillStyle=u,l.font=m;var p=n.boxWidth,b=this.legendHitBoxes;e.each(this.legendItems,function(t,e){var i=l.measureText(t.text).width,u=p+c/2+i,f=h.x,g=h.y;f+u>=r&&(g=h.y+=c+n.padding,h.line++,f=h.x=this.left+(r-s[h.line])/2),l.save(),l.fillStyle=d(t.fillStyle,a.defaultColor),l.lineCap=d(t.lineCap,o.borderCapStyle),l.lineDashOffset=d(t.lineDashOffset,o.borderDashOffset),l.lineJoin=d(t.lineJoin,o.borderJoinStyle),l.lineWidth=d(t.lineWidth,o.borderWidth),l.strokeStyle=d(t.strokeStyle,a.defaultColor),l.setLineDash&&l.setLineDash(d(t.lineDash,o.borderDash)),l.strokeRect(f,g,p,c),l.fillRect(f,g,p,c),l.restore(),b[e].left=f,b[e].top=g,l.fillText(t.text,p+c/2+f,g),t.hidden&&(l.beginPath(),l.lineWidth=2,l.moveTo(p+c/2+f,g+c/2),l.lineTo(p+c/2+f+i,g+c/2),l.stroke()),h.x+=u+n.padding},this)}}},handleEvent:function(t){var i=e.getRelativePosition(t,this.chart.chart),n=i.x,a=i.y,o=this.options;if(n>=this.left&&n<=this.right&&a>=this.top&&a<=this.bottom)for(var r=this.legendHitBoxes,s=0;s<r.length;++s){var l=r[s];if(n>=l.left&&n<=l.left+l.width&&a>=l.top&&a<=l.top+l.height){o.onClick&&o.onClick.call(this,t,this.legendItems[s]);break}}}})}},{}],29:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.plugins=[],t.pluginService={register:function(e){var i=t.plugins;-1===i.indexOf(e)&&i.push(e)},remove:function(e){var i=t.plugins,n=i.indexOf(e);-1!==n&&i.splice(n,1)},notifyPlugins:function(i,n,a){e.each(t.plugins,function(t){t[i]&&"function"==typeof t[i]&&t[i].apply(a,n)},a)}};var i=e.noop;t.PluginBase=t.Element.extend({beforeInit:i,afterInit:i,beforeUpdate:i,afterUpdate:i,beforeDraw:i,afterDraw:i,destroy:i})}},{}],30:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",offsetGridLines:!1},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:10,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:function(t){return""+t}}},t.Scale=t.Element.extend({beforeUpdate:function(){e.callCallback(this.options.beforeUpdate,[this])},update:function(t,i,n){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=i,this.margins=e.extend({left:0,right:0,top:0,bottom:0},n),this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this.beforeBuildTicks(),this.buildTicks(),this.afterBuildTicks(),this.beforeTickToLabelConversion(),this.convertTicksToLabels(),this.afterTickToLabelConversion(),this.beforeCalculateTickRotation(),this.calculateTickRotation(),this.afterCalculateTickRotation(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:function(){e.callCallback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){e.callCallback(this.options.beforeSetDimensions,[this])},setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0},afterSetDimensions:function(){e.callCallback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){e.callCallback(this.options.beforeDataLimits,[this])},determineDataLimits:e.noop,afterDataLimits:function(){e.callCallback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){e.callCallback(this.options.beforeBuildTicks,[this])},buildTicks:e.noop,afterBuildTicks:function(){e.callCallback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){e.callCallback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){this.ticks=this.ticks.map(function(t,e,i){return this.options.ticks.userCallback?this.options.ticks.userCallback(t,e,i):this.options.ticks.callback(t,e,i)},this)},afterTickToLabelConversion:function(){e.callCallback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){e.callCallback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var i=this.ctx,n=t.defaults.global,a=this.options.ticks,o=e.getValueOrDefault(a.fontSize,n.defaultFontSize),r=e.getValueOrDefault(a.fontStyle,n.defaultFontStyle),s=e.getValueOrDefault(a.fontFamily,n.defaultFontFamily),l=e.fontString(o,r,s);i.font=l;var h,d=i.measureText(this.ticks[0]).width,u=i.measureText(this.ticks[this.ticks.length-1]).width;if(this.labelRotation=a.minRotation||0,this.paddingRight=0,this.paddingLeft=0,this.options.display&&this.isHorizontal()){this.paddingRight=u/2+3,this.paddingLeft=d/2+3,this.longestTextCache||(this.longestTextCache={});for(var c,f,g=e.longestText(i,l,this.ticks,this.longestTextCache),m=g,p=this.getPixelForTick(1)-this.getPixelForTick(0)-6;m>p&&this.labelRotation<a.maxRotation;){if(c=Math.cos(e.toRadians(this.labelRotation)),f=Math.sin(e.toRadians(this.labelRotation)),h=c*d,h+o/2>this.yLabelWidth&&(this.paddingLeft=h+o/2),this.paddingRight=o/2,f*g>this.maxHeight){this.labelRotation--;break}this.labelRotation++,m=c*g}}this.margins&&(this.paddingLeft=Math.max(this.paddingLeft-this.margins.left,0),this.paddingRight=Math.max(this.paddingRight-this.margins.right,0))},afterCalculateTickRotation:function(){e.callCallback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){e.callCallback(this.options.beforeFit,[this])},fit:function(){var i=this.minSize={width:0,height:0},n=this.options,a=t.defaults.global,o=n.ticks,r=n.scaleLabel,s=n.display,l=this.isHorizontal(),h=e.getValueOrDefault(o.fontSize,a.defaultFontSize),d=e.getValueOrDefault(o.fontStyle,a.defaultFontStyle),u=e.getValueOrDefault(o.fontFamily,a.defaultFontFamily),c=e.fontString(h,d,u),f=e.getValueOrDefault(r.fontSize,a.defaultFontSize),g=e.getValueOrDefault(r.fontStyle,a.defaultFontStyle),m=e.getValueOrDefault(r.fontFamily,a.defaultFontFamily),p=(e.fontString(f,g,m),n.gridLines.tickMarkLength);if(l?i.width=this.isFullWidth()?this.maxWidth-this.margins.left-this.margins.right:this.maxWidth:i.width=s?p:0,l?i.height=s?p:0:i.height=this.maxHeight,r.display&&s&&(l?i.height+=1.5*f:i.width+=1.5*f),o.display&&s){this.longestTextCache||(this.longestTextCache={});var b=e.longestText(this.ctx,c,this.ticks,this.longestTextCache);if(l){this.longestLabelWidth=b;var v=Math.sin(e.toRadians(this.labelRotation))*this.longestLabelWidth+1.5*h;i.height=Math.min(this.maxHeight,i.height+v),this.ctx.font=c;var y=this.ctx.measureText(this.ticks[0]).width,x=this.ctx.measureText(this.ticks[this.ticks.length-1]).width,k=Math.cos(e.toRadians(this.labelRotation)),_=Math.sin(e.toRadians(this.labelRotation));this.paddingLeft=0!==this.labelRotation?k*y+3:y/2+3,this.paddingRight=0!==this.labelRotation?_*(h/2)+3:x/2+3}else{var S=this.maxWidth-i.width,w=o.mirror;w?b=0:b+=this.options.ticks.padding,S>b?i.width+=b:i.width=this.maxWidth,this.paddingTop=h/2,this.paddingBottom=h/2}}this.margins&&(this.paddingLeft=Math.max(this.paddingLeft-this.margins.left,0),this.paddingTop=Math.max(this.paddingTop-this.margins.top,0),this.paddingRight=Math.max(this.paddingRight-this.margins.right,0),this.paddingBottom=Math.max(this.paddingBottom-this.margins.bottom,0)),this.width=i.width,this.height=i.height},afterFit:function(){e.callCallback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function i(t){return null===t||"undefined"==typeof t?NaN:"number"==typeof t&&isNaN(t)?NaN:"object"==typeof t?t instanceof Date||t.isValid?t:i(this.isHorizontal()?t.x:t.y):t},getLabelForIndex:e.noop,getPixelForValue:e.noop,getValueForPixel:e.noop,getPixelForTick:function(t,e){if(this.isHorizontal()){var i=this.width-(this.paddingLeft+this.paddingRight),n=i/Math.max(this.ticks.length-(this.options.gridLines.offsetGridLines?0:1),1),a=n*t+this.paddingLeft;e&&(a+=n/2);var o=this.left+Math.round(a);return o+=this.isFullWidth()?this.margins.left:0}var r=this.height-(this.paddingTop+this.paddingBottom);return this.top+t*(r/(this.ticks.length-1))},getPixelForDecimal:function(t){if(this.isHorizontal()){var e=this.width-(this.paddingLeft+this.paddingRight),i=e*t+this.paddingLeft,n=this.left+Math.round(i);return n+=this.isFullWidth()?this.margins.left:0}return this.top+t*this.height},getBasePixel:function(){var t=this,e=t.min,i=t.max;return t.getPixelForValue(t.beginAtZero?0:0>e&&0>i?i:e>0&&i>0?e:0)},draw:function(i){var n=this.options;if(n.display){var a,o,r,s,l,h=this.ctx,d=t.defaults.global,u=n.ticks,c=n.gridLines,f=n.scaleLabel,g=0!==this.labelRotation,m=u.autoSkip;u.maxTicksLimit&&(l=u.maxTicksLimit);var p=e.getValueOrDefault(u.fontColor,d.defaultFontColor),b=e.getValueOrDefault(u.fontSize,d.defaultFontSize),v=e.getValueOrDefault(u.fontStyle,d.defaultFontStyle),y=e.getValueOrDefault(u.fontFamily,d.defaultFontFamily),x=e.fontString(b,v,y),k=c.tickMarkLength,_=e.getValueOrDefault(f.fontColor,d.defaultFontColor),S=e.getValueOrDefault(f.fontSize,d.defaultFontSize),w=e.getValueOrDefault(f.fontStyle,d.defaultFontStyle),M=e.getValueOrDefault(f.fontFamily,d.defaultFontFamily),C=e.fontString(S,w,M),D=e.toRadians(this.labelRotation),T=Math.cos(D),P=(Math.sin(D),this.longestLabelWidth*T);if(h.fillStyle=p,this.isHorizontal()){a=!0;var A="bottom"===n.position?this.top:this.bottom-k,F="bottom"===n.position?this.top+k:this.bottom;if(o=!1,g&&(P/=2),(P+u.autoSkipPadding)*this.ticks.length>this.width-(this.paddingLeft+this.paddingRight)&&(o=1+Math.floor((P+u.autoSkipPadding)*this.ticks.length/(this.width-(this.paddingLeft+this.paddingRight)))),l&&this.ticks.length>l)for(;!o||this.ticks.length/(o||1)>l;)o||(o=1),o+=1;m||(o=!1),e.each(this.ticks,function(t,r){var s=this.ticks.length===r+1,l=o>1&&r%o>0||r%o===0&&r+o>=this.ticks.length;if((!l||s)&&void 0!==t&&null!==t){var d=this.getPixelForTick(r),f=this.getPixelForTick(r,c.offsetGridLines);c.display&&(r===("undefined"!=typeof this.zeroLineIndex?this.zeroLineIndex:0)?(h.lineWidth=c.zeroLineWidth,h.strokeStyle=c.zeroLineColor,a=!0):a&&(h.lineWidth=c.lineWidth,h.strokeStyle=c.color,a=!1),d+=e.aliasPixel(h.lineWidth),h.beginPath(),c.drawTicks&&(h.moveTo(d,A),h.lineTo(d,F)),c.drawOnChartArea&&(h.moveTo(d,i.top),h.lineTo(d,i.bottom)),h.stroke()),u.display&&(h.save(),h.translate(f+u.labelOffset,g?this.top+12:"top"===n.position?this.bottom-k:this.top+k),h.rotate(-1*D),h.font=x,h.textAlign=g?"right":"center",h.textBaseline=g?"middle":"top"===n.position?"bottom":"top",h.fillText(t,0,0),h.restore())}},this),f.display&&(h.textAlign="center",h.textBaseline="middle",h.fillStyle=_,h.font=C,r=this.left+(this.right-this.left)/2,s="bottom"===n.position?this.bottom-S/2:this.top+S/2,h.fillText(f.labelString,r,s))}else{a=!0;var I="right"===n.position?this.left:this.right-5,O="right"===n.position?this.left+5:this.right;if(e.each(this.ticks,function(t,o){if(void 0!==t&&null!==t){var r=this.getPixelForTick(o);if(c.display&&(o===("undefined"!=typeof this.zeroLineIndex?this.zeroLineIndex:0)?(h.lineWidth=c.zeroLineWidth,h.strokeStyle=c.zeroLineColor,a=!0):a&&(h.lineWidth=c.lineWidth,h.strokeStyle=c.color,a=!1),r+=e.aliasPixel(h.lineWidth),h.beginPath(),c.drawTicks&&(h.moveTo(I,r),h.lineTo(O,r)),c.drawOnChartArea&&(h.moveTo(i.left,r),h.lineTo(i.right,r)),h.stroke()),u.display){var s,l=this.getPixelForTick(o,c.offsetGridLines);h.save(),"left"===n.position?u.mirror?(s=this.right+u.padding,h.textAlign="left"):(s=this.right-u.padding,h.textAlign="right"):u.mirror?(s=this.left-u.padding,h.textAlign="right"):(s=this.left+u.padding,h.textAlign="left"),h.translate(s,l+u.labelOffset),h.rotate(-1*D),h.font=x,h.textBaseline="middle",h.fillText(t,0,0),h.restore()}}},this),f.display){r="left"===n.position?this.left+S/2:this.right-S/2,s=this.top+(this.bottom-this.top)/2;var R="left"===n.position?-.5*Math.PI:.5*Math.PI;h.save(),h.translate(r,s),h.rotate(R),h.textAlign="center",h.fillStyle=_,h.font=C,h.textBaseline="middle",h.fillText(f.labelString,0,0),h.restore()}}if(c.drawBorder){h.lineWidth=c.lineWidth,h.strokeStyle=c.color;var W=this.left,V=this.right,L=this.top,B=this.bottom,z=e.aliasPixel(h.lineWidth);this.isHorizontal()?(L=B="top"===n.position?this.bottom:this.top,L+=z,B+=z):(W=V="left"===n.position?this.right:this.left,W+=z,V+=z),h.beginPath(),h.moveTo(W,L),h.lineTo(V,B),h.stroke()}}}})}},{}],31:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,i,n){this.constructors[t]=i,this.defaults[t]=e.clone(n)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(i){return this.defaults.hasOwnProperty(i)?e.scaleMerge(t.defaults.scale,this.defaults[i]):{}},updateScaleDefaults:function(t,i){var n=this.defaults;n.hasOwnProperty(t)&&(n[t]=e.extend(n[t],i))},addScalesToLayout:function(i){e.each(i.scales,function(e){t.layoutService.addBox(i,e)})}}}},{}],32:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.title={display:!1,position:"top",fullWidth:!0,fontStyle:"bold",padding:10,text:""};var i=e.noop;t.Title=t.Element.extend({initialize:function(i){e.extend(this,i),this.options=e.configMerge(t.defaults.global.title,i.options),this.legendHitBoxes=[]},beforeUpdate:i,update:function(t,e,i){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this.margins=i,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeBuildLabels(),this.buildLabels(),this.afterBuildLabels(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:i,beforeSetDimensions:i,setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0,this.minSize={width:0,height:0}},afterSetDimensions:i,beforeBuildLabels:i,buildLabels:i,afterBuildLabels:i,beforeFit:i,fit:function(){var i=this,n=(i.ctx,e.getValueOrDefault),a=i.options,o=t.defaults.global,r=a.display,s=n(a.fontSize,o.defaultFontSize),l=i.minSize;i.isHorizontal()?(l.width=i.maxWidth,l.height=r?s+2*a.padding:0):(l.width=r?s+2*a.padding:0,l.height=i.maxHeight),i.width=l.width,i.height=l.height},afterFit:i,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var i=this,n=i.ctx,a=e.getValueOrDefault,o=i.options,r=t.defaults.global;if(o.display){var s,l,h=a(o.fontSize,r.defaultFontSize),d=a(o.fontStyle,r.defaultFontStyle),u=a(o.fontFamily,r.defaultFontFamily),c=e.fontString(h,d,u),f=0,g=i.top,m=i.left,p=i.bottom,b=i.right;n.fillStyle=a(o.fontColor,r.defaultFontColor),n.font=c,i.isHorizontal()?(s=m+(b-m)/2,l=g+(p-g)/2):(s="left"===o.position?m+h/2:b-h/2,l=g+(p-g)/2,f=Math.PI*("left"===o.position?-.5:.5)),n.save(),n.translate(s,l),n.rotate(f),n.textAlign="center",n.textBaseline="middle",n.fillText(o.text,0,0),n.restore()}}})}},{}],33:[function(t,e,i){"use strict";e.exports=function(t){function e(t,e){return e&&(i.isArray(e)?t=t.concat(e):t.push(e)),t}var i=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"single",backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleColor:"#fff",titleAlign:"left",bodySpacing:2,bodyColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,yAlign:"center",xAlign:"center",caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",callbacks:{beforeTitle:i.noop,title:function(t,e){var i="";return t.length>0&&(t[0].xLabel?i=t[0].xLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},afterTitle:i.noop,beforeBody:i.noop,beforeLabel:i.noop,label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i+": "+t.yLabel},afterLabel:i.noop,afterBody:i.noop,beforeFooter:i.noop,footer:i.noop,afterFooter:i.noop}},t.Tooltip=t.Element.extend({initialize:function(){var e=t.defaults.global,n=this._options,a=n.tooltips;i.extend(this,{_model:{xPadding:a.xPadding,yPadding:a.yPadding,xAlign:a.yAlign,yAlign:a.xAlign,bodyColor:a.bodyColor,_bodyFontFamily:i.getValueOrDefault(a.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:i.getValueOrDefault(a.bodyFontStyle,e.defaultFontStyle),_bodyAlign:a.bodyAlign,bodyFontSize:i.getValueOrDefault(a.bodyFontSize,e.defaultFontSize),bodySpacing:a.bodySpacing,titleColor:a.titleColor,_titleFontFamily:i.getValueOrDefault(a.titleFontFamily,e.defaultFontFamily),_titleFontStyle:i.getValueOrDefault(a.titleFontStyle,e.defaultFontStyle),titleFontSize:i.getValueOrDefault(a.titleFontSize,e.defaultFontSize),_titleAlign:a.titleAlign,titleSpacing:a.titleSpacing,titleMarginBottom:a.titleMarginBottom,footerColor:a.footerColor,_footerFontFamily:i.getValueOrDefault(a.footerFontFamily,e.defaultFontFamily),_footerFontStyle:i.getValueOrDefault(a.footerFontStyle,e.defaultFontStyle),footerFontSize:i.getValueOrDefault(a.footerFontSize,e.defaultFontSize),_footerAlign:a.footerAlign,footerSpacing:a.footerSpacing,footerMarginTop:a.footerMarginTop,caretSize:a.caretSize,cornerRadius:a.cornerRadius,backgroundColor:a.backgroundColor,opacity:0,legendColorBackground:a.multiKeyBackground}})},getTitle:function(){var t=this._options.tooltips.callbacks.beforeTitle.apply(this,arguments),i=this._options.tooltips.callbacks.title.apply(this,arguments),n=this._options.tooltips.callbacks.afterTitle.apply(this,arguments),a=[];return a=e(a,t),a=e(a,i),a=e(a,n)},getBeforeBody:function(){var t=this._options.tooltips.callbacks.beforeBody.apply(this,arguments);return i.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var n=[];return i.each(t,function(t){i.pushAllIfDefined(this._options.tooltips.callbacks.beforeLabel.call(this,t,e),n),i.pushAllIfDefined(this._options.tooltips.callbacks.label.call(this,t,e),n),i.pushAllIfDefined(this._options.tooltips.callbacks.afterLabel.call(this,t,e),n)},this),n},getAfterBody:function(){var t=this._options.tooltips.callbacks.afterBody.apply(this,arguments);return i.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this._options.tooltips.callbacks.beforeFooter.apply(this,arguments),i=this._options.tooltips.callbacks.footer.apply(this,arguments),n=this._options.tooltips.callbacks.afterFooter.apply(this,arguments),a=[];return a=e(a,t),a=e(a,i),a=e(a,n)},getAveragePosition:function(t){if(!t.length)return!1;var e=[],n=[];i.each(t,function(t){if(t&&t.hasValue()){var i=t.tooltipPosition();e.push(i.x),n.push(i.y)}});for(var a=0,o=0,r=0;r<e.length;r++)a+=e[r],o+=n[r];return{x:Math.round(a/e.length),y:Math.round(o/e.length)}},update:function(t){if(this._active.length){this._model.opacity=1;var e,n=this._active[0],a=[],o=[];if("single"===this._options.tooltips.mode){var r=n._yScale||n._scale;o.push({xLabel:n._xScale?n._xScale.getLabelForIndex(n._index,n._datasetIndex):"",yLabel:r?r.getLabelForIndex(n._index,n._datasetIndex):"",index:n._index,datasetIndex:n._datasetIndex}),e=this.getAveragePosition(this._active)}else i.each(this._data.datasets,function(t,e){if(this._chartInstance.isDatasetVisible(e)){var i=this._chartInstance.getDatasetMeta(e),a=i.data[n._index];if(a){var r=n._yScale||n._scale;o.push({xLabel:a._xScale?a._xScale.getLabelForIndex(a._index,a._datasetIndex):"",yLabel:r?r.getLabelForIndex(a._index,a._datasetIndex):"",index:n._index,datasetIndex:e})}}},this),i.each(this._active,function(t){t&&a.push({borderColor:t._view.borderColor,backgroundColor:t._view.backgroundColor})},null),e=this.getAveragePosition(this._active);i.extend(this._model,{title:this.getTitle(o,this._data),beforeBody:this.getBeforeBody(o,this._data),body:this.getBody(o,this._data),afterBody:this.getAfterBody(o,this._data),footer:this.getFooter(o,this._data)}),i.extend(this._model,{x:Math.round(e.x),y:Math.round(e.y),caretPadding:i.getValueOrDefault(e.padding,2),labelColors:a});var s=this.getTooltipSize(this._model);this.determineAlignment(s),i.extend(this._model,this.getBackgroundPoint(this._model,s))}else this._model.opacity=0;return t&&this._options.tooltips.custom&&this._options.tooltips.custom.call(this,this._model),this},getTooltipSize:function(t){var e=this._chart.ctx,n={height:2*t.yPadding,width:0},a=t.body.length+t.beforeBody.length+t.afterBody.length;return n.height+=t.title.length*t.titleFontSize,n.height+=(t.title.length-1)*t.titleSpacing,n.height+=t.title.length?t.titleMarginBottom:0,n.height+=a*t.bodyFontSize,n.height+=a?(a-1)*t.bodySpacing:0,n.height+=t.footer.length?t.footerMarginTop:0,n.height+=t.footer.length*t.footerFontSize,n.height+=t.footer.length?(t.footer.length-1)*t.footerSpacing:0,e.font=i.fontString(t.titleFontSize,t._titleFontStyle,t._titleFontFamily),i.each(t.title,function(t){n.width=Math.max(n.width,e.measureText(t).width)}),e.font=i.fontString(t.bodyFontSize,t._bodyFontStyle,t._bodyFontFamily),i.each(t.beforeBody.concat(t.afterBody),function(t){n.width=Math.max(n.width,e.measureText(t).width)}),i.each(t.body,function(i){n.width=Math.max(n.width,e.measureText(i).width+("single"!==this._options.tooltips.mode?t.bodyFontSize+2:0))},this),e.font=i.fontString(t.footerFontSize,t._footerFontStyle,t._footerFontFamily),i.each(t.footer,function(t){n.width=Math.max(n.width,e.measureText(t).width)}),n.width+=2*t.xPadding,n},determineAlignment:function(t){this._model.y<t.height?this._model.yAlign="top":this._model.y>this._chart.height-t.height&&(this._model.yAlign="bottom");var e,i,n,a,o,r=this,s=(this._chartInstance.chartArea.left+this._chartInstance.chartArea.right)/2,l=(this._chartInstance.chartArea.top+this._chartInstance.chartArea.bottom)/2;"center"===this._model.yAlign?(e=function(t){return s>=t},i=function(t){return t>s}):(e=function(e){return e<=t.width/2},i=function(e){return e>=r._chart.width-t.width/2}),n=function(e){return e+t.width>r._chart.width},a=function(e){return e-t.width<0},o=function(t){return l>=t?"top":"bottom"},e(this._model.x)?(this._model.xAlign="left",n(this._model.x)&&(this._model.xAlign="center",this._model.yAlign=o(this._model.y))):i(this._model.x)&&(this._model.xAlign="right",a(this._model.x)&&(this._model.xAlign="center",this._model.yAlign=o(this._model.y)))},getBackgroundPoint:function(t,e){var i={
+x:t.x,y:t.y};return"right"===t.xAlign?i.x-=e.width:"center"===t.xAlign&&(i.x-=e.width/2),"top"===t.yAlign?i.y+=t.caretPadding+t.caretSize:"bottom"===t.yAlign?i.y-=e.height+t.caretPadding+t.caretSize:i.y-=e.height/2,"center"===t.yAlign?"left"===t.xAlign?i.x+=t.caretPadding+t.caretSize:"right"===t.xAlign&&(i.x-=t.caretPadding+t.caretSize):"left"===t.xAlign?i.x-=t.cornerRadius+t.caretPadding:"right"===t.xAlign&&(i.x+=t.cornerRadius+t.caretPadding),i},drawCaret:function(t,e,n,a){var o,r,s,l,h,d,u=this._view,c=this._chart.ctx;"center"===u.yAlign?("left"===u.xAlign?(o=t.x,r=o-u.caretSize,s=o):(o=t.x+e.width,r=o+u.caretSize,s=o),h=t.y+e.height/2,l=h-u.caretSize,d=h+u.caretSize):("left"===u.xAlign?(o=t.x+u.cornerRadius,r=o+u.caretSize,s=r+u.caretSize):"right"===u.xAlign?(o=t.x+e.width-u.cornerRadius,r=o-u.caretSize,s=r-u.caretSize):(r=t.x+e.width/2,o=r-u.caretSize,s=r+u.caretSize),"top"===u.yAlign?(l=t.y,h=l-u.caretSize,d=l):(l=t.y+e.height,h=l+u.caretSize,d=l));var f=i.color(u.backgroundColor);c.fillStyle=f.alpha(n*f.alpha()).rgbString(),c.beginPath(),c.moveTo(o,l),c.lineTo(r,h),c.lineTo(s,d),c.closePath(),c.fill()},drawTitle:function(t,e,n,a){if(e.title.length){n.textAlign=e._titleAlign,n.textBaseline="top";var o=i.color(e.titleColor);n.fillStyle=o.alpha(a*o.alpha()).rgbString(),n.font=i.fontString(e.titleFontSize,e._titleFontStyle,e._titleFontFamily),i.each(e.title,function(i,a){n.fillText(i,t.x,t.y),t.y+=e.titleFontSize+e.titleSpacing,a+1===e.title.length&&(t.y+=e.titleMarginBottom-e.titleSpacing)})}},drawBody:function(t,e,n,a){n.textAlign=e._bodyAlign,n.textBaseline="top";var o=i.color(e.bodyColor);n.fillStyle=o.alpha(a*o.alpha()).rgbString(),n.font=i.fontString(e.bodyFontSize,e._bodyFontStyle,e._bodyFontFamily),i.each(e.beforeBody,function(i){n.fillText(i,t.x,t.y),t.y+=e.bodyFontSize+e.bodySpacing}),i.each(e.body,function(o,r){"single"!==this._options.tooltips.mode&&(n.fillStyle=i.color(e.legendColorBackground).alpha(a).rgbaString(),n.fillRect(t.x,t.y,e.bodyFontSize,e.bodyFontSize),n.strokeStyle=i.color(e.labelColors[r].borderColor).alpha(a).rgbaString(),n.strokeRect(t.x,t.y,e.bodyFontSize,e.bodyFontSize),n.fillStyle=i.color(e.labelColors[r].backgroundColor).alpha(a).rgbaString(),n.fillRect(t.x+1,t.y+1,e.bodyFontSize-2,e.bodyFontSize-2),n.fillStyle=i.color(e.bodyColor).alpha(a).rgbaString()),n.fillText(o,t.x+("single"!==this._options.tooltips.mode?e.bodyFontSize+2:0),t.y),t.y+=e.bodyFontSize+e.bodySpacing},this),i.each(e.afterBody,function(i){n.fillText(i,t.x,t.y),t.y+=e.bodyFontSize}),t.y-=e.bodySpacing},drawFooter:function(t,e,n,a){if(e.footer.length){t.y+=e.footerMarginTop,n.textAlign=e._footerAlign,n.textBaseline="top";var o=i.color(e.footerColor);n.fillStyle=o.alpha(a*o.alpha()).rgbString(),n.font=i.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),i.each(e.footer,function(i){n.fillText(i,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing})}},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n=e.caretPadding,a=this.getTooltipSize(e),o={x:e.x,y:e.y},r=Math.abs(e.opacity<.001)?0:e.opacity;if(this._options.tooltips.enabled){var s=i.color(e.backgroundColor);t.fillStyle=s.alpha(r*s.alpha()).rgbString(),i.drawRoundedRectangle(t,o.x,o.y,a.width,a.height,e.cornerRadius),t.fill(),this.drawCaret(o,a,r,n),o.x+=e.xPadding,o.y+=e.yPadding,this.drawTitle(o,e,t,r),this.drawBody(o,e,t,r),this.drawFooter(o,e,t,r)}}}})}},{}],34:[function(t,e,i){"use strict";e.exports=function(t,e){var i=t.helpers,n=t.defaults.global;n.elements.arc={backgroundColor:n.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2):!1},inRange:function(t,e){var n=this._view;if(n){for(var a=i.getAngleFromPoint(n,{x:t,y:e}),o=a.angle,r=a.distance,s=n.startAngle,l=n.endAngle;s>l;)l+=2*Math.PI;for(;o>l;)o-=2*Math.PI;for(;s>o;)o+=2*Math.PI;var h=o>=s&&l>=o,d=r>=n.innerRadius&&r<=n.outerRadius;return h&&d}return!1},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,i=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},draw:function(){var t=this._chart.ctx,e=this._view,i=e.startAngle,n=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,i,n),t.arc(e.x,e.y,e.innerRadius,n,i,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],35:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:i.defaultColor,borderWidth:3,borderColor:i.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",fill:!0},t.elements.Line=t.Element.extend({lineToNextPoint:function(t,e,i,n,a){var o=this._chart.ctx;e._view.skip?n.call(this,t,e,i):t._view.skip?a.call(this,t,e,i):0===e._view.tension?o.lineTo(e._view.x,e._view.y):o.bezierCurveTo(t._view.controlPointNextX,t._view.controlPointNextY,e._view.controlPointPreviousX,e._view.controlPointPreviousY,e._view.x,e._view.y)},draw:function(){function t(t){r._view.skip||s._view.skip?t&&o.lineTo(n._view.scaleZero.x,n._view.scaleZero.y):o.bezierCurveTo(s._view.controlPointNextX,s._view.controlPointNextY,r._view.controlPointPreviousX,r._view.controlPointPreviousY,r._view.x,r._view.y)}var n=this,a=this._view,o=this._chart.ctx,r=this._children[0],s=this._children[this._children.length-1];o.save(),this._children.length>0&&a.fill&&(o.beginPath(),e.each(this._children,function(t,i){var n=e.previousItem(this._children,i),r=e.nextItem(this._children,i);0===i?(this._loop?o.moveTo(a.scaleZero.x,a.scaleZero.y):o.moveTo(t._view.x,a.scaleZero),t._view.skip?this._loop||o.moveTo(r._view.x,this._view.scaleZero):o.lineTo(t._view.x,t._view.y)):this.lineToNextPoint(n,t,r,function(t,e,i){this._loop?o.lineTo(this._view.scaleZero.x,this._view.scaleZero.y):(o.lineTo(t._view.x,this._view.scaleZero),o.moveTo(i._view.x,this._view.scaleZero))},function(t,e){o.lineTo(e._view.x,e._view.y)})},this),this._loop?t(!0):(o.lineTo(this._children[this._children.length-1]._view.x,a.scaleZero),o.lineTo(this._children[0]._view.x,a.scaleZero)),o.fillStyle=a.backgroundColor||i.defaultColor,o.closePath(),o.fill());var l=i.elements.line;o.lineCap=a.borderCapStyle||l.borderCapStyle,o.setLineDash&&o.setLineDash(a.borderDash||l.borderDash),o.lineDashOffset=a.borderDashOffset||l.borderDashOffset,o.lineJoin=a.borderJoinStyle||l.borderJoinStyle,o.lineWidth=a.borderWidth||l.borderWidth,o.strokeStyle=a.borderColor||i.defaultColor,o.beginPath(),e.each(this._children,function(t,i){var n=e.previousItem(this._children,i),a=e.nextItem(this._children,i);0===i?o.moveTo(t._view.x,t._view.y):this.lineToNextPoint(n,t,a,function(t,e,i){o.moveTo(i._view.x,i._view.y)},function(t,e){o.moveTo(e._view.x,e._view.y)})},this),this._loop&&this._children.length>0&&t(),o.stroke(),o.restore()}})}},{}],36:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global,n=i.defaultColor;i.elements.point={radius:3,pointStyle:"circle",backgroundColor:n,borderWidth:1,borderColor:n,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var i=this._view;return i?Math.pow(t-i.x,2)+Math.pow(e-i.y,2)<Math.pow(i.hitRadius+i.radius,2):!1},inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2):!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(){var t,a,o,r,s,l,h=this._view,d=this._chart.ctx,u=h.pointStyle,c=h.radius,f=h.x,g=h.y;if(!h.skip){if("object"==typeof u&&(t=u.toString(),"[object HTMLImageElement]"===t||"[object HTMLCanvasElement]"===t))return void d.drawImage(u,f-u.width/2,g-u.height/2);if(!(isNaN(c)||0>=c)){switch(d.strokeStyle=h.borderColor||n,d.lineWidth=e.getValueOrDefault(h.borderWidth,i.elements.point.borderWidth),d.fillStyle=h.backgroundColor||n,u){default:d.beginPath(),d.arc(f,g,c,0,2*Math.PI),d.closePath(),d.fill();break;case"triangle":d.beginPath(),a=3*c/Math.sqrt(3),s=a*Math.sqrt(3)/2,d.moveTo(f-a/2,g+s/3),d.lineTo(f+a/2,g+s/3),d.lineTo(f,g-2*s/3),d.closePath(),d.fill();break;case"rect":l=1/Math.SQRT2*c,d.fillRect(f-l,g-l,2*l,2*l),d.strokeRect(f-l,g-l,2*l,2*l);break;case"rectRot":d.translate(f,g),d.rotate(Math.PI/4),l=1/Math.SQRT2*c,d.fillRect(-l,-l,2*l,2*l),d.strokeRect(-l,-l,2*l,2*l),d.setTransform(1,0,0,1,0,0);break;case"cross":d.beginPath(),d.moveTo(f,g+c),d.lineTo(f,g-c),d.moveTo(f-c,g),d.lineTo(f+c,g),d.closePath();break;case"crossRot":d.beginPath(),o=Math.cos(Math.PI/4)*c,r=Math.sin(Math.PI/4)*c,d.moveTo(f-o,g-r),d.lineTo(f+o,g+r),d.moveTo(f-o,g+r),d.lineTo(f+o,g-r),d.closePath();break;case"star":d.beginPath(),d.moveTo(f,g+c),d.lineTo(f,g-c),d.moveTo(f-c,g),d.lineTo(f+c,g),o=Math.cos(Math.PI/4)*c,r=Math.sin(Math.PI/4)*c,d.moveTo(f-o,g-r),d.lineTo(f+o,g+r),d.moveTo(f-o,g+r),d.lineTo(f+o,g-r),d.closePath();break;case"line":d.beginPath(),d.moveTo(f-c,g),d.lineTo(f+c,g),d.closePath();break;case"dash":d.beginPath(),d.moveTo(f,g),d.lineTo(f+c,g),d.closePath()}d.stroke()}}}})}},{}],37:[function(t,e,i){"use strict";e.exports=function(t){var e=(t.helpers,t.defaults.global);e.elements.rectangle={backgroundColor:e.defaultColor,borderWidth:0,borderColor:e.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return l[(d+t)%4]}var e=this._chart.ctx,i=this._view,n=i.width/2,a=i.x-n,o=i.x+n,r=i.base-(i.base-i.y),s=i.borderWidth/2;i.borderWidth&&(a+=s,o-=s,r+=s),e.beginPath(),e.fillStyle=i.backgroundColor,e.strokeStyle=i.borderColor,e.lineWidth=i.borderWidth;var l=[[a,i.base],[a,r],[o,r],[o,i.base]],h=["bottom","left","top","right"],d=h.indexOf(i.borderSkipped,0);-1===d&&(d=0),e.moveTo.apply(e,t(0));for(var u=1;4>u;u++)e.lineTo.apply(e,t(u));e.fill(),i.borderWidth&&e.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=this._view;return i?i.y<i.base?t>=i.x-i.width/2&&t<=i.x+i.width/2&&e>=i.y&&e<=i.base:t>=i.x-i.width/2&&t<=i.x+i.width/2&&e>=i.base&&e<=i.y:!1},inLabelRange:function(t){var e=this._view;return e?t>=e.x-e.width/2&&t<=e.x+e.width/2:!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],38:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"bottom"},n=t.Scale.extend({determineDataLimits:function(){this.minIndex=0,this.maxIndex=this.chart.data.labels.length-1;var t;void 0!==this.options.ticks.min&&(t=e.indexOf(this.chart.data.labels,this.options.ticks.min),this.minIndex=-1!==t?t:this.minIndex),void 0!==this.options.ticks.max&&(t=e.indexOf(this.chart.data.labels,this.options.ticks.max),this.maxIndex=-1!==t?t:this.maxIndex),this.min=this.chart.data.labels[this.minIndex],this.max=this.chart.data.labels[this.maxIndex]},buildTicks:function(t){this.ticks=0===this.minIndex&&this.maxIndex===this.chart.data.labels.length-1?this.chart.data.labels:this.chart.data.labels.slice(this.minIndex,this.maxIndex+1)},getLabelForIndex:function(t,e){return this.ticks[t]},getPixelForValue:function(t,e,i,n){var a=Math.max(this.maxIndex+1-this.minIndex-(this.options.gridLines.offsetGridLines?0:1),1);if(this.isHorizontal()){var o=this.width-(this.paddingLeft+this.paddingRight),r=o/a,s=r*(e-this.minIndex)+this.paddingLeft;return this.options.gridLines.offsetGridLines&&n&&(s+=r/2),this.left+Math.round(s)}var l=this.height-(this.paddingTop+this.paddingBottom),h=l/a,d=h*(e-this.minIndex)+this.paddingTop;return this.options.gridLines.offsetGridLines&&n&&(d+=h/2),this.top+Math.round(d)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e,i=Math.max(this.ticks.length-(this.options.gridLines.offsetGridLines?0:1),1),n=this.isHorizontal(),a=n?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),o=a/i;return this.options.gridLines.offsetGridLines&&(t-=o/2),t-=n?this.paddingLeft:this.paddingTop,e=0>=t?0:Math.round(t/o)}});t.scaleService.registerScaleType("category",n,i)}},{}],39:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"left",ticks:{callback:function(t,i,n){var a=n.length>3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var o=e.log10(Math.abs(a)),r="";if(0!==t){var s=-1*Math.floor(o);s=Math.max(Math.min(s,20),0),r=t.toFixed(s)}else r="0";return r}}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===i.id:t.yAxisID===i.id}var i=this,n=i.options,a=n.ticks,o=i.chart,r=o.data,s=r.datasets,l=i.isHorizontal();if(i.min=null,i.max=null,n.stacked){var h={},d=!1,u=!1;e.each(s,function(a,r){var s=o.getDatasetMeta(r);void 0===h[s.type]&&(h[s.type]={positiveValues:[],negativeValues:[]});var l=h[s.type].positiveValues,c=h[s.type].negativeValues;o.isDatasetVisible(r)&&t(s)&&e.each(a.data,function(t,e){var a=+i.getRightValue(t);isNaN(a)||s.data[e].hidden||(l[e]=l[e]||0,c[e]=c[e]||0,n.relativePoints?l[e]=100:0>a?(u=!0,c[e]+=a):(d=!0,l[e]+=a))})}),e.each(h,function(t){var n=t.positiveValues.concat(t.negativeValues),a=e.min(n),o=e.max(n);i.min=null===i.min?a:Math.min(i.min,a),i.max=null===i.max?o:Math.max(i.max,o)})}else e.each(s,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&e.each(n.data,function(t,e){var n=+i.getRightValue(t);isNaN(n)||r.data[e].hidden||(null===i.min?i.min=n:n<i.min&&(i.min=n),null===i.max?i.max=n:n>i.max&&(i.max=n))})});if(a.beginAtZero){var c=e.sign(i.min),f=e.sign(i.max);0>c&&0>f?i.max=0:c>0&&f>0&&(i.min=0)}void 0!==a.min?i.min=a.min:void 0!==a.suggestedMin&&(i.min=Math.min(i.min,a.suggestedMin)),void 0!==a.max?i.max=a.max:void 0!==a.suggestedMax&&(i.max=Math.max(i.max,a.suggestedMax)),i.min===i.max&&(i.max++,a.beginAtZero||i.min--)},buildTicks:function(){var i,n=this,a=n.options,o=a.ticks,r=e.getValueOrDefault,s=n.isHorizontal(),l=n.ticks=[];if(s)i=Math.min(o.maxTicksLimit?o.maxTicksLimit:11,Math.ceil(n.width/50));else{var h=r(o.fontSize,t.defaults.global.defaultFontSize);i=Math.min(o.maxTicksLimit?o.maxTicksLimit:11,Math.ceil(n.height/(2*h)))}i=Math.max(2,i);var d,u=o.fixedStepSize&&o.fixedStepSize>0||o.stepSize&&o.stepSize>0;if(u)d=r(o.fixedStepSize,o.stepSize);else{var c=e.niceNum(n.max-n.min,!1);d=e.niceNum(c/(i-1),!0)}var f=Math.floor(n.min/d)*d,g=Math.ceil(n.max/d)*d,m=(g-f)/d;m=e.almostEquals(m,Math.round(m),d/1e3)?Math.round(m):Math.ceil(m),l.push(void 0!==o.min?o.min:f);for(var p=1;m>p;++p)l.push(f+p*d);l.push(void 0!==o.max?o.max:g),s||l.reverse(),n.max=e.max(l),n.min=e.min(l),o.reverse?(l.reverse(),n.start=n.max,n.end=n.min):(n.start=n.min,n.end=n.max)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)},getPixelForValue:function(t,e,i,n){var a,o,r=this,s=r.paddingLeft,l=r.paddingBottom,h=r.start,d=+r.getRightValue(t),u=r.end-h;return r.isHorizontal()?(o=r.width-(s+r.paddingRight),a=r.left+o/u*(d-h),Math.round(a+s)):(o=r.height-(r.paddingTop+l),a=r.bottom-l-o/u*(d-h),Math.round(a))},getValueForPixel:function(t){var e=this,i=e.isHorizontal(),n=e.paddingLeft,a=e.paddingBottom,o=i?e.width-(n+e.paddingRight):e.height-(e.paddingTop+a),r=(i?t-e.left-n:e.bottom-a-t)/o;return e.start+(e.end-e.start)*r},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticksAsNumbers[t],null,null,e)}});t.scaleService.registerScaleType("linear",n,i)}},{}],40:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"left",ticks:{callback:function(t,i,n){var a=t/Math.pow(10,Math.floor(e.log10(t)));return 1===a||2===a||5===a||0===i||i===n.length-1?t.toExponential():""}}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return h?t.xAxisID===i.id:t.yAxisID===i.id}var i=this,n=i.options,a=n.ticks,o=i.chart,r=o.data,s=r.datasets,l=e.getValueOrDefault,h=i.isHorizontal();if(i.min=null,i.max=null,n.stacked){var d={};e.each(s,function(a,r){var s=o.getDatasetMeta(r);o.isDatasetVisible(r)&&t(s)&&(void 0===d[s.type]&&(d[s.type]=[]),e.each(a.data,function(t,e){var a=d[s.type],o=+i.getRightValue(t);isNaN(o)||s.data[e].hidden||(a[e]=a[e]||0,n.relativePoints?a[e]=100:a[e]+=o)}))}),e.each(d,function(t){var n=e.min(t),a=e.max(t);i.min=null===i.min?n:Math.min(i.min,n),i.max=null===i.max?a:Math.max(i.max,a)})}else e.each(s,function(n,a){var r=o.getDatasetMeta(a);o.isDatasetVisible(a)&&t(r)&&e.each(n.data,function(t,e){var n=+i.getRightValue(t);isNaN(n)||r.data[e].hidden||(null===i.min?i.min=n:n<i.min&&(i.min=n),null===i.max?i.max=n:n>i.max&&(i.max=n))})});i.min=l(a.min,i.min),i.max=l(a.max,i.max),i.min===i.max&&(0!==i.min&&null!==i.min?(i.min=Math.pow(10,Math.floor(e.log10(i.min))-1),i.max=Math.pow(10,Math.floor(e.log10(i.max))+1)):(i.min=1,i.max=10))},buildTicks:function(){for(var t=this,i=t.options,n=i.ticks,a=e.getValueOrDefault,o=t.ticks=[],r=a(n.min,Math.pow(10,Math.floor(e.log10(t.min))));r<t.max;){o.push(r);var s=Math.floor(e.log10(r)),l=Math.floor(r/Math.pow(10,s))+1;10===l&&(l=1,++s),r=l*Math.pow(10,s)}var h=a(n.max,r);o.push(h),t.isHorizontal()||o.reverse(),t.max=e.max(o),t.min=e.min(o),n.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickValues[t],null,null,e)},getPixelForValue:function(t,i,n,a){var o,r,s=this,l=s.start,h=+s.getRightValue(t),d=e.log10(s.end)-e.log10(l),u=s.paddingTop,c=s.paddingBottom,f=s.paddingLeft;return s.isHorizontal()?0===h?r=s.left+f:(o=s.width-(f+s.paddingRight),r=s.left+o/d*(e.log10(h)-e.log10(l)),r+=f):0===h?r=s.top+u:(o=s.height-(u+c),r=s.bottom-c-o/d*(e.log10(h)-e.log10(l))),r},getValueForPixel:function(t){var i,n,a=this,o=e.log10(a.end)-e.log10(a.start);return a.isHorizontal()?(n=a.width-(a.paddingLeft+a.paddingRight),i=a.start*Math.pow(10,(t-a.left-a.paddingLeft)*o/n)):(n=a.height-(a.paddingTop+a.paddingBottom),i=Math.pow(10,(a.bottom-a.paddingBottom-t)*o/n)/a.start),i}});t.scaleService.registerScaleType("logarithmic",n,i)}},{}],41:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global,n={display:!0,animate:!0,lineArc:!1,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2},pointLabels:{fontSize:10,callback:function(t){return t}}},a=t.Scale.extend({getValueCount:function(){return this.chart.data.labels.length},setDimensions:function(){var t=this.options;this.width=this.maxWidth,this.height=this.maxHeight,this.xCenter=Math.round(this.width/2),this.yCenter=Math.round(this.height/2);var n=e.min([this.height,this.width]),a=e.getValueOrDefault(t.ticks.fontSize,i.defaultFontSize);this.drawingArea=t.display?n/2-(a/2+t.ticks.backdropPaddingY):n/2},determineDataLimits:function(){if(this.min=null,this.max=null,e.each(this.chart.data.datasets,function(t,i){if(this.chart.isDatasetVisible(i)){var n=this.chart.getDatasetMeta(i);e.each(t.data,function(t,e){var i=+this.getRightValue(t);isNaN(i)||n.data[e].hidden||(null===this.min?this.min=i:i<this.min&&(this.min=i),null===this.max?this.max=i:i>this.max&&(this.max=i))},this)}},this),this.options.ticks.beginAtZero){var t=e.sign(this.min),i=e.sign(this.max);0>t&&0>i?this.max=0:t>0&&i>0&&(this.min=0)}void 0!==this.options.ticks.min?this.min=this.options.ticks.min:void 0!==this.options.ticks.suggestedMin&&(this.min=Math.min(this.min,this.options.ticks.suggestedMin)),void 0!==this.options.ticks.max?this.max=this.options.ticks.max:void 0!==this.options.ticks.suggestedMax&&(this.max=Math.max(this.max,this.options.ticks.suggestedMax)),this.min===this.max&&(this.min--,this.max++)},buildTicks:function(){this.ticks=[];var t=e.getValueOrDefault(this.options.ticks.fontSize,i.defaultFontSize),n=Math.min(this.options.ticks.maxTicksLimit?this.options.ticks.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*t)));n=Math.max(2,n);var a=e.niceNum(this.max-this.min,!1),o=e.niceNum(a/(n-1),!0),r=Math.floor(this.min/o)*o,s=Math.ceil(this.max/o)*o,l=Math.ceil((s-r)/o);this.ticks.push(void 0!==this.options.ticks.min?this.options.ticks.min:r);for(var h=1;l>h;++h)this.ticks.push(r+h*o);this.ticks.push(void 0!==this.options.ticks.max?this.options.ticks.max:s),this.max=e.max(this.ticks),this.min=e.min(this.ticks),this.options.ticks.reverse?(this.ticks.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),this.zeroLineIndex=this.ticks.indexOf(0)},convertTicksToLabels:function(){t.Scale.prototype.convertTicksToLabels.call(this),this.pointLabels=this.chart.data.labels.map(this.options.pointLabels.callback,this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,n,a,o,r,s,l,h,d,u,c,f,g=this.options.pointLabels,m=e.getValueOrDefault(g.fontSize,i.defaultFontSize),p=e.getValueOrDefault(g.fontStyle,i.defaultFontStyle),b=e.getValueOrDefault(g.fontFamily,i.defaultFontFamily),v=e.fontString(m,p,b),y=e.min([this.height/2-m-5,this.width/2]),x=this.width,k=0;for(this.ctx.font=v,n=0;n<this.getValueCount();n++)t=this.getPointPosition(n,y),a=this.ctx.measureText(this.pointLabels[n]?this.pointLabels[n]:"").width+5,0===n||n===this.getValueCount()/2?(o=a/2,t.x+o>x&&(x=t.x+o,r=n),t.x-o<k&&(k=t.x-o,l=n)):n<this.getValueCount()/2?t.x+a>x&&(x=t.x+a,r=n):n>this.getValueCount()/2&&t.x-a<k&&(k=t.x-a,l=n);d=k,u=Math.ceil(x-this.width),s=this.getIndexAngle(r),h=this.getIndexAngle(l),c=u/Math.sin(s+Math.PI/2),f=d/Math.sin(h+Math.PI/2),c=e.isNumber(c)?c:0,f=e.isNumber(f)?f:0,this.drawingArea=Math.round(y-(f+c)/2),this.setCenterPoint(f,c)},setCenterPoint:function(t,e){var i=this.width-e-this.drawingArea,n=t+this.drawingArea;this.xCenter=Math.round((n+i)/2+this.left),this.yCenter=Math.round(this.height/2+this.top)},getIndexAngle:function(t){var e=2*Math.PI/this.getValueCount();return t*e-Math.PI/2},getDistanceFromCenterForValue:function(t){if(null===t)return 0;var e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e},getPointPosition:function(t,e){var i=this.getIndexAngle(t);return{x:Math.round(Math.cos(i)*e)+this.xCenter,y:Math.round(Math.sin(i)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,i=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:0>e&&0>i?i:e>0&&i>0?e:0)},draw:function(){if(this.options.display){var t=this.ctx;if(e.each(this.ticks,function(n,a){if(a>0||this.options.reverse){var o=this.getDistanceFromCenterForValue(this.ticks[a]),r=this.yCenter-o;if(this.options.gridLines.display)if(t.strokeStyle=this.options.gridLines.color,t.lineWidth=this.options.gridLines.lineWidth,this.options.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,o,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var s=0;s<this.getValueCount();s++){var l=this.getPointPosition(s,this.getDistanceFromCenterForValue(this.ticks[a]));0===s?t.moveTo(l.x,l.y):t.lineTo(l.x,l.y)}t.closePath(),t.stroke()}if(this.options.ticks.display){var h=e.getValueOrDefault(this.options.ticks.fontColor,i.defaultFontColor),d=e.getValueOrDefault(this.options.ticks.fontSize,i.defaultFontSize),u=e.getValueOrDefault(this.options.ticks.fontStyle,i.defaultFontStyle),c=e.getValueOrDefault(this.options.ticks.fontFamily,i.defaultFontFamily),f=e.fontString(d,u,c);if(t.font=f,this.options.ticks.showLabelBackdrop){var g=t.measureText(n).width;t.fillStyle=this.options.ticks.backdropColor,t.fillRect(this.xCenter-g/2-this.options.ticks.backdropPaddingX,r-d/2-this.options.ticks.backdropPaddingY,g+2*this.options.ticks.backdropPaddingX,d+2*this.options.ticks.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=h,t.fillText(n,this.xCenter,r)}}},this),!this.options.lineArc){t.lineWidth=this.options.angleLines.lineWidth,t.strokeStyle=this.options.angleLines.color;for(var n=this.getValueCount()-1;n>=0;n--){if(this.options.angleLines.display){var a=this.getPointPosition(n,this.getDistanceFromCenterForValue(this.options.reverse?this.min:this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(a.x,a.y),t.stroke(),t.closePath()}var o=this.getPointPosition(n,this.getDistanceFromCenterForValue(this.options.reverse?this.min:this.max)+5),r=e.getValueOrDefault(this.options.pointLabels.fontColor,i.defaultFontColor),s=e.getValueOrDefault(this.options.pointLabels.fontSize,i.defaultFontSize),l=e.getValueOrDefault(this.options.pointLabels.fontStyle,i.defaultFontStyle),h=e.getValueOrDefault(this.options.pointLabels.fontFamily,i.defaultFontFamily),d=e.fontString(s,l,h);t.font=d,t.fillStyle=r;var u=this.pointLabels.length,c=this.pointLabels.length/2,f=c/2,g=f>n||n>u-f,m=n===f||n===u-f;0===n?t.textAlign="center":n===c?t.textAlign="center":c>n?t.textAlign="left":t.textAlign="right",m?t.textBaseline="middle":g?t.textBaseline="bottom":t.textBaseline="top",t.fillText(this.pointLabels[n]?this.pointLabels[n]:"",o.x,o.y)}}}}});t.scaleService.registerScaleType("radialLinear",a,n)}},{}],42:[function(t,e,i){"use strict";var n=t("moment");n="function"==typeof n?n:window.moment,e.exports=function(t){var e=t.helpers,i={units:[{name:"millisecond",steps:[1,2,5,10,20,50,100,250,500]},{name:"second",steps:[1,2,5,10,30]},{name:"minute",steps:[1,2,5,10,30]},{name:"hour",steps:[1,2,3,6,12]},{name:"day",steps:[1,2,5]},{name:"week",maxStep:4},{name:"month",maxStep:3},{name:"quarter",maxStep:4},{name:"year",maxStep:!1}]},a={position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}},o=t.Scale.extend({initialize:function(){if(!n)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");t.Scale.prototype.initialize.call(this)},getLabelMoment:function(t,e){return this.labelMoments[t][e]},getMomentStartOf:function(t){return"week"===this.options.time.unit&&this.options.time.isoWeekday!==!1?t.clone().startOf("isoWeek").isoWeekday(this.options.time.isoWeekday):t.clone().startOf(this.tickUnit)},determineDataLimits:function(){this.labelMoments=[];var t=[];this.chart.data.labels&&this.chart.data.labels.length>0?(e.each(this.chart.data.labels,function(e,i){var n=this.parseTime(e);n.isValid()&&(this.options.time.round&&n.startOf(this.options.time.round),t.push(n))},this),this.firstTick=n.min.call(this,t),this.lastTick=n.max.call(this,t)):(this.firstTick=null,this.lastTick=null),e.each(this.chart.data.datasets,function(i,a){var o=[],r=this.chart.isDatasetVisible(a);"object"==typeof i.data[0]&&null!==i.data[0]?e.each(i.data,function(t,e){var i=this.parseTime(this.getRightValue(t));i.isValid()&&(this.options.time.round&&i.startOf(this.options.time.round),o.push(i),r&&(this.firstTick=null!==this.firstTick?n.min(this.firstTick,i):i,this.lastTick=null!==this.lastTick?n.max(this.lastTick,i):i))},this):o=t,this.labelMoments.push(o)},this),this.options.time.min&&(this.firstTick=this.parseTime(this.options.time.min)),this.options.time.max&&(this.lastTick=this.parseTime(this.options.time.max)),this.firstTick=(this.firstTick||n()).clone(),this.lastTick=(this.lastTick||n()).clone()},buildTicks:function(n){this.ctx.save();var a=e.getValueOrDefault(this.options.ticks.fontSize,t.defaults.global.defaultFontSize),o=e.getValueOrDefault(this.options.ticks.fontStyle,t.defaults.global.defaultFontStyle),r=e.getValueOrDefault(this.options.ticks.fontFamily,t.defaults.global.defaultFontFamily),s=e.fontString(a,o,r);if(this.ctx.font=s,this.ticks=[],this.unitScale=1,this.scaleSizeInUnits=0,this.options.time.unit)this.tickUnit=this.options.time.unit||"day",this.displayFormat=this.options.time.displayFormats[this.tickUnit],this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0),this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,1);else{var l=this.isHorizontal()?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),h=this.tickFormatFunction(this.firstTick,0,[]),d=this.ctx.measureText(h).width,u=Math.cos(e.toRadians(this.options.ticks.maxRotation)),c=Math.sin(e.toRadians(this.options.ticks.maxRotation));d=d*u+a*c;var f=l/d;this.tickUnit="millisecond",this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0),this.displayFormat=this.options.time.displayFormats[this.tickUnit];for(var g=0,m=i.units[g];g<i.units.length;){if(this.unitScale=1,e.isArray(m.steps)&&Math.ceil(this.scaleSizeInUnits/f)<e.max(m.steps)){for(var p=0;p<m.steps.length;++p)if(m.steps[p]>=Math.ceil(this.scaleSizeInUnits/f)){this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,m.steps[p]);break}break}if(m.maxStep===!1||Math.ceil(this.scaleSizeInUnits/f)<m.maxStep){this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,Math.ceil(this.scaleSizeInUnits/f));break}++g,m=i.units[g],this.tickUnit=m.name;var b=this.firstTick.diff(this.getMomentStartOf(this.firstTick),this.tickUnit,!0),v=this.getMomentStartOf(this.lastTick.clone().add(1,this.tickUnit)).diff(this.lastTick,this.tickUnit,!0);this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0)+b+v,this.displayFormat=this.options.time.displayFormats[m.name]}}var y;if(this.options.time.min?y=this.getMomentStartOf(this.firstTick):(this.firstTick=this.getMomentStartOf(this.firstTick),y=this.firstTick),!this.options.time.max){var x=this.getMomentStartOf(this.lastTick);0!==x.diff(this.lastTick,this.tickUnit,!0)&&(this.lastTick=this.getMomentStartOf(this.lastTick.add(1,this.tickUnit)))}this.smallestLabelSeparation=this.width,e.each(this.chart.data.datasets,function(t,e){for(var i=1;i<this.labelMoments[e].length;i++)this.smallestLabelSeparation=Math.min(this.smallestLabelSeparation,this.labelMoments[e][i].diff(this.labelMoments[e][i-1],this.tickUnit,!0))},this),this.options.time.displayFormat&&(this.displayFormat=this.options.time.displayFormat),this.ticks.push(this.firstTick.clone());for(var k=1;k<=this.scaleSizeInUnits;++k){var _=y.clone().add(k,this.tickUnit);if(this.options.time.max&&_.diff(this.lastTick,this.tickUnit,!0)>=0)break;k%this.unitScale===0&&this.ticks.push(_)}var S=this.ticks[this.ticks.length-1].diff(this.lastTick,this.tickUnit);(0!==S||0===this.scaleSizeInUnits)&&(this.options.time.max?(this.ticks.push(this.lastTick.clone()),this.scaleSizeInUnits=this.lastTick.diff(this.ticks[0],this.tickUnit,!0)):(this.ticks.push(this.lastTick.clone()),this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0))),this.ctx.restore()},getLabelForIndex:function(t,e){var i=this.chart.data.labels&&t<this.chart.data.labels.length?this.chart.data.labels[t]:"";return"object"==typeof this.chart.data.datasets[e].data[0]&&(i=this.getRightValue(this.chart.data.datasets[e].data[t])),this.options.time.tooltipFormat&&(i=this.parseTime(i).format(this.options.time.tooltipFormat)),i},tickFormatFunction:function(t,i,n){var a=t.format(this.displayFormat),o=this.options.ticks,r=e.getValueOrDefault(o.callback,o.userCallback);return r?r(a,i,n):a},convertTicksToLabels:function(){this.tickMoments=this.ticks,this.ticks=this.ticks.map(this.tickFormatFunction,this)},getPixelForValue:function(t,e,i,n){var a=t&&t.isValid&&t.isValid()?t:this.getLabelMoment(i,e);if(a){var o=a.diff(this.firstTick,this.tickUnit,!0),r=o/this.scaleSizeInUnits;if(this.isHorizontal()){var s=this.width-(this.paddingLeft+this.paddingRight),l=(s/Math.max(this.ticks.length-1,1),
+s*r+this.paddingLeft);return this.left+Math.round(l)}var h=this.height-(this.paddingTop+this.paddingBottom),d=(h/Math.max(this.ticks.length-1,1),h*r+this.paddingTop);return this.top+Math.round(d)}},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickMoments[t],null,null,e)},getValueForPixel:function(t){var e=this.isHorizontal()?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),i=(t-(this.isHorizontal()?this.left+this.paddingLeft:this.top+this.paddingTop))/e;return i*=this.scaleSizeInUnits,this.firstTick.clone().add(n.duration(i,this.tickUnit).asSeconds(),"seconds")},parseTime:function(t){return"string"==typeof this.options.time.parser?n(t,this.options.time.parser):"function"==typeof this.options.time.parser?this.options.time.parser(t):"function"==typeof t.getMonth||"number"==typeof t?n(t):t.isValid&&t.isValid()?t:"string"!=typeof this.options.time.format&&this.options.time.format.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale"),this.options.time.format(t)):n(t,this.options.time.format)}});t.scaleService.registerScaleType("time",o,a)}},{moment:6}]},{},[7]);
\ No newline at end of file
* Released under the MIT license
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
*/
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
},{}],2:[function(require,module,exports){
/* MIT license */\r
-var colorNames = require(6);\r
+var colorNames = require('color-name');\r
\r
module.exports = {\r
getRgba: getRgba,\r
reverseNames[colorNames[name]] = name;\r
}\r
-},{"6":6}],3:[function(require,module,exports){
+},{"color-name":6}],3:[function(require,module,exports){
/* MIT license */\r
-var convert = require(5);\r
-var string = require(2);\r
+var convert = require('color-convert');\r
+var string = require('chartjs-color-string');\r
\r
var Color = function (obj) {\r
if (obj instanceof Color) {\r
\r
module.exports = Color;\r
-},{"2":2,"5":5}],4:[function(require,module,exports){
+},{"chartjs-color-string":2,"color-convert":5}],4:[function(require,module,exports){
/* MIT license */
module.exports = {
}
},{}],5:[function(require,module,exports){
-var conversions = require(4);
+var conversions = require("./conversions");
var convert = function() {
return new Converter();
});
module.exports = convert;
-},{"4":4}],6:[function(require,module,exports){
+},{"./conversions":4}],6:[function(require,module,exports){
module.exports = {\r
"aliceblue": [240, 248, 255],\r
"antiquewhite": [250, 235, 215],\r
"yellowgreen": [154, 205, 50]\r
};
},{}],7:[function(require,module,exports){
-var Chart = require(26)();
-
-require(25)(Chart);
-require(24)(Chart);
-require(21)(Chart);
-require(22)(Chart);
-require(23)(Chart);
-require(27)(Chart);
-require(31)(Chart);
-require(29)(Chart);
-require(30)(Chart);
-require(32)(Chart);
-require(28)(Chart);
-require(33)(Chart);
-
-require(34)(Chart);
-require(35)(Chart);
-require(36)(Chart);
-require(37)(Chart);
-
-require(40)(Chart);
-require(38)(Chart);
-require(39)(Chart);
-require(41)(Chart);
-require(42)(Chart);
-require(43)(Chart);
-
-// Controllers must be loaded after elements
-// See Chart.core.datasetController.dataElementType
-require(15)(Chart);
-require(16)(Chart);
-require(17)(Chart);
-require(18)(Chart);
-require(19)(Chart);
-require(20)(Chart);
-
-require(8)(Chart);
-require(9)(Chart);
-require(10)(Chart);
-require(11)(Chart);
-require(12)(Chart);
-require(13)(Chart);
-require(14)(Chart);
-
-window.Chart = module.exports = Chart;
-
-},{"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"23":23,"24":24,"25":25,"26":26,"27":27,"28":28,"29":29,"30":30,"31":31,"32":32,"33":33,"34":34,"35":35,"36":36,"37":37,"38":38,"39":39,"40":40,"41":41,"42":42,"43":43,"8":8,"9":9}],8:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Bar = function(context, config) {
- config.type = 'bar';
-
- return new Chart(context, config);
- };
+var Chart = require('./core/core.js')();\r
+\r
+require('./core/core.helpers')(Chart);\r
+require('./core/core.element')(Chart);\r
+require('./core/core.animation')(Chart);\r
+require('./core/core.controller')(Chart);\r
+require('./core/core.datasetController')(Chart);\r
+require('./core/core.layoutService')(Chart);\r
+require('./core/core.legend')(Chart);\r
+require('./core/core.plugin.js')(Chart);\r
+require('./core/core.scale')(Chart);\r
+require('./core/core.scaleService')(Chart);\r
+require('./core/core.title')(Chart);\r
+require('./core/core.tooltip')(Chart);\r
+\r
+require('./elements/element.arc')(Chart);\r
+require('./elements/element.line')(Chart);\r
+require('./elements/element.point')(Chart);\r
+require('./elements/element.rectangle')(Chart);\r
+\r
+require('./scales/scale.category')(Chart);\r
+require('./scales/scale.linear')(Chart);\r
+require('./scales/scale.logarithmic')(Chart);\r
+require('./scales/scale.radialLinear')(Chart);\r
+require('./scales/scale.time')(Chart);\r
+\r
+// Controllers must be loaded after elements\r
+// See Chart.core.datasetController.dataElementType\r
+require('./controllers/controller.bar')(Chart);\r
+require('./controllers/controller.bubble')(Chart);\r
+require('./controllers/controller.doughnut')(Chart);\r
+require('./controllers/controller.line')(Chart);\r
+require('./controllers/controller.polarArea')(Chart);\r
+require('./controllers/controller.radar')(Chart);\r
+\r
+require('./charts/Chart.Bar')(Chart);\r
+require('./charts/Chart.Bubble')(Chart);\r
+require('./charts/Chart.Doughnut')(Chart);\r
+require('./charts/Chart.Line')(Chart);\r
+require('./charts/Chart.PolarArea')(Chart);\r
+require('./charts/Chart.Radar')(Chart);\r
+require('./charts/Chart.Scatter')(Chart);\r
+\r
+window.Chart = module.exports = Chart;\r
+},{"./charts/Chart.Bar":8,"./charts/Chart.Bubble":9,"./charts/Chart.Doughnut":10,"./charts/Chart.Line":11,"./charts/Chart.PolarArea":12,"./charts/Chart.Radar":13,"./charts/Chart.Scatter":14,"./controllers/controller.bar":15,"./controllers/controller.bubble":16,"./controllers/controller.doughnut":17,"./controllers/controller.line":18,"./controllers/controller.polarArea":19,"./controllers/controller.radar":20,"./core/core.animation":21,"./core/core.controller":22,"./core/core.datasetController":23,"./core/core.element":24,"./core/core.helpers":25,"./core/core.js":26,"./core/core.layoutService":27,"./core/core.legend":28,"./core/core.plugin.js":29,"./core/core.scale":30,"./core/core.scaleService":31,"./core/core.title":32,"./core/core.tooltip":33,"./elements/element.arc":34,"./elements/element.line":35,"./elements/element.point":36,"./elements/element.rectangle":37,"./scales/scale.category":38,"./scales/scale.linear":39,"./scales/scale.logarithmic":40,"./scales/scale.radialLinear":41,"./scales/scale.time":42}],8:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Bar = function(context, config) {\r
+ config.type = 'bar';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],9:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Bubble = function(context, config) {
- config.type = 'bubble';
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Bubble = function(context, config) {\r
+ config.type = 'bubble';\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],10:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Doughnut = function(context, config) {
- config.type = 'doughnut';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Doughnut = function(context, config) {\r
+ config.type = 'doughnut';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],11:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Line = function(context, config) {
- config.type = 'line';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.Line = function(context, config) {\r
+ config.type = 'line';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],12:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.PolarArea = function(context, config) {
- config.type = 'polarArea';
-
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ Chart.PolarArea = function(context, config) {\r
+ config.type = 'polarArea';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],13:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- Chart.Radar = function(context, config) {
- config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);
- config.type = 'radar';
-
- return new Chart(context, config);
- };
-
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+ \r
+ Chart.Radar = function(context, config) {\r
+ config.options = Chart.helpers.configMerge({ aspectRatio: 1 }, config.options);\r
+ config.type = 'radar';\r
+\r
+ return new Chart(context, config);\r
+ };\r
+\r
+};\r
},{}],14:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var defaultConfig = {
- hover: {
- mode: 'single'
- },
-
- scales: {
- xAxes: [{
- type: "linear", // scatter should not use a category axis
- position: "bottom",
- id: "x-axis-1" // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: "linear",
- position: "left",
- id: "y-axis-1"
- }]
- },
-
- tooltips: {
- callbacks: {
- title: function(tooltipItems, data) {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem, data) {
- return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
- }
- }
- }
- };
-
- // Register the default config for this type
- Chart.defaults.scatter = defaultConfig;
-
- // Scatter charts use line controllers
- Chart.controllers.scatter = Chart.controllers.line;
-
- Chart.Scatter = function(context, config) {
- config.type = 'scatter';
- return new Chart(context, config);
- };
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var defaultConfig = {\r
+ hover: {\r
+ mode: 'single'\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear", // scatter should not use a category axis\r
+ position: "bottom",\r
+ id: "x-axis-1" // need an ID so datasets can reference the scale\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ position: "left",\r
+ id: "y-axis-1"\r
+ }]\r
+ },\r
+\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Title doesn't make sense for scatter since we format the data as a point\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ // Register the default config for this type\r
+ Chart.defaults.scatter = defaultConfig;\r
+\r
+ // Scatter charts use line controllers\r
+ Chart.controllers.scatter = Chart.controllers.line;\r
+\r
+ Chart.Scatter = function(context, config) {\r
+ config.type = 'scatter';\r
+ return new Chart(context, config);\r
+ };\r
+\r
};
},{}],15:[function(require,module,exports){
-"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 getBarCount() {
- 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 update(reset) {
- var me = this;
- helpers.each(me.getMeta().data, function(rectangle, index) {
- me.updateElement(rectangle, index, reset);
- }, me);
- },
-
- updateElement: function updateElement(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();
-
- helpers.extend(rectangle, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: me.calculateBarX(index, me.index),
- 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(index),
- 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 = datasets[datasetIndex].data[index];
-
- if (value < 0) {
- for (var i = 0; i < datasetIndex; i++) {
- var negDS = datasets[i];
- var negDSMeta = chart.getDatasetMeta(i);
- if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
- }
- }
- } else {
- for (var j = 0; j < datasetIndex; j++) {
- var posDS = datasets[j];
- var posDSMeta = chart.getDatasetMeta(j);
- if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {
- base += posDS.data[index] > 0 ? posDS.data[index] : 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(index) {
- var xScale = this.getScaleForId(this.getMeta().xAxisID);
- var ruler = this.getRuler(index);
- 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) {
- var me = this;
- var meta = me.getMeta();
- var xScale = me.getScaleForId(meta.xAxisID);
- var barIndex = me.getBarIndex(datasetIndex);
-
- var ruler = me.getRuler(index);
- 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 = 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)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return yScale.getPixelForValue(sumNeg + value);
- } else {
- return yScale.getPixelForValue(sumPos + value);
- }
- }
-
- return yScale.getPixelForValue(value);
- },
-
- draw: function(ease) {
- var me = this;
- var easingDecimal = ease || 1;
- helpers.each(me.getMeta().data, function(rectangle, index) {
- var d = me.getDataset().data[index];
- if (d !== null && d !== undefined && !isNaN(d)) {
- rectangle.transition(easingDecimal).draw();
- }
- }, me);
- },
-
- 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 updateElement(rectangle, index, reset, numBars) {
- 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;
-
- helpers.extend(rectangle, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: reset ? scaleBase : me.calculateBarX(index, me.index),
- y: me.calculateBarY(index, me.index),
-
- // Tooltip
- label: me.chart.data.labels[index],
- datasetLabel: dataset.label,
-
- // Appearance
- base: reset ? scaleBase : me.calculateBarBase(me.index, index),
- height: me.calculateBarHeight(index),
- 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)
- },
-
- 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(index) {
- return corners[(startCorner + index) % 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();
- }
- },
-
- inRange: function (mouseX, mouseY) {
- var vm = this._view;
- var inRange = false;
-
- if (vm) {
- if (vm.x < vm.base) {
- inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);
- } else {
- inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);
- }
- }
-
- return inRange;
- }
- });
-
- 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 value = me.chart.data.datasets[datasetIndex].data[index];
-
- if (value < 0) {
- for (var i = 0; i < datasetIndex; i++) {
- var negDS = me.chart.data.datasets[i];
- var negDSMeta = me.chart.getDatasetMeta(i);
- if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
- }
- }
- } else {
- for (var j = 0; j < datasetIndex; j++) {
- var posDS = me.chart.data.datasets[j];
- var posDSMeta = me.chart.getDatasetMeta(j);
- if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(j)) {
- base += posDS.data[index] > 0 ? posDS.data[index] : 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 (index) {
- var me = this;
- var yScale = me.getScaleForId(me.getMeta().yAxisID);
- var ruler = me.getRuler(index);
- 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 = 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)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return xScale.getPixelForValue(sumNeg + value);
- } else {
- return xScale.getPixelForValue(sumPos + value);
- }
- }
-
- return xScale.getPixelForValue(value);
- },
-
- calculateBarY: function (index, datasetIndex) {
- var me = this;
- var meta = me.getMeta();
- var yScale = me.getScaleForId(meta.yAxisID);
- var barIndex = me.getBarIndex(datasetIndex);
-
- var ruler = me.getRuler(index);
- 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);
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.bar = {\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "category",\r
+\r
+ // Specific to Bar Controller\r
+ categoryPercentage: 0.8,\r
+ barPercentage: 0.9,\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ offsetGridLines: true\r
+ }\r
+ }],\r
+ yAxes: [{\r
+ type: "linear"\r
+ }]\r
+ }\r
+ };\r
+\r
+ Chart.controllers.bar = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Rectangle,\r
+\r
+ initialize: function(chart, datasetIndex) {\r
+ Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);\r
+\r
+ // Use this to indicate that this is a bar dataset.\r
+ this.getMeta().bar = true;\r
+ },\r
+\r
+ // Get the number of datasets that display bars. We use this to correctly calculate the bar width\r
+ getBarCount: function getBarCount() {\r
+ var barCount = 0;\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ var meta = this.chart.getDatasetMeta(datasetIndex);\r
+ if (meta.bar && this.chart.isDatasetVisible(datasetIndex)) {\r
+ ++barCount;\r
+ }\r
+ }, this);\r
+ return barCount;\r
+ },\r
+\r
+ update: function update(reset) {\r
+ helpers.each(this.getMeta().data, function(rectangle, index) {\r
+ this.updateElement(rectangle, index, reset);\r
+ }, this);\r
+ },\r
+\r
+ updateElement: function updateElement(rectangle, index, reset) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var scaleBase = yScale.getBasePixel();\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+ var custom = rectangle.custom || {};\r
+ var dataset = this.getDataset();\r
+\r
+ helpers.extend(rectangle, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: this.calculateBarX(index, this.index),\r
+ y: reset ? scaleBase : this.calculateBarY(index, this.index),\r
+\r
+ // Tooltip\r
+ label: this.chart.data.labels[index],\r
+ datasetLabel: dataset.label,\r
+\r
+ // Appearance\r
+ base: reset ? scaleBase : this.calculateBarBase(this.index, index),\r
+ width: this.calculateBarWidth(index),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+ borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+ }\r
+ });\r
+ rectangle.pivot();\r
+ },\r
+\r
+ calculateBarBase: function(datasetIndex, index) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var base = 0;\r
+\r
+ if (yScale.options.stacked) {\r
+ var chart = this.chart;\r
+ var datasets = chart.data.datasets;\r
+ var value = datasets[datasetIndex].data[index];\r
+\r
+ if (value < 0) {\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var negDS = datasets[i];\r
+ var negDSMeta = chart.getDatasetMeta(i);\r
+ if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {\r
+ base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
+ }\r
+ }\r
+ } else {\r
+ for (var j = 0; j < datasetIndex; j++) {\r
+ var posDS = datasets[j];\r
+ var posDSMeta = chart.getDatasetMeta(j);\r
+ if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {\r
+ base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(base);\r
+ }\r
+\r
+ return yScale.getBasePixel();\r
+ },\r
+\r
+ getRuler: function(index) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var datasetCount = this.getBarCount();\r
+\r
+ var tickWidth;\r
+\r
+ if (xScale.options.type === 'category') {\r
+ tickWidth = xScale.getPixelForTick(index + 1) - xScale.getPixelForTick(index);\r
+ } else {\r
+ // Average width\r
+ tickWidth = xScale.width / xScale.ticks.length;\r
+ }\r
+ var categoryWidth = tickWidth * xScale.options.categoryPercentage;\r
+ var categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;\r
+ var fullBarWidth = categoryWidth / datasetCount;\r
+\r
+ if (xScale.ticks.length !== this.chart.data.labels.length) {\r
+ var perc = xScale.ticks.length / this.chart.data.labels.length;\r
+ fullBarWidth = fullBarWidth * perc;\r
+ }\r
+\r
+ var barWidth = fullBarWidth * xScale.options.barPercentage;\r
+ var barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);\r
+\r
+ return {\r
+ datasetCount: datasetCount,\r
+ tickWidth: tickWidth,\r
+ categoryWidth: categoryWidth,\r
+ categorySpacing: categorySpacing,\r
+ fullBarWidth: fullBarWidth,\r
+ barWidth: barWidth,\r
+ barSpacing: barSpacing\r
+ };\r
+ },\r
+\r
+ calculateBarWidth: function(index) {\r
+ var xScale = this.getScaleForId(this.getMeta().xAxisID);\r
+ var ruler = this.getRuler(index);\r
+ return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;\r
+ },\r
+\r
+ // Get bar index from the given dataset index accounting for the fact that not all bars are visible\r
+ getBarIndex: function(datasetIndex) {\r
+ var barIndex = 0;\r
+ var meta, j;\r
+\r
+ for (j = 0; j < datasetIndex; ++j) {\r
+ meta = this.chart.getDatasetMeta(j);\r
+ if (meta.bar && this.chart.isDatasetVisible(j)) {\r
+ ++barIndex;\r
+ }\r
+ }\r
+\r
+ return barIndex;\r
+ },\r
+\r
+ calculateBarX: function(index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var barIndex = this.getBarIndex(datasetIndex);\r
+\r
+ var ruler = this.getRuler(index);\r
+ var leftTick = xScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);\r
+ leftTick -= this.chart.isCombo ? (ruler.tickWidth / 2) : 0;\r
+\r
+ if (xScale.options.stacked) {\r
+ return leftTick + (ruler.categoryWidth / 2) + ruler.categorySpacing;\r
+ }\r
+\r
+ return leftTick +\r
+ (ruler.barWidth / 2) +\r
+ ruler.categorySpacing +\r
+ (ruler.barWidth * barIndex) +\r
+ (ruler.barSpacing / 2) +\r
+ (ruler.barSpacing * barIndex);\r
+ },\r
+\r
+ calculateBarY: function(index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var value = this.getDataset().data[index];\r
+\r
+ if (yScale.options.stacked) {\r
+\r
+ var sumPos = 0,\r
+ sumNeg = 0;\r
+\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var ds = this.chart.data.datasets[i];\r
+ var dsMeta = this.chart.getDatasetMeta(i);\r
+ if (dsMeta.bar && dsMeta.yAxisID === yScale.id && this.chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return yScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return yScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(value);\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ helpers.each(this.getMeta().data, function(rectangle, index) {\r
+ var d = this.getDataset().data[index];\r
+ if (d !== null && d !== undefined && !isNaN(d)) {\r
+ rectangle.transition(easingDecimal).draw();\r
+ }\r
+ }, this);\r
+ },\r
+\r
+ setHoverStyle: function(rectangle) {\r
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+ var index = rectangle._index;\r
+\r
+ var custom = rectangle.custom || {};\r
+ var model = rectangle._model;\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(rectangle) {\r
+ var dataset = this.chart.data.datasets[rectangle._datasetIndex];\r
+ var index = rectangle._index;\r
+ var custom = rectangle.custom || {};\r
+ var model = rectangle._model;\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);\r
+ }\r
+\r
+ });\r
+\r
+\r
+ // including horizontalBar in the bar file, instead of a file of its own\r
+ // it extends bar (like pie extends doughnut)\r
+ Chart.defaults.horizontalBar = {\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear",\r
+ position: "bottom"\r
+ }],\r
+ yAxes: [{\r
+ position: "left",\r
+ type: "category",\r
+\r
+ // Specific to Horizontal Bar Controller\r
+ categoryPercentage: 0.8,\r
+ barPercentage: 0.9,\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ offsetGridLines: true\r
+ }\r
+ }]\r
+ },\r
+ elements: {\r
+ rectangle: {\r
+ borderSkipped: 'left'\r
+ }\r
+ },\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Pick first xLabel for now\r
+ var title = '';\r
+\r
+ if (tooltipItems.length > 0) {\r
+ if (tooltipItems[0].yLabel) {\r
+ title = tooltipItems[0].yLabel;\r
+ } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
+ title = data.labels[tooltipItems[0].index];\r
+ }\r
+ }\r
+\r
+ return title;\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ return datasetLabel + ': ' + tooltipItem.xLabel;\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.horizontalBar = Chart.controllers.bar.extend({\r
+ updateElement: function updateElement(rectangle, index, reset, numBars) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var scaleBase = xScale.getBasePixel();\r
+ var custom = rectangle.custom || {};\r
+ var dataset = this.getDataset();\r
+ var rectangleElementOptions = this.chart.options.elements.rectangle;\r
+\r
+ helpers.extend(rectangle, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? scaleBase : this.calculateBarX(index, this.index),\r
+ y: this.calculateBarY(index, this.index),\r
+\r
+ // Tooltip\r
+ label: this.chart.data.labels[index],\r
+ datasetLabel: dataset.label,\r
+\r
+ // Appearance\r
+ base: reset ? scaleBase : this.calculateBarBase(this.index, index),\r
+ height: this.calculateBarHeight(index),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\r
+ borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\r
+ },\r
+\r
+ draw: function () {\r
+\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ var halfHeight = vm.height / 2,\r
+ topY = vm.y - halfHeight,\r
+ bottomY = vm.y + halfHeight,\r
+ right = vm.base - (vm.base - vm.x),\r
+ halfStroke = vm.borderWidth / 2;\r
+\r
+ // Canvas doesn't allow us to stroke inside the width so we can\r
+ // adjust the sizes to fit if we're setting a stroke on the line\r
+ if (vm.borderWidth) {\r
+ topY += halfStroke;\r
+ bottomY -= halfStroke;\r
+ right += halfStroke;\r
+ }\r
+\r
+ ctx.beginPath();\r
+\r
+ ctx.fillStyle = vm.backgroundColor;\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ // Corner points, from bottom-left to bottom-right clockwise\r
+ // | 1 2 |\r
+ // | 0 3 |\r
+ var corners = [\r
+ [vm.base, bottomY],\r
+ [vm.base, topY],\r
+ [right, topY],\r
+ [right, bottomY]\r
+ ];\r
+\r
+ // Find first (starting) corner with fallback to 'bottom'\r
+ var borders = ['bottom', 'left', 'top', 'right'];\r
+ var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
+ if (startCorner === -1)\r
+ startCorner = 0;\r
+\r
+ function cornerAt(index) {\r
+ return corners[(startCorner + index) % 4];\r
+ }\r
+\r
+ // Draw rectangle from 'startCorner'\r
+ ctx.moveTo.apply(ctx, cornerAt(0));\r
+ for (var i = 1; i < 4; i++)\r
+ ctx.lineTo.apply(ctx, cornerAt(i));\r
+\r
+ ctx.fill();\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ },\r
+\r
+ inRange: function (mouseX, mouseY) {\r
+ var vm = this._view;\r
+ var inRange = false;\r
+\r
+ if (vm) {\r
+ if (vm.x < vm.base) {\r
+ inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.x && mouseX <= vm.base);\r
+ } else {\r
+ inRange = (mouseY >= vm.y - vm.height / 2 && mouseY <= vm.y + vm.height / 2) && (mouseX >= vm.base && mouseX <= vm.x);\r
+ }\r
+ }\r
+\r
+ return inRange;\r
+ }\r
+ });\r
+\r
+ rectangle.pivot();\r
+ },\r
+\r
+ calculateBarBase: function (datasetIndex, index) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var base = 0;\r
+\r
+ if (xScale.options.stacked) {\r
+\r
+ var value = this.chart.data.datasets[datasetIndex].data[index];\r
+\r
+ if (value < 0) {\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var negDS = this.chart.data.datasets[i];\r
+ var negDSMeta = this.chart.getDatasetMeta(i);\r
+ if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {\r
+ base += negDS.data[index] < 0 ? negDS.data[index] : 0;\r
+ }\r
+ }\r
+ } else {\r
+ for (var j = 0; j < datasetIndex; j++) {\r
+ var posDS = this.chart.data.datasets[j];\r
+ var posDSMeta = this.chart.getDatasetMeta(j);\r
+ if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(j)) {\r
+ base += posDS.data[index] > 0 ? posDS.data[index] : 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ return xScale.getPixelForValue(base);\r
+ }\r
+\r
+ return xScale.getBasePixel();\r
+ },\r
+\r
+ getRuler: function (index) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var datasetCount = this.getBarCount();\r
+\r
+ var tickHeight;\r
+ if (yScale.options.type === 'category') {\r
+ tickHeight = yScale.getPixelForTick(index + 1) - yScale.getPixelForTick(index);\r
+ } else {\r
+ // Average width\r
+ tickHeight = yScale.width / yScale.ticks.length;\r
+ }\r
+ var categoryHeight = tickHeight * yScale.options.categoryPercentage;\r
+ var categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;\r
+ var fullBarHeight = categoryHeight / datasetCount;\r
+\r
+ if (yScale.ticks.length !== this.chart.data.labels.length) {\r
+ var perc = yScale.ticks.length / this.chart.data.labels.length;\r
+ fullBarHeight = fullBarHeight * perc;\r
+ }\r
+\r
+ var barHeight = fullBarHeight * yScale.options.barPercentage;\r
+ var barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);\r
+\r
+ return {\r
+ datasetCount: datasetCount,\r
+ tickHeight: tickHeight,\r
+ categoryHeight: categoryHeight,\r
+ categorySpacing: categorySpacing,\r
+ fullBarHeight: fullBarHeight,\r
+ barHeight: barHeight,\r
+ barSpacing: barSpacing,\r
+ };\r
+ },\r
+\r
+ calculateBarHeight: function (index) {\r
+ var yScale = this.getScaleForId(this.getMeta().yAxisID);\r
+ var ruler = this.getRuler(index);\r
+ return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;\r
+ },\r
+\r
+ calculateBarX: function (index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var value = this.getDataset().data[index];\r
+\r
+ if (xScale.options.stacked) {\r
+\r
+ var sumPos = 0,\r
+ sumNeg = 0;\r
+\r
+ for (var i = 0; i < datasetIndex; i++) {\r
+ var ds = this.chart.data.datasets[i];\r
+ var dsMeta = this.chart.getDatasetMeta(i);\r
+ if (dsMeta.bar && dsMeta.xAxisID === xScale.id && this.chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return xScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return xScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return xScale.getPixelForValue(value);\r
+ },\r
+\r
+ calculateBarY: function (index, datasetIndex) {\r
+ var meta = this.getMeta();\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+ var barIndex = this.getBarIndex(datasetIndex);\r
+\r
+ var ruler = this.getRuler(index);\r
+ var topTick = yScale.getPixelForValue(null, index, datasetIndex, this.chart.isCombo);\r
+ topTick -= this.chart.isCombo ? (ruler.tickHeight / 2) : 0;\r
+\r
+ if (yScale.options.stacked) {\r
+ return topTick + (ruler.categoryHeight / 2) + ruler.categorySpacing;\r
+ }\r
+\r
+ return topTick +\r
+ (ruler.barHeight / 2) +\r
+ ruler.categorySpacing +\r
+ (ruler.barHeight * barIndex) +\r
+ (ruler.barSpacing / 2) +\r
+ (ruler.barSpacing * barIndex);\r
+ }\r
+ });\r
+};\r
},{}],16:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.bubble = {
- hover: {
- mode: "single"
- },
-
- scales: {
- xAxes: [{
- type: "linear", // bubble should probably use a linear scale by default
- position: "bottom",
- id: "x-axis-0" // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: "linear",
- position: "left",
- id: "y-axis-0"
- }]
- },
-
- tooltips: {
- callbacks: {
- title: function(tooltipItems, data) {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
- return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';
- }
- }
- }
- };
-
- Chart.controllers.bubble = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Point,
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var points = meta.data;
-
- // Update Points
- helpers.each(points, function(point, index) {
- me.updateElement(point, index, reset);
- });
- },
-
- updateElement: function(point, index, reset) {
- var me = this;
- var meta = me.getMeta();
- var xScale = me.getScaleForId(meta.xAxisID);
- var yScale = me.getScaleForId(meta.yAxisID);
-
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var data = dataset.data[index];
- var pointElementOptions = me.chart.options.elements.point;
- var dsIndex = me.index;
-
- helpers.extend(point, {
- // Utility
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: dsIndex,
- _index: index,
-
- // Desired view properties
- _model: {
- x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, dsIndex, me.chart.isCombo),
- y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex),
- // Appearance
- radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data),
-
- // Tooltip
- hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
- }
- });
-
- // Trick to reset the styles of the point
- Chart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions);
-
- var model = point._model;
- model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));
-
- point.pivot();
- },
-
- getRadius: function(value) {
- return value.r || this.chart.options.elements.point.radius;
- },
-
- setHoverStyle: function(point) {
- var me = this;
- Chart.DatasetController.prototype.setHoverStyle.call(me, point);
-
- // Radius
- var dataset = me.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
- model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]);
- },
-
- removeHoverStyle: function(point) {
- var me = this;
- Chart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point);
-
- var dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index];
- var custom = point.custom || {};
- var model = point._model;
-
- model.radius = custom.radius ? custom.radius : me.getRadius(dataVal);
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.bubble = {\r
+ hover: {\r
+ mode: "single"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "linear", // bubble should probably use a linear scale by default\r
+ position: "bottom",\r
+ id: "x-axis-0" // need an ID so datasets can reference the scale\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ position: "left",\r
+ id: "y-axis-0"\r
+ }]\r
+ },\r
+\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function(tooltipItems, data) {\r
+ // Title doesn't make sense for scatter since we format the data as a point\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
+ return datasetLabel + ': (' + dataPoint.x + ', ' + dataPoint.y + ', ' + dataPoint.r + ')';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.bubble = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ update: function update(reset) {\r
+ var meta = this.getMeta();\r
+ var points = meta.data;\r
+\r
+ // Update Points\r
+ helpers.each(points, function(point, index) {\r
+ this.updateElement(point, index, reset);\r
+ }, this);\r
+ },\r
+\r
+ updateElement: function(point, index, reset) {\r
+ var meta = this.getMeta();\r
+ var xScale = this.getScaleForId(meta.xAxisID);\r
+ var yScale = this.getScaleForId(meta.yAxisID);\r
+\r
+ var custom = point.custom || {};\r
+ var dataset = this.getDataset();\r
+ var data = dataset.data[index];\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ helpers.extend(point, {\r
+ // Utility\r
+ _xScale: xScale,\r
+ _yScale: yScale,\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, this.index, this.chart.isCombo),\r
+ y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, this.index),\r
+ // Appearance\r
+ radius: reset ? 0 : custom.radius ? custom.radius : this.getRadius(data),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor),\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth),\r
+\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\r
+ }\r
+ });\r
+\r
+ var model = point._model;\r
+ model.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));\r
+\r
+ point.pivot();\r
+ },\r
+\r
+ getRadius: function(value) {\r
+ return value.r || this.chart.options.elements.point.radius;\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, this.chart.options.elements.point.hoverRadius)) + this.getRadius(this.getDataset().data[point._index]);\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ model.radius = custom.radius ? custom.radius : this.getRadius(dataset.data[point._index]);\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, pointElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, pointElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, pointElementOptions.borderWidth);\r
+ }\r
+ });\r
+};\r
},{}],17:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- defaults = Chart.defaults;
-
- defaults.doughnut = {
- animation: {
- //Boolean - Whether we animate the rotation of the Doughnut
- animateRotate: true,
- //Boolean - Whether we animate scaling the Doughnut from the centre
- animateScale: false
- },
- aspectRatio: 1,
- hover: {
- mode: 'single'
- },
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('</li>');
- }
- }
-
- text.push('</ul>');
- return text.join("");
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc.custom || {};
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- } else {
- return [];
- }
- }
- },
-
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
-
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- meta.data[index].hidden = !meta.data[index].hidden;
- }
-
- chart.update();
- }
- },
-
- //The percentage of the chart that we cut out of the middle.
- cutoutPercentage: 50,
-
- //The rotation of the chart, where the first data arc begins.
- rotation: Math.PI * -0.5,
-
- //The total circumference of the chart.
- circumference: Math.PI * 2.0,
-
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
- }
- }
- }
- };
-
- defaults.pie = helpers.clone(defaults.doughnut);
- helpers.extend(defaults.pie, {
- cutoutPercentage: 0
- });
-
-
- Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Arc,
-
- linkScales: helpers.noop,
-
- // 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 (this.chart.isDatasetVisible(j)) {
- ++ringIndex;
- }
- }
-
- return ringIndex;
- },
-
- update: function update(reset) {
- var me = this;
- var chart = me.chart,
- chartArea = chart.chartArea,
- opts = chart.options,
- arcOpts = opts.elements.arc,
- availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
- availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
- minSize = Math.min(availableWidth, availableHeight),
- offset = {
- x: 0,
- y: 0
- },
- meta = me.getMeta(),
- cutoutPercentage = opts.cutoutPercentage,
- circumference = opts.circumference;
-
- // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
- if (circumference < Math.PI * 2.0) {
- var startAngle = opts.rotation % (Math.PI * 2.0);
- startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
- var endAngle = startAngle + circumference;
- var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
- var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
- var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
- var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
- var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
- var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
- var cutout = cutoutPercentage / 100.0;
- var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
- var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
- var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
- minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
- offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
- }
-
- chart.outerRadius = Math.max(minSize / 2, 0);
- chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);
- chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
- chart.offsetX = offset.x * chart.outerRadius;
- chart.offsetY = offset.y * chart.outerRadius;
-
- meta.total = me.calculateTotal();
-
- me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
- me.innerRadius = me.outerRadius - chart.radiusLength;
-
- helpers.each(meta.data, function(arc, index) {
- me.updateElement(arc, index, reset);
- });
- },
-
- updateElement: function(arc, index, reset) {
- var me = this;
- var chart = me.chart,
- chartArea = chart.chartArea,
- opts = chart.options,
- animationOpts = opts.animation,
- arcOpts = opts.elements.arc,
- centerX = (chartArea.left + chartArea.right) / 2,
- centerY = (chartArea.top + chartArea.bottom) / 2,
- startAngle = opts.rotation, // non reset case handled later
- endAngle = opts.rotation, // non reset case handled later
- dataset = me.getDataset(),
- circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),
- innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius,
- outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius,
- custom = arc.custom || {},
- valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
-
- helpers.extend(arc, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
-
- // Desired view properties
- _model: {
- x: centerX + chart.offsetX,
- y: centerY + chart.offsetY,
- startAngle: startAngle,
- endAngle: endAngle,
- circumference: circumference,
- outerRadius: outerRadius,
- innerRadius: innerRadius,
- label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])
- }
- });
-
- var model = arc._model;
- // Resets the visual styles
- this.removeHoverStyle(arc);
-
- // Set correct angles if not resetting
- if (!reset || !animationOpts.animateRotate) {
- if (index === 0) {
- model.startAngle = opts.rotation;
- } else {
- model.startAngle = me.getMeta().data[index - 1]._model.endAngle;
- }
-
- model.endAngle = model.startAngle + model.circumference;
- }
-
- arc.pivot();
- },
-
- removeHoverStyle: function(arc) {
- Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
- },
-
- calculateTotal: function() {
- var dataset = this.getDataset();
- var meta = this.getMeta();
- var total = 0;
- var value;
-
- helpers.each(meta.data, function(element, index) {
- value = dataset.data[index];
- if (!isNaN(value) && !element.hidden) {
- total += Math.abs(value);
- }
- });
-
- return total;
- },
-
- calculateCircumference: function(value) {
- var total = this.getMeta().total;
- if (total > 0 && !isNaN(value)) {
- return (Math.PI * 2.0) * (value / total);
- } else {
- return 0;
- }
- }
- });
-};
-
-},{}],18:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.line = {
- showLines: true,
-
- hover: {
- mode: "label"
- },
-
- scales: {
- xAxes: [{
- type: "category",
- id: 'x-axis-0'
- }],
- yAxes: [{
- type: "linear",
- id: 'y-axis-0'
- }]
- }
- };
-
- function lineEnabled(dataset, options) {
- return helpers.getValueOrDefault(dataset.showLine, options.showLines);
- }
-
- Chart.controllers.line = Chart.DatasetController.extend({
-
- datasetElementType: Chart.elements.Line,
-
- dataElementType: Chart.elements.Point,
-
- addElementAndReset: function(index) {
- var me = this;
- var options = me.chart.options;
- var meta = me.getMeta();
-
- Chart.DatasetController.prototype.addElementAndReset.call(me, index);
-
- // Make sure bezier control points are updated
- if (lineEnabled(me.getDataset(), options) && meta.dataset._model.tension !== 0) {
- me.updateBezierControlPoints();
- }
- },
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var line = meta.dataset;
- var points = meta.data || [];
- var options = me.chart.options;
- var lineElementOptions = options.elements.line;
- var scale = me.getScaleForId(meta.yAxisID);
- var i, ilen, custom;
- var dataset = me.getDataset();
- var showLine = lineEnabled(dataset, options);
-
- // Update Line
- if (showLine) {
- custom = line.custom || {};
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
- dataset.lineTension = dataset.tension;
- }
-
- // Utility
- line._scale = scale;
- line._datasetIndex = me.index;
- // Data
- line._children = points;
- // Model
- line._model = {
- // Appearance
- // The default behavior of lines is to break at null values, according
- // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
- // This option gives linse the ability to span gaps
- spanGaps: dataset.spanGaps ? dataset.spanGaps : false,
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
- borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
- borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
- borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
- borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
- borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
- fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
- // Scale
- scaleTop: scale.top,
- scaleBottom: scale.bottom,
- scaleZero: scale.getBasePixel()
- };
-
- line.pivot();
- }
-
- // Update Points
- for (i=0, ilen=points.length; i<ilen; ++i) {
- me.updateElement(points[i], i, reset);
- }
-
- if (showLine && line._model.tension !== 0) {
- me.updateBezierControlPoints();
- }
-
- // Now pivot the point for animation
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].pivot();
- }
- },
-
- getPointBackgroundColor: function(point, index) {
- var backgroundColor = this.chart.options.elements.point.backgroundColor;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.backgroundColor) {
- backgroundColor = custom.backgroundColor;
- } else if (dataset.pointBackgroundColor) {
- backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);
- } else if (dataset.backgroundColor) {
- backgroundColor = dataset.backgroundColor;
- }
-
- return backgroundColor;
- },
-
- getPointBorderColor: function(point, index) {
- var borderColor = this.chart.options.elements.point.borderColor;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.borderColor) {
- borderColor = custom.borderColor;
- } else if (dataset.pointBorderColor) {
- borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);
- } else if (dataset.borderColor) {
- borderColor = dataset.borderColor;
- }
-
- return borderColor;
- },
-
- getPointBorderWidth: function(point, index) {
- var borderWidth = this.chart.options.elements.point.borderWidth;
- var dataset = this.getDataset();
- var custom = point.custom || {};
-
- if (custom.borderWidth) {
- borderWidth = custom.borderWidth;
- } else if (dataset.pointBorderWidth) {
- borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);
- } else if (dataset.borderWidth) {
- borderWidth = dataset.borderWidth;
- }
-
- return borderWidth;
- },
-
- updateElement: function(point, index, reset) {
- var me = this;
- var meta = me.getMeta();
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var datasetIndex = me.index;
- var value = dataset.data[index];
- var yScale = me.getScaleForId(meta.yAxisID);
- var xScale = me.getScaleForId(meta.xAxisID);
- var pointOptions = me.chart.options.elements.point;
- var x, y;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
- dataset.pointRadius = dataset.radius;
- }
- if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {
- dataset.pointHitRadius = dataset.hitRadius;
- }
-
- x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);
- y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);
-
- // Utility
- point._xScale = xScale;
- point._yScale = yScale;
- point._datasetIndex = datasetIndex;
- point._index = index;
-
- // Desired view properties
- point._model = {
- x: x,
- y: y,
- skip: custom.skip || isNaN(x) || isNaN(y),
- // Appearance
- radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),
- pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),
- backgroundColor: me.getPointBackgroundColor(point, index),
- borderColor: me.getPointBorderColor(point, index),
- borderWidth: me.getPointBorderWidth(point, index),
- tension: meta.dataset._model ? meta.dataset._model.tension : 0,
- // Tooltip
- hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
- };
- },
-
- calculatePointY: function(value, index, datasetIndex, isCombo) {
- var me = this;
- var chart = me.chart;
- var meta = me.getMeta();
- var yScale = me.getScaleForId(meta.yAxisID);
- var sumPos = 0;
- var sumNeg = 0;
- var i, ds, dsMeta;
-
- if (yScale.options.stacked) {
- for (i = 0; i < datasetIndex; i++) {
- ds = chart.data.datasets[i];
- dsMeta = chart.getDatasetMeta(i);
- if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
- } else {
- sumPos += ds.data[index] || 0;
- }
- }
- }
-
- if (value < 0) {
- return yScale.getPixelForValue(sumNeg + value);
- } else {
- return yScale.getPixelForValue(sumPos + value);
- }
- }
-
- return yScale.getPixelForValue(value);
- },
-
- updateBezierControlPoints: function() {
- var meta = this.getMeta();
- var area = this.chart.chartArea;
- var points = meta.data || [];
- var i, ilen, point, model, controlPoints;
-
- for (i=0, ilen=points.length; i<ilen; ++i) {
- point = points[i];
- model = point._model;
- controlPoints = helpers.splineCurve(
- helpers.previousItem(points, i)._model,
- model,
- helpers.nextItem(points, i)._model,
- meta.dataset._model.tension
- );
-
- // Prevent the bezier going outside of the bounds of the graph
- model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, area.right), area.left);
- model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, area.bottom), area.top);
- model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, area.right), area.left);
- model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, area.bottom), area.top);
- }
- },
-
- draw: function(ease) {
- var me = this;
- var meta = me.getMeta();
- var points = meta.data || [];
- var easingDecimal = ease || 1;
- var i, ilen;
-
- // Transition Point Locations
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].transition(easingDecimal);
- }
-
- // Transition and Draw the line
- if (lineEnabled(me.getDataset(), me.chart.options)) {
- meta.dataset.transition(easingDecimal).draw();
- }
-
- // Draw the points
- for (i=0, ilen=points.length; i<ilen; ++i) {
- points[i].draw();
- }
- },
-
- setHoverStyle: function(point) {
- // Point
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
-
- model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
- model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
- },
-
- removeHoverStyle: function(point) {
- var me = this;
- var dataset = me.chart.data.datasets[point._datasetIndex];
- var index = point._index;
- var custom = point.custom || {};
- var model = point._model;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {
- dataset.pointRadius = dataset.radius;
- }
-
- model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);
- model.backgroundColor = me.getPointBackgroundColor(point, index);
- model.borderColor = me.getPointBorderColor(point, index);
- model.borderWidth = me.getPointBorderWidth(point, index);
- }
- });
-};
-
-},{}],19:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.polarArea = {
-
- scale: {
- type: "radialLinear",
- lineArc: true // so that lines are circular
- },
-
- //Boolean - Whether to animate the rotation of the chart
- animation: {
- animateRotate: true,
- animateScale: true
- },
-
- aspectRatio: 1,
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('</span></li>');
- }
- }
-
- text.push('</ul>');
- return text.join("");
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc.custom || {};
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- } else {
- return [];
- }
- }
- },
-
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
-
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- meta.data[index].hidden = !meta.data[index].hidden;
- }
-
- chart.update();
- }
- },
-
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;
- }
- }
- }
- };
-
- Chart.controllers.polarArea = Chart.DatasetController.extend({
-
- dataElementType: Chart.elements.Arc,
-
- linkScales: helpers.noop,
-
- update: function update(reset) {
- var me = this;
- var chart = me.chart;
- var chartArea = chart.chartArea;
- var meta = me.getMeta();
- var opts = chart.options;
- var arcOpts = opts.elements.arc;
- var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
- chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);
- chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
- chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
-
- me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);
- me.innerRadius = me.outerRadius - chart.radiusLength;
-
- meta.count = me.countVisibleElements();
-
- helpers.each(meta.data, function(arc, index) {
- me.updateElement(arc, index, reset);
- });
- },
-
- updateElement: function(arc, index, reset) {
- var me = this;
- var chart = me.chart;
- var chartArea = chart.chartArea;
- var dataset = me.getDataset();
- var opts = chart.options;
- var animationOpts = opts.animation;
- var arcOpts = opts.elements.arc;
- var custom = arc.custom || {};
- var scale = chart.scale;
- var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
- var labels = chart.data.labels;
-
- var circumference = me.calculateCircumference(dataset.data[index]);
- var centerX = (chartArea.left + chartArea.right) / 2;
- var centerY = (chartArea.top + chartArea.bottom) / 2;
-
- // If there is NaN data before us, we need to calculate the starting angle correctly.
- // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
- var visibleCount = 0;
- var meta = me.getMeta();
- for (var i = 0; i < index; ++i) {
- if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {
- ++visibleCount;
- }
- }
-
- var negHalfPI = -0.5 * Math.PI;
- var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
- var startAngle = (negHalfPI) + (circumference * visibleCount);
- var endAngle = startAngle + (arc.hidden ? 0 : circumference);
-
- var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
-
- helpers.extend(arc, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
- _scale: scale,
-
- // Desired view properties
- _model: {
- x: centerX,
- y: centerY,
- innerRadius: 0,
- outerRadius: reset ? resetRadius : distance,
- startAngle: reset && animationOpts.animateRotate ? negHalfPI : startAngle,
- endAngle: reset && animationOpts.animateRotate ? negHalfPI : endAngle,
- label: getValueAtIndexOrDefault(labels, index, labels[index])
- }
- });
-
- // Apply border and fill style
- me.removeHoverStyle(arc);
-
- arc.pivot();
- },
-
- removeHoverStyle: function(arc) {
- Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);
- },
-
- countVisibleElements: function() {
- var dataset = this.getDataset();
- var meta = this.getMeta();
- var count = 0;
-
- helpers.each(meta.data, function(element, index) {
- if (!isNaN(dataset.data[index]) && !element.hidden) {
- count++;
- }
- });
-
- return count;
- },
-
- calculateCircumference: function(value) {
- var count = this.getMeta().count;
- if (count > 0 && !isNaN(value)) {
- return (2 * Math.PI) / count;
- } else {
- return 0;
- }
- }
- });
-};
-
-},{}],20:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.radar = {
- scale: {
- type: "radialLinear"
- },
- elements: {
- line: {
- tension: 0 // no bezier in radar
- }
- }
- };
-
- Chart.controllers.radar = Chart.DatasetController.extend({
-
- datasetElementType: Chart.elements.Line,
-
- dataElementType: Chart.elements.Point,
-
- linkScales: helpers.noop,
-
- addElementAndReset: function(index) {
- Chart.DatasetController.prototype.addElementAndReset.call(this, index);
-
- // Make sure bezier control points are updated
- this.updateBezierControlPoints();
- },
-
- update: function update(reset) {
- var me = this;
- var meta = me.getMeta();
- var line = meta.dataset;
- var points = meta.data;
- var custom = line.custom || {};
- var dataset = me.getDataset();
- var lineElementOptions = me.chart.options.elements.line;
- var scale = me.chart.scale;
-
- // Compatibility: If the properties are defined with only the old name, use those values
- if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {
- dataset.lineTension = dataset.tension;
- }
-
- helpers.extend(meta.dataset, {
- // Utility
- _datasetIndex: me.index,
- // Data
- _children: points,
- _loop: true,
- // Model
- _model: {
- // Appearance
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
- borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),
- fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
- borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),
- borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),
- borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
- borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
-
- // Scale
- scaleTop: scale.top,
- scaleBottom: scale.bottom,
- scaleZero: scale.getBasePosition()
- }
- });
-
- meta.dataset.pivot();
-
- // Update Points
- helpers.each(points, function(point, index) {
- me.updateElement(point, index, reset);
- }, me);
-
-
- // Update bezier control points
- me.updateBezierControlPoints();
- },
- updateElement: function(point, index, reset) {
- var me = this;
- var custom = point.custom || {};
- var dataset = me.getDataset();
- var scale = me.chart.scale;
- var pointElementOptions = me.chart.options.elements.point;
- var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
-
- helpers.extend(point, {
- // Utility
- _datasetIndex: me.index,
- _index: index,
- _scale: scale,
-
- // Desired view properties
- _model: {
- x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales
- y: reset ? scale.yCenter : pointPosition.y,
-
- // Appearance
- tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.tension, me.chart.options.elements.line.tension),
- radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),
- backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),
- borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),
- borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),
- pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),
-
- // Tooltip
- hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)
- }
- });
-
- point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));
- },
- updateBezierControlPoints: function() {
- var chartArea = this.chart.chartArea;
- var meta = this.getMeta();
-
- helpers.each(meta.data, function(point, index) {
- var model = point._model;
- var controlPoints = helpers.splineCurve(
- helpers.previousItem(meta.data, index, true)._model,
- model,
- helpers.nextItem(meta.data, index, true)._model,
- model.tension
- );
-
- // Prevent the bezier going outside of the bounds of the graph
- model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);
- model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);
-
- model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);
- model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);
-
- // Now pivot the point for animation
- point.pivot();
- });
- },
-
- draw: function(ease) {
- var meta = this.getMeta();
- var easingDecimal = ease || 1;
-
- // Transition Point Locations
- helpers.each(meta.data, function(point, index) {
- point.transition(easingDecimal);
- });
-
- // Transition and Draw the line
- meta.dataset.transition(easingDecimal).draw();
-
- // Draw the points
- helpers.each(meta.data, function(point) {
- point.draw();
- });
- },
-
- setHoverStyle: function(point) {
- // Point
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var custom = point.custom || {};
- var index = point._index;
- var model = point._model;
-
- model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);
- model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);
- },
-
- removeHoverStyle: function(point) {
- var dataset = this.chart.data.datasets[point._datasetIndex];
- var custom = point.custom || {};
- var index = point._index;
- var model = point._model;
- var pointElementOptions = this.chart.options.elements.point;
-
- model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);
- model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);
- model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);
- model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);
- }
- });
-};
-
-},{}],21:[function(require,module,exports){
-/*global window: false */
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.animation = {
- duration: 1000,
- easing: "easeOutQuart",
- onProgress: helpers.noop,
- onComplete: helpers.noop
- };
-
- Chart.Animation = Chart.Element.extend({
- currentStep: null, // the current animation step
- numSteps: 60, // default number of steps
- easing: "", // the easing to use for this animation
- render: null, // render function used by the animation service
-
- onAnimationProgress: null, // user specified callback to fire on each step of the animation
- onAnimationComplete: null // user specified callback to fire when the animation finishes
- });
-
- Chart.animationService = {
- frameDuration: 17,
- animations: [],
- dropFrames: 0,
- request: null,
- addAnimation: function(chartInstance, animationObject, duration, lazy) {
- var me = this;
-
- if (!lazy) {
- chartInstance.animating = true;
- }
-
- for (var index = 0; index < me.animations.length; ++index) {
- if (me.animations[index].chartInstance === chartInstance) {
- // replacing an in progress animation
- me.animations[index].animationObject = animationObject;
- return;
- }
- }
-
- me.animations.push({
- chartInstance: chartInstance,
- animationObject: animationObject
- });
-
- // If there are no animations queued, manually kickstart a digest, for lack of a better word
- if (me.animations.length === 1) {
- me.requestAnimationFrame();
- }
- },
- // Cancel the animation for a given chart instance
- cancelAnimation: function(chartInstance) {
- var index = helpers.findIndex(this.animations, function(animationWrapper) {
- return animationWrapper.chartInstance === chartInstance;
- });
-
- if (index !== -1) {
- this.animations.splice(index, 1);
- chartInstance.animating = false;
- }
- },
- requestAnimationFrame: function() {
- var me = this;
- if (me.request === null) {
- // Skip animation frame requests until the active one is executed.
- // This can happen when processing mouse events, e.g. 'mousemove'
- // and 'mouseout' events will trigger multiple renders.
- me.request = helpers.requestAnimFrame.call(window, function() {
- me.request = null;
- me.startDigest();
- });
- }
- },
- startDigest: function() {
- var me = this;
-
- var startTime = Date.now();
- var framesToDrop = 0;
-
- if (me.dropFrames > 1) {
- framesToDrop = Math.floor(me.dropFrames);
- me.dropFrames = me.dropFrames % 1;
- }
-
- var i = 0;
- while (i < me.animations.length) {
- if (me.animations[i].animationObject.currentStep === null) {
- me.animations[i].animationObject.currentStep = 0;
- }
-
- me.animations[i].animationObject.currentStep += 1 + framesToDrop;
-
- if (me.animations[i].animationObject.currentStep > me.animations[i].animationObject.numSteps) {
- me.animations[i].animationObject.currentStep = me.animations[i].animationObject.numSteps;
- }
-
- me.animations[i].animationObject.render(me.animations[i].chartInstance, me.animations[i].animationObject);
- if (me.animations[i].animationObject.onAnimationProgress && me.animations[i].animationObject.onAnimationProgress.call) {
- me.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance, me.animations[i]);
- }
-
- if (me.animations[i].animationObject.currentStep === me.animations[i].animationObject.numSteps) {
- if (me.animations[i].animationObject.onAnimationComplete && me.animations[i].animationObject.onAnimationComplete.call) {
- me.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance, me.animations[i]);
- }
-
- // executed the last frame. Remove the animation.
- me.animations[i].chartInstance.animating = false;
-
- me.animations.splice(i, 1);
- } else {
- ++i;
- }
- }
-
- var endTime = Date.now();
- var dropFrames = (endTime - startTime) / me.frameDuration;
-
- me.dropFrames += dropFrames;
-
- // Do we have more stuff to animate?
- if (me.animations.length > 0) {
- me.requestAnimationFrame();
- }
- }
- };
-};
-},{}],22:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- //Create a dictionary of chart types, to allow for extension of existing types
- Chart.types = {};
-
- //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
- //Destroy method on the chart will remove the instance of the chart from this reference.
- Chart.instances = {};
-
- // Controllers available for dataset visualization eg. bar, line, slice, etc.
- Chart.controllers = {};
-
- // The main controller of a chart
- Chart.Controller = function(instance) {
-
- this.chart = instance;
- this.config = instance.config;
- this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});
- this.id = helpers.uid();
-
- Object.defineProperty(this, 'data', {
- get: function() {
- return this.config.data;
- }
- });
-
- //Add the chart instance to the global namespace
- Chart.instances[this.id] = this;
-
- if (this.options.responsive) {
- // Silent resize before chart draws
- this.resize(true);
- }
-
- this.initialize();
-
- return this;
- };
-
- helpers.extend(Chart.Controller.prototype, {
-
- initialize: function initialize() {
- var me = this;
- // Before init plugin notification
- Chart.pluginService.notifyPlugins('beforeInit', [me]);
-
- me.bindEvents();
-
- // Make sure controllers are built first so that each dataset is bound to an axis before the scales
- // are built
- me.ensureScalesHaveIDs();
- me.buildOrUpdateControllers();
- me.buildScales();
- me.updateLayout();
- me.resetElements();
- me.initToolTip();
- me.update();
-
- // After init plugin notification
- Chart.pluginService.notifyPlugins('afterInit', [me]);
-
- return me;
- },
-
- clear: function clear() {
- helpers.clear(this.chart);
- return this;
- },
-
- stop: function stop() {
- // Stops any current animation loop occuring
- Chart.animationService.cancelAnimation(this);
- return this;
- },
-
- resize: function resize(silent) {
- var me = this;
- var chart = me.chart;
- var canvas = chart.canvas;
- var newWidth = helpers.getMaximumWidth(canvas);
- var aspectRatio = chart.aspectRatio;
- var newHeight = (me.options.maintainAspectRatio && isNaN(aspectRatio) === false && isFinite(aspectRatio) && aspectRatio !== 0) ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas);
-
- var sizeChanged = chart.width !== newWidth || chart.height !== newHeight;
-
- if (!sizeChanged) {
- return me;
- }
-
- canvas.width = chart.width = newWidth;
- canvas.height = chart.height = newHeight;
-
- helpers.retinaScale(chart);
-
- // Notify any plugins about the resize
- var newSize = { width: newWidth, height: newHeight };
- Chart.pluginService.notifyPlugins('resize', [me, newSize]);
-
- // Notify of resize
- if (me.options.onResize) {
- me.options.onResize(me, newSize);
- }
-
- if (!silent) {
- me.stop();
- me.update(me.options.responsiveAnimationDuration);
- }
-
- return me;
- },
-
- ensureScalesHaveIDs: function ensureScalesHaveIDs() {
- var options = this.options;
- var scalesOptions = options.scales || {};
- var scaleOptions = options.scale;
-
- helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
- xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);
- });
-
- helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {
- yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);
- });
-
- if (scaleOptions) {
- scaleOptions.id = scaleOptions.id || 'scale';
- }
- },
-
- /**
- * Builds a map of scale ID to scale object for future lookup.
- */
- buildScales: function buildScales() {
- var me = this;
- var options = me.options;
- var scales = me.scales = {};
- var items = [];
-
- if (options.scales) {
- items = items.concat(
- (options.scales.xAxes || []).map(function(xAxisOptions) {
- return { options: xAxisOptions, dtype: 'category' }; }),
- (options.scales.yAxes || []).map(function(yAxisOptions) {
- return { options: yAxisOptions, dtype: 'linear' }; }));
- }
-
- if (options.scale) {
- items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });
- }
-
- helpers.each(items, function(item, index) {
- var scaleOptions = item.options;
- var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);
- var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
- if (!scaleClass) {
- return;
- }
-
- var scale = new scaleClass({
- id: scaleOptions.id,
- options: scaleOptions,
- ctx: me.chart.ctx,
- chart: me
- });
-
- scales[scale.id] = scale;
-
- // TODO(SB): I think we should be able to remove this custom case (options.scale)
- // and consider it as a regular scale part of the "scales"" map only! This would
- // make the logic easier and remove some useless? custom code.
- if (item.isDefault) {
- me.scale = scale;
- }
- });
-
- Chart.scaleService.addScalesToLayout(this);
- },
-
- updateLayout: function() {
- Chart.layoutService.update(this, this.chart.width, this.chart.height);
- },
-
- buildOrUpdateControllers: function buildOrUpdateControllers() {
- var me = this;
- var types = [];
- var newControllers = [];
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- var meta = me.getDatasetMeta(datasetIndex);
- if (!meta.type) {
- meta.type = dataset.type || me.config.type;
- }
-
- types.push(meta.type);
-
- if (meta.controller) {
- meta.controller.updateIndex(datasetIndex);
- } else {
- meta.controller = new Chart.controllers[meta.type](me, datasetIndex);
- newControllers.push(meta.controller);
- }
- }, me);
-
- if (types.length > 1) {
- for (var i = 1; i < types.length; i++) {
- if (types[i] !== types[i - 1]) {
- me.isCombo = true;
- break;
- }
- }
- }
-
- return newControllers;
- },
-
- resetElements: function resetElements() {
- var me = this;
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.reset();
- }, me);
- },
-
- update: function update(animationDuration, lazy) {
- var me = this;
- Chart.pluginService.notifyPlugins('beforeUpdate', [me]);
-
- // In case the entire data object changed
- me.tooltip._data = me.data;
-
- // Make sure dataset controllers are updated and new controllers are reset
- var newControllers = me.buildOrUpdateControllers();
-
- // Make sure all dataset controllers have correct meta data counts
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();
- }, me);
-
- Chart.layoutService.update(me, me.chart.width, me.chart.height);
-
- // Apply changes to the dataets that require the scales to have been calculated i.e BorderColor chages
- Chart.pluginService.notifyPlugins('afterScaleUpdate', [me]);
-
- // Can only reset the new controllers after the scales have been updated
- helpers.each(newControllers, function(controller) {
- controller.reset();
- });
-
- // This will loop through any data and do the appropriate element update for the type
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- me.getDatasetMeta(datasetIndex).controller.update();
- }, me);
-
- // Do this before render so that any plugins that need final scale updates can use it
- Chart.pluginService.notifyPlugins('afterUpdate', [me]);
-
- me.render(animationDuration, lazy);
- },
-
- render: function render(duration, lazy) {
- var me = this;
- Chart.pluginService.notifyPlugins('beforeRender', [me]);
-
- var animationOptions = me.options.animation;
- if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {
- var animation = new Chart.Animation();
- animation.numSteps = (duration || animationOptions.duration) / 16.66; //60 fps
- animation.easing = animationOptions.easing;
-
- // render function
- animation.render = function(chartInstance, animationObject) {
- var easingFunction = helpers.easingEffects[animationObject.easing];
- var stepDecimal = animationObject.currentStep / animationObject.numSteps;
- var easeDecimal = easingFunction(stepDecimal);
-
- chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
- };
-
- // user events
- animation.onAnimationProgress = animationOptions.onProgress;
- animation.onAnimationComplete = animationOptions.onComplete;
-
- Chart.animationService.addAnimation(me, animation, duration, lazy);
- } else {
- me.draw();
- if (animationOptions && animationOptions.onComplete && animationOptions.onComplete.call) {
- animationOptions.onComplete.call(me);
- }
- }
- return me;
- },
-
- draw: function(ease) {
- var me = this;
- var easingDecimal = ease || 1;
- me.clear();
-
- Chart.pluginService.notifyPlugins('beforeDraw', [me, easingDecimal]);
-
- // Draw all the scales
- helpers.each(me.boxes, function(box) {
- box.draw(me.chartArea);
- }, me);
- if (me.scale) {
- me.scale.draw();
- }
-
- Chart.pluginService.notifyPlugins('beforeDatasetDraw', [me, easingDecimal]);
-
- // Draw each dataset via its respective controller (reversed to support proper line stacking)
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- me.getDatasetMeta(datasetIndex).controller.draw(ease);
- }
- }, me, true);
-
- Chart.pluginService.notifyPlugins('afterDatasetDraw', [me, easingDecimal]);
-
- // Finally draw the tooltip
- me.tooltip.transition(easingDecimal).draw();
-
- Chart.pluginService.notifyPlugins('afterDraw', [me, easingDecimal]);
- },
-
- // Get the single element that was clicked on
- // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw
- getElementAtEvent: function(e) {
- var me = this;
- var eventPosition = helpers.getRelativePosition(e, me.chart);
- var elementsArray = [];
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- var meta = me.getDatasetMeta(datasetIndex);
- helpers.each(meta.data, function(element, index) {
- if (element.inRange(eventPosition.x, eventPosition.y)) {
- elementsArray.push(element);
- return elementsArray;
- }
- });
- }
- });
-
- return elementsArray;
- },
-
- getElementsAtEvent: function(e) {
- var me = this;
- var eventPosition = helpers.getRelativePosition(e, me.chart);
- var elementsArray = [];
-
- var found = (function() {
- if (me.data.datasets) {
- for (var i = 0; i < me.data.datasets.length; i++) {
- var meta = me.getDatasetMeta(i);
- if (me.isDatasetVisible(i)) {
- for (var j = 0; j < meta.data.length; j++) {
- if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {
- return meta.data[j];
- }
- }
- }
- }
- }
- }).call(me);
-
- if (!found) {
- return elementsArray;
- }
-
- helpers.each(me.data.datasets, function(dataset, datasetIndex) {
- if (me.isDatasetVisible(datasetIndex)) {
- var meta = me.getDatasetMeta(datasetIndex);
- elementsArray.push(meta.data[found._index]);
- }
- }, me);
-
- return elementsArray;
- },
-
- getElementsAtEventForMode: function(e, mode) {
- var me = this;
- switch (mode) {
- case 'single':
- return me.getElementAtEvent(e);
- case 'label':
- return me.getElementsAtEvent(e);
- case 'dataset':
- return me.getDatasetAtEvent(e);
- default:
- return e;
- }
- },
-
- getDatasetAtEvent: function(e) {
- var elementsArray = this.getElementAtEvent(e);
-
- if (elementsArray.length > 0) {
- elementsArray = this.getDatasetMeta(elementsArray[0]._datasetIndex).data;
- }
-
- return elementsArray;
- },
-
- getDatasetMeta: function(datasetIndex) {
- var me = this;
- var dataset = me.data.datasets[datasetIndex];
- if (!dataset._meta) {
- dataset._meta = {};
- }
-
- var meta = dataset._meta[me.id];
- if (!meta) {
- meta = dataset._meta[me.id] = {
- type: null,
- data: [],
- dataset: null,
- controller: null,
- hidden: null, // See isDatasetVisible() comment
- xAxisID: null,
- yAxisID: null
- };
- }
-
- return meta;
- },
-
- getVisibleDatasetCount: function() {
- var count = 0;
- for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {
- if (this.isDatasetVisible(i)) {
- count++;
- }
- }
- return count;
- },
-
- isDatasetVisible: function(datasetIndex) {
- var meta = this.getDatasetMeta(datasetIndex);
-
- // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,
- // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.
- return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
- },
-
- generateLegend: function generateLegend() {
- return this.options.legendCallback(this);
- },
-
- destroy: function destroy() {
- var me = this;
- me.stop();
- me.clear();
- helpers.unbindEvents(me, me.events);
- helpers.removeResizeListener(me.chart.canvas.parentNode);
-
- // Reset canvas height/width attributes
- var canvas = me.chart.canvas;
- canvas.width = me.chart.width;
- canvas.height = me.chart.height;
-
- // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here
- if (me.chart.originalDevicePixelRatio !== undefined) {
- me.chart.ctx.scale(1 / me.chart.originalDevicePixelRatio, 1 / me.chart.originalDevicePixelRatio);
- }
-
- // Reset to the old style since it may have been changed by the device pixel ratio changes
- canvas.style.width = me.chart.originalCanvasStyleWidth;
- canvas.style.height = me.chart.originalCanvasStyleHeight;
-
- Chart.pluginService.notifyPlugins('destroy', [me]);
-
- delete Chart.instances[me.id];
- },
-
- toBase64Image: function toBase64Image() {
- return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
- },
-
- initToolTip: function initToolTip() {
- var me = this;
- me.tooltip = new Chart.Tooltip({
- _chart: me.chart,
- _chartInstance: me,
- _data: me.data,
- _options: me.options.tooltips
- }, me);
- },
-
- bindEvents: function bindEvents() {
- var me = this;
- helpers.bindEvents(me, me.options.events, function(evt) {
- me.eventHandler(evt);
- });
- },
-
- updateHoverStyle: function(elements, mode, enabled) {
- var method = enabled? 'setHoverStyle' : 'removeHoverStyle';
- var element, i, ilen;
-
- switch (mode) {
- case 'single':
- elements = [ elements[0] ];
- break;
- case 'label':
- case 'dataset':
- // elements = elements;
- break;
- default:
- // unsupported mode
- return;
- }
-
- for (i=0, ilen=elements.length; i<ilen; ++i) {
- element = elements[i];
- if (element) {
- this.getDatasetMeta(element._datasetIndex).controller[method](element);
- }
- }
- },
-
- eventHandler: function eventHandler(e) {
- var me = this;
- var tooltip = me.tooltip;
- var options = me.options || {};
- var hoverOptions = options.hover;
- var tooltipsOptions = options.tooltips;
-
- me.lastActive = me.lastActive || [];
- me.lastTooltipActive = me.lastTooltipActive || [];
-
- // Find Active Elements for hover and tooltips
- if (e.type === 'mouseout') {
- me.active = [];
- me.tooltipActive = [];
- } else {
- me.active = me.getElementsAtEventForMode(e, hoverOptions.mode);
- me.tooltipActive = me.getElementsAtEventForMode(e, tooltipsOptions.mode);
- }
-
- // On Hover hook
- if (hoverOptions.onHover) {
- hoverOptions.onHover.call(me, me.active);
- }
-
- if (e.type === 'mouseup' || e.type === 'click') {
- if (options.onClick) {
- options.onClick.call(me, e, me.active);
- }
- if (me.legend && me.legend.handleEvent) {
- me.legend.handleEvent(e);
- }
- }
-
- // Remove styling for last active (even if it may still be active)
- if (me.lastActive.length) {
- me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);
- }
-
- // Built in hover styling
- if (me.active.length && hoverOptions.mode) {
- me.updateHoverStyle(me.active, hoverOptions.mode, true);
- }
-
- // Built in Tooltips
- if (tooltipsOptions.enabled || tooltipsOptions.custom) {
- tooltip.initialize();
- tooltip._active = me.tooltipActive;
- tooltip.update(true);
- }
-
- // Hover animations
- tooltip.pivot();
-
- if (!me.animating) {
- // If entering, leaving, or changing elements, animate the change via pivot
- if (!helpers.arrayEquals(me.active, me.lastActive) ||
- !helpers.arrayEquals(me.tooltipActive, me.lastTooltipActive)) {
-
- me.stop();
-
- if (tooltipsOptions.enabled || tooltipsOptions.custom) {
- tooltip.update(true);
- }
-
- // We only need to render at this point. Updating will cause scales to be
- // recomputed generating flicker & using more memory than necessary.
- me.render(hoverOptions.animationDuration, true);
- }
- }
-
- // Remember Last Actives
- me.lastActive = me.active;
- me.lastTooltipActive = me.tooltipActive;
- return me;
- }
- });
-};
-
-},{}],23:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var noop = helpers.noop;
-
- // Base class for all dataset controllers (line, bar, etc)
- Chart.DatasetController = function(chart, datasetIndex) {
- this.initialize.call(this, chart, datasetIndex);
- };
-
- helpers.extend(Chart.DatasetController.prototype, {
-
- /**
- * Element type used to generate a meta dataset (e.g. Chart.element.Line).
- * @type {Chart.core.element}
- */
- datasetElementType: null,
-
- /**
- * Element type used to generate a meta data (e.g. Chart.element.Point).
- * @type {Chart.core.element}
- */
- dataElementType: null,
-
- initialize: function(chart, datasetIndex) {
- var me = this;
- me.chart = chart;
- me.index = datasetIndex;
- me.linkScales();
- me.addElements();
- },
-
- updateIndex: function(datasetIndex) {
- this.index = datasetIndex;
- },
-
- linkScales: function() {
- var me = this;
- var meta = me.getMeta();
- var dataset = me.getDataset();
-
- if (meta.xAxisID === null) {
- meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id;
- }
- if (meta.yAxisID === null) {
- meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id;
- }
- },
-
- getDataset: function() {
- return this.chart.data.datasets[this.index];
- },
-
- getMeta: function() {
- return this.chart.getDatasetMeta(this.index);
- },
-
- getScaleForId: function(scaleID) {
- return this.chart.scales[scaleID];
- },
-
- reset: function() {
- this.update(true);
- },
-
- createMetaDataset: function() {
- var me = this;
- var type = me.datasetElementType;
- return type && new type({
- _chart: me.chart.chart,
- _datasetIndex: me.index
- });
- },
-
- createMetaData: function(index) {
- var me = this;
- var type = me.dataElementType;
- return type && new type({
- _chart: me.chart.chart,
- _datasetIndex: me.index,
- _index: index
- });
- },
-
- addElements: function() {
- var me = this;
- var meta = me.getMeta();
- var data = me.getDataset().data || [];
- var metaData = meta.data;
- var i, ilen;
-
- for (i=0, ilen=data.length; i<ilen; ++i) {
- metaData[i] = metaData[i] || me.createMetaData(meta, i);
- }
-
- meta.dataset = meta.dataset || me.createMetaDataset();
- },
-
- addElementAndReset: function(index) {
- var me = this;
- var element = me.createMetaData(index);
- me.getMeta().data.splice(index, 0, element);
- me.updateElement(element, index, true);
- },
-
- buildOrUpdateElements: function buildOrUpdateElements() {
- // Handle the number of data points changing
- var meta = this.getMeta(),
- md = meta.data,
- numData = this.getDataset().data.length,
- numMetaData = md.length;
-
- // Make sure that we handle number of datapoints changing
- if (numData < numMetaData) {
- // Remove excess bars for data points that have been removed
- md.splice(numData, numMetaData - numData);
- } else if (numData > numMetaData) {
- // Add new elements
- for (var index = numMetaData; index < numData; ++index) {
- this.addElementAndReset(index);
- }
- }
- },
-
- update: noop,
-
- draw: function(ease) {
- var easingDecimal = ease || 1;
- helpers.each(this.getMeta().data, function(element, index) {
- element.transition(easingDecimal).draw();
- });
- },
-
- removeHoverStyle: function(element, elementOpts) {
- var dataset = this.chart.data.datasets[element._datasetIndex],
- index = element._index,
- custom = element.custom || {},
- valueOrDefault = helpers.getValueAtIndexOrDefault,
- color = helpers.color,
- model = element._model;
-
- model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
- model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);
- model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);
- },
-
- setHoverStyle: function(element) {
- var dataset = this.chart.data.datasets[element._datasetIndex],
- index = element._index,
- custom = element.custom || {},
- valueOrDefault = helpers.getValueAtIndexOrDefault,
- color = helpers.color,
- getHoverColor = helpers.getHoverColor,
- model = element._model;
-
- model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));
- model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
- model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
- }
- });
-
- Chart.DatasetController.extend = helpers.inherits;
-};
-},{}],24:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.elements = {};
-
- Chart.Element = function(configuration) {
- helpers.extend(this, configuration);
- this.initialize.apply(this, arguments);
- };
-
- helpers.extend(Chart.Element.prototype, {
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ defaults = Chart.defaults;\r
+\r
+ defaults.doughnut = {\r
+ animation: {\r
+ //Boolean - Whether we animate the rotation of the Doughnut\r
+ animateRotate: true,\r
+ //Boolean - Whether we animate scaling the Doughnut from the centre\r
+ animateScale: false\r
+ },\r
+ aspectRatio: 1,\r
+ hover: {\r
+ mode: 'single'\r
+ },\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var labels = data.labels;\r
+\r
+ if (datasets.length) {\r
+ for (var i = 0; i < datasets[0].data.length; ++i) {\r
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');\r
+ if (labels[i]) {\r
+ text.push(labels[i]);\r
+ }\r
+ text.push('</li>');\r
+ }\r
+ }\r
+\r
+ text.push('</ul>');\r
+ return text.join("");\r
+ },\r
+ legend: {\r
+ labels: {\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ if (data.labels.length && data.datasets.length) {\r
+ return data.labels.map(function(label, i) {\r
+ var meta = chart.getDatasetMeta(0);\r
+ var ds = data.datasets[0];\r
+ var arc = meta.data[i];\r
+ var custom = arc.custom || {};\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var arcOpts = chart.options.elements.arc;\r
+ var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
+ var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
+ var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
+\r
+ return {\r
+ text: label,\r
+ fillStyle: fill,\r
+ strokeStyle: stroke,\r
+ lineWidth: bw,\r
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
+\r
+ // Extra data used for toggling the correct item\r
+ index: i\r
+ };\r
+ });\r
+ } else {\r
+ return [];\r
+ }\r
+ }\r
+ },\r
+\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.index;\r
+ var chart = this.chart;\r
+ var i, ilen, meta;\r
+\r
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
+ meta = chart.getDatasetMeta(i);\r
+ meta.data[index].hidden = !meta.data[index].hidden;\r
+ }\r
+\r
+ chart.update();\r
+ }\r
+ },\r
+\r
+ //The percentage of the chart that we cut out of the middle.\r
+ cutoutPercentage: 50,\r
+\r
+ //The rotation of the chart, where the first data arc begins.\r
+ rotation: Math.PI * -0.5,\r
+\r
+ //The total circumference of the chart.\r
+ circumference: Math.PI * 2.0,\r
+\r
+ // Need to override these to give a nice default\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function() {\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return data.labels[tooltipItem.index] + ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ defaults.pie = helpers.clone(defaults.doughnut);\r
+ helpers.extend(defaults.pie, {\r
+ cutoutPercentage: 0\r
+ });\r
+\r
+\r
+ Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Arc,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly\r
+ getRingIndex: function getRingIndex(datasetIndex) {\r
+ var ringIndex = 0;\r
+\r
+ for (var j = 0; j < datasetIndex; ++j) {\r
+ if (this.chart.isDatasetVisible(j)) {\r
+ ++ringIndex;\r
+ }\r
+ }\r
+\r
+ return ringIndex;\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var _this = this;\r
+ var chart = _this.chart,\r
+ chartArea = chart.chartArea,\r
+ opts = chart.options,\r
+ arcOpts = opts.elements.arc,\r
+ availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,\r
+ availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,\r
+ minSize = Math.min(availableWidth, availableHeight),\r
+ offset = {\r
+ x: 0,\r
+ y: 0\r
+ },\r
+ meta = _this.getMeta(),\r
+ cutoutPercentage = opts.cutoutPercentage,\r
+ circumference = opts.circumference;\r
+\r
+ // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc\r
+ if (circumference < Math.PI * 2.0) {\r
+ var startAngle = opts.rotation % (Math.PI * 2.0);\r
+ startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);\r
+ var endAngle = startAngle + circumference;\r
+ var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};\r
+ var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};\r
+ var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);\r
+ var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);\r
+ var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);\r
+ var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);\r
+ var cutout = cutoutPercentage / 100.0;\r
+ var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};\r
+ var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};\r
+ var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};\r
+ minSize = Math.min(availableWidth / size.width, availableHeight / size.height);\r
+ offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};\r
+ }\r
+\r
+ chart.outerRadius = Math.max(minSize / 2, 0);\r
+ chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);\r
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
+ chart.offsetX = offset.x * chart.outerRadius;\r
+ chart.offsetY = offset.y * chart.outerRadius;\r
+\r
+ meta.total = _this.calculateTotal();\r
+\r
+ _this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.getRingIndex(_this.index));\r
+ _this.innerRadius = _this.outerRadius - chart.radiusLength;\r
+\r
+ helpers.each(meta.data, function(arc, index) {\r
+ _this.updateElement(arc, index, reset);\r
+ });\r
+ },\r
+\r
+ updateElement: function(arc, index, reset) {\r
+ var _this = this;\r
+ var chart = _this.chart,\r
+ chartArea = chart.chartArea,\r
+ opts = chart.options,\r
+ animationOpts = opts.animation,\r
+ arcOpts = opts.elements.arc,\r
+ centerX = (chartArea.left + chartArea.right) / 2,\r
+ centerY = (chartArea.top + chartArea.bottom) / 2,\r
+ startAngle = opts.rotation, // non reset case handled later\r
+ endAngle = opts.rotation, // non reset case handled later\r
+ dataset = _this.getDataset(),\r
+ circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : _this.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),\r
+ innerRadius = reset && animationOpts.animateScale ? 0 : _this.innerRadius,\r
+ outerRadius = reset && animationOpts.animateScale ? 0 : _this.outerRadius,\r
+ custom = arc.custom || {},\r
+ valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+\r
+ helpers.extend(arc, {\r
+ // Utility\r
+ _datasetIndex: _this.index,\r
+ _index: index,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: centerX + chart.offsetX,\r
+ y: centerY + chart.offsetY,\r
+ startAngle: startAngle,\r
+ endAngle: endAngle,\r
+ circumference: circumference,\r
+ outerRadius: outerRadius,\r
+ innerRadius: innerRadius,\r
+ label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])\r
+ }\r
+ });\r
+\r
+ var model = arc._model;\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor);\r
+ model.hoverBackgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, arcOpts.hoverBackgroundColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor);\r
+\r
+ // Set correct angles if not resetting\r
+ if (!reset || !animationOpts.animateRotate) {\r
+ if (index === 0) {\r
+ model.startAngle = opts.rotation;\r
+ } else {\r
+ model.startAngle = _this.getMeta().data[index - 1]._model.endAngle;\r
+ }\r
+\r
+ model.endAngle = model.startAngle + model.circumference;\r
+ }\r
+\r
+ arc.pivot();\r
+ },\r
+\r
+ removeHoverStyle: function(arc) {\r
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\r
+ },\r
+\r
+ calculateTotal: function() {\r
+ var dataset = this.getDataset();\r
+ var meta = this.getMeta();\r
+ var total = 0;\r
+ var value;\r
+\r
+ helpers.each(meta.data, function(element, index) {\r
+ value = dataset.data[index];\r
+ if (!isNaN(value) && !element.hidden) {\r
+ total += Math.abs(value);\r
+ }\r
+ });\r
+\r
+ return total;\r
+ },\r
+\r
+ calculateCircumference: function(value) {\r
+ var total = this.getMeta().total;\r
+ if (total > 0 && !isNaN(value)) {\r
+ return (Math.PI * 2.0) * (value / total);\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ });\r
+};\r
- initialize: function() {
- this.hidden = false;
- },
+},{}],18:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.line = {\r
+ showLines: true,\r
+\r
+ hover: {\r
+ mode: "label"\r
+ },\r
+\r
+ scales: {\r
+ xAxes: [{\r
+ type: "category",\r
+ id: 'x-axis-0'\r
+ }],\r
+ yAxes: [{\r
+ type: "linear",\r
+ id: 'y-axis-0'\r
+ }]\r
+ }\r
+ };\r
+\r
+ Chart.controllers.line = Chart.DatasetController.extend({\r
+\r
+ datasetElementType: Chart.elements.Line,\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ addElementAndReset: function(index) {\r
+ var me = this;\r
+ var options = me.chart.options;\r
+\r
+ Chart.DatasetController.prototype.addElementAndReset.call(me, index);\r
+\r
+ // Make sure bezier control points are updated\r
+ if (options.showLines && options.elements.line.tension !== 0) {\r
+ me.updateBezierControlPoints();\r
+ }\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var line = meta.dataset;\r
+ var points = meta.data || [];\r
+ var options = me.chart.options;\r
+ var lineElementOptions = options.elements.line;\r
+ var scale = me.getScaleForId(meta.yAxisID);\r
+ var i, ilen, dataset, custom;\r
+\r
+ // Update Line\r
+ if (options.showLines) {\r
+ dataset = me.getDataset();\r
+ custom = line.custom || {};\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\r
+ dataset.lineTension = dataset.tension;\r
+ }\r
+\r
+ // Utility\r
+ line._scale = scale;\r
+ line._datasetIndex = me.index;\r
+ // Data\r
+ line._children = points;\r
+ // Model\r
+ line._model = {\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\r
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\r
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\r
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\r
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\r
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\r
+ // Scale\r
+ scaleTop: scale.top,\r
+ scaleBottom: scale.bottom,\r
+ scaleZero: scale.getBasePixel()\r
+ };\r
+\r
+ line.pivot();\r
+ }\r
+\r
+ // Update Points\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ me.updateElement(points[i], i, reset);\r
+ }\r
+\r
+ if (options.showLines && lineElementOptions.tension !== 0) {\r
+ me.updateBezierControlPoints();\r
+ }\r
+ },\r
+\r
+ getPointBackgroundColor: function(point, index) {\r
+ var backgroundColor = this.chart.options.elements.point.backgroundColor;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.backgroundColor) {\r
+ backgroundColor = custom.backgroundColor;\r
+ } else if (dataset.pointBackgroundColor) {\r
+ backgroundColor = helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor);\r
+ } else if (dataset.backgroundColor) {\r
+ backgroundColor = dataset.backgroundColor;\r
+ }\r
+\r
+ return backgroundColor;\r
+ },\r
+\r
+ getPointBorderColor: function(point, index) {\r
+ var borderColor = this.chart.options.elements.point.borderColor;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.borderColor) {\r
+ borderColor = custom.borderColor;\r
+ } else if (dataset.pointBorderColor) {\r
+ borderColor = helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor);\r
+ } else if (dataset.borderColor) {\r
+ borderColor = dataset.borderColor;\r
+ }\r
+\r
+ return borderColor;\r
+ },\r
+\r
+ getPointBorderWidth: function(point, index) {\r
+ var borderWidth = this.chart.options.elements.point.borderWidth;\r
+ var dataset = this.getDataset();\r
+ var custom = point.custom || {};\r
+\r
+ if (custom.borderWidth) {\r
+ borderWidth = custom.borderWidth;\r
+ } else if (dataset.pointBorderWidth) {\r
+ borderWidth = helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth);\r
+ } else if (dataset.borderWidth) {\r
+ borderWidth = dataset.borderWidth;\r
+ }\r
+\r
+ return borderWidth;\r
+ },\r
+\r
+ updateElement: function(point, index, reset) {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var custom = point.custom || {};\r
+ var dataset = me.getDataset();\r
+ var datasetIndex = me.index;\r
+ var value = dataset.data[index];\r
+ var yScale = me.getScaleForId(meta.yAxisID);\r
+ var xScale = me.getScaleForId(meta.xAxisID);\r
+ var pointOptions = me.chart.options.elements.point;\r
+ var x, y;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
+ dataset.pointRadius = dataset.radius;\r
+ }\r
+ if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) {\r
+ dataset.pointHitRadius = dataset.hitRadius;\r
+ }\r
+\r
+ x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);\r
+ y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);\r
+\r
+ // Utility\r
+ point._xScale = xScale;\r
+ point._yScale = yScale;\r
+ point._datasetIndex = datasetIndex;\r
+ point._index = index;\r
+\r
+ // Desired view properties\r
+ point._model = {\r
+ x: x,\r
+ y: y,\r
+ skip: custom.skip || isNaN(x) || isNaN(y),\r
+ // Appearance\r
+ radius: custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius),\r
+ pointStyle: custom.pointStyle || helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle),\r
+ backgroundColor: me.getPointBackgroundColor(point, index),\r
+ borderColor: me.getPointBorderColor(point, index),\r
+ borderWidth: me.getPointBorderWidth(point, index),\r
+ tension: meta.dataset._model ? meta.dataset._model.tension : 0,\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)\r
+ };\r
+ },\r
+\r
+ calculatePointY: function(value, index, datasetIndex, isCombo) {\r
+ var me = this;\r
+ var chart = me.chart;\r
+ var meta = me.getMeta();\r
+ var yScale = me.getScaleForId(meta.yAxisID);\r
+ var sumPos = 0;\r
+ var sumNeg = 0;\r
+ var i, ds, dsMeta;\r
+\r
+ if (yScale.options.stacked) {\r
+ for (i = 0; i < datasetIndex; i++) {\r
+ ds = chart.data.datasets[i];\r
+ dsMeta = chart.getDatasetMeta(i);\r
+ if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {\r
+ if (ds.data[index] < 0) {\r
+ sumNeg += ds.data[index] || 0;\r
+ } else {\r
+ sumPos += ds.data[index] || 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (value < 0) {\r
+ return yScale.getPixelForValue(sumNeg + value);\r
+ } else {\r
+ return yScale.getPixelForValue(sumPos + value);\r
+ }\r
+ }\r
+\r
+ return yScale.getPixelForValue(value);\r
+ },\r
+\r
+ updateBezierControlPoints: function() {\r
+ var meta = this.getMeta();\r
+ var area = this.chart.chartArea;\r
+ var points = meta.data || [];\r
+ var i, ilen, point, model, controlPoints;\r
+\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ point = points[i];\r
+ model = point._model;\r
+ controlPoints = helpers.splineCurve(\r
+ helpers.previousItem(points, i)._model,\r
+ model,\r
+ helpers.nextItem(points, i)._model,\r
+ meta.dataset._model.tension\r
+ );\r
+\r
+ // Prevent the bezier going outside of the bounds of the graph\r
+ model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, area.right), area.left);\r
+ model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, area.bottom), area.top);\r
+ model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, area.right), area.left);\r
+ model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, area.bottom), area.top);\r
+\r
+ // Now pivot the point for animation\r
+ point.pivot();\r
+ }\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var meta = this.getMeta();\r
+ var points = meta.data || [];\r
+ var easingDecimal = ease || 1;\r
+ var i, ilen;\r
+\r
+ // Transition Point Locations\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ points[i].transition(easingDecimal);\r
+ }\r
+\r
+ // Transition and Draw the line\r
+ if (this.chart.options.showLines) {\r
+ meta.dataset.transition(easingDecimal).draw();\r
+ }\r
+\r
+ // Draw the points\r
+ for (i=0, ilen=points.length; i<ilen; ++i) {\r
+ points[i].draw();\r
+ }\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius || helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\r
+ model.backgroundColor = custom.hoverBackgroundColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth || helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var me = this;\r
+ var dataset = me.chart.data.datasets[point._datasetIndex];\r
+ var index = point._index;\r
+ var custom = point.custom || {};\r
+ var model = point._model;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) {\r
+ dataset.pointRadius = dataset.radius;\r
+ }\r
+\r
+ model.radius = custom.radius || helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius);\r
+ model.backgroundColor = me.getPointBackgroundColor(point, index);\r
+ model.borderColor = me.getPointBorderColor(point, index);\r
+ model.borderWidth = me.getPointBorderWidth(point, index);\r
+ }\r
+ });\r
+};\r
- pivot: function() {
- var me = this;
- if (!me._view) {
- me._view = helpers.clone(me._model);
- }
- me._start = helpers.clone(me._view);
- return me;
- },
+},{}],19:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.polarArea = {\r
+\r
+ scale: {\r
+ type: "radialLinear",\r
+ lineArc: true // so that lines are circular\r
+ },\r
+\r
+ //Boolean - Whether to animate the rotation of the chart\r
+ animation: {\r
+ animateRotate: true,\r
+ animateScale: true\r
+ },\r
+\r
+ aspectRatio: 1,\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var labels = data.labels;\r
+\r
+ if (datasets.length) {\r
+ for (var i = 0; i < datasets[0].data.length; ++i) {\r
+ text.push('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '">');\r
+ if (labels[i]) {\r
+ text.push(labels[i]);\r
+ }\r
+ text.push('</span></li>');\r
+ }\r
+ }\r
+\r
+ text.push('</ul>');\r
+ return text.join("");\r
+ },\r
+ legend: {\r
+ labels: {\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ if (data.labels.length && data.datasets.length) {\r
+ return data.labels.map(function(label, i) {\r
+ var meta = chart.getDatasetMeta(0);\r
+ var ds = data.datasets[0];\r
+ var arc = meta.data[i];\r
+ var custom = arc.custom || {};\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var arcOpts = chart.options.elements.arc;\r
+ var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\r
+ var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\r
+ var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\r
+\r
+ return {\r
+ text: label,\r
+ fillStyle: fill,\r
+ strokeStyle: stroke,\r
+ lineWidth: bw,\r
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,\r
+\r
+ // Extra data used for toggling the correct item\r
+ index: i\r
+ };\r
+ });\r
+ } else {\r
+ return [];\r
+ }\r
+ }\r
+ },\r
+\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.index;\r
+ var chart = this.chart;\r
+ var i, ilen, meta;\r
+\r
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\r
+ meta = chart.getDatasetMeta(i);\r
+ meta.data[index].hidden = !meta.data[index].hidden;\r
+ }\r
+\r
+ chart.update();\r
+ }\r
+ },\r
+\r
+ // Need to override these to give a nice default\r
+ tooltips: {\r
+ callbacks: {\r
+ title: function() {\r
+ return '';\r
+ },\r
+ label: function(tooltipItem, data) {\r
+ return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.polarArea = Chart.DatasetController.extend({\r
+\r
+ dataElementType: Chart.elements.Arc,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ update: function update(reset) {\r
+ var _this = this;\r
+ var chart = _this.chart;\r
+ var chartArea = chart.chartArea;\r
+ var meta = this.getMeta();\r
+ var opts = chart.options;\r
+ var arcOpts = opts.elements.arc;\r
+ var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\r
+ chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);\r
+ chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);\r
+ chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\r
+\r
+ _this.outerRadius = chart.outerRadius - (chart.radiusLength * _this.index);\r
+ _this.innerRadius = _this.outerRadius - chart.radiusLength;\r
+\r
+ meta.count = _this.countVisibleElements();\r
+\r
+ helpers.each(meta.data, function(arc, index) {\r
+ _this.updateElement(arc, index, reset);\r
+ });\r
+ },\r
+\r
+ updateElement: function(arc, index, reset) {\r
+ var _this = this;\r
+ var chart = _this.chart;\r
+ var chartArea = chart.chartArea;\r
+ var dataset = _this.getDataset();\r
+ var opts = chart.options;\r
+ var animationOpts = opts.animation;\r
+ var arcOpts = opts.elements.arc;\r
+ var custom = arc.custom || {};\r
+ var scale = chart.scale;\r
+ var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\r
+ var labels = chart.data.labels;\r
+\r
+ var circumference = _this.calculateCircumference(dataset.data[index]);\r
+ var centerX = (chartArea.left + chartArea.right) / 2;\r
+ var centerY = (chartArea.top + chartArea.bottom) / 2;\r
+\r
+ // If there is NaN data before us, we need to calculate the starting angle correctly.\r
+ // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data\r
+ var visibleCount = 0;\r
+ var meta = _this.getMeta();\r
+ for (var i = 0; i < index; ++i) {\r
+ if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {\r
+ ++visibleCount;\r
+ }\r
+ }\r
+\r
+ var distance = arc.hidden? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\r
+ var startAngle = (-0.5 * Math.PI) + (circumference * visibleCount);\r
+ var endAngle = startAngle + (arc.hidden? 0 : circumference);\r
+\r
+ var resetModel = {\r
+ x: centerX,\r
+ y: centerY,\r
+ innerRadius: 0,\r
+ outerRadius: animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]),\r
+ startAngle: animationOpts.animateRotate ? Math.PI * -0.5 : startAngle,\r
+ endAngle: animationOpts.animateRotate ? Math.PI * -0.5 : endAngle,\r
+\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),\r
+\r
+ label: getValueAtIndexOrDefault(labels, index, labels[index])\r
+ };\r
+\r
+ helpers.extend(arc, {\r
+ // Utility\r
+ _datasetIndex: _this.index,\r
+ _index: index,\r
+ _scale: scale,\r
+\r
+ // Desired view properties\r
+ _model: reset ? resetModel : {\r
+ x: centerX,\r
+ y: centerY,\r
+ innerRadius: 0,\r
+ outerRadius: distance,\r
+ startAngle: startAngle,\r
+ endAngle: endAngle,\r
+\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(dataset.backgroundColor, index, arcOpts.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(dataset.borderWidth, index, arcOpts.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(dataset.borderColor, index, arcOpts.borderColor),\r
+\r
+ label: getValueAtIndexOrDefault(labels, index, labels[index])\r
+ }\r
+ });\r
+\r
+ arc.pivot();\r
+ },\r
+\r
+ removeHoverStyle: function(arc) {\r
+ Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\r
+ },\r
+\r
+ countVisibleElements: function() {\r
+ var dataset = this.getDataset();\r
+ var meta = this.getMeta();\r
+ var count = 0;\r
+\r
+ helpers.each(meta.data, function(element, index) {\r
+ if (!isNaN(dataset.data[index]) && !element.hidden) {\r
+ count++;\r
+ }\r
+ });\r
+\r
+ return count;\r
+ },\r
+\r
+ calculateCircumference: function(value) {\r
+ var count = this.getMeta().count;\r
+ if (count > 0 && !isNaN(value)) {\r
+ return (2 * Math.PI) / count;\r
+ } else {\r
+ return 0;\r
+ }\r
+ }\r
+ });\r
+};\r
- transition: function(ease) {
- var me = this;
-
- if (!me._view) {
- me._view = helpers.clone(me._model);
- }
-
- // No animation -> No Transition
- if (ease === 1) {
- me._view = me._model;
- me._start = null;
- return me;
- }
-
- if (!me._start) {
- me.pivot();
- }
-
- helpers.each(me._model, function(value, key) {
-
- if (key[0] === '_') {
- // Only non-underscored properties
- }
-
- // Init if doesn't exist
- else if (!me._view.hasOwnProperty(key)) {
- if (typeof value === 'number' && !isNaN(me._view[key])) {
- me._view[key] = value * ease;
- } else {
- me._view[key] = value;
- }
- }
-
- // No unnecessary computations
- else if (value === me._view[key]) {
- // It's the same! Woohoo!
- }
-
- // Color transitions if possible
- else if (typeof value === 'string') {
- try {
- var color = helpers.color(me._model[key]).mix(helpers.color(me._start[key]), ease);
- me._view[key] = color.rgbString();
- } catch (err) {
- me._view[key] = value;
- }
- }
- // Number transitions
- else if (typeof value === 'number') {
- var startVal = me._start[key] !== undefined && isNaN(me._start[key]) === false ? me._start[key] : 0;
- me._view[key] = ((me._model[key] - startVal) * ease) + startVal;
- }
- // Everything else
- else {
- me._view[key] = value;
- }
- }, me);
-
- return me;
- },
-
- tooltipPosition: function() {
- return {
- x: this._model.x,
- y: this._model.y
- };
- },
-
- hasValue: function() {
- return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
- }
- });
+},{}],20:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.radar = {\r
+ scale: {\r
+ type: "radialLinear"\r
+ },\r
+ elements: {\r
+ line: {\r
+ tension: 0 // no bezier in radar\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.controllers.radar = Chart.DatasetController.extend({\r
+\r
+ datasetElementType: Chart.elements.Line,\r
+\r
+ dataElementType: Chart.elements.Point,\r
+\r
+ linkScales: helpers.noop,\r
+\r
+ addElementAndReset: function(index) {\r
+ Chart.DatasetController.prototype.addElementAndReset.call(this, index);\r
+\r
+ // Make sure bezier control points are updated\r
+ this.updateBezierControlPoints();\r
+ },\r
+\r
+ update: function update(reset) {\r
+ var meta = this.getMeta();\r
+ var line = meta.dataset;\r
+ var points = meta.data;\r
+ var custom = line.custom || {};\r
+ var dataset = this.getDataset();\r
+ var lineElementOptions = this.chart.options.elements.line;\r
+ var scale = this.chart.scale;\r
+\r
+ // Compatibility: If the properties are defined with only the old name, use those values\r
+ if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\r
+ dataset.lineTension = dataset.tension;\r
+ }\r
+\r
+ helpers.extend(meta.dataset, {\r
+ // Utility\r
+ _datasetIndex: this.index,\r
+ // Data\r
+ _children: points,\r
+ _loop: true,\r
+ // Model\r
+ _model: {\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\r
+ borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\r
+ fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\r
+ borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\r
+ borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\r
+ borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\r
+ borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\r
+\r
+ // Scale\r
+ scaleTop: scale.top,\r
+ scaleBottom: scale.bottom,\r
+ scaleZero: scale.getBasePosition()\r
+ }\r
+ });\r
+\r
+ meta.dataset.pivot();\r
+\r
+ // Update Points\r
+ helpers.each(points, function(point, index) {\r
+ this.updateElement(point, index, reset);\r
+ }, this);\r
+\r
+\r
+ // Update bezier control points\r
+ this.updateBezierControlPoints();\r
+ },\r
+ updateElement: function(point, index, reset) {\r
+ var custom = point.custom || {};\r
+ var dataset = this.getDataset();\r
+ var scale = this.chart.scale;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+ var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);\r
+\r
+ helpers.extend(point, {\r
+ // Utility\r
+ _datasetIndex: this.index,\r
+ _index: index,\r
+ _scale: scale,\r
+\r
+ // Desired view properties\r
+ _model: {\r
+ x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales\r
+ y: reset ? scale.yCenter : pointPosition.y,\r
+\r
+ // Appearance\r
+ tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.tension, this.chart.options.elements.line.tension),\r
+ radius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),\r
+ backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),\r
+ borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),\r
+ borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),\r
+ pointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),\r
+\r
+ // Tooltip\r
+ hitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\r
+ }\r
+ });\r
+\r
+ point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));\r
+ },\r
+ updateBezierControlPoints: function() {\r
+ var chartArea = this.chart.chartArea;\r
+ var meta = this.getMeta();\r
+\r
+ helpers.each(meta.data, function(point, index) {\r
+ var model = point._model;\r
+ var controlPoints = helpers.splineCurve(\r
+ helpers.previousItem(meta.data, index, true)._model,\r
+ model,\r
+ helpers.nextItem(meta.data, index, true)._model,\r
+ model.tension\r
+ );\r
+\r
+ // Prevent the bezier going outside of the bounds of the graph\r
+ model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);\r
+ model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);\r
+\r
+ model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);\r
+ model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);\r
+\r
+ // Now pivot the point for animation\r
+ point.pivot();\r
+ }, this);\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var meta = this.getMeta();\r
+ var easingDecimal = ease || 1;\r
+\r
+ // Transition Point Locations\r
+ helpers.each(meta.data, function(point, index) {\r
+ point.transition(easingDecimal);\r
+ });\r
+\r
+ // Transition and Draw the line\r
+ meta.dataset.transition(easingDecimal).draw();\r
+\r
+ // Draw the points\r
+ helpers.each(meta.data, function(point) {\r
+ point.draw();\r
+ });\r
+ },\r
+\r
+ setHoverStyle: function(point) {\r
+ // Point\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var custom = point.custom || {};\r
+ var index = point._index;\r
+ var model = point._model;\r
+\r
+ model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\r
+ },\r
+\r
+ removeHoverStyle: function(point) {\r
+ var dataset = this.chart.data.datasets[point._datasetIndex];\r
+ var custom = point.custom || {};\r
+ var index = point._index;\r
+ var model = point._model;\r
+ var pointElementOptions = this.chart.options.elements.point;\r
+\r
+ model.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);\r
+ }\r
+ });\r
+};\r
- Chart.Element.extend = helpers.inherits;
+},{}],21:[function(require,module,exports){
+/*global window: false */\r
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.animation = {\r
+ duration: 1000,\r
+ easing: "easeOutQuart",\r
+ onProgress: helpers.noop,\r
+ onComplete: helpers.noop\r
+ };\r
+\r
+ Chart.Animation = Chart.Element.extend({\r
+ currentStep: null, // the current animation step\r
+ numSteps: 60, // default number of steps\r
+ easing: "", // the easing to use for this animation\r
+ render: null, // render function used by the animation service\r
+\r
+ onAnimationProgress: null, // user specified callback to fire on each step of the animation\r
+ onAnimationComplete: null // user specified callback to fire when the animation finishes\r
+ });\r
+\r
+ Chart.animationService = {\r
+ frameDuration: 17,\r
+ animations: [],\r
+ dropFrames: 0,\r
+ request: null,\r
+ addAnimation: function(chartInstance, animationObject, duration, lazy) {\r
+\r
+ if (!lazy) {\r
+ chartInstance.animating = true;\r
+ }\r
+\r
+ for (var index = 0; index < this.animations.length; ++index) {\r
+ if (this.animations[index].chartInstance === chartInstance) {\r
+ // replacing an in progress animation\r
+ this.animations[index].animationObject = animationObject;\r
+ return;\r
+ }\r
+ }\r
+\r
+ this.animations.push({\r
+ chartInstance: chartInstance,\r
+ animationObject: animationObject\r
+ });\r
+\r
+ // If there are no animations queued, manually kickstart a digest, for lack of a better word\r
+ if (this.animations.length === 1) {\r
+ this.requestAnimationFrame();\r
+ }\r
+ },\r
+ // Cancel the animation for a given chart instance\r
+ cancelAnimation: function(chartInstance) {\r
+ var index = helpers.findIndex(this.animations, function(animationWrapper) {\r
+ return animationWrapper.chartInstance === chartInstance;\r
+ });\r
+\r
+ if (index !== -1) {\r
+ this.animations.splice(index, 1);\r
+ chartInstance.animating = false;\r
+ }\r
+ },\r
+ requestAnimationFrame: function() {\r
+ var me = this;\r
+ if (me.request === null) {\r
+ // Skip animation frame requests until the active one is executed.\r
+ // This can happen when processing mouse events, e.g. 'mousemove'\r
+ // and 'mouseout' events will trigger multiple renders.\r
+ me.request = helpers.requestAnimFrame.call(window, function() {\r
+ me.request = null;\r
+ me.startDigest();\r
+ });\r
+ }\r
+ },\r
+ startDigest: function() {\r
+\r
+ var startTime = Date.now();\r
+ var framesToDrop = 0;\r
+\r
+ if (this.dropFrames > 1) {\r
+ framesToDrop = Math.floor(this.dropFrames);\r
+ this.dropFrames = this.dropFrames % 1;\r
+ }\r
+\r
+ var i = 0;\r
+ while (i < this.animations.length) {\r
+ if (this.animations[i].animationObject.currentStep === null) {\r
+ this.animations[i].animationObject.currentStep = 0;\r
+ }\r
+\r
+ this.animations[i].animationObject.currentStep += 1 + framesToDrop;\r
+\r
+ if (this.animations[i].animationObject.currentStep > this.animations[i].animationObject.numSteps) {\r
+ this.animations[i].animationObject.currentStep = this.animations[i].animationObject.numSteps;\r
+ }\r
+\r
+ this.animations[i].animationObject.render(this.animations[i].chartInstance, this.animations[i].animationObject);\r
+ if (this.animations[i].animationObject.onAnimationProgress && this.animations[i].animationObject.onAnimationProgress.call) {\r
+ this.animations[i].animationObject.onAnimationProgress.call(this.animations[i].chartInstance, this.animations[i]);\r
+ }\r
+\r
+ if (this.animations[i].animationObject.currentStep === this.animations[i].animationObject.numSteps) {\r
+ if (this.animations[i].animationObject.onAnimationComplete && this.animations[i].animationObject.onAnimationComplete.call) {\r
+ this.animations[i].animationObject.onAnimationComplete.call(this.animations[i].chartInstance, this.animations[i]);\r
+ }\r
+\r
+ // executed the last frame. Remove the animation.\r
+ this.animations[i].chartInstance.animating = false;\r
+\r
+ this.animations.splice(i, 1);\r
+ } else {\r
+ ++i;\r
+ }\r
+ }\r
+\r
+ var endTime = Date.now();\r
+ var dropFrames = (endTime - startTime) / this.frameDuration;\r
+\r
+ this.dropFrames += dropFrames;\r
+\r
+ // Do we have more stuff to animate?\r
+ if (this.animations.length > 0) {\r
+ this.requestAnimationFrame();\r
+ }\r
+ }\r
+ };\r
+};
+},{}],22:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ //Create a dictionary of chart types, to allow for extension of existing types\r
+ Chart.types = {};\r
+\r
+ //Store a reference to each instance - allowing us to globally resize chart instances on window resize.\r
+ //Destroy method on the chart will remove the instance of the chart from this reference.\r
+ Chart.instances = {};\r
+\r
+ // Controllers available for dataset visualization eg. bar, line, slice, etc.\r
+ Chart.controllers = {};\r
+\r
+ // The main controller of a chart\r
+ Chart.Controller = function(instance) {\r
+\r
+ this.chart = instance;\r
+ this.config = instance.config;\r
+ this.options = this.config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[this.config.type], this.config.options || {});\r
+ this.id = helpers.uid();\r
+\r
+ Object.defineProperty(this, 'data', {\r
+ get: function() {\r
+ return this.config.data;\r
+ }\r
+ });\r
+\r
+ //Add the chart instance to the global namespace\r
+ Chart.instances[this.id] = this;\r
+\r
+ if (this.options.responsive) {\r
+ // Silent resize before chart draws\r
+ this.resize(true);\r
+ }\r
+\r
+ this.initialize();\r
+\r
+ return this;\r
+ };\r
+\r
+ helpers.extend(Chart.Controller.prototype, {\r
+\r
+ initialize: function initialize() {\r
+ // Before init plugin notification\r
+ Chart.pluginService.notifyPlugins('beforeInit', [this]);\r
+\r
+ this.bindEvents();\r
+\r
+ // Make sure controllers are built first so that each dataset is bound to an axis before the scales\r
+ // are built\r
+ this.ensureScalesHaveIDs();\r
+ this.buildOrUpdateControllers();\r
+ this.buildScales();\r
+ this.buildSurroundingItems();\r
+ this.updateLayout();\r
+ this.resetElements();\r
+ this.initToolTip();\r
+ this.update();\r
+\r
+ // After init plugin notification\r
+ Chart.pluginService.notifyPlugins('afterInit', [this]);\r
+\r
+ return this;\r
+ },\r
+\r
+ clear: function clear() {\r
+ helpers.clear(this.chart);\r
+ return this;\r
+ },\r
+\r
+ stop: function stop() {\r
+ // Stops any current animation loop occuring\r
+ Chart.animationService.cancelAnimation(this);\r
+ return this;\r
+ },\r
+\r
+ resize: function resize(silent) {\r
+ var canvas = this.chart.canvas;\r
+ var newWidth = helpers.getMaximumWidth(this.chart.canvas);\r
+ var newHeight = (this.options.maintainAspectRatio && isNaN(this.chart.aspectRatio) === false && isFinite(this.chart.aspectRatio) && this.chart.aspectRatio !== 0) ? newWidth / this.chart.aspectRatio : helpers.getMaximumHeight(this.chart.canvas);\r
+\r
+ var sizeChanged = this.chart.width !== newWidth || this.chart.height !== newHeight;\r
+\r
+ if (!sizeChanged)\r
+ return this;\r
+\r
+ canvas.width = this.chart.width = newWidth;\r
+ canvas.height = this.chart.height = newHeight;\r
+\r
+ helpers.retinaScale(this.chart);\r
+\r
+ if (!silent) {\r
+ this.stop();\r
+ this.update(this.options.responsiveAnimationDuration);\r
+ }\r
+\r
+ return this;\r
+ },\r
+\r
+ ensureScalesHaveIDs: function ensureScalesHaveIDs() {\r
+ var options = this.options;\r
+ var scalesOptions = options.scales || {};\r
+ var scaleOptions = options.scale;\r
+\r
+ helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {\r
+ xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);\r
+ });\r
+\r
+ helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {\r
+ yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);\r
+ });\r
+\r
+ if (scaleOptions) {\r
+ scaleOptions.id = scaleOptions.id || 'scale';\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Builds a map of scale ID to scale object for future lookup.\r
+ */\r
+ buildScales: function buildScales() {\r
+ var me = this;\r
+ var options = me.options;\r
+ var scales = me.scales = {};\r
+ var items = [];\r
+\r
+ if (options.scales) {\r
+ items = items.concat(\r
+ (options.scales.xAxes || []).map(function(xAxisOptions) {\r
+ return { options: xAxisOptions, dtype: 'category' }; }),\r
+ (options.scales.yAxes || []).map(function(yAxisOptions) {\r
+ return { options: yAxisOptions, dtype: 'linear' }; }));\r
+ }\r
+\r
+ if (options.scale) {\r
+ items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });\r
+ }\r
+\r
+ helpers.each(items, function(item, index) {\r
+ var scaleOptions = item.options;\r
+ var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);\r
+ var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);\r
+ if (!scaleClass) {\r
+ return;\r
+ }\r
+\r
+ var scale = new scaleClass({\r
+ id: scaleOptions.id,\r
+ options: scaleOptions,\r
+ ctx: me.chart.ctx,\r
+ chart: me\r
+ });\r
+\r
+ scales[scale.id] = scale;\r
+\r
+ // TODO(SB): I think we should be able to remove this custom case (options.scale)\r
+ // and consider it as a regular scale part of the "scales"" map only! This would\r
+ // make the logic easier and remove some useless? custom code.\r
+ if (item.isDefault) {\r
+ me.scale = scale;\r
+ }\r
+ });\r
+\r
+ Chart.scaleService.addScalesToLayout(this);\r
+ },\r
+\r
+ buildSurroundingItems: function() {\r
+ if (this.options.title) {\r
+ this.titleBlock = new Chart.Title({\r
+ ctx: this.chart.ctx,\r
+ options: this.options.title,\r
+ chart: this\r
+ });\r
+\r
+ Chart.layoutService.addBox(this, this.titleBlock);\r
+ }\r
+\r
+ if (this.options.legend) {\r
+ this.legend = new Chart.Legend({\r
+ ctx: this.chart.ctx,\r
+ options: this.options.legend,\r
+ chart: this\r
+ });\r
+\r
+ Chart.layoutService.addBox(this, this.legend);\r
+ }\r
+ },\r
+\r
+ updateLayout: function() {\r
+ Chart.layoutService.update(this, this.chart.width, this.chart.height);\r
+ },\r
+\r
+ buildOrUpdateControllers: function buildOrUpdateControllers() {\r
+ var types = [];\r
+ var newControllers = [];\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ if (!meta.type) {\r
+ meta.type = dataset.type || this.config.type;\r
+ }\r
+\r
+ types.push(meta.type);\r
+\r
+ if (meta.controller) {\r
+ meta.controller.updateIndex(datasetIndex);\r
+ } else {\r
+ meta.controller = new Chart.controllers[meta.type](this, datasetIndex);\r
+ newControllers.push(meta.controller);\r
+ }\r
+ }, this);\r
+\r
+ if (types.length > 1) {\r
+ for (var i = 1; i < types.length; i++) {\r
+ if (types[i] !== types[i - 1]) {\r
+ this.isCombo = true;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return newControllers;\r
+ },\r
+\r
+ resetElements: function resetElements() {\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.reset();\r
+ }, this);\r
+ },\r
+\r
+ update: function update(animationDuration, lazy) {\r
+ Chart.pluginService.notifyPlugins('beforeUpdate', [this]);\r
+\r
+ // In case the entire data object changed\r
+ this.tooltip._data = this.data;\r
+\r
+ // Make sure dataset controllers are updated and new controllers are reset\r
+ var newControllers = this.buildOrUpdateControllers();\r
+\r
+ // Make sure all dataset controllers have correct meta data counts\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();\r
+ }, this);\r
+\r
+ Chart.layoutService.update(this, this.chart.width, this.chart.height);\r
+\r
+ // Apply changes to the dataets that require the scales to have been calculated i.e BorderColor chages\r
+ Chart.pluginService.notifyPlugins('afterScaleUpdate', [this]);\r
+\r
+ // Can only reset the new controllers after the scales have been updated\r
+ helpers.each(newControllers, function(controller) {\r
+ controller.reset();\r
+ });\r
+\r
+ // This will loop through any data and do the appropriate element update for the type\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ this.getDatasetMeta(datasetIndex).controller.update();\r
+ }, this);\r
+\r
+ // Do this before render so that any plugins that need final scale updates can use it\r
+ Chart.pluginService.notifyPlugins('afterUpdate', [this]);\r
+\r
+ this.render(animationDuration, lazy);\r
+ },\r
+\r
+ render: function render(duration, lazy) {\r
+ Chart.pluginService.notifyPlugins('beforeRender', [this]);\r
+\r
+ var animationOptions = this.options.animation;\r
+ if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {\r
+ var animation = new Chart.Animation();\r
+ animation.numSteps = (duration || animationOptions.duration) / 16.66; //60 fps\r
+ animation.easing = animationOptions.easing;\r
+\r
+ // render function\r
+ animation.render = function(chartInstance, animationObject) {\r
+ var easingFunction = helpers.easingEffects[animationObject.easing];\r
+ var stepDecimal = animationObject.currentStep / animationObject.numSteps;\r
+ var easeDecimal = easingFunction(stepDecimal);\r
+\r
+ chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);\r
+ };\r
+\r
+ // user events\r
+ animation.onAnimationProgress = animationOptions.onProgress;\r
+ animation.onAnimationComplete = animationOptions.onComplete;\r
+\r
+ Chart.animationService.addAnimation(this, animation, duration, lazy);\r
+ } else {\r
+ this.draw();\r
+ if (animationOptions && animationOptions.onComplete && animationOptions.onComplete.call) {\r
+ animationOptions.onComplete.call(this);\r
+ }\r
+ }\r
+ return this;\r
+ },\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ this.clear();\r
+\r
+ Chart.pluginService.notifyPlugins('beforeDraw', [this, easingDecimal]);\r
+\r
+ // Draw all the scales\r
+ helpers.each(this.boxes, function(box) {\r
+ box.draw(this.chartArea);\r
+ }, this);\r
+ if (this.scale) {\r
+ this.scale.draw();\r
+ }\r
+\r
+ // Clip out the chart area so that anything outside does not draw. This is necessary for zoom and pan to function\r
+ var context = this.chart.ctx;\r
+ context.save();\r
+ context.beginPath();\r
+ context.rect(this.chartArea.left, this.chartArea.top, this.chartArea.right - this.chartArea.left, this.chartArea.bottom - this.chartArea.top);\r
+ context.clip();\r
+\r
+ // Draw each dataset via its respective controller (reversed to support proper line stacking)\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ this.getDatasetMeta(datasetIndex).controller.draw(ease);\r
+ }\r
+ }, this, true);\r
+\r
+ // Restore from the clipping operation\r
+ context.restore();\r
+\r
+ // Finally draw the tooltip\r
+ this.tooltip.transition(easingDecimal).draw();\r
+\r
+ Chart.pluginService.notifyPlugins('afterDraw', [this, easingDecimal]);\r
+ },\r
+\r
+ // Get the single element that was clicked on\r
+ // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw\r
+ getElementAtEvent: function(e) {\r
+ var eventPosition = helpers.getRelativePosition(e, this.chart);\r
+ var elementsArray = [];\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ helpers.each(meta.data, function(element, index) {\r
+ if (element.inRange(eventPosition.x, eventPosition.y)) {\r
+ elementsArray.push(element);\r
+ return elementsArray;\r
+ }\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getElementsAtEvent: function(e) {\r
+ var eventPosition = helpers.getRelativePosition(e, this.chart);\r
+ var elementsArray = [];\r
+\r
+ var found = (function() {\r
+ if (this.data.datasets) {\r
+ for (var i = 0; i < this.data.datasets.length; i++) {\r
+ var meta = this.getDatasetMeta(i);\r
+ if (this.isDatasetVisible(i)) {\r
+ for (var j = 0; j < meta.data.length; j++) {\r
+ if (meta.data[j].inRange(eventPosition.x, eventPosition.y)) {\r
+ return meta.data[j];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }).call(this);\r
+\r
+ if (!found) {\r
+ return elementsArray;\r
+ }\r
+\r
+ helpers.each(this.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+ elementsArray.push(meta.data[found._index]);\r
+ }\r
+ }, this);\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getElementsAtEventForMode: function(e, mode) {\r
+ var me = this;\r
+ switch (mode) {\r
+ case 'single':\r
+ return me.getElementAtEvent(e);\r
+ case 'label':\r
+ return me.getElementsAtEvent(e);\r
+ case 'dataset':\r
+ return me.getDatasetAtEvent(e);\r
+ default:\r
+ return e;\r
+ }\r
+ },\r
+\r
+ getDatasetAtEvent: function(e) {\r
+ var elementsArray = this.getElementAtEvent(e);\r
+\r
+ if (elementsArray.length > 0) {\r
+ elementsArray = this.getDatasetMeta(elementsArray[0]._datasetIndex).data;\r
+ }\r
+\r
+ return elementsArray;\r
+ },\r
+\r
+ getDatasetMeta: function(datasetIndex) {\r
+ var dataset = this.data.datasets[datasetIndex];\r
+ if (!dataset._meta) {\r
+ dataset._meta = {};\r
+ }\r
+\r
+ var meta = dataset._meta[this.id];\r
+ if (!meta) {\r
+ meta = dataset._meta[this.id] = {\r
+ type: null,\r
+ data: [],\r
+ dataset: null,\r
+ controller: null,\r
+ hidden: null, // See isDatasetVisible() comment\r
+ xAxisID: null,\r
+ yAxisID: null\r
+ };\r
+ }\r
+\r
+ return meta;\r
+ },\r
+\r
+ getVisibleDatasetCount: function() {\r
+ var count = 0;\r
+ for (var i = 0, ilen = this.data.datasets.length; i<ilen; ++i) {\r
+ if (this.isDatasetVisible(i)) {\r
+ count++;\r
+ }\r
+ }\r
+ return count;\r
+ },\r
+\r
+ isDatasetVisible: function(datasetIndex) {\r
+ var meta = this.getDatasetMeta(datasetIndex);\r
+\r
+ // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false,\r
+ // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned.\r
+ return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;\r
+ },\r
+\r
+ generateLegend: function generateLegend() {\r
+ return this.options.legendCallback(this);\r
+ },\r
+\r
+ destroy: function destroy() {\r
+ this.clear();\r
+ helpers.unbindEvents(this, this.events);\r
+ helpers.removeResizeListener(this.chart.canvas.parentNode);\r
+\r
+ // Reset canvas height/width attributes\r
+ var canvas = this.chart.canvas;\r
+ canvas.width = this.chart.width;\r
+ canvas.height = this.chart.height;\r
+\r
+ // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here\r
+ if (this.chart.originalDevicePixelRatio !== undefined) {\r
+ this.chart.ctx.scale(1 / this.chart.originalDevicePixelRatio, 1 / this.chart.originalDevicePixelRatio);\r
+ }\r
+\r
+ // Reset to the old style since it may have been changed by the device pixel ratio changes\r
+ canvas.style.width = this.chart.originalCanvasStyleWidth;\r
+ canvas.style.height = this.chart.originalCanvasStyleHeight;\r
+\r
+ Chart.pluginService.notifyPlugins('destroy', [this]);\r
+\r
+ delete Chart.instances[this.id];\r
+ },\r
+\r
+ toBase64Image: function toBase64Image() {\r
+ return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);\r
+ },\r
+\r
+ initToolTip: function initToolTip() {\r
+ this.tooltip = new Chart.Tooltip({\r
+ _chart: this.chart,\r
+ _chartInstance: this,\r
+ _data: this.data,\r
+ _options: this.options\r
+ }, this);\r
+ },\r
+\r
+ bindEvents: function bindEvents() {\r
+ helpers.bindEvents(this, this.options.events, function(evt) {\r
+ this.eventHandler(evt);\r
+ });\r
+ },\r
+\r
+ updateHoverStyle: function(elements, mode, enabled) {\r
+ var method = enabled? 'setHoverStyle' : 'removeHoverStyle';\r
+ var element, i, ilen;\r
+\r
+ switch (mode) {\r
+ case 'single':\r
+ elements = [ elements[0] ];\r
+ break;\r
+ case 'label':\r
+ case 'dataset':\r
+ // elements = elements;\r
+ break;\r
+ default:\r
+ // unsupported mode\r
+ return;\r
+ }\r
+\r
+ for (i=0, ilen=elements.length; i<ilen; ++i) {\r
+ element = elements[i];\r
+ if (element) {\r
+ this.getDatasetMeta(element._datasetIndex).controller[method](element);\r
+ }\r
+ }\r
+ },\r
+\r
+ eventHandler: function eventHandler(e) {\r
+ var me = this;\r
+ var tooltip = me.tooltip;\r
+ var options = me.options || {};\r
+ var hoverOptions = options.hover;\r
+ var tooltipsOptions = options.tooltips;\r
+\r
+ me.lastActive = me.lastActive || [];\r
+ me.lastTooltipActive = me.lastTooltipActive || [];\r
+\r
+ // Find Active Elements for hover and tooltips\r
+ if (e.type === 'mouseout') {\r
+ me.active = [];\r
+ me.tooltipActive = [];\r
+ } else {\r
+ me.active = me.getElementsAtEventForMode(e, hoverOptions.mode);\r
+ me.tooltipActive = me.getElementsAtEventForMode(e, tooltipsOptions.mode);\r
+ }\r
+\r
+ // On Hover hook\r
+ if (hoverOptions.onHover) {\r
+ hoverOptions.onHover.call(me, me.active);\r
+ }\r
+\r
+ if (e.type === 'mouseup' || e.type === 'click') {\r
+ if (options.onClick) {\r
+ options.onClick.call(me, e, me.active);\r
+ }\r
+ if (me.legend && me.legend.handleEvent) {\r
+ me.legend.handleEvent(e);\r
+ }\r
+ }\r
+\r
+ // Remove styling for last active (even if it may still be active)\r
+ if (me.lastActive.length) {\r
+ me.updateHoverStyle(me.lastActive, hoverOptions.mode, false);\r
+ }\r
+\r
+ // Built in hover styling\r
+ if (me.active.length && hoverOptions.mode) {\r
+ me.updateHoverStyle(me.active, hoverOptions.mode, true);\r
+ }\r
+\r
+ // Built in Tooltips\r
+ if (tooltipsOptions.enabled || tooltipsOptions.custom) {\r
+ tooltip.initialize();\r
+ tooltip._active = me.tooltipActive;\r
+ tooltip.update(true);\r
+ }\r
+\r
+ // Hover animations\r
+ tooltip.pivot();\r
+\r
+ if (!me.animating) {\r
+ // If entering, leaving, or changing elements, animate the change via pivot\r
+ if (!helpers.arrayEquals(me.active, me.lastActive) ||\r
+ !helpers.arrayEquals(me.tooltipActive, me.lastTooltipActive)) {\r
+\r
+ me.stop();\r
+\r
+ if (tooltipsOptions.enabled || tooltipsOptions.custom) {\r
+ tooltip.update(true);\r
+ }\r
+\r
+ // We only need to render at this point. Updating will cause scales to be\r
+ // recomputed generating flicker & using more memory than necessary.\r
+ me.render(hoverOptions.animationDuration, true);\r
+ }\r
+ }\r
+\r
+ // Remember Last Actives\r
+ me.lastActive = me.active;\r
+ me.lastTooltipActive = me.tooltipActive;\r
+ return me;\r
+ }\r
+ });\r
+};\r
+},{}],23:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var noop = helpers.noop;\r
+\r
+ // Base class for all dataset controllers (line, bar, etc)\r
+ Chart.DatasetController = function(chart, datasetIndex) {\r
+ this.initialize.call(this, chart, datasetIndex);\r
+ };\r
+\r
+ helpers.extend(Chart.DatasetController.prototype, {\r
+\r
+ /**\r
+ * Element type used to generate a meta dataset (e.g. Chart.element.Line).\r
+ * @type {Chart.core.element}\r
+ */\r
+ datasetElementType: null,\r
+\r
+ /**\r
+ * Element type used to generate a meta data (e.g. Chart.element.Point).\r
+ * @type {Chart.core.element}\r
+ */\r
+ dataElementType: null,\r
+\r
+ initialize: function(chart, datasetIndex) {\r
+ this.chart = chart;\r
+ this.index = datasetIndex;\r
+ this.linkScales();\r
+ this.addElements();\r
+ },\r
+\r
+ updateIndex: function(datasetIndex) {\r
+ this.index = datasetIndex;\r
+ },\r
+\r
+ linkScales: function() {\r
+ var meta = this.getMeta();\r
+ var dataset = this.getDataset();\r
+\r
+ if (meta.xAxisID === null) {\r
+ meta.xAxisID = dataset.xAxisID || this.chart.options.scales.xAxes[0].id;\r
+ }\r
+ if (meta.yAxisID === null) {\r
+ meta.yAxisID = dataset.yAxisID || this.chart.options.scales.yAxes[0].id;\r
+ }\r
+ },\r
+\r
+ getDataset: function() {\r
+ return this.chart.data.datasets[this.index];\r
+ },\r
+\r
+ getMeta: function() {\r
+ return this.chart.getDatasetMeta(this.index);\r
+ },\r
+\r
+ getScaleForId: function(scaleID) {\r
+ return this.chart.scales[scaleID];\r
+ },\r
+\r
+ reset: function() {\r
+ this.update(true);\r
+ },\r
+\r
+ createMetaDataset: function() {\r
+ var me = this;\r
+ var type = me.datasetElementType;\r
+ return type && new type({\r
+ _chart: me.chart.chart,\r
+ _datasetIndex: me.index\r
+ });\r
+ },\r
+\r
+ createMetaData: function(index) {\r
+ var me = this;\r
+ var type = me.dataElementType;\r
+ return type && new type({\r
+ _chart: me.chart.chart,\r
+ _datasetIndex: me.index,\r
+ _index: index\r
+ });\r
+ },\r
+\r
+ addElements: function() {\r
+ var me = this;\r
+ var meta = me.getMeta();\r
+ var data = me.getDataset().data || [];\r
+ var metaData = meta.data;\r
+ var i, ilen;\r
+\r
+ for (i=0, ilen=data.length; i<ilen; ++i) {\r
+ metaData[i] = metaData[i] || me.createMetaData(meta, i);\r
+ }\r
+\r
+ meta.dataset = meta.dataset || me.createMetaDataset();\r
+ },\r
+\r
+ addElementAndReset: function(index) {\r
+ var me = this;\r
+ var element = me.createMetaData(index);\r
+ me.getMeta().data.splice(index, 0, element);\r
+ me.updateElement(element, index, true);\r
+ },\r
+\r
+ buildOrUpdateElements: function buildOrUpdateElements() {\r
+ // Handle the number of data points changing\r
+ var meta = this.getMeta(),\r
+ md = meta.data,\r
+ numData = this.getDataset().data.length,\r
+ numMetaData = md.length;\r
+\r
+ // Make sure that we handle number of datapoints changing\r
+ if (numData < numMetaData) {\r
+ // Remove excess bars for data points that have been removed\r
+ md.splice(numData, numMetaData - numData);\r
+ } else if (numData > numMetaData) {\r
+ // Add new elements\r
+ for (var index = numMetaData; index < numData; ++index) {\r
+ this.addElementAndReset(index);\r
+ }\r
+ }\r
+ },\r
+\r
+ update: noop,\r
+\r
+ draw: function(ease) {\r
+ var easingDecimal = ease || 1;\r
+ helpers.each(this.getMeta().data, function(element, index) {\r
+ element.transition(easingDecimal).draw();\r
+ });\r
+ },\r
+\r
+ removeHoverStyle: function(element, elementOpts) {\r
+ var dataset = this.chart.data.datasets[element._datasetIndex],\r
+ index = element._index,\r
+ custom = element.custom || {},\r
+ valueOrDefault = helpers.getValueAtIndexOrDefault,\r
+ color = helpers.color,\r
+ model = element._model;\r
+\r
+ model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);\r
+ model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor);\r
+ model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth);\r
+ },\r
+\r
+ setHoverStyle: function(element) {\r
+ var dataset = this.chart.data.datasets[element._datasetIndex],\r
+ index = element._index,\r
+ custom = element.custom || {},\r
+ valueOrDefault = helpers.getValueAtIndexOrDefault,\r
+ color = helpers.color,\r
+ getHoverColor = helpers.getHoverColor,\r
+ model = element._model;\r
+\r
+ model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor));\r
+ model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));\r
+ model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\r
+ }\r
+ });\r
+\r
+ Chart.DatasetController.extend = helpers.inherits;\r
};
+},{}],24:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.elements = {};\r
+\r
+ Chart.Element = function(configuration) {\r
+ helpers.extend(this, configuration);\r
+ this.initialize.apply(this, arguments);\r
+ };\r
+ helpers.extend(Chart.Element.prototype, {\r
+ initialize: function() {\r
+ this.hidden = false;\r
+ },\r
+ pivot: function() {\r
+ if (!this._view) {\r
+ this._view = helpers.clone(this._model);\r
+ }\r
+ this._start = helpers.clone(this._view);\r
+ return this;\r
+ },\r
+ transition: function(ease) {\r
+ if (!this._view) {\r
+ this._view = helpers.clone(this._model);\r
+ }\r
+\r
+ // No animation -> No Transition\r
+ if (ease === 1) {\r
+ this._view = this._model;\r
+ this._start = null;\r
+ return this;\r
+ }\r
+\r
+ if (!this._start) {\r
+ this.pivot();\r
+ }\r
+\r
+ helpers.each(this._model, function(value, key) {\r
+\r
+ if (key[0] === '_') {\r
+ // Only non-underscored properties\r
+ }\r
+\r
+ // Init if doesn't exist\r
+ else if (!this._view.hasOwnProperty(key)) {\r
+ if (typeof value === 'number' && !isNaN(this._view[key])) {\r
+ this._view[key] = value * ease;\r
+ } else {\r
+ this._view[key] = value;\r
+ }\r
+ }\r
+\r
+ // No unnecessary computations\r
+ else if (value === this._view[key]) {\r
+ // It's the same! Woohoo!\r
+ }\r
+\r
+ // Color transitions if possible\r
+ else if (typeof value === 'string') {\r
+ try {\r
+ var color = helpers.color(this._model[key]).mix(helpers.color(this._start[key]), ease);\r
+ this._view[key] = color.rgbString();\r
+ } catch (err) {\r
+ this._view[key] = value;\r
+ }\r
+ }\r
+ // Number transitions\r
+ else if (typeof value === 'number') {\r
+ var startVal = this._start[key] !== undefined && isNaN(this._start[key]) === false ? this._start[key] : 0;\r
+ this._view[key] = ((this._model[key] - startVal) * ease) + startVal;\r
+ }\r
+ // Everything else\r
+ else {\r
+ this._view[key] = value;\r
+ }\r
+ }, this);\r
+\r
+ return this;\r
+ },\r
+ tooltipPosition: function() {\r
+ return {\r
+ x: this._model.x,\r
+ y: this._model.y\r
+ };\r
+ },\r
+ hasValue: function() {\r
+ return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);\r
+ }\r
+ });\r
+\r
+ Chart.Element.extend = helpers.inherits;\r
+\r
+};\r
},{}],25:[function(require,module,exports){
-/*global window: false */
-/*global document: false */
-"use strict";
-
-var color = require(3);
-
-module.exports = function(Chart) {
- //Global Chart helpers object for utility methods and classes
- var helpers = Chart.helpers = {};
-
- //-- Basic js utility methods
- helpers.each = function(loopable, callback, self, reverse) {
- // Check to see if null or undefined firstly.
- var i, len;
- if (helpers.isArray(loopable)) {
- len = loopable.length;
- if (reverse) {
- for (i = len - 1; i >= 0; i--) {
- callback.call(self, loopable[i], i);
- }
- } else {
- for (i = 0; i < len; i++) {
- callback.call(self, loopable[i], i);
- }
- }
- } else if (typeof loopable === 'object') {
- var keys = Object.keys(loopable);
- len = keys.length;
- for (i = 0; i < len; i++) {
- callback.call(self, loopable[keys[i]], keys[i]);
- }
- }
- };
- helpers.clone = function(obj) {
- var objClone = {};
- helpers.each(obj, function(value, key) {
- if (helpers.isArray(value)) {
- objClone[key] = value.slice(0);
- } else if (typeof value === 'object' && value !== null) {
- objClone[key] = helpers.clone(value);
- } else {
- objClone[key] = value;
- }
- });
- return objClone;
- };
- helpers.extend = function(base) {
- var len = arguments.length;
- var additionalArgs = [];
- for (var i = 1; i < len; i++) {
- additionalArgs.push(arguments[i]);
- }
- helpers.each(additionalArgs, function(extensionObject) {
- helpers.each(extensionObject, function(value, key) {
- base[key] = value;
- });
- });
- return base;
- };
- // Need a special merge function to chart configs since they are now grouped
- helpers.configMerge = function(_base) {
- var base = helpers.clone(_base);
- helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {
- helpers.each(extension, function(value, key) {
- if (key === 'scales') {
- // Scale config merging is complex. Add out own function here for that
- base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);
-
- } else if (key === 'scale') {
- // Used in polar area & radar charts since there is only one scale
- base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
- } else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
- // In this case we have an array of objects replacing another array. Rather than doing a strict replace,
- // merge. This allows easy scale option merging
- var baseArray = base[key];
-
- helpers.each(value, function(valueObj, index) {
-
- if (index < baseArray.length) {
- if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {
- // Two objects are coming together. Do a merge of them.
- baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
- } else {
- // Just overwrite in this case since there is nothing to merge
- baseArray[index] = valueObj;
- }
- } else {
- baseArray.push(valueObj); // nothing to merge
- }
- });
-
- } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
- // If we are overwriting an object with an object, do a merge of the properties.
- base[key] = helpers.configMerge(base[key], value);
-
- } else {
- // can just overwrite the value in this case
- base[key] = value;
- }
- });
- });
-
- return base;
- };
- helpers.extendDeep = function(_base) {
- return _extendDeep.apply(this, arguments);
-
- function _extendDeep(dst) {
- helpers.each(arguments, function(obj) {
- if (obj !== dst) {
- helpers.each(obj, function(value, key) {
- if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
- _extendDeep(dst[key], value);
- } else {
- dst[key] = value;
- }
- });
- }
- });
- return dst;
- }
- };
- helpers.scaleMerge = function(_base, extension) {
- var base = helpers.clone(_base);
-
- helpers.each(extension, function(value, key) {
- if (key === 'xAxes' || key === 'yAxes') {
- // These properties are arrays of items
- if (base.hasOwnProperty(key)) {
- helpers.each(value, function(valueObj, index) {
- var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
- var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);
- if (index >= base[key].length || !base[key][index].type) {
- base[key].push(helpers.configMerge(axisDefaults, valueObj));
- } else if (valueObj.type && valueObj.type !== base[key][index].type) {
- // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults
- base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);
- } else {
- // Type is the same
- base[key][index] = helpers.configMerge(base[key][index], valueObj);
- }
- });
- } else {
- base[key] = [];
- helpers.each(value, function(valueObj) {
- var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');
- base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));
- });
- }
- } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {
- // If we are overwriting an object with an object, do a merge of the properties.
- base[key] = helpers.configMerge(base[key], value);
-
- } else {
- // can just overwrite the value in this case
- base[key] = value;
- }
- });
-
- return base;
- };
- helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {
- if (value === undefined || value === null) {
- return defaultValue;
- }
-
- if (helpers.isArray(value)) {
- return index < value.length ? value[index] : defaultValue;
- }
-
- return value;
- };
- helpers.getValueOrDefault = function(value, defaultValue) {
- return value === undefined ? defaultValue : value;
- };
- helpers.indexOf = function(arrayToSearch, item) {
- if (Array.prototype.indexOf) {
- return arrayToSearch.indexOf(item);
- } else {
- for (var i = 0; i < arrayToSearch.length; i++) {
- if (arrayToSearch[i] === item)
- return i;
- }
- return -1;
- }
- };
- helpers.where = function(collection, filterCallback) {
- if (helpers.isArray(collection) && Array.prototype.filter) {
- return collection.filter(filterCallback);
- } else {
- var filtered = [];
-
- helpers.each(collection, function(item) {
- if (filterCallback(item)) {
- filtered.push(item);
- }
- });
-
- return filtered;
- }
- };
- helpers.findIndex = function(arrayToSearch, callback, thisArg) {
- var index = -1;
- if (Array.prototype.findIndex) {
- index = arrayToSearch.findIndex(callback, thisArg);
- } else {
- for (var i = 0; i < arrayToSearch.length; ++i) {
- thisArg = thisArg !== undefined ? thisArg : arrayToSearch;
-
- if (callback.call(thisArg, arrayToSearch[i], i, arrayToSearch)) {
- index = i;
- break;
- }
- }
- }
-
- return index;
- };
- helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {
- // Default to start of the array
- if (startIndex === undefined || startIndex === null) {
- startIndex = -1;
- }
- for (var i = startIndex + 1; i < arrayToSearch.length; i++) {
- var currentItem = arrayToSearch[i];
- if (filterCallback(currentItem)) {
- return currentItem;
- }
- }
- };
- helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {
- // Default to end of the array
- if (startIndex === undefined || startIndex === null) {
- startIndex = arrayToSearch.length;
- }
- for (var i = startIndex - 1; i >= 0; i--) {
- var currentItem = arrayToSearch[i];
- if (filterCallback(currentItem)) {
- return currentItem;
- }
- }
- };
- helpers.inherits = function(extensions) {
- //Basic javascript inheritance based on the model created in Backbone.js
- var parent = this;
- var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function() {
- return parent.apply(this, arguments);
- };
-
- var Surrogate = function() {
- this.constructor = ChartElement;
- };
- Surrogate.prototype = parent.prototype;
- ChartElement.prototype = new Surrogate();
-
- ChartElement.extend = helpers.inherits;
-
- if (extensions) {
- helpers.extend(ChartElement.prototype, extensions);
- }
-
- ChartElement.__super__ = parent.prototype;
-
- return ChartElement;
- };
- helpers.noop = function() {};
- helpers.uid = (function() {
- var id = 0;
- return function() {
- return id++;
- };
- })();
- helpers.warn = function(str) {
- //Method for warning of errors
- if (console && typeof console.warn === "function") {
- console.warn(str);
- }
- };
- //-- Math methods
- helpers.isNumber = function(n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- };
- helpers.almostEquals = function(x, y, epsilon) {
- return Math.abs(x - y) < epsilon;
- };
- helpers.max = function(array) {
- return array.reduce(function(max, value) {
- if (!isNaN(value)) {
- return Math.max(max, value);
- } else {
- return max;
- }
- }, Number.NEGATIVE_INFINITY);
- };
- helpers.min = function(array) {
- return array.reduce(function(min, value) {
- if (!isNaN(value)) {
- return Math.min(min, value);
- } else {
- return min;
- }
- }, Number.POSITIVE_INFINITY);
- };
- helpers.sign = function(x) {
- if (Math.sign) {
- return Math.sign(x);
- } else {
- x = +x; // convert to a number
- if (x === 0 || isNaN(x)) {
- return x;
- }
- return x > 0 ? 1 : -1;
- }
- };
- helpers.log10 = function(x) {
- if (Math.log10) {
- return Math.log10(x);
- } else {
- return Math.log(x) / Math.LN10;
- }
- };
- helpers.toRadians = function(degrees) {
- return degrees * (Math.PI / 180);
- };
- helpers.toDegrees = function(radians) {
- return radians * (180 / Math.PI);
- };
- // Gets the angle from vertical upright to the point about a centre.
- helpers.getAngleFromPoint = function(centrePoint, anglePoint) {
- var distanceFromXCenter = anglePoint.x - centrePoint.x,
- distanceFromYCenter = anglePoint.y - centrePoint.y,
- radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
-
- var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
-
- if (angle < (-0.5 * Math.PI)) {
- angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
- }
-
- return {
- angle: angle,
- distance: radialDistanceFromCenter
- };
- };
- helpers.aliasPixel = function(pixelWidth) {
- return (pixelWidth % 2 === 0) ? 0 : 0.5;
- };
- helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {
- //Props to Rob Spencer at scaled innovation for his post on splining between points
- //http://scaledinnovation.com/analytics/splines/aboutSplines.html
-
- // This function must also respect "skipped" points
-
- var previous = firstPoint.skip ? middlePoint : firstPoint,
- current = middlePoint,
- next = afterPoint.skip ? middlePoint : afterPoint;
-
- var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));
- var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));
-
- var s01 = d01 / (d01 + d12);
- var s12 = d12 / (d01 + d12);
-
- // If all points are the same, s01 & s02 will be inf
- s01 = isNaN(s01) ? 0 : s01;
- s12 = isNaN(s12) ? 0 : s12;
-
- var fa = t * s01; // scaling factor for triangle Ta
- var fb = t * s12;
-
- return {
- previous: {
- x: current.x - fa * (next.x - previous.x),
- y: current.y - fa * (next.y - previous.y)
- },
- next: {
- x: current.x + fb * (next.x - previous.x),
- y: current.y + fb * (next.y - previous.y)
- }
- };
- };
- helpers.nextItem = function(collection, index, loop) {
- if (loop) {
- return index >= collection.length - 1 ? collection[0] : collection[index + 1];
- }
-
- return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];
- };
- helpers.previousItem = function(collection, index, loop) {
- if (loop) {
- return index <= 0 ? collection[collection.length - 1] : collection[index - 1];
- }
- return index <= 0 ? collection[0] : collection[index - 1];
- };
- // Implementation of the nice number algorithm used in determining where axis labels will go
- helpers.niceNum = function(range, round) {
- var exponent = Math.floor(helpers.log10(range));
- var fraction = range / Math.pow(10, exponent);
- var niceFraction;
-
- if (round) {
- if (fraction < 1.5) {
- niceFraction = 1;
- } else if (fraction < 3) {
- niceFraction = 2;
- } else if (fraction < 7) {
- niceFraction = 5;
- } else {
- niceFraction = 10;
- }
- } else {
- if (fraction <= 1.0) {
- niceFraction = 1;
- } else if (fraction <= 2) {
- niceFraction = 2;
- } else if (fraction <= 5) {
- niceFraction = 5;
- } else {
- niceFraction = 10;
- }
- }
-
- return niceFraction * Math.pow(10, exponent);
- };
- //Easing functions adapted from Robert Penner's easing equations
- //http://www.robertpenner.com/easing/
- var easingEffects = helpers.easingEffects = {
- linear: function(t) {
- return t;
- },
- easeInQuad: function(t) {
- return t * t;
- },
- easeOutQuad: function(t) {
- return -1 * t * (t - 2);
- },
- easeInOutQuad: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t;
- }
- return -1 / 2 * ((--t) * (t - 2) - 1);
- },
- easeInCubic: function(t) {
- return t * t * t;
- },
- easeOutCubic: function(t) {
- return 1 * ((t = t / 1 - 1) * t * t + 1);
- },
- easeInOutCubic: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t;
- }
- return 1 / 2 * ((t -= 2) * t * t + 2);
- },
- easeInQuart: function(t) {
- return t * t * t * t;
- },
- easeOutQuart: function(t) {
- return -1 * ((t = t / 1 - 1) * t * t * t - 1);
- },
- easeInOutQuart: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t * t;
- }
- return -1 / 2 * ((t -= 2) * t * t * t - 2);
- },
- easeInQuint: function(t) {
- return 1 * (t /= 1) * t * t * t * t;
- },
- easeOutQuint: function(t) {
- return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);
- },
- easeInOutQuint: function(t) {
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * t * t * t * t * t;
- }
- return 1 / 2 * ((t -= 2) * t * t * t * t + 2);
- },
- easeInSine: function(t) {
- return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;
- },
- easeOutSine: function(t) {
- return 1 * Math.sin(t / 1 * (Math.PI / 2));
- },
- easeInOutSine: function(t) {
- return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);
- },
- easeInExpo: function(t) {
- return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));
- },
- easeOutExpo: function(t) {
- return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);
- },
- easeInOutExpo: function(t) {
- if (t === 0) {
- return 0;
- }
- if (t === 1) {
- return 1;
- }
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * Math.pow(2, 10 * (t - 1));
- }
- return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);
- },
- easeInCirc: function(t) {
- if (t >= 1) {
- return t;
- }
- return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);
- },
- easeOutCirc: function(t) {
- return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);
- },
- easeInOutCirc: function(t) {
- if ((t /= 1 / 2) < 1) {
- return -1 / 2 * (Math.sqrt(1 - t * t) - 1);
- }
- return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);
- },
- easeInElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1) === 1) {
- return 1;
- }
- if (!p) {
- p = 1 * 0.3;
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
- },
- easeOutElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1) === 1) {
- return 1;
- }
- if (!p) {
- p = 1 * 0.3;
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;
- },
- easeInOutElastic: function(t) {
- var s = 1.70158;
- var p = 0;
- var a = 1;
- if (t === 0) {
- return 0;
- }
- if ((t /= 1 / 2) === 2) {
- return 1;
- }
- if (!p) {
- p = 1 * (0.3 * 1.5);
- }
- if (a < Math.abs(1)) {
- a = 1;
- s = p / 4;
- } else {
- s = p / (2 * Math.PI) * Math.asin(1 / a);
- }
- if (t < 1) {
- return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));
- }
- return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;
- },
- easeInBack: function(t) {
- var s = 1.70158;
- return 1 * (t /= 1) * t * ((s + 1) * t - s);
- },
- easeOutBack: function(t) {
- var s = 1.70158;
- return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);
- },
- easeInOutBack: function(t) {
- var s = 1.70158;
- if ((t /= 1 / 2) < 1) {
- return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));
- }
- return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
- },
- easeInBounce: function(t) {
- return 1 - easingEffects.easeOutBounce(1 - t);
- },
- easeOutBounce: function(t) {
- if ((t /= 1) < (1 / 2.75)) {
- return 1 * (7.5625 * t * t);
- } else if (t < (2 / 2.75)) {
- return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);
- } else if (t < (2.5 / 2.75)) {
- return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);
- } else {
- return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);
- }
- },
- easeInOutBounce: function(t) {
- if (t < 1 / 2) {
- return easingEffects.easeInBounce(t * 2) * 0.5;
- }
- return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;
- }
- };
- //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
- helpers.requestAnimFrame = (function() {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function(callback) {
- return window.setTimeout(callback, 1000 / 60);
- };
- })();
- helpers.cancelAnimFrame = (function() {
- return window.cancelAnimationFrame ||
- window.webkitCancelAnimationFrame ||
- window.mozCancelAnimationFrame ||
- window.oCancelAnimationFrame ||
- window.msCancelAnimationFrame ||
- function(callback) {
- return window.clearTimeout(callback, 1000 / 60);
- };
- })();
- //-- DOM methods
- helpers.getRelativePosition = function(evt, chart) {
- var mouseX, mouseY;
- var e = evt.originalEvent || evt,
- canvas = evt.currentTarget || evt.srcElement,
- boundingRect = canvas.getBoundingClientRect();
-
- var touches = e.touches;
- if (touches && touches.length > 0) {
- mouseX = touches[0].clientX;
- mouseY = touches[0].clientY;
-
- } else {
- mouseX = e.clientX;
- mouseY = e.clientY;
- }
-
- // Scale mouse coordinates into canvas coordinates
- // by following the pattern laid out by 'jerryj' in the comments of
- // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/
- var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));
- var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));
- var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));
- var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));
- var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;
- var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;
-
- // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However
- // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here
- mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);
- mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);
-
- return {
- x: mouseX,
- y: mouseY
- };
-
- };
- helpers.addEvent = function(node, eventType, method) {
- if (node.addEventListener) {
- node.addEventListener(eventType, method);
- } else if (node.attachEvent) {
- node.attachEvent("on" + eventType, method);
- } else {
- node["on" + eventType] = method;
- }
- };
- helpers.removeEvent = function(node, eventType, handler) {
- if (node.removeEventListener) {
- node.removeEventListener(eventType, handler, false);
- } else if (node.detachEvent) {
- node.detachEvent("on" + eventType, handler);
- } else {
- node["on" + eventType] = helpers.noop;
- }
- };
- helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {
- // Create the events object if it's not already present
- var events = chartInstance.events = chartInstance.events || {};
-
- helpers.each(arrayOfEvents, function(eventName) {
- events[eventName] = function() {
- handler.apply(chartInstance, arguments);
- };
- helpers.addEvent(chartInstance.chart.canvas, eventName, events[eventName]);
- });
- };
- helpers.unbindEvents = function(chartInstance, arrayOfEvents) {
- var canvas = chartInstance.chart.canvas;
- helpers.each(arrayOfEvents, function(handler, eventName) {
- helpers.removeEvent(canvas, eventName, handler);
- });
- };
-
- // Private helper function to convert max-width/max-height values that may be percentages into a number
- function parseMaxStyle(styleValue, node, parentProperty) {
- var valueInPixels;
- if (typeof(styleValue) === 'string') {
- valueInPixels = parseInt(styleValue, 10);
-
- if (styleValue.indexOf('%') != -1) {
- // percentage * size in dimension
- valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
- }
- } else {
- valueInPixels = styleValue;
- }
-
- return valueInPixels;
- }
-
- /**
- * Returns if the given value contains an effective constraint.
- * @private
- */
- function isConstrainedValue(value) {
- return value !== undefined && value !== null && value !== 'none';
- }
-
- // Private helper to get a constraint dimension
- // @param domNode : the node to check the constraint on
- // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)
- // @param percentageProperty : property of parent to use when calculating width as a percentage
- // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser
- function getConstraintDimension(domNode, maxStyle, percentageProperty) {
- var view = document.defaultView;
- var parentNode = domNode.parentNode;
- var constrainedNode = view.getComputedStyle(domNode)[maxStyle];
- var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];
- var hasCNode = isConstrainedValue(constrainedNode);
- var hasCContainer = isConstrainedValue(constrainedContainer);
- var infinity = Number.POSITIVE_INFINITY;
-
- if (hasCNode || hasCContainer) {
- return Math.min(
- hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,
- hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);
- }
-
- return 'none';
- }
- // returns Number or undefined if no constraint
- helpers.getConstraintWidth = function(domNode) {
- return getConstraintDimension(domNode, 'max-width', 'clientWidth');
- };
- // returns Number or undefined if no constraint
- helpers.getConstraintHeight = function(domNode) {
- return getConstraintDimension(domNode, 'max-height', 'clientHeight');
- };
- helpers.getMaximumWidth = function(domNode) {
- var container = domNode.parentNode;
- var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));
- var w = container.clientWidth - padding;
- var cw = helpers.getConstraintWidth(domNode);
- return isNaN(cw)? w : Math.min(w, cw);
- };
- helpers.getMaximumHeight = function(domNode) {
- var container = domNode.parentNode;
- var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));
- var h = container.clientHeight - padding;
- var ch = helpers.getConstraintHeight(domNode);
- return isNaN(ch)? h : Math.min(h, ch);
- };
- helpers.getStyle = function(el, property) {
- return el.currentStyle ?
- el.currentStyle[property] :
- document.defaultView.getComputedStyle(el, null).getPropertyValue(property);
- };
- helpers.retinaScale = function(chart) {
- var ctx = chart.ctx;
- var canvas = chart.canvas;
- var width = canvas.width;
- var height = canvas.height;
- var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;
-
- if (pixelRatio !== 1) {
- canvas.height = height * pixelRatio;
- canvas.width = width * pixelRatio;
- ctx.scale(pixelRatio, pixelRatio);
-
- // Store the device pixel ratio so that we can go backwards in `destroy`.
- // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same
- // when destroy is called
- chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;
- }
-
- canvas.style.width = width + 'px';
- canvas.style.height = height + 'px';
- };
- //-- Canvas methods
- helpers.clear = function(chart) {
- chart.ctx.clearRect(0, 0, chart.width, chart.height);
- };
- helpers.fontString = function(pixelSize, fontStyle, fontFamily) {
- return fontStyle + " " + pixelSize + "px " + fontFamily;
- };
- helpers.longestText = function(ctx, font, arrayOfThings, cache) {
- cache = cache || {};
- var data = cache.data = cache.data || {};
- var gc = cache.garbageCollect = cache.garbageCollect || [];
-
- if (cache.font !== font) {
- data = cache.data = {};
- gc = cache.garbageCollect = [];
- cache.font = font;
- }
-
- ctx.font = font;
- var longest = 0;
- helpers.each(arrayOfThings, function(thing) {
- // Undefined strings and arrays should not be measured
- if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) {
- longest = helpers.measureText(ctx, data, gc, longest, thing);
- } else if (helpers.isArray(thing)) {
- // if it is an array lets measure each element
- // to do maybe simplify this function a bit so we can do this more recursively?
- helpers.each(thing, function(nestedThing) {
- // Undefined strings and arrays should not be measured
- if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) {
- longest = helpers.measureText(ctx, data, gc, longest, nestedThing);
- }
- });
- }
- });
-
- var gcLen = gc.length / 2;
- if (gcLen > arrayOfThings.length) {
- for (var i = 0; i < gcLen; i++) {
- delete data[gc[i]];
- }
- gc.splice(0, gcLen);
- }
- return longest;
- };
- helpers.measureText = function (ctx, data, gc, longest, string) {
- var textWidth = data[string];
- if (!textWidth) {
- textWidth = data[string] = ctx.measureText(string).width;
- gc.push(string);
- }
- if (textWidth > longest) {
- longest = textWidth;
- }
- return longest;
- };
- helpers.numberOfLabelLines = function(arrayOfThings) {
- var numberOfLines = 1;
- helpers.each(arrayOfThings, function(thing) {
- if (helpers.isArray(thing)) {
- if (thing.length > numberOfLines) {
- numberOfLines = thing.length;
- }
- }
- });
- return numberOfLines;
- };
- helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) {
- ctx.beginPath();
- ctx.moveTo(x + radius, y);
- ctx.lineTo(x + width - radius, y);
- ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
- ctx.lineTo(x + width, y + height - radius);
- ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
- ctx.lineTo(x + radius, y + height);
- ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
- ctx.lineTo(x, y + radius);
- ctx.quadraticCurveTo(x, y, x + radius, y);
- ctx.closePath();
- };
- helpers.color = function(c) {
- if (!color) {
- console.log('Color.js not found!');
- return c;
- }
-
- /* global CanvasGradient */
- if (c instanceof CanvasGradient) {
- return color(Chart.defaults.global.defaultColor);
- }
-
- return color(c);
- };
- helpers.addResizeListener = function(node, callback) {
- // Hide an iframe before the node
- var hiddenIframe = document.createElement('iframe');
- var hiddenIframeClass = 'chartjs-hidden-iframe';
-
- if (hiddenIframe.classlist) {
- // can use classlist
- hiddenIframe.classlist.add(hiddenIframeClass);
- } else {
- hiddenIframe.setAttribute('class', hiddenIframeClass);
- }
-
- // Set the style
- var style = hiddenIframe.style;
- style.width = '100%';
- style.display = 'block';
- style.border = 0;
- style.height = 0;
- style.margin = 0;
- style.position = 'absolute';
- style.left = 0;
- style.right = 0;
- style.top = 0;
- style.bottom = 0;
-
- // Insert the iframe so that contentWindow is available
- node.insertBefore(hiddenIframe, node.firstChild);
-
- (hiddenIframe.contentWindow || hiddenIframe).onresize = function() {
- if (callback) {
- callback();
- }
- };
- };
- helpers.removeResizeListener = function(node) {
- var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');
-
- // Remove the resize detect iframe
- if (hiddenIframe) {
- hiddenIframe.parentNode.removeChild(hiddenIframe);
- }
- };
- helpers.isArray = function(obj) {
- if (!Array.isArray) {
- return Object.prototype.toString.call(obj) === '[object Array]';
- }
- return Array.isArray(obj);
- };
- //! @see http://stackoverflow.com/a/14853974
- helpers.arrayEquals = function(a0, a1) {
- var i, ilen, v0, v1;
-
- if (!a0 || !a1 || a0.length != a1.length) {
- return false;
- }
-
- for (i = 0, ilen=a0.length; i < ilen; ++i) {
- v0 = a0[i];
- v1 = a1[i];
-
- if (v0 instanceof Array && v1 instanceof Array) {
- if (!helpers.arrayEquals(v0, v1)) {
- return false;
- }
- } else if (v0 != v1) {
- // NOTE: two different object instances will never be equal: {x:20} != {x:20}
- return false;
- }
- }
-
- return true;
- };
- helpers.callCallback = function(fn, args, _tArg) {
- if (fn && typeof fn.call === 'function') {
- fn.apply(_tArg, args);
- }
- };
- helpers.getHoverColor = function(color) {
- /* global CanvasPattern */
- return (color instanceof CanvasPattern) ?
- color :
- helpers.color(color).saturate(0.5).darken(0.1).rgbString();
- };
-};
-
-},{"3":3}],26:[function(require,module,exports){
-"use strict";
-
-module.exports = function() {
-
- //Occupy the global variable of Chart, and create a simple base class
- var Chart = function(context, config) {
- var me = this;
- var helpers = Chart.helpers;
- me.config = config;
-
- // Support a jQuery'd canvas element
- if (context.length && context[0].getContext) {
- context = context[0];
- }
-
- // Support a canvas domnode
- if (context.getContext) {
- context = context.getContext("2d");
- }
-
- me.ctx = context;
- me.canvas = context.canvas;
-
- context.canvas.style.display = context.canvas.style.display || 'block';
-
- // Figure out what the size of the chart will be.
- // If the canvas has a specified width and height, we use those else
- // we look to see if the canvas node has a CSS width and height.
- // If there is still no height, fill the parent container
- me.width = context.canvas.width || parseInt(helpers.getStyle(context.canvas, 'width'), 10) || helpers.getMaximumWidth(context.canvas);
- me.height = context.canvas.height || parseInt(helpers.getStyle(context.canvas, 'height'), 10) || helpers.getMaximumHeight(context.canvas);
-
- me.aspectRatio = me.width / me.height;
-
- if (isNaN(me.aspectRatio) || isFinite(me.aspectRatio) === false) {
- // If the canvas has no size, try and figure out what the aspect ratio will be.
- // Some charts prefer square canvases (pie, radar, etc). If that is specified, use that
- // else use the canvas default ratio of 2
- me.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;
- }
-
- // Store the original style of the element so we can set it back
- me.originalCanvasStyleWidth = context.canvas.style.width;
- me.originalCanvasStyleHeight = context.canvas.style.height;
-
- // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
- helpers.retinaScale(me);
-
- if (config) {
- me.controller = new Chart.Controller(me);
- }
-
- // Always bind this so that if the responsive state changes we still work
- helpers.addResizeListener(context.canvas.parentNode, function() {
- if (me.controller && me.controller.config.options.responsive) {
- me.controller.resize();
- }
- });
-
- return me.controller ? me.controller : me;
-
- };
-
- //Globally expose the defaults to allow for user updating/changing
- Chart.defaults = {
- global: {
- responsive: true,
- responsiveAnimationDuration: 0,
- maintainAspectRatio: true,
- events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],
- hover: {
- onHover: null,
- mode: 'single',
- animationDuration: 400
- },
- onClick: null,
- defaultColor: 'rgba(0,0,0,0.1)',
- defaultFontColor: '#666',
- defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
- defaultFontSize: 12,
- defaultFontStyle: 'normal',
- showLines: true,
-
- // Element defaults defined in element extensions
- elements: {},
-
- // Legend callback string
- legendCallback: function(chart) {
- var text = [];
- text.push('<ul class="' + chart.id + '-legend">');
- for (var i = 0; i < chart.data.datasets.length; i++) {
- text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
- if (chart.data.datasets[i].label) {
- text.push(chart.data.datasets[i].label);
- }
- text.push('</li>');
- }
- text.push('</ul>');
-
- return text.join("");
- }
- }
- };
-
- Chart.Chart = Chart;
-
- return Chart;
+/*global window: false */\r
+/*global document: false */\r
+"use strict";\r
+\r
+var color = require('chartjs-color');\r
+\r
+module.exports = function(Chart) {\r
+ //Global Chart helpers object for utility methods and classes\r
+ var helpers = Chart.helpers = {};\r
+\r
+ //-- Basic js utility methods\r
+ helpers.each = function(loopable, callback, self, reverse) {\r
+ // Check to see if null or undefined firstly.\r
+ var i, len;\r
+ if (helpers.isArray(loopable)) {\r
+ len = loopable.length;\r
+ if (reverse) {\r
+ for (i = len - 1; i >= 0; i--) {\r
+ callback.call(self, loopable[i], i);\r
+ }\r
+ } else {\r
+ for (i = 0; i < len; i++) {\r
+ callback.call(self, loopable[i], i);\r
+ }\r
+ }\r
+ } else if (typeof loopable === 'object') {\r
+ var keys = Object.keys(loopable);\r
+ len = keys.length;\r
+ for (i = 0; i < len; i++) {\r
+ callback.call(self, loopable[keys[i]], keys[i]);\r
+ }\r
+ }\r
+ };\r
+ helpers.clone = function(obj) {\r
+ var objClone = {};\r
+ helpers.each(obj, function(value, key) {\r
+ if (helpers.isArray(value)) {\r
+ objClone[key] = value.slice(0);\r
+ } else if (typeof value === 'object' && value !== null) {\r
+ objClone[key] = helpers.clone(value);\r
+ } else {\r
+ objClone[key] = value;\r
+ }\r
+ });\r
+ return objClone;\r
+ };\r
+ helpers.extend = function(base) {\r
+ var len = arguments.length;\r
+ var additionalArgs = [];\r
+ for (var i = 1; i < len; i++) {\r
+ additionalArgs.push(arguments[i]);\r
+ }\r
+ helpers.each(additionalArgs, function(extensionObject) {\r
+ helpers.each(extensionObject, function(value, key) {\r
+ base[key] = value;\r
+ });\r
+ });\r
+ return base;\r
+ };\r
+ // Need a special merge function to chart configs since they are now grouped\r
+ helpers.configMerge = function(_base) {\r
+ var base = helpers.clone(_base);\r
+ helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {\r
+ helpers.each(extension, function(value, key) {\r
+ if (key === 'scales') {\r
+ // Scale config merging is complex. Add out own function here for that\r
+ base[key] = helpers.scaleMerge(base.hasOwnProperty(key) ? base[key] : {}, value);\r
+\r
+ } else if (key === 'scale') {\r
+ // Used in polar area & radar charts since there is only one scale\r
+ base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);\r
+ } else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {\r
+ // In this case we have an array of objects replacing another array. Rather than doing a strict replace,\r
+ // merge. This allows easy scale option merging\r
+ var baseArray = base[key];\r
+\r
+ helpers.each(value, function(valueObj, index) {\r
+\r
+ if (index < baseArray.length) {\r
+ if (typeof baseArray[index] === 'object' && baseArray[index] !== null && typeof valueObj === 'object' && valueObj !== null) {\r
+ // Two objects are coming together. Do a merge of them.\r
+ baseArray[index] = helpers.configMerge(baseArray[index], valueObj);\r
+ } else {\r
+ // Just overwrite in this case since there is nothing to merge\r
+ baseArray[index] = valueObj;\r
+ }\r
+ } else {\r
+ baseArray.push(valueObj); // nothing to merge\r
+ }\r
+ });\r
+\r
+ } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {\r
+ // If we are overwriting an object with an object, do a merge of the properties.\r
+ base[key] = helpers.configMerge(base[key], value);\r
+\r
+ } else {\r
+ // can just overwrite the value in this case\r
+ base[key] = value;\r
+ }\r
+ });\r
+ });\r
+\r
+ return base;\r
+ };\r
+ helpers.extendDeep = function(_base) {\r
+ return _extendDeep.apply(this, arguments);\r
+\r
+ function _extendDeep(dst) {\r
+ helpers.each(arguments, function(obj) {\r
+ if (obj !== dst) {\r
+ helpers.each(obj, function(value, key) {\r
+ if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {\r
+ _extendDeep(dst[key], value);\r
+ } else {\r
+ dst[key] = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ return dst;\r
+ }\r
+ };\r
+ helpers.scaleMerge = function(_base, extension) {\r
+ var base = helpers.clone(_base);\r
+\r
+ helpers.each(extension, function(value, key) {\r
+ if (key === 'xAxes' || key === 'yAxes') {\r
+ // These properties are arrays of items\r
+ if (base.hasOwnProperty(key)) {\r
+ helpers.each(value, function(valueObj, index) {\r
+ var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');\r
+ var axisDefaults = Chart.scaleService.getScaleDefaults(axisType);\r
+ if (index >= base[key].length || !base[key][index].type) {\r
+ base[key].push(helpers.configMerge(axisDefaults, valueObj));\r
+ } else if (valueObj.type && valueObj.type !== base[key][index].type) {\r
+ // Type changed. Bring in the new defaults before we bring in valueObj so that valueObj can override the correct scale defaults\r
+ base[key][index] = helpers.configMerge(base[key][index], axisDefaults, valueObj);\r
+ } else {\r
+ // Type is the same\r
+ base[key][index] = helpers.configMerge(base[key][index], valueObj);\r
+ }\r
+ });\r
+ } else {\r
+ base[key] = [];\r
+ helpers.each(value, function(valueObj) {\r
+ var axisType = helpers.getValueOrDefault(valueObj.type, key === 'xAxes' ? 'category' : 'linear');\r
+ base[key].push(helpers.configMerge(Chart.scaleService.getScaleDefaults(axisType), valueObj));\r
+ });\r
+ }\r
+ } else if (base.hasOwnProperty(key) && typeof base[key] === "object" && base[key] !== null && typeof value === "object") {\r
+ // If we are overwriting an object with an object, do a merge of the properties.\r
+ base[key] = helpers.configMerge(base[key], value);\r
+\r
+ } else {\r
+ // can just overwrite the value in this case\r
+ base[key] = value;\r
+ }\r
+ });\r
+\r
+ return base;\r
+ };\r
+ helpers.getValueAtIndexOrDefault = function(value, index, defaultValue) {\r
+ if (value === undefined || value === null) {\r
+ return defaultValue;\r
+ }\r
+\r
+ if (helpers.isArray(value)) {\r
+ return index < value.length ? value[index] : defaultValue;\r
+ }\r
+\r
+ return value;\r
+ };\r
+ helpers.getValueOrDefault = function(value, defaultValue) {\r
+ return value === undefined ? defaultValue : value;\r
+ };\r
+ helpers.indexOf = function(arrayToSearch, item) {\r
+ if (Array.prototype.indexOf) {\r
+ return arrayToSearch.indexOf(item);\r
+ } else {\r
+ for (var i = 0; i < arrayToSearch.length; i++) {\r
+ if (arrayToSearch[i] === item)\r
+ return i;\r
+ }\r
+ return -1;\r
+ }\r
+ };\r
+ helpers.where = function(collection, filterCallback) {\r
+ if (helpers.isArray(collection) && Array.prototype.filter) {\r
+ return collection.filter(filterCallback);\r
+ } else {\r
+ var filtered = [];\r
+\r
+ helpers.each(collection, function(item) {\r
+ if (filterCallback(item)) {\r
+ filtered.push(item);\r
+ }\r
+ });\r
+\r
+ return filtered;\r
+ }\r
+ };\r
+ helpers.findIndex = function(arrayToSearch, callback, thisArg) {\r
+ var index = -1;\r
+ if (Array.prototype.findIndex) {\r
+ index = arrayToSearch.findIndex(callback, thisArg);\r
+ } else {\r
+ for (var i = 0; i < arrayToSearch.length; ++i) {\r
+ thisArg = thisArg !== undefined ? thisArg : arrayToSearch;\r
+\r
+ if (callback.call(thisArg, arrayToSearch[i], i, arrayToSearch)) {\r
+ index = i;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return index;\r
+ };\r
+ helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) {\r
+ // Default to start of the array\r
+ if (startIndex === undefined || startIndex === null) {\r
+ startIndex = -1;\r
+ }\r
+ for (var i = startIndex + 1; i < arrayToSearch.length; i++) {\r
+ var currentItem = arrayToSearch[i];\r
+ if (filterCallback(currentItem)) {\r
+ return currentItem;\r
+ }\r
+ }\r
+ };\r
+ helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) {\r
+ // Default to end of the array\r
+ if (startIndex === undefined || startIndex === null) {\r
+ startIndex = arrayToSearch.length;\r
+ }\r
+ for (var i = startIndex - 1; i >= 0; i--) {\r
+ var currentItem = arrayToSearch[i];\r
+ if (filterCallback(currentItem)) {\r
+ return currentItem;\r
+ }\r
+ }\r
+ };\r
+ helpers.inherits = function(extensions) {\r
+ //Basic javascript inheritance based on the model created in Backbone.js\r
+ var parent = this;\r
+ var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function() {\r
+ return parent.apply(this, arguments);\r
+ };\r
+\r
+ var Surrogate = function() {\r
+ this.constructor = ChartElement;\r
+ };\r
+ Surrogate.prototype = parent.prototype;\r
+ ChartElement.prototype = new Surrogate();\r
+\r
+ ChartElement.extend = helpers.inherits;\r
+\r
+ if (extensions) {\r
+ helpers.extend(ChartElement.prototype, extensions);\r
+ }\r
+\r
+ ChartElement.__super__ = parent.prototype;\r
+\r
+ return ChartElement;\r
+ };\r
+ helpers.noop = function() {};\r
+ helpers.uid = (function() {\r
+ var id = 0;\r
+ return function() {\r
+ return id++;\r
+ };\r
+ })();\r
+ helpers.warn = function(str) {\r
+ //Method for warning of errors\r
+ if (console && typeof console.warn === "function") {\r
+ console.warn(str);\r
+ }\r
+ };\r
+ //-- Math methods\r
+ helpers.isNumber = function(n) {\r
+ return !isNaN(parseFloat(n)) && isFinite(n);\r
+ };\r
+ helpers.almostEquals = function(x, y, epsilon) {\r
+ return Math.abs(x - y) < epsilon;\r
+ };\r
+ helpers.max = function(array) {\r
+ return array.reduce(function(max, value) {\r
+ if (!isNaN(value)) {\r
+ return Math.max(max, value);\r
+ } else {\r
+ return max;\r
+ }\r
+ }, Number.NEGATIVE_INFINITY);\r
+ };\r
+ helpers.min = function(array) {\r
+ return array.reduce(function(min, value) {\r
+ if (!isNaN(value)) {\r
+ return Math.min(min, value);\r
+ } else {\r
+ return min;\r
+ }\r
+ }, Number.POSITIVE_INFINITY);\r
+ };\r
+ helpers.sign = function(x) {\r
+ if (Math.sign) {\r
+ return Math.sign(x);\r
+ } else {\r
+ x = +x; // convert to a number\r
+ if (x === 0 || isNaN(x)) {\r
+ return x;\r
+ }\r
+ return x > 0 ? 1 : -1;\r
+ }\r
+ };\r
+ helpers.log10 = function(x) {\r
+ if (Math.log10) {\r
+ return Math.log10(x);\r
+ } else {\r
+ return Math.log(x) / Math.LN10;\r
+ }\r
+ };\r
+ helpers.toRadians = function(degrees) {\r
+ return degrees * (Math.PI / 180);\r
+ };\r
+ helpers.toDegrees = function(radians) {\r
+ return radians * (180 / Math.PI);\r
+ };\r
+ // Gets the angle from vertical upright to the point about a centre.\r
+ helpers.getAngleFromPoint = function(centrePoint, anglePoint) {\r
+ var distanceFromXCenter = anglePoint.x - centrePoint.x,\r
+ distanceFromYCenter = anglePoint.y - centrePoint.y,\r
+ radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);\r
+\r
+ var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);\r
+\r
+ if (angle < (-0.5 * Math.PI)) {\r
+ angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]\r
+ }\r
+\r
+ return {\r
+ angle: angle,\r
+ distance: radialDistanceFromCenter\r
+ };\r
+ };\r
+ helpers.aliasPixel = function(pixelWidth) {\r
+ return (pixelWidth % 2 === 0) ? 0 : 0.5;\r
+ };\r
+ helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) {\r
+ //Props to Rob Spencer at scaled innovation for his post on splining between points\r
+ //http://scaledinnovation.com/analytics/splines/aboutSplines.html\r
+\r
+ // This function must also respect "skipped" points\r
+\r
+ var previous = firstPoint.skip ? middlePoint : firstPoint,\r
+ current = middlePoint,\r
+ next = afterPoint.skip ? middlePoint : afterPoint;\r
+\r
+ var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2));\r
+ var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2));\r
+\r
+ var s01 = d01 / (d01 + d12);\r
+ var s12 = d12 / (d01 + d12);\r
+\r
+ // If all points are the same, s01 & s02 will be inf\r
+ s01 = isNaN(s01) ? 0 : s01;\r
+ s12 = isNaN(s12) ? 0 : s12;\r
+\r
+ var fa = t * s01; // scaling factor for triangle Ta\r
+ var fb = t * s12;\r
+\r
+ return {\r
+ previous: {\r
+ x: current.x - fa * (next.x - previous.x),\r
+ y: current.y - fa * (next.y - previous.y)\r
+ },\r
+ next: {\r
+ x: current.x + fb * (next.x - previous.x),\r
+ y: current.y + fb * (next.y - previous.y)\r
+ }\r
+ };\r
+ };\r
+ helpers.nextItem = function(collection, index, loop) {\r
+ if (loop) {\r
+ return index >= collection.length - 1 ? collection[0] : collection[index + 1];\r
+ }\r
+\r
+ return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1];\r
+ };\r
+ helpers.previousItem = function(collection, index, loop) {\r
+ if (loop) {\r
+ return index <= 0 ? collection[collection.length - 1] : collection[index - 1];\r
+ }\r
+ return index <= 0 ? collection[0] : collection[index - 1];\r
+ };\r
+ // Implementation of the nice number algorithm used in determining where axis labels will go\r
+ helpers.niceNum = function(range, round) {\r
+ var exponent = Math.floor(helpers.log10(range));\r
+ var fraction = range / Math.pow(10, exponent);\r
+ var niceFraction;\r
+\r
+ if (round) {\r
+ if (fraction < 1.5) {\r
+ niceFraction = 1;\r
+ } else if (fraction < 3) {\r
+ niceFraction = 2;\r
+ } else if (fraction < 7) {\r
+ niceFraction = 5;\r
+ } else {\r
+ niceFraction = 10;\r
+ }\r
+ } else {\r
+ if (fraction <= 1.0) {\r
+ niceFraction = 1;\r
+ } else if (fraction <= 2) {\r
+ niceFraction = 2;\r
+ } else if (fraction <= 5) {\r
+ niceFraction = 5;\r
+ } else {\r
+ niceFraction = 10;\r
+ }\r
+ }\r
+\r
+ return niceFraction * Math.pow(10, exponent);\r
+ };\r
+ //Easing functions adapted from Robert Penner's easing equations\r
+ //http://www.robertpenner.com/easing/\r
+ var easingEffects = helpers.easingEffects = {\r
+ linear: function(t) {\r
+ return t;\r
+ },\r
+ easeInQuad: function(t) {\r
+ return t * t;\r
+ },\r
+ easeOutQuad: function(t) {\r
+ return -1 * t * (t - 2);\r
+ },\r
+ easeInOutQuad: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t;\r
+ }\r
+ return -1 / 2 * ((--t) * (t - 2) - 1);\r
+ },\r
+ easeInCubic: function(t) {\r
+ return t * t * t;\r
+ },\r
+ easeOutCubic: function(t) {\r
+ return 1 * ((t = t / 1 - 1) * t * t + 1);\r
+ },\r
+ easeInOutCubic: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t;\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * t + 2);\r
+ },\r
+ easeInQuart: function(t) {\r
+ return t * t * t * t;\r
+ },\r
+ easeOutQuart: function(t) {\r
+ return -1 * ((t = t / 1 - 1) * t * t * t - 1);\r
+ },\r
+ easeInOutQuart: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t * t;\r
+ }\r
+ return -1 / 2 * ((t -= 2) * t * t * t - 2);\r
+ },\r
+ easeInQuint: function(t) {\r
+ return 1 * (t /= 1) * t * t * t * t;\r
+ },\r
+ easeOutQuint: function(t) {\r
+ return 1 * ((t = t / 1 - 1) * t * t * t * t + 1);\r
+ },\r
+ easeInOutQuint: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * t * t * t * t * t;\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * t * t * t + 2);\r
+ },\r
+ easeInSine: function(t) {\r
+ return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1;\r
+ },\r
+ easeOutSine: function(t) {\r
+ return 1 * Math.sin(t / 1 * (Math.PI / 2));\r
+ },\r
+ easeInOutSine: function(t) {\r
+ return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1);\r
+ },\r
+ easeInExpo: function(t) {\r
+ return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1));\r
+ },\r
+ easeOutExpo: function(t) {\r
+ return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1);\r
+ },\r
+ easeInOutExpo: function(t) {\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if (t === 1) {\r
+ return 1;\r
+ }\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * Math.pow(2, 10 * (t - 1));\r
+ }\r
+ return 1 / 2 * (-Math.pow(2, -10 * --t) + 2);\r
+ },\r
+ easeInCirc: function(t) {\r
+ if (t >= 1) {\r
+ return t;\r
+ }\r
+ return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1);\r
+ },\r
+ easeOutCirc: function(t) {\r
+ return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t);\r
+ },\r
+ easeInOutCirc: function(t) {\r
+ if ((t /= 1 / 2) < 1) {\r
+ return -1 / 2 * (Math.sqrt(1 - t * t) - 1);\r
+ }\r
+ return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1);\r
+ },\r
+ easeInElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1) === 1) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * 0.3;\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\r
+ },\r
+ easeOutElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1) === 1) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * 0.3;\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1;\r
+ },\r
+ easeInOutElastic: function(t) {\r
+ var s = 1.70158;\r
+ var p = 0;\r
+ var a = 1;\r
+ if (t === 0) {\r
+ return 0;\r
+ }\r
+ if ((t /= 1 / 2) === 2) {\r
+ return 1;\r
+ }\r
+ if (!p) {\r
+ p = 1 * (0.3 * 1.5);\r
+ }\r
+ if (a < Math.abs(1)) {\r
+ a = 1;\r
+ s = p / 4;\r
+ } else {\r
+ s = p / (2 * Math.PI) * Math.asin(1 / a);\r
+ }\r
+ if (t < 1) {\r
+ return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p));\r
+ }\r
+ return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1;\r
+ },\r
+ easeInBack: function(t) {\r
+ var s = 1.70158;\r
+ return 1 * (t /= 1) * t * ((s + 1) * t - s);\r
+ },\r
+ easeOutBack: function(t) {\r
+ var s = 1.70158;\r
+ return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1);\r
+ },\r
+ easeInOutBack: function(t) {\r
+ var s = 1.70158;\r
+ if ((t /= 1 / 2) < 1) {\r
+ return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s));\r
+ }\r
+ return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);\r
+ },\r
+ easeInBounce: function(t) {\r
+ return 1 - easingEffects.easeOutBounce(1 - t);\r
+ },\r
+ easeOutBounce: function(t) {\r
+ if ((t /= 1) < (1 / 2.75)) {\r
+ return 1 * (7.5625 * t * t);\r
+ } else if (t < (2 / 2.75)) {\r
+ return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75);\r
+ } else if (t < (2.5 / 2.75)) {\r
+ return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375);\r
+ } else {\r
+ return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375);\r
+ }\r
+ },\r
+ easeInOutBounce: function(t) {\r
+ if (t < 1 / 2) {\r
+ return easingEffects.easeInBounce(t * 2) * 0.5;\r
+ }\r
+ return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5;\r
+ }\r
+ };\r
+ //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\r
+ helpers.requestAnimFrame = (function() {\r
+ return window.requestAnimationFrame ||\r
+ window.webkitRequestAnimationFrame ||\r
+ window.mozRequestAnimationFrame ||\r
+ window.oRequestAnimationFrame ||\r
+ window.msRequestAnimationFrame ||\r
+ function(callback) {\r
+ return window.setTimeout(callback, 1000 / 60);\r
+ };\r
+ })();\r
+ helpers.cancelAnimFrame = (function() {\r
+ return window.cancelAnimationFrame ||\r
+ window.webkitCancelAnimationFrame ||\r
+ window.mozCancelAnimationFrame ||\r
+ window.oCancelAnimationFrame ||\r
+ window.msCancelAnimationFrame ||\r
+ function(callback) {\r
+ return window.clearTimeout(callback, 1000 / 60);\r
+ };\r
+ })();\r
+ //-- DOM methods\r
+ helpers.getRelativePosition = function(evt, chart) {\r
+ var mouseX, mouseY;\r
+ var e = evt.originalEvent || evt,\r
+ canvas = evt.currentTarget || evt.srcElement,\r
+ boundingRect = canvas.getBoundingClientRect();\r
+\r
+ var touches = e.touches;\r
+ if (touches && touches.length > 0) {\r
+ mouseX = touches[0].clientX;\r
+ mouseY = touches[0].clientY;\r
+\r
+ } else {\r
+ mouseX = e.clientX;\r
+ mouseY = e.clientY;\r
+ }\r
+\r
+ // Scale mouse coordinates into canvas coordinates\r
+ // by following the pattern laid out by 'jerryj' in the comments of\r
+ // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/\r
+ var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left'));\r
+ var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top'));\r
+ var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right'));\r
+ var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom'));\r
+ var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight;\r
+ var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom;\r
+\r
+ // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However\r
+ // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here\r
+ mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio);\r
+ mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio);\r
+\r
+ return {\r
+ x: mouseX,\r
+ y: mouseY\r
+ };\r
+\r
+ };\r
+ helpers.addEvent = function(node, eventType, method) {\r
+ if (node.addEventListener) {\r
+ node.addEventListener(eventType, method);\r
+ } else if (node.attachEvent) {\r
+ node.attachEvent("on" + eventType, method);\r
+ } else {\r
+ node["on" + eventType] = method;\r
+ }\r
+ };\r
+ helpers.removeEvent = function(node, eventType, handler) {\r
+ if (node.removeEventListener) {\r
+ node.removeEventListener(eventType, handler, false);\r
+ } else if (node.detachEvent) {\r
+ node.detachEvent("on" + eventType, handler);\r
+ } else {\r
+ node["on" + eventType] = helpers.noop;\r
+ }\r
+ };\r
+ helpers.bindEvents = function(chartInstance, arrayOfEvents, handler) {\r
+ // Create the events object if it's not already present\r
+ var events = chartInstance.events = chartInstance.events || {};\r
+\r
+ helpers.each(arrayOfEvents, function(eventName) {\r
+ events[eventName] = function() {\r
+ handler.apply(chartInstance, arguments);\r
+ };\r
+ helpers.addEvent(chartInstance.chart.canvas, eventName, events[eventName]);\r
+ });\r
+ };\r
+ helpers.unbindEvents = function(chartInstance, arrayOfEvents) {\r
+ var canvas = chartInstance.chart.canvas;\r
+ helpers.each(arrayOfEvents, function(handler, eventName) {\r
+ helpers.removeEvent(canvas, eventName, handler);\r
+ });\r
+ };\r
+\r
+ // Private helper function to convert max-width/max-height values that may be percentages into a number\r
+ function parseMaxStyle(styleValue, node, parentProperty) {\r
+ var valueInPixels;\r
+ if (typeof(styleValue) === 'string') {\r
+ valueInPixels = parseInt(styleValue, 10);\r
+\r
+ if (styleValue.indexOf('%') != -1) {\r
+ // percentage * size in dimension\r
+ valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];\r
+ }\r
+ } else {\r
+ valueInPixels = styleValue;\r
+ }\r
+\r
+ return valueInPixels;\r
+ }\r
+\r
+ /**\r
+ * Returns if the given value contains an effective constraint.\r
+ * @private\r
+ */\r
+ function isConstrainedValue(value) {\r
+ return value !== undefined && value !== null && value !== 'none';\r
+ }\r
+\r
+ // Private helper to get a constraint dimension\r
+ // @param domNode : the node to check the constraint on\r
+ // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight)\r
+ // @param percentageProperty : property of parent to use when calculating width as a percentage\r
+ // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser\r
+ function getConstraintDimension(domNode, maxStyle, percentageProperty) {\r
+ var view = document.defaultView;\r
+ var parentNode = domNode.parentNode;\r
+ var constrainedNode = view.getComputedStyle(domNode)[maxStyle];\r
+ var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle];\r
+ var hasCNode = isConstrainedValue(constrainedNode);\r
+ var hasCContainer = isConstrainedValue(constrainedContainer);\r
+ var infinity = Number.POSITIVE_INFINITY;\r
+\r
+ if (hasCNode || hasCContainer) {\r
+ return Math.min(\r
+ hasCNode? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity,\r
+ hasCContainer? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity);\r
+ }\r
+\r
+ return 'none';\r
+ }\r
+ // returns Number or undefined if no constraint\r
+ helpers.getConstraintWidth = function(domNode) {\r
+ return getConstraintDimension(domNode, 'max-width', 'clientWidth');\r
+ };\r
+ // returns Number or undefined if no constraint\r
+ helpers.getConstraintHeight = function(domNode) {\r
+ return getConstraintDimension(domNode, 'max-height', 'clientHeight');\r
+ };\r
+ helpers.getMaximumWidth = function(domNode) {\r
+ var container = domNode.parentNode;\r
+ var padding = parseInt(helpers.getStyle(container, 'padding-left')) + parseInt(helpers.getStyle(container, 'padding-right'));\r
+ var w = container.clientWidth - padding;\r
+ var cw = helpers.getConstraintWidth(domNode);\r
+ return isNaN(cw)? w : Math.min(w, cw);\r
+ };\r
+ helpers.getMaximumHeight = function(domNode) {\r
+ var container = domNode.parentNode;\r
+ var padding = parseInt(helpers.getStyle(container, 'padding-top')) + parseInt(helpers.getStyle(container, 'padding-bottom'));\r
+ var h = container.clientHeight - padding;\r
+ var ch = helpers.getConstraintHeight(domNode);\r
+ return isNaN(ch)? h : Math.min(h, ch);\r
+ };\r
+ helpers.getStyle = function(el, property) {\r
+ return el.currentStyle ?\r
+ el.currentStyle[property] :\r
+ document.defaultView.getComputedStyle(el, null).getPropertyValue(property);\r
+ };\r
+ helpers.retinaScale = function(chart) {\r
+ var ctx = chart.ctx;\r
+ var canvas = chart.canvas;\r
+ var width = canvas.width;\r
+ var height = canvas.height;\r
+ var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1;\r
+\r
+ if (pixelRatio !== 1) {\r
+ canvas.height = height * pixelRatio;\r
+ canvas.width = width * pixelRatio;\r
+ ctx.scale(pixelRatio, pixelRatio);\r
+\r
+ // Store the device pixel ratio so that we can go backwards in `destroy`.\r
+ // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same\r
+ // when destroy is called\r
+ chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || pixelRatio;\r
+ }\r
+\r
+ canvas.style.width = width + 'px';\r
+ canvas.style.height = height + 'px';\r
+ };\r
+ //-- Canvas methods\r
+ helpers.clear = function(chart) {\r
+ chart.ctx.clearRect(0, 0, chart.width, chart.height);\r
+ };\r
+ helpers.fontString = function(pixelSize, fontStyle, fontFamily) {\r
+ return fontStyle + " " + pixelSize + "px " + fontFamily;\r
+ };\r
+ helpers.longestText = function(ctx, font, arrayOfStrings, cache) {\r
+ cache = cache || {};\r
+ var data = cache.data = cache.data || {};\r
+ var gc = cache.garbageCollect = cache.garbageCollect || [];\r
+\r
+ if (cache.font !== font) {\r
+ data = cache.data = {};\r
+ gc = cache.garbageCollect = [];\r
+ cache.font = font;\r
+ }\r
+\r
+ ctx.font = font;\r
+ var longest = 0;\r
+ helpers.each(arrayOfStrings, function(string) {\r
+ // Undefined strings should not be measured\r
+ if (string !== undefined && string !== null) {\r
+ var textWidth = data[string];\r
+ if (!textWidth) {\r
+ textWidth = data[string] = ctx.measureText(string).width;\r
+ gc.push(string);\r
+ }\r
+\r
+ if (textWidth > longest) {\r
+ longest = textWidth;\r
+ }\r
+ }\r
+ });\r
+\r
+ var gcLen = gc.length / 2;\r
+ if (gcLen > arrayOfStrings.length) {\r
+ for (var i = 0; i < gcLen; i++) {\r
+ delete data[gc[i]];\r
+ }\r
+ gc.splice(0, gcLen);\r
+ }\r
+\r
+ return longest;\r
+ };\r
+ helpers.drawRoundedRectangle = function(ctx, x, y, width, height, radius) {\r
+ ctx.beginPath();\r
+ ctx.moveTo(x + radius, y);\r
+ ctx.lineTo(x + width - radius, y);\r
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);\r
+ ctx.lineTo(x + width, y + height - radius);\r
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);\r
+ ctx.lineTo(x + radius, y + height);\r
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);\r
+ ctx.lineTo(x, y + radius);\r
+ ctx.quadraticCurveTo(x, y, x + radius, y);\r
+ ctx.closePath();\r
+ };\r
+ helpers.color = function(c) {\r
+ if (!color) {\r
+ console.log('Color.js not found!');\r
+ return c;\r
+ }\r
+\r
+ /* global CanvasGradient */\r
+ if (c instanceof CanvasGradient) {\r
+ return color(Chart.defaults.global.defaultColor);\r
+ }\r
+\r
+ return color(c);\r
+ };\r
+ helpers.addResizeListener = function(node, callback) {\r
+ // Hide an iframe before the node\r
+ var hiddenIframe = document.createElement('iframe');\r
+ var hiddenIframeClass = 'chartjs-hidden-iframe';\r
+\r
+ if (hiddenIframe.classlist) {\r
+ // can use classlist\r
+ hiddenIframe.classlist.add(hiddenIframeClass);\r
+ } else {\r
+ hiddenIframe.setAttribute('class', hiddenIframeClass);\r
+ }\r
+\r
+ // Set the style\r
+ var style = hiddenIframe.style;\r
+ style.width = '100%';\r
+ style.display = 'block';\r
+ style.border = 0;\r
+ style.height = 0;\r
+ style.margin = 0;\r
+ style.position = 'absolute';\r
+ style.left = 0;\r
+ style.right = 0;\r
+ style.top = 0;\r
+ style.bottom = 0;\r
+\r
+ // Insert the iframe so that contentWindow is available\r
+ node.insertBefore(hiddenIframe, node.firstChild);\r
+\r
+ (hiddenIframe.contentWindow || hiddenIframe).onresize = function() {\r
+ if (callback) {\r
+ callback();\r
+ }\r
+ };\r
+ };\r
+ helpers.removeResizeListener = function(node) {\r
+ var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');\r
+\r
+ // Remove the resize detect iframe\r
+ if (hiddenIframe) {\r
+ hiddenIframe.parentNode.removeChild(hiddenIframe);\r
+ }\r
+ };\r
+ helpers.isArray = function(obj) {\r
+ if (!Array.isArray) {\r
+ return Object.prototype.toString.call(obj) === '[object Array]';\r
+ }\r
+ return Array.isArray(obj);\r
+ };\r
+ //! @see http://stackoverflow.com/a/14853974\r
+ helpers.arrayEquals = function(a0, a1) {\r
+ var i, ilen, v0, v1;\r
+\r
+ if (!a0 || !a1 || a0.length != a1.length) {\r
+ return false;\r
+ }\r
+\r
+ for (i = 0, ilen=a0.length; i < ilen; ++i) {\r
+ v0 = a0[i];\r
+ v1 = a1[i];\r
+\r
+ if (v0 instanceof Array && v1 instanceof Array) {\r
+ if (!helpers.arrayEquals(v0, v1)) {\r
+ return false;\r
+ }\r
+ } else if (v0 != v1) {\r
+ // NOTE: two different object instances will never be equal: {x:20} != {x:20}\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+ };\r
+ helpers.pushAllIfDefined = function(element, array) {\r
+ if (typeof element === "undefined") {\r
+ return;\r
+ }\r
+\r
+ if (helpers.isArray(element)) {\r
+ array.push.apply(array, element);\r
+ } else {\r
+ array.push(element);\r
+ }\r
+ };\r
+ helpers.callCallback = function(fn, args, _tArg) {\r
+ if (fn && typeof fn.call === 'function') {\r
+ fn.apply(_tArg, args);\r
+ }\r
+ };\r
+ helpers.getHoverColor = function(color) {\r
+ /* global CanvasPattern */\r
+ return (color instanceof CanvasPattern) ?\r
+ color :\r
+ helpers.color(color).saturate(0.5).darken(0.1).rgbString();\r
+ };\r
+};\r
-};
+},{"chartjs-color":3}],26:[function(require,module,exports){
+"use strict";\r
+\r
+module.exports = function() {\r
+\r
+ //Occupy the global variable of Chart, and create a simple base class\r
+ var Chart = function(context, config) {\r
+ this.config = config;\r
+\r
+ // Support a jQuery'd canvas element\r
+ if (context.length && context[0].getContext) {\r
+ context = context[0];\r
+ }\r
+\r
+ // Support a canvas domnode\r
+ if (context.getContext) {\r
+ context = context.getContext("2d");\r
+ }\r
+\r
+ this.ctx = context;\r
+ this.canvas = context.canvas;\r
+\r
+ // Figure out what the size of the chart will be.\r
+ // If the canvas has a specified width and height, we use those else\r
+ // we look to see if the canvas node has a CSS width and height.\r
+ // If there is still no height, fill the parent container\r
+ this.width = context.canvas.width || parseInt(Chart.helpers.getStyle(context.canvas, 'width')) || Chart.helpers.getMaximumWidth(context.canvas);\r
+ this.height = context.canvas.height || parseInt(Chart.helpers.getStyle(context.canvas, 'height')) || Chart.helpers.getMaximumHeight(context.canvas);\r
+\r
+ this.aspectRatio = this.width / this.height;\r
+\r
+ if (isNaN(this.aspectRatio) || isFinite(this.aspectRatio) === false) {\r
+ // If the canvas has no size, try and figure out what the aspect ratio will be.\r
+ // Some charts prefer square canvases (pie, radar, etc). If that is specified, use that\r
+ // else use the canvas default ratio of 2\r
+ this.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;\r
+ }\r
+\r
+ // Store the original style of the element so we can set it back\r
+ this.originalCanvasStyleWidth = context.canvas.style.width;\r
+ this.originalCanvasStyleHeight = context.canvas.style.height;\r
+\r
+ // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.\r
+ Chart.helpers.retinaScale(this);\r
+\r
+ if (config) {\r
+ this.controller = new Chart.Controller(this);\r
+ }\r
+\r
+ // Always bind this so that if the responsive state changes we still work\r
+ var _this = this;\r
+ Chart.helpers.addResizeListener(context.canvas.parentNode, function() {\r
+ if (_this.controller && _this.controller.config.options.responsive) {\r
+ _this.controller.resize();\r
+ }\r
+ });\r
+\r
+ return this.controller ? this.controller : this;\r
+\r
+ };\r
+\r
+ //Globally expose the defaults to allow for user updating/changing\r
+ Chart.defaults = {\r
+ global: {\r
+ responsive: true,\r
+ responsiveAnimationDuration: 0,\r
+ maintainAspectRatio: true,\r
+ events: ["mousemove", "mouseout", "click", "touchstart", "touchmove"],\r
+ hover: {\r
+ onHover: null,\r
+ mode: 'single',\r
+ animationDuration: 400\r
+ },\r
+ onClick: null,\r
+ defaultColor: 'rgba(0,0,0,0.1)',\r
+ defaultFontColor: '#666',\r
+ defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",\r
+ defaultFontSize: 12,\r
+ defaultFontStyle: 'normal',\r
+ showLines: true,\r
+\r
+ // Element defaults defined in element extensions\r
+ elements: {},\r
+\r
+ // Legend callback string\r
+ legendCallback: function(chart) {\r
+ var text = [];\r
+ text.push('<ul class="' + chart.id + '-legend">');\r
+ for (var i = 0; i < chart.data.datasets.length; i++) {\r
+ text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');\r
+ if (chart.data.datasets[i].label) {\r
+ text.push(chart.data.datasets[i].label);\r
+ }\r
+ text.push('</li>');\r
+ }\r
+ text.push('</ul>');\r
+\r
+ return text.join("");\r
+ }\r
+ }\r
+ };\r
+\r
+ return Chart;\r
+\r
+};\r
},{}],27:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- // The layout service is very self explanatory. It's responsible for the layout within a chart.
- // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need
- // It is this service's responsibility of carrying out that layout.
- Chart.layoutService = {
- defaults: {},
-
- // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins.
- addBox: function(chartInstance, box) {
- if (!chartInstance.boxes) {
- chartInstance.boxes = [];
- }
- chartInstance.boxes.push(box);
- },
-
- removeBox: function(chartInstance, box) {
- if (!chartInstance.boxes) {
- return;
- }
- chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1);
- },
-
- // The most important function
- update: function(chartInstance, width, height) {
-
- if (!chartInstance) {
- return;
- }
-
- var xPadding = 0;
- var yPadding = 0;
-
- var leftBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "left";
- });
- var rightBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "right";
- });
- var topBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "top";
- });
- var bottomBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "bottom";
- });
-
- // Boxes that overlay the chartarea such as the radialLinear scale
- var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) {
- return box.options.position === "chartArea";
- });
-
- // Ensure that full width boxes are at the very top / bottom
- topBoxes.sort(function(a, b) {
- return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0);
- });
- bottomBoxes.sort(function(a, b) {
- return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0);
- });
-
- // Essentially we now have any number of boxes on each of the 4 sides.
- // Our canvas looks like the following.
- // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
- // B1 is the bottom axis
- // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays
- // These locations are single-box locations only, when trying to register a chartArea location that is already taken,
- // an error will be thrown.
- //
- // |----------------------------------------------------|
- // | T1 (Full Width) |
- // |----------------------------------------------------|
- // | | | T2 | |
- // | |----|-------------------------------------|----|
- // | | | C1 | | C2 | |
- // | | |----| |----| |
- // | | | | |
- // | L1 | L2 | ChartArea (C0) | R1 |
- // | | | | |
- // | | |----| |----| |
- // | | | C3 | | C4 | |
- // | |----|-------------------------------------|----|
- // | | | B1 | |
- // |----------------------------------------------------|
- // | B2 (Full Width) |
- // |----------------------------------------------------|
- //
- // What we do to find the best sizing, we do the following
- // 1. Determine the minimum size of the chart area.
- // 2. Split the remaining width equally between each vertical axis
- // 3. Split the remaining height equally between each horizontal axis
- // 4. Give each layout the maximum size it can be. The layout will return it's minimum size
- // 5. Adjust the sizes of each axis based on it's minimum reported size.
- // 6. Refit each axis
- // 7. Position each axis in the final location
- // 8. Tell the chart the final location of the chart area
- // 9. Tell any axes that overlay the chart area the positions of the chart area
-
- // Step 1
- var chartWidth = width - (2 * xPadding);
- var chartHeight = height - (2 * yPadding);
- var chartAreaWidth = chartWidth / 2; // min 50%
- var chartAreaHeight = chartHeight / 2; // min 50%
-
- // Step 2
- var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
-
- // Step 3
- var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
-
- // Step 4
- var maxChartAreaWidth = chartWidth;
- var maxChartAreaHeight = chartHeight;
- var minBoxSizes = [];
-
- helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
-
- function getMinimumBoxSize(box) {
- var minSize;
- var isHorizontal = box.isHorizontal();
-
- if (isHorizontal) {
- minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
- maxChartAreaHeight -= minSize.height;
- } else {
- minSize = box.update(verticalBoxWidth, chartAreaHeight);
- maxChartAreaWidth -= minSize.width;
- }
-
- minBoxSizes.push({
- horizontal: isHorizontal,
- minSize: minSize,
- box: box
- });
- }
-
- // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
- // be if the axes are drawn at their minimum sizes.
-
- // Steps 5 & 6
- var totalLeftBoxesWidth = xPadding;
- var totalRightBoxesWidth = xPadding;
- var totalTopBoxesHeight = yPadding;
- var totalBottomBoxesHeight = yPadding;
-
- // Update, and calculate the left and right margins for the horizontal boxes
- helpers.each(leftBoxes.concat(rightBoxes), fitBox);
-
- helpers.each(leftBoxes, function(box) {
- totalLeftBoxesWidth += box.width;
- });
-
- helpers.each(rightBoxes, function(box) {
- totalRightBoxesWidth += box.width;
- });
-
- // Set the Left and Right margins for the horizontal boxes
- helpers.each(topBoxes.concat(bottomBoxes), fitBox);
-
- // Function to fit a box
- function fitBox(box) {
- var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
- return minBoxSize.box === box;
- });
-
- if (minBoxSize) {
- if (box.isHorizontal()) {
- var scaleMargin = {
- left: totalLeftBoxesWidth,
- right: totalRightBoxesWidth,
- top: 0,
- bottom: 0
- };
-
- // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends
- // on the margin. Sometimes they need to increase in size slightly
- box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
- } else {
- box.update(minBoxSize.minSize.width, maxChartAreaHeight);
- }
- }
- }
-
- // Figure out how much margin is on the top and bottom of the vertical boxes
- helpers.each(topBoxes, function(box) {
- totalTopBoxesHeight += box.height;
- });
-
- helpers.each(bottomBoxes, function(box) {
- totalBottomBoxesHeight += box.height;
- });
-
- // Let the left layout know the final margin
- helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
-
- function finalFitVerticalBox(box) {
- var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {
- return minBoxSize.box === box;
- });
-
- var scaleMargin = {
- left: 0,
- right: 0,
- top: totalTopBoxesHeight,
- bottom: totalBottomBoxesHeight
- };
-
- if (minBoxSize) {
- box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
- }
- }
-
- // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
- totalLeftBoxesWidth = xPadding;
- totalRightBoxesWidth = xPadding;
- totalTopBoxesHeight = yPadding;
- totalBottomBoxesHeight = yPadding;
-
- helpers.each(leftBoxes, function(box) {
- totalLeftBoxesWidth += box.width;
- });
-
- helpers.each(rightBoxes, function(box) {
- totalRightBoxesWidth += box.width;
- });
-
- helpers.each(topBoxes, function(box) {
- totalTopBoxesHeight += box.height;
- });
- helpers.each(bottomBoxes, function(box) {
- totalBottomBoxesHeight += box.height;
- });
-
- // Figure out if our chart area changed. This would occur if the dataset layout label rotation
- // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
- // without calling `fit` again
- var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
- var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
-
- if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
- helpers.each(leftBoxes, function(box) {
- box.height = newMaxChartAreaHeight;
- });
-
- helpers.each(rightBoxes, function(box) {
- box.height = newMaxChartAreaHeight;
- });
-
- helpers.each(topBoxes, function(box) {
- if (!box.options.fullWidth) {
- box.width = newMaxChartAreaWidth;
- }
- });
-
- helpers.each(bottomBoxes, function(box) {
- if (!box.options.fullWidth) {
- box.width = newMaxChartAreaWidth;
- }
- });
-
- maxChartAreaHeight = newMaxChartAreaHeight;
- maxChartAreaWidth = newMaxChartAreaWidth;
- }
-
- // Step 7 - Position the boxes
- var left = xPadding;
- var top = yPadding;
- var right = 0;
- var bottom = 0;
-
- helpers.each(leftBoxes.concat(topBoxes), placeBox);
-
- // Account for chart width and height
- left += maxChartAreaWidth;
- top += maxChartAreaHeight;
-
- helpers.each(rightBoxes, placeBox);
- helpers.each(bottomBoxes, placeBox);
-
- function placeBox(box) {
- if (box.isHorizontal()) {
- box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth;
- box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth;
- box.top = top;
- box.bottom = top + box.height;
-
- // Move to next point
- top = box.bottom;
-
- } else {
-
- box.left = left;
- box.right = left + box.width;
- box.top = totalTopBoxesHeight;
- box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
-
- // Move to next point
- left = box.right;
- }
- }
-
- // Step 8
- chartInstance.chartArea = {
- left: totalLeftBoxesWidth,
- top: totalTopBoxesHeight,
- right: totalLeftBoxesWidth + maxChartAreaWidth,
- bottom: totalTopBoxesHeight + maxChartAreaHeight
- };
-
- // Step 9
- helpers.each(chartAreaBoxes, function(box) {
- box.left = chartInstance.chartArea.left;
- box.top = chartInstance.chartArea.top;
- box.right = chartInstance.chartArea.right;
- box.bottom = chartInstance.chartArea.bottom;
-
- box.update(maxChartAreaWidth, maxChartAreaHeight);
- });
- }
- };
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ // The layout service is very self explanatory. It's responsible for the layout within a chart.\r
+ // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need\r
+ // It is this service's responsibility of carrying out that layout.\r
+ Chart.layoutService = {\r
+ defaults: {},\r
+\r
+ // Register a box to a chartInstance. A box is simply a reference to an object that requires layout. eg. Scales, Legend, Plugins.\r
+ addBox: function(chartInstance, box) {\r
+ if (!chartInstance.boxes) {\r
+ chartInstance.boxes = [];\r
+ }\r
+ chartInstance.boxes.push(box);\r
+ },\r
+\r
+ removeBox: function(chartInstance, box) {\r
+ if (!chartInstance.boxes) {\r
+ return;\r
+ }\r
+ chartInstance.boxes.splice(chartInstance.boxes.indexOf(box), 1);\r
+ },\r
+\r
+ // The most important function\r
+ update: function(chartInstance, width, height) {\r
+\r
+ if (!chartInstance) {\r
+ return;\r
+ }\r
+\r
+ var xPadding = 0;\r
+ var yPadding = 0;\r
+\r
+ var leftBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "left";\r
+ });\r
+ var rightBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "right";\r
+ });\r
+ var topBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "top";\r
+ });\r
+ var bottomBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "bottom";\r
+ });\r
+\r
+ // Boxes that overlay the chartarea such as the radialLinear scale\r
+ var chartAreaBoxes = helpers.where(chartInstance.boxes, function(box) {\r
+ return box.options.position === "chartArea";\r
+ });\r
+\r
+ // Ensure that full width boxes are at the very top / bottom\r
+ topBoxes.sort(function(a, b) {\r
+ return (b.options.fullWidth ? 1 : 0) - (a.options.fullWidth ? 1 : 0);\r
+ });\r
+ bottomBoxes.sort(function(a, b) {\r
+ return (a.options.fullWidth ? 1 : 0) - (b.options.fullWidth ? 1 : 0);\r
+ });\r
+\r
+ // Essentially we now have any number of boxes on each of the 4 sides.\r
+ // Our canvas looks like the following.\r
+ // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and\r
+ // B1 is the bottom axis\r
+ // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays\r
+ // These locations are single-box locations only, when trying to register a chartArea location that is already taken,\r
+ // an error will be thrown.\r
+ //\r
+ // |----------------------------------------------------|\r
+ // | T1 (Full Width) |\r
+ // |----------------------------------------------------|\r
+ // | | | T2 | |\r
+ // | |----|-------------------------------------|----|\r
+ // | | | C1 | | C2 | |\r
+ // | | |----| |----| |\r
+ // | | | | |\r
+ // | L1 | L2 | ChartArea (C0) | R1 |\r
+ // | | | | |\r
+ // | | |----| |----| |\r
+ // | | | C3 | | C4 | |\r
+ // | |----|-------------------------------------|----|\r
+ // | | | B1 | |\r
+ // |----------------------------------------------------|\r
+ // | B2 (Full Width) |\r
+ // |----------------------------------------------------|\r
+ //\r
+ // What we do to find the best sizing, we do the following\r
+ // 1. Determine the minimum size of the chart area.\r
+ // 2. Split the remaining width equally between each vertical axis\r
+ // 3. Split the remaining height equally between each horizontal axis\r
+ // 4. Give each layout the maximum size it can be. The layout will return it's minimum size\r
+ // 5. Adjust the sizes of each axis based on it's minimum reported size.\r
+ // 6. Refit each axis\r
+ // 7. Position each axis in the final location\r
+ // 8. Tell the chart the final location of the chart area\r
+ // 9. Tell any axes that overlay the chart area the positions of the chart area\r
+\r
+ // Step 1\r
+ var chartWidth = width - (2 * xPadding);\r
+ var chartHeight = height - (2 * yPadding);\r
+ var chartAreaWidth = chartWidth / 2; // min 50%\r
+ var chartAreaHeight = chartHeight / 2; // min 50%\r
+\r
+ // Step 2\r
+ var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);\r
+\r
+ // Step 3\r
+ var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);\r
+\r
+ // Step 4\r
+ var maxChartAreaWidth = chartWidth;\r
+ var maxChartAreaHeight = chartHeight;\r
+ var minBoxSizes = [];\r
+\r
+ helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);\r
+\r
+ function getMinimumBoxSize(box) {\r
+ var minSize;\r
+ var isHorizontal = box.isHorizontal();\r
+\r
+ if (isHorizontal) {\r
+ minSize = box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);\r
+ maxChartAreaHeight -= minSize.height;\r
+ } else {\r
+ minSize = box.update(verticalBoxWidth, chartAreaHeight);\r
+ maxChartAreaWidth -= minSize.width;\r
+ }\r
+\r
+ minBoxSizes.push({\r
+ horizontal: isHorizontal,\r
+ minSize: minSize,\r
+ box: box\r
+ });\r
+ }\r
+\r
+ // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could\r
+ // be if the axes are drawn at their minimum sizes.\r
+\r
+ // Steps 5 & 6\r
+ var totalLeftBoxesWidth = xPadding;\r
+ var totalRightBoxesWidth = xPadding;\r
+ var totalTopBoxesHeight = yPadding;\r
+ var totalBottomBoxesHeight = yPadding;\r
+\r
+ // Update, and calculate the left and right margins for the horizontal boxes\r
+ helpers.each(leftBoxes.concat(rightBoxes), fitBox);\r
+\r
+ helpers.each(leftBoxes, function(box) {\r
+ totalLeftBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ totalRightBoxesWidth += box.width;\r
+ });\r
+\r
+ // Set the Left and Right margins for the horizontal boxes\r
+ helpers.each(topBoxes.concat(bottomBoxes), fitBox);\r
+\r
+ // Function to fit a box\r
+ function fitBox(box) {\r
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {\r
+ return minBoxSize.box === box;\r
+ });\r
+\r
+ if (minBoxSize) {\r
+ if (box.isHorizontal()) {\r
+ var scaleMargin = {\r
+ left: totalLeftBoxesWidth,\r
+ right: totalRightBoxesWidth,\r
+ top: 0,\r
+ bottom: 0\r
+ };\r
+\r
+ // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends\r
+ // on the margin. Sometimes they need to increase in size slightly\r
+ box.update(box.options.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);\r
+ } else {\r
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight);\r
+ }\r
+ }\r
+ }\r
+\r
+ // Figure out how much margin is on the top and bottom of the vertical boxes\r
+ helpers.each(topBoxes, function(box) {\r
+ totalTopBoxesHeight += box.height;\r
+ });\r
+\r
+ helpers.each(bottomBoxes, function(box) {\r
+ totalBottomBoxesHeight += box.height;\r
+ });\r
+\r
+ // Let the left layout know the final margin\r
+ helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);\r
+\r
+ function finalFitVerticalBox(box) {\r
+ var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBoxSize) {\r
+ return minBoxSize.box === box;\r
+ });\r
+\r
+ var scaleMargin = {\r
+ left: 0,\r
+ right: 0,\r
+ top: totalTopBoxesHeight,\r
+ bottom: totalBottomBoxesHeight\r
+ };\r
+\r
+ if (minBoxSize) {\r
+ box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);\r
+ }\r
+ }\r
+\r
+ // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)\r
+ totalLeftBoxesWidth = xPadding;\r
+ totalRightBoxesWidth = xPadding;\r
+ totalTopBoxesHeight = yPadding;\r
+ totalBottomBoxesHeight = yPadding;\r
+\r
+ helpers.each(leftBoxes, function(box) {\r
+ totalLeftBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ totalRightBoxesWidth += box.width;\r
+ });\r
+\r
+ helpers.each(topBoxes, function(box) {\r
+ totalTopBoxesHeight += box.height;\r
+ });\r
+ helpers.each(bottomBoxes, function(box) {\r
+ totalBottomBoxesHeight += box.height;\r
+ });\r
+\r
+ // Figure out if our chart area changed. This would occur if the dataset layout label rotation\r
+ // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do\r
+ // without calling `fit` again\r
+ var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;\r
+ var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;\r
+\r
+ if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {\r
+ helpers.each(leftBoxes, function(box) {\r
+ box.height = newMaxChartAreaHeight;\r
+ });\r
+\r
+ helpers.each(rightBoxes, function(box) {\r
+ box.height = newMaxChartAreaHeight;\r
+ });\r
+\r
+ helpers.each(topBoxes, function(box) {\r
+ if (!box.options.fullWidth) {\r
+ box.width = newMaxChartAreaWidth;\r
+ }\r
+ });\r
+\r
+ helpers.each(bottomBoxes, function(box) {\r
+ if (!box.options.fullWidth) {\r
+ box.width = newMaxChartAreaWidth;\r
+ }\r
+ });\r
+\r
+ maxChartAreaHeight = newMaxChartAreaHeight;\r
+ maxChartAreaWidth = newMaxChartAreaWidth;\r
+ }\r
+\r
+ // Step 7 - Position the boxes\r
+ var left = xPadding;\r
+ var top = yPadding;\r
+ var right = 0;\r
+ var bottom = 0;\r
+\r
+ helpers.each(leftBoxes.concat(topBoxes), placeBox);\r
+\r
+ // Account for chart width and height\r
+ left += maxChartAreaWidth;\r
+ top += maxChartAreaHeight;\r
+\r
+ helpers.each(rightBoxes, placeBox);\r
+ helpers.each(bottomBoxes, placeBox);\r
+\r
+ function placeBox(box) {\r
+ if (box.isHorizontal()) {\r
+ box.left = box.options.fullWidth ? xPadding : totalLeftBoxesWidth;\r
+ box.right = box.options.fullWidth ? width - xPadding : totalLeftBoxesWidth + maxChartAreaWidth;\r
+ box.top = top;\r
+ box.bottom = top + box.height;\r
+\r
+ // Move to next point\r
+ top = box.bottom;\r
+\r
+ } else {\r
+\r
+ box.left = left;\r
+ box.right = left + box.width;\r
+ box.top = totalTopBoxesHeight;\r
+ box.bottom = totalTopBoxesHeight + maxChartAreaHeight;\r
+\r
+ // Move to next point\r
+ left = box.right;\r
+ }\r
+ }\r
+\r
+ // Step 8\r
+ chartInstance.chartArea = {\r
+ left: totalLeftBoxesWidth,\r
+ top: totalTopBoxesHeight,\r
+ right: totalLeftBoxesWidth + maxChartAreaWidth,\r
+ bottom: totalTopBoxesHeight + maxChartAreaHeight\r
+ };\r
+\r
+ // Step 9\r
+ helpers.each(chartAreaBoxes, function(box) {\r
+ box.left = chartInstance.chartArea.left;\r
+ box.top = chartInstance.chartArea.top;\r
+ box.right = chartInstance.chartArea.right;\r
+ box.bottom = chartInstance.chartArea.bottom;\r
+\r
+ box.update(maxChartAreaWidth, maxChartAreaHeight);\r
+ });\r
+ }\r
+ };\r
+};\r
},{}],28:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var noop = helpers.noop;
-
- Chart.defaults.global.legend = {
-
- display: true,
- position: 'top',
- fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
- reverse: false,
-
- // a callback that will handle
- onClick: function(e, legendItem) {
- var index = legendItem.datasetIndex;
- var ci = this.chart;
- var meta = ci.getDatasetMeta(index);
-
- // See controller.isDatasetVisible comment
- meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
-
- // We hid a dataset ... rerender the chart
- ci.update();
- },
-
- labels: {
- boxWidth: 40,
- padding: 10,
- // Generates labels shown in the legend
- // Valid properties to return:
- // text : text to display
- // fillStyle : fill of coloured box
- // strokeStyle: stroke of coloured box
- // hidden : if this legend item refers to a hidden item
- // lineCap : cap style for line
- // lineDash
- // lineDashOffset :
- // lineJoin :
- // lineWidth :
- generateLabels: function(chart) {
- var data = chart.data;
- return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {
- return {
- text: dataset.label,
- fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]),
- hidden: !chart.isDatasetVisible(i),
- lineCap: dataset.borderCapStyle,
- lineDash: dataset.borderDash,
- lineDashOffset: dataset.borderDashOffset,
- lineJoin: dataset.borderJoinStyle,
- lineWidth: dataset.borderWidth,
- strokeStyle: dataset.borderColor,
-
- // Below is extra data used for toggling the datasets
- datasetIndex: i
- };
- }, this) : [];
- }
- }
- };
-
- Chart.Legend = Chart.Element.extend({
-
- initialize: function(config) {
- helpers.extend(this, config);
-
- // Contains hit boxes for each dataset (in dataset order)
- this.legendHitBoxes = [];
-
- // Are we in doughnut mode which has a different data type
- this.doughnutMode = false;
- },
-
- // These methods are ordered by lifecyle. Utilities then follow.
- // Any function defined here is inherited by all legend types.
- // Any function can be extended by the legend type
-
- beforeUpdate: noop,
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = margins;
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
- // Labels
- me.beforeBuildLabels();
- me.buildLabels();
- me.afterBuildLabels();
-
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
- },
- afterUpdate: noop,
-
- //
-
- beforeSetDimensions: noop,
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
-
- // Reset minSize
- me.minSize = {
- width: 0,
- height: 0
- };
- },
- afterSetDimensions: noop,
-
- //
-
- beforeBuildLabels: noop,
- buildLabels: function() {
- var me = this;
- me.legendItems = me.options.labels.generateLabels.call(me, me.chart);
- if(me.options.reverse){
- me.legendItems.reverse();
- }
- },
- afterBuildLabels: noop,
-
- //
-
- beforeFit: noop,
- fit: function() {
- var me = this;
- var opts = me.options;
- var labelOpts = opts.labels;
- var display = opts.display;
-
- var ctx = me.ctx;
-
- var globalDefault = Chart.defaults.global,
- itemOrDefault = helpers.getValueOrDefault,
- fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
- fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
- fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
- labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
-
- // Reset hit boxes
- var hitboxes = me.legendHitBoxes = [];
-
- var minSize = me.minSize;
- var isHorizontal = me.isHorizontal();
-
- if (isHorizontal) {
- minSize.width = me.maxWidth; // fill all the width
- minSize.height = display ? 10 : 0;
- } else {
- minSize.width = display ? 10 : 0;
- minSize.height = me.maxHeight; // fill all the height
- }
-
- // Increase sizes here
- if (display) {
- if (isHorizontal) {
- // Labels
-
- // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one
- var lineWidths = me.lineWidths = [0];
- var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0;
-
- ctx.textAlign = "left";
- ctx.textBaseline = 'top';
- ctx.font = labelFont;
-
- helpers.each(me.legendItems, function(legendItem, i) {
- var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
- if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) {
- totalHeight += fontSize + (labelOpts.padding);
- lineWidths[lineWidths.length] = me.left;
- }
-
- // Store the hitbox width and height here. Final position will be updated in `draw`
- hitboxes[i] = {
- left: 0,
- top: 0,
- width: width,
- height: fontSize
- };
-
- lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
- }, me);
-
- minSize.height += totalHeight;
-
- } else {
- // TODO vertical
- }
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
- },
- afterFit: noop,
-
- // Shared Methods
- isHorizontal: function() {
- return this.options.position === "top" || this.options.position === "bottom";
- },
-
- // Actualy draw the legend on the canvas
- draw: function() {
- var me = this;
- var opts = me.options;
- var labelOpts = opts.labels;
- var globalDefault = Chart.defaults.global,
- lineDefault = globalDefault.elements.line,
- legendWidth = me.width,
- lineWidths = me.lineWidths;
-
- if (opts.display) {
- var ctx = me.ctx,
- cursor = {
- x: me.left + ((legendWidth - lineWidths[0]) / 2),
- y: me.top + labelOpts.padding,
- line: 0
- },
- itemOrDefault = helpers.getValueOrDefault,
- fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),
- fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
- fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
- fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),
- labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);
-
- // Horizontal
- if (me.isHorizontal()) {
- // Labels
- ctx.textAlign = "left";
- ctx.textBaseline = 'top';
- ctx.lineWidth = 0.5;
- ctx.strokeStyle = fontColor; // for strikethrough effect
- ctx.fillStyle = fontColor; // render in correct colour
- ctx.font = labelFont;
-
- var boxWidth = labelOpts.boxWidth,
- hitboxes = me.legendHitBoxes;
-
- helpers.each(me.legendItems, function(legendItem, i) {
- var textWidth = ctx.measureText(legendItem.text).width,
- width = boxWidth + (fontSize / 2) + textWidth,
- x = cursor.x,
- y = cursor.y;
-
- if (x + width >= legendWidth) {
- y = cursor.y += fontSize + (labelOpts.padding);
- cursor.line++;
- x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
- }
-
- // Set the ctx for the box
- ctx.save();
-
- ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
- ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
- ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);
- ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);
- ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);
- ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);
-
- if (ctx.setLineDash) {
- // IE 9 and 10 do not support line dash
- ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));
- }
-
- // Draw the box
- ctx.strokeRect(x, y, boxWidth, fontSize);
- ctx.fillRect(x, y, boxWidth, fontSize);
-
- ctx.restore();
-
- hitboxes[i].left = x;
- hitboxes[i].top = y;
-
- // Fill the actual label
- ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);
-
- if (legendItem.hidden) {
- // Strikethrough the text if hidden
- ctx.beginPath();
- ctx.lineWidth = 2;
- ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));
- ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));
- ctx.stroke();
- }
-
- cursor.x += width + (labelOpts.padding);
- }, me);
- } else {
-
- }
- }
- },
-
- // Handle an event
- handleEvent: function(e) {
- var me = this;
- var position = helpers.getRelativePosition(e, me.chart.chart),
- x = position.x,
- y = position.y,
- opts = me.options;
-
- if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) {
- // See if we are touching one of the dataset boxes
- var lh = me.legendHitBoxes;
- for (var i = 0; i < lh.length; ++i) {
- var hitBox = lh[i];
-
- if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
- // Touching an element
- if (opts.onClick) {
- opts.onClick.call(me, e, me.legendItems[i]);
- }
- break;
- }
- }
- }
- }
- });
-
- // Register the legend plugin
- Chart.pluginService.register({
- beforeInit: function(chartInstance) {
- var opts = chartInstance.options;
- var legendOpts = opts.legend;
-
- if (legendOpts) {
- chartInstance.legend = new Chart.Legend({
- ctx: chartInstance.chart.ctx,
- options: legendOpts,
- chart: chartInstance
- });
-
- Chart.layoutService.addBox(chartInstance, chartInstance.legend);
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var noop = helpers.noop;\r
+\r
+ Chart.defaults.global.legend = {\r
+\r
+ display: true,\r
+ position: 'top',\r
+ fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)\r
+ reverse: false,\r
+\r
+ // a callback that will handle\r
+ onClick: function(e, legendItem) {\r
+ var index = legendItem.datasetIndex;\r
+ var ci = this.chart;\r
+ var meta = ci.getDatasetMeta(index);\r
+\r
+ // See controller.isDatasetVisible comment\r
+ meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;\r
+\r
+ // We hid a dataset ... rerender the chart\r
+ ci.update();\r
+ },\r
+\r
+ labels: {\r
+ boxWidth: 40,\r
+ padding: 10,\r
+ // Generates labels shown in the legend\r
+ // Valid properties to return:\r
+ // text : text to display\r
+ // fillStyle : fill of coloured box\r
+ // strokeStyle: stroke of coloured box\r
+ // hidden : if this legend item refers to a hidden item\r
+ // lineCap : cap style for line\r
+ // lineDash\r
+ // lineDashOffset :\r
+ // lineJoin :\r
+ // lineWidth :\r
+ generateLabels: function(chart) {\r
+ var data = chart.data;\r
+ return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) {\r
+ return {\r
+ text: dataset.label,\r
+ fillStyle: dataset.backgroundColor,\r
+ hidden: !chart.isDatasetVisible(i),\r
+ lineCap: dataset.borderCapStyle,\r
+ lineDash: dataset.borderDash,\r
+ lineDashOffset: dataset.borderDashOffset,\r
+ lineJoin: dataset.borderJoinStyle,\r
+ lineWidth: dataset.borderWidth,\r
+ strokeStyle: dataset.borderColor,\r
+\r
+ // Below is extra data used for toggling the datasets\r
+ datasetIndex: i\r
+ };\r
+ }, this) : [];\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.Legend = Chart.Element.extend({\r
+\r
+ initialize: function(config) {\r
+ helpers.extend(this, config);\r
+\r
+ // Contains hit boxes for each dataset (in dataset order)\r
+ this.legendHitBoxes = [];\r
+\r
+ // Are we in doughnut mode which has a different data type\r
+ this.doughnutMode = false;\r
+ },\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+ // Any function defined here is inherited by all legend types.\r
+ // Any function can be extended by the legend type\r
+\r
+ beforeUpdate: noop,\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = margins;\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+ // Labels\r
+ this.beforeBuildLabels();\r
+ this.buildLabels();\r
+ this.afterBuildLabels();\r
+\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+ },\r
+ afterUpdate: noop,\r
+\r
+ //\r
+\r
+ beforeSetDimensions: noop,\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+\r
+ // Reset minSize\r
+ this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+ },\r
+ afterSetDimensions: noop,\r
+\r
+ //\r
+\r
+ beforeBuildLabels: noop,\r
+ buildLabels: function() {\r
+ this.legendItems = this.options.labels.generateLabels.call(this, this.chart);\r
+ if(this.options.reverse){\r
+ this.legendItems.reverse();\r
+ }\r
+ },\r
+ afterBuildLabels: noop,\r
+\r
+ //\r
+\r
+ beforeFit: noop,\r
+ fit: function() {\r
+ var opts = this.options;\r
+ var labelOpts = opts.labels;\r
+ var display = opts.display;\r
+\r
+ var ctx = this.ctx;\r
+\r
+ var globalDefault = Chart.defaults.global,\r
+ itemOrDefault = helpers.getValueOrDefault,\r
+ fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),\r
+ fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),\r
+ fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),\r
+ labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);\r
+\r
+ // Reset hit boxes\r
+ var hitboxes = this.legendHitBoxes = [];\r
+\r
+ var minSize = this.minSize;\r
+ var isHorizontal = this.isHorizontal();\r
+\r
+ if (isHorizontal) {\r
+ minSize.width = this.maxWidth; // fill all the width\r
+ minSize.height = display ? 10 : 0;\r
+ } else {\r
+ minSize.width = display ? 10 : 0;\r
+ minSize.height = this.maxHeight; // fill all the height\r
+ }\r
+\r
+ // Increase sizes here\r
+ if (display) {\r
+ if (isHorizontal) {\r
+ // Labels\r
+\r
+ // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one\r
+ var lineWidths = this.lineWidths = [0];\r
+ var totalHeight = this.legendItems.length ? fontSize + (labelOpts.padding) : 0;\r
+\r
+ ctx.textAlign = "left";\r
+ ctx.textBaseline = 'top';\r
+ ctx.font = labelFont;\r
+\r
+ helpers.each(this.legendItems, function(legendItem, i) {\r
+ var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;\r
+ if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= this.width) {\r
+ totalHeight += fontSize + (labelOpts.padding);\r
+ lineWidths[lineWidths.length] = this.left;\r
+ }\r
+\r
+ // Store the hitbox width and height here. Final position will be updated in `draw`\r
+ hitboxes[i] = {\r
+ left: 0,\r
+ top: 0,\r
+ width: width,\r
+ height: fontSize\r
+ };\r
+\r
+ lineWidths[lineWidths.length - 1] += width + labelOpts.padding;\r
+ }, this);\r
+\r
+ minSize.height += totalHeight;\r
+\r
+ } else {\r
+ // TODO vertical\r
+ }\r
+ }\r
+\r
+ this.width = minSize.width;\r
+ this.height = minSize.height;\r
+ },\r
+ afterFit: noop,\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ return this.options.position === "top" || this.options.position === "bottom";\r
+ },\r
+\r
+ // Actualy draw the legend on the canvas\r
+ draw: function() {\r
+ var opts = this.options;\r
+ var labelOpts = opts.labels;\r
+ var globalDefault = Chart.defaults.global,\r
+ lineDefault = globalDefault.elements.line,\r
+ legendWidth = this.width,\r
+ lineWidths = this.lineWidths;\r
+\r
+ if (opts.display) {\r
+ var ctx = this.ctx,\r
+ cursor = {\r
+ x: this.left + ((legendWidth - lineWidths[0]) / 2),\r
+ y: this.top + labelOpts.padding,\r
+ line: 0\r
+ },\r
+ itemOrDefault = helpers.getValueOrDefault,\r
+ fontColor = itemOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor),\r
+ fontSize = itemOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),\r
+ fontStyle = itemOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),\r
+ fontFamily = itemOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily),\r
+ labelFont = helpers.fontString(fontSize, fontStyle, fontFamily);\r
+\r
+ // Horizontal\r
+ if (this.isHorizontal()) {\r
+ // Labels\r
+ ctx.textAlign = "left";\r
+ ctx.textBaseline = 'top';\r
+ ctx.lineWidth = 0.5;\r
+ ctx.strokeStyle = fontColor; // for strikethrough effect\r
+ ctx.fillStyle = fontColor; // render in correct colour\r
+ ctx.font = labelFont;\r
+\r
+ var boxWidth = labelOpts.boxWidth,\r
+ hitboxes = this.legendHitBoxes;\r
+\r
+ helpers.each(this.legendItems, function(legendItem, i) {\r
+ var textWidth = ctx.measureText(legendItem.text).width,\r
+ width = boxWidth + (fontSize / 2) + textWidth,\r
+ x = cursor.x,\r
+ y = cursor.y;\r
+\r
+ if (x + width >= legendWidth) {\r
+ y = cursor.y += fontSize + (labelOpts.padding);\r
+ cursor.line++;\r
+ x = cursor.x = this.left + ((legendWidth - lineWidths[cursor.line]) / 2);\r
+ }\r
+\r
+ // Set the ctx for the box\r
+ ctx.save();\r
+\r
+ ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);\r
+ ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);\r
+ ctx.lineDashOffset = itemOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset);\r
+ ctx.lineJoin = itemOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle);\r
+ ctx.lineWidth = itemOrDefault(legendItem.lineWidth, lineDefault.borderWidth);\r
+ ctx.strokeStyle = itemOrDefault(legendItem.strokeStyle, globalDefault.defaultColor);\r
+\r
+ if (ctx.setLineDash) {\r
+ // IE 9 and 10 do not support line dash\r
+ ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));\r
+ }\r
+\r
+ // Draw the box\r
+ ctx.strokeRect(x, y, boxWidth, fontSize);\r
+ ctx.fillRect(x, y, boxWidth, fontSize);\r
+\r
+ ctx.restore();\r
+\r
+ hitboxes[i].left = x;\r
+ hitboxes[i].top = y;\r
+\r
+ // Fill the actual label\r
+ ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);\r
+\r
+ if (legendItem.hidden) {\r
+ // Strikethrough the text if hidden\r
+ ctx.beginPath();\r
+ ctx.lineWidth = 2;\r
+ ctx.moveTo(boxWidth + (fontSize / 2) + x, y + (fontSize / 2));\r
+ ctx.lineTo(boxWidth + (fontSize / 2) + x + textWidth, y + (fontSize / 2));\r
+ ctx.stroke();\r
+ }\r
+\r
+ cursor.x += width + (labelOpts.padding);\r
+ }, this);\r
+ } else {\r
+\r
+ }\r
+ }\r
+ },\r
+\r
+ // Handle an event\r
+ handleEvent: function(e) {\r
+ var position = helpers.getRelativePosition(e, this.chart.chart),\r
+ x = position.x,\r
+ y = position.y,\r
+ opts = this.options;\r
+\r
+ if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {\r
+ // See if we are touching one of the dataset boxes\r
+ var lh = this.legendHitBoxes;\r
+ for (var i = 0; i < lh.length; ++i) {\r
+ var hitBox = lh[i];\r
+\r
+ if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {\r
+ // Touching an element\r
+ if (opts.onClick) {\r
+ opts.onClick.call(this, e, this.legendItems[i]);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+};\r
},{}],29:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
- var helpers = Chart.helpers;
-
- // Plugins are stored here
- Chart.plugins = [];
- Chart.pluginService = {
- // Register a new plugin
- register: function(plugin) {
- var p = Chart.plugins;
- if (p.indexOf(plugin) === -1) {
- p.push(plugin);
- }
- },
-
- // Remove a registered plugin
- remove: function(plugin) {
- var p = Chart.plugins;
- var idx = p.indexOf(plugin);
- if (idx !== -1) {
- p.splice(idx, 1);
- }
- },
-
- // Iterate over all plugins
- notifyPlugins: function(method, args, scope) {
- helpers.each(Chart.plugins, function(plugin) {
- if (plugin[method] && typeof plugin[method] === 'function') {
- plugin[method].apply(scope, args);
- }
- }, scope);
- }
- };
-
- var noop = helpers.noop;
- Chart.PluginBase = Chart.Element.extend({
- // Plugin methods. All functions are passed the chart instance
-
- // Called at start of chart init
- beforeInit: noop,
-
- // Called at end of chart init
- afterInit: noop,
-
- // Called at start of update
- beforeUpdate: noop,
-
- // Called at end of update
- afterUpdate: noop,
-
- // Called at start of draw
- beforeDraw: noop,
-
- // Called at end of draw
- afterDraw: noop,
-
- // Called during destroy
- destroy: noop
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+ var helpers = Chart.helpers;\r
+\r
+ // Plugins are stored here\r
+ Chart.plugins = [];\r
+ Chart.pluginService = {\r
+ // Register a new plugin\r
+ register: function(plugin) {\r
+ var p = Chart.plugins;\r
+ if (p.indexOf(plugin) === -1) {\r
+ p.push(plugin);\r
+ }\r
+ },\r
+\r
+ // Remove a registered plugin\r
+ remove: function(plugin) {\r
+ var p = Chart.plugins;\r
+ var idx = p.indexOf(plugin);\r
+ if (idx !== -1) {\r
+ p.splice(idx, 1);\r
+ }\r
+ },\r
+\r
+ // Iterate over all plugins\r
+ notifyPlugins: function(method, args, scope) {\r
+ helpers.each(Chart.plugins, function(plugin) {\r
+ if (plugin[method] && typeof plugin[method] === 'function') {\r
+ plugin[method].apply(scope, args);\r
+ }\r
+ }, scope);\r
+ }\r
+ };\r
+\r
+ var noop = helpers.noop;\r
+ Chart.PluginBase = Chart.Element.extend({\r
+ // Plugin methods. All functions are passed the chart instance\r
+\r
+ // Called at start of chart init\r
+ beforeInit: noop,\r
+\r
+ // Called at end of chart init\r
+ afterInit: noop,\r
+\r
+ // Called at start of update\r
+ beforeUpdate: noop,\r
+\r
+ // Called at end of update\r
+ afterUpdate: noop,\r
+\r
+ // Called at start of draw\r
+ beforeDraw: noop,\r
+\r
+ // Called at end of draw\r
+ afterDraw: noop,\r
+\r
+ // Called during destroy\r
+ destroy: noop\r
+ });\r
+};\r
},{}],30:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.scale = {
- display: true,
- position: "left",
-
- // grid line settings
- gridLines: {
- display: true,
- color: "rgba(0, 0, 0, 0.1)",
- lineWidth: 1,
- drawBorder: true,
- drawOnChartArea: true,
- drawTicks: true,
- tickMarkLength: 10,
- zeroLineWidth: 1,
- zeroLineColor: "rgba(0,0,0,0.25)",
- offsetGridLines: false
- },
-
- // scale label
- scaleLabel: {
- // actual label
- labelString: '',
-
- // display property
- display: false
- },
-
- // label settings
- ticks: {
- beginAtZero: false,
- minRotation: 0,
- maxRotation: 50,
- mirror: false,
- padding: 10,
- reverse: false,
- display: true,
- autoSkip: true,
- autoSkipPadding: 0,
- labelOffset: 0,
- // We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
- callback: function(value) {
- return helpers.isArray(value) ? value : '' + value;
- }
- }
- };
-
- Chart.Scale = Chart.Element.extend({
-
- // These methods are ordered by lifecyle. Utilities then follow.
- // Any function defined here is inherited by all scale types.
- // Any function can be extended by the scale type
-
- beforeUpdate: function() {
- helpers.callCallback(this.options.beforeUpdate, [this]);
- },
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = helpers.extend({
- left: 0,
- right: 0,
- top: 0,
- bottom: 0
- }, margins);
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
-
- // Data min/max
- me.beforeDataLimits();
- me.determineDataLimits();
- me.afterDataLimits();
-
- // Ticks
- me.beforeBuildTicks();
- me.buildTicks();
- me.afterBuildTicks();
-
- me.beforeTickToLabelConversion();
- me.convertTicksToLabels();
- me.afterTickToLabelConversion();
-
- // Tick Rotation
- me.beforeCalculateTickRotation();
- me.calculateTickRotation();
- me.afterCalculateTickRotation();
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
-
- },
- afterUpdate: function() {
- helpers.callCallback(this.options.afterUpdate, [this]);
- },
-
- //
-
- beforeSetDimensions: function() {
- helpers.callCallback(this.options.beforeSetDimensions, [this]);
- },
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
- },
- afterSetDimensions: function() {
- helpers.callCallback(this.options.afterSetDimensions, [this]);
- },
-
- // Data limits
- beforeDataLimits: function() {
- helpers.callCallback(this.options.beforeDataLimits, [this]);
- },
- determineDataLimits: helpers.noop,
- afterDataLimits: function() {
- helpers.callCallback(this.options.afterDataLimits, [this]);
- },
-
- //
- beforeBuildTicks: function() {
- helpers.callCallback(this.options.beforeBuildTicks, [this]);
- },
- buildTicks: helpers.noop,
- afterBuildTicks: function() {
- helpers.callCallback(this.options.afterBuildTicks, [this]);
- },
-
- beforeTickToLabelConversion: function() {
- helpers.callCallback(this.options.beforeTickToLabelConversion, [this]);
- },
- convertTicksToLabels: function() {
- var me = this;
- // Convert ticks to strings
- me.ticks = me.ticks.map(function(numericalTick, index, ticks) {
- if (me.options.ticks.userCallback) {
- return me.options.ticks.userCallback(numericalTick, index, ticks);
- }
- return me.options.ticks.callback(numericalTick, index, ticks);
- },
- me);
- },
- afterTickToLabelConversion: function() {
- helpers.callCallback(this.options.afterTickToLabelConversion, [this]);
- },
-
- //
-
- beforeCalculateTickRotation: function() {
- helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);
- },
- calculateTickRotation: function() {
- var me = this;
- var context = me.ctx;
- var globalDefaults = Chart.defaults.global;
- var optionTicks = me.options.ticks;
-
- //Get the width of each grid by calculating the difference
- //between x offsets between 0 and 1.
- var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- context.font = tickLabelFont;
-
- var firstWidth = context.measureText(me.ticks[0]).width;
- var lastWidth = context.measureText(me.ticks[me.ticks.length - 1]).width;
- var firstRotated;
-
- me.labelRotation = optionTicks.minRotation || 0;
- me.paddingRight = 0;
- me.paddingLeft = 0;
-
- if (me.options.display) {
- if (me.isHorizontal()) {
- me.paddingRight = lastWidth / 2 + 3;
- me.paddingLeft = firstWidth / 2 + 3;
-
- if (!me.longestTextCache) {
- me.longestTextCache = {};
- }
- var originalLabelWidth = helpers.longestText(context, tickLabelFont, me.ticks, me.longestTextCache);
- var labelWidth = originalLabelWidth;
- var cosRotation;
- var sinRotation;
-
- // Allow 3 pixels x2 padding either side for label readability
- // only the index matters for a dataset scale, but we want a consistent interface between scales
- var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6;
-
- //Max label rotation can be set or default to 90 - also act as a loop counter
- while (labelWidth > tickWidth && me.labelRotation < optionTicks.maxRotation) {
- cosRotation = Math.cos(helpers.toRadians(me.labelRotation));
- sinRotation = Math.sin(helpers.toRadians(me.labelRotation));
-
- firstRotated = cosRotation * firstWidth;
-
- // We're right aligning the text now.
- if (firstRotated + tickFontSize / 2 > me.yLabelWidth) {
- me.paddingLeft = firstRotated + tickFontSize / 2;
- }
-
- me.paddingRight = tickFontSize / 2;
-
- if (sinRotation * originalLabelWidth > me.maxHeight) {
- // go back one step
- me.labelRotation--;
- break;
- }
-
- me.labelRotation++;
- labelWidth = cosRotation * originalLabelWidth;
- }
- }
- }
-
- if (me.margins) {
- me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
- me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
- }
- },
- afterCalculateTickRotation: function() {
- helpers.callCallback(this.options.afterCalculateTickRotation, [this]);
- },
-
- //
-
- beforeFit: function() {
- helpers.callCallback(this.options.beforeFit, [this]);
- },
- fit: function() {
- var me = this;
- // Reset
- var minSize = me.minSize = {
- width: 0,
- height: 0
- };
-
- var opts = me.options;
- var globalDefaults = Chart.defaults.global;
- var tickOpts = opts.ticks;
- var scaleLabelOpts = opts.scaleLabel;
- var display = opts.display;
- var isHorizontal = me.isHorizontal();
-
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
-
- var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);
- var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
- var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
- var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
-
- var tickMarkLength = opts.gridLines.tickMarkLength;
-
- // Width
- if (isHorizontal) {
- // subtract the margins to line up with the chartArea if we are a full width scale
- minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth;
- } else {
- minSize.width = display ? tickMarkLength : 0;
- }
-
- // height
- if (isHorizontal) {
- minSize.height = display ? tickMarkLength : 0;
- } else {
- minSize.height = me.maxHeight; // fill all the height
- }
-
- // Are we showing a title for the scale?
- if (scaleLabelOpts.display && display) {
- if (isHorizontal) {
- minSize.height += (scaleLabelFontSize * 1.5);
- } else {
- minSize.width += (scaleLabelFontSize * 1.5);
- }
- }
-
- if (tickOpts.display && display) {
- // Don't bother fitting the ticks if we are not showing them
- if (!me.longestTextCache) {
- me.longestTextCache = {};
- }
-
- var largestTextWidth = helpers.longestText(me.ctx, tickLabelFont, me.ticks, me.longestTextCache);
- var tallestLabelHeightInLines = helpers.numberOfLabelLines(me.ticks);
- var lineSpace = tickFontSize * 0.5;
-
- if (isHorizontal) {
- // A horizontal axis is more constrained by the height.
- me.longestLabelWidth = largestTextWidth;
-
- // TODO - improve this calculation
- var labelHeight = (Math.sin(helpers.toRadians(me.labelRotation)) * me.longestLabelWidth) + (tickFontSize * tallestLabelHeightInLines) + (lineSpace * tallestLabelHeightInLines);
-
- minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight);
- me.ctx.font = tickLabelFont;
-
- var firstLabelWidth = me.ctx.measureText(me.ticks[0]).width;
- var lastLabelWidth = me.ctx.measureText(me.ticks[me.ticks.length - 1]).width;
-
- // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated
- // by the font height
- var cosRotation = Math.cos(helpers.toRadians(me.labelRotation));
- var sinRotation = Math.sin(helpers.toRadians(me.labelRotation));
- me.paddingLeft = me.labelRotation !== 0 ? (cosRotation * firstLabelWidth) + 3 : firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges
- me.paddingRight = me.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated
- } else {
- // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first
- var maxLabelWidth = me.maxWidth - minSize.width;
-
- // Account for padding
- var mirror = tickOpts.mirror;
- if (!mirror) {
- largestTextWidth += me.options.ticks.padding;
- } else {
- // If mirrored text is on the inside so don't expand
- largestTextWidth = 0;
- }
-
- if (largestTextWidth < maxLabelWidth) {
- // We don't need all the room
- minSize.width += largestTextWidth;
- } else {
- // Expand to max size
- minSize.width = me.maxWidth;
- }
-
- me.paddingTop = tickFontSize / 2;
- me.paddingBottom = tickFontSize / 2;
- }
- }
-
- if (me.margins) {
- me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0);
- me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0);
- me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0);
- me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0);
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
-
- },
- afterFit: function() {
- helpers.callCallback(this.options.afterFit, [this]);
- },
-
- // Shared Methods
- isHorizontal: function() {
- return this.options.position === "top" || this.options.position === "bottom";
- },
- isFullWidth: function() {
- return (this.options.fullWidth);
- },
-
- // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not
- getRightValue: function getRightValue(rawValue) {
- // Null and undefined values first
- if (rawValue === null || typeof(rawValue) === 'undefined') {
- return NaN;
- }
- // isNaN(object) returns true, so make sure NaN is checking for a number
- if (typeof(rawValue) === 'number' && isNaN(rawValue)) {
- return NaN;
- }
- // If it is in fact an object, dive in one more level
- if (typeof(rawValue) === "object") {
- if ((rawValue instanceof Date) || (rawValue.isValid)) {
- return rawValue;
- } else {
- return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
- }
- }
-
- // Value is good, return it
- return rawValue;
- },
-
- // Used to get the value to display in the tooltip for the data at the given index
- // function getLabelForIndex(index, datasetIndex)
- getLabelForIndex: helpers.noop,
-
- // Used to get data value locations. Value can either be an index or a numerical value
- getPixelForValue: helpers.noop,
-
- // Used to get the data value from a given pixel. This is the inverse of getPixelForValue
- getValueForPixel: helpers.noop,
-
- // Used for tick location, should
- getPixelForTick: function(index, includeOffset) {
- var me = this;
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var tickWidth = innerWidth / Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
- var pixel = (tickWidth * index) + me.paddingLeft;
-
- if (includeOffset) {
- pixel += tickWidth / 2;
- }
-
- var finalVal = me.left + Math.round(pixel);
- finalVal += me.isFullWidth() ? me.margins.left : 0;
- return finalVal;
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- return me.top + (index * (innerHeight / (me.ticks.length - 1)));
- }
- },
-
- // Utility for getting the pixel location of a percentage of scale
- getPixelForDecimal: function(decimal /*, includeOffset*/ ) {
- var me = this;
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueOffset = (innerWidth * decimal) + me.paddingLeft;
-
- var finalVal = me.left + Math.round(valueOffset);
- finalVal += me.isFullWidth() ? me.margins.left : 0;
- return finalVal;
- } else {
- return me.top + (decimal * me.height);
- }
- },
-
- getBasePixel: function() {
- var me = this;
- var min = me.min;
- var max = me.max;
-
- return me.getPixelForValue(
- me.beginAtZero? 0:
- min < 0 && max < 0? max :
- min > 0 && max > 0? min :
- 0);
- },
-
- // Actualy draw the scale on the canvas
- // @param {rectangle} chartArea : the area of the chart to draw full grid lines on
- draw: function(chartArea) {
- var me = this;
- var options = me.options;
- if (!options.display) {
- return;
- }
-
- var context = me.ctx;
- var globalDefaults = Chart.defaults.global;
- var optionTicks = options.ticks;
- var gridLines = options.gridLines;
- var scaleLabel = options.scaleLabel;
-
- var setContextLineSettings;
- var isRotated = me.labelRotation !== 0;
- var skipRatio;
- var scaleLabelX;
- var scaleLabelY;
- var useAutoskipper = optionTicks.autoSkip;
-
- // figure out the maximum number of gridlines to show
- var maxTicks;
- if (optionTicks.maxTicksLimit) {
- maxTicks = optionTicks.maxTicksLimit;
- }
-
- var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);
- var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- var tl = gridLines.tickMarkLength;
-
- var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);
- var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);
- var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabel.fontStyle, globalDefaults.defaultFontStyle);
- var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabel.fontFamily, globalDefaults.defaultFontFamily);
- var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
-
- var labelRotationRadians = helpers.toRadians(me.labelRotation);
- var cosRotation = Math.cos(labelRotationRadians);
- var sinRotation = Math.sin(labelRotationRadians);
- var longestRotatedLabel = me.longestLabelWidth * cosRotation;
- var rotatedLabelHeight = tickFontSize * sinRotation;
-
- // Make sure we draw text in the correct color and font
- context.fillStyle = tickFontColor;
-
- if (me.isHorizontal()) {
- setContextLineSettings = true;
- var yTickStart = options.position === "bottom" ? me.top : me.bottom - tl;
- var yTickEnd = options.position === "bottom" ? me.top + tl : me.bottom;
- skipRatio = false;
-
- // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation
- // See #2584
- if (isRotated) {
- longestRotatedLabel /= 2;
- }
-
- if ((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length > (me.width - (me.paddingLeft + me.paddingRight))) {
- skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length) / (me.width - (me.paddingLeft + me.paddingRight)));
- }
-
- // if they defined a max number of optionTicks,
- // increase skipRatio until that number is met
- if (maxTicks && me.ticks.length > maxTicks) {
- while (!skipRatio || me.ticks.length / (skipRatio || 1) > maxTicks) {
- if (!skipRatio) {
- skipRatio = 1;
- }
- skipRatio += 1;
- }
- }
-
- if (!useAutoskipper) {
- skipRatio = false;
- }
-
- helpers.each(me.ticks, function (label, index) {
- // Blank optionTicks
- var isLastTick = me.ticks.length === index + 1;
-
- // Since we always show the last tick,we need may need to hide the last shown one before
- var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= me.ticks.length);
- if (shouldSkip && !isLastTick || (label === undefined || label === null)) {
- return;
- }
- var xLineValue = me.getPixelForTick(index); // xvalues for grid lines
- var xLabelValue = me.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
-
- if (gridLines.display) {
- if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) {
- // Draw the first index specially
- context.lineWidth = gridLines.zeroLineWidth;
- context.strokeStyle = gridLines.zeroLineColor;
- setContextLineSettings = true; // reset next time
- } else if (setContextLineSettings) {
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- setContextLineSettings = false;
- }
-
- xLineValue += helpers.aliasPixel(context.lineWidth);
-
- // Draw the label area
- context.beginPath();
-
- if (gridLines.drawTicks) {
- context.moveTo(xLineValue, yTickStart);
- context.lineTo(xLineValue, yTickEnd);
- }
-
- // Draw the chart area
- if (gridLines.drawOnChartArea) {
- context.moveTo(xLineValue, chartArea.top);
- context.lineTo(xLineValue, chartArea.bottom);
- }
-
- // Need to stroke in the loop because we are potentially changing line widths & colours
- context.stroke();
- }
-
- if (optionTicks.display) {
- context.save();
- context.translate(xLabelValue + optionTicks.labelOffset, (isRotated) ? me.top + 12 : options.position === "top" ? me.bottom - tl : me.top + tl);
- context.rotate(labelRotationRadians * -1);
- context.font = tickLabelFont;
- context.textAlign = (isRotated) ? "right" : "center";
- context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top";
-
- if (helpers.isArray(label)) {
- for (var i = 0, y = 0; i < label.length; ++i) {
- // We just make sure the multiline element is a string here..
- context.fillText('' + label[i], 0, y);
- // apply same lineSpacing as calculated @ L#320
- y += (tickFontSize * 1.5);
- }
- } else {
- context.fillText(label, 0, 0);
- }
-
- context.restore();
- }
- }, me);
-
- if (scaleLabel.display) {
- // Draw the scale label
- context.textAlign = "center";
- context.textBaseline = 'middle';
- context.fillStyle = scaleLabelFontColor; // render in correct colour
- context.font = scaleLabelFont;
-
- scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width
- scaleLabelY = options.position === 'bottom' ? me.bottom - (scaleLabelFontSize / 2) : me.top + (scaleLabelFontSize / 2);
-
- context.fillText(scaleLabel.labelString, scaleLabelX, scaleLabelY);
- }
-
- } else {
- setContextLineSettings = true;
- var xTickStart = options.position === "right" ? me.left : me.right - 5;
- var xTickEnd = options.position === "right" ? me.left + 5 : me.right;
-
- helpers.each(me.ticks, function (label, index) {
- // If the callback returned a null or undefined value, do not draw this line
- if (label === undefined || label === null) {
- return;
- }
-
- var yLineValue = me.getPixelForTick(index); // xvalues for grid lines
-
- if (gridLines.display) {
- if (index === (typeof me.zeroLineIndex !== 'undefined' ? me.zeroLineIndex : 0)) {
- // Draw the first index specially
- context.lineWidth = gridLines.zeroLineWidth;
- context.strokeStyle = gridLines.zeroLineColor;
- setContextLineSettings = true; // reset next time
- } else if (setContextLineSettings) {
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- setContextLineSettings = false;
- }
-
- yLineValue += helpers.aliasPixel(context.lineWidth);
-
- // Draw the label area
- context.beginPath();
-
- if (gridLines.drawTicks) {
- context.moveTo(xTickStart, yLineValue);
- context.lineTo(xTickEnd, yLineValue);
- }
-
- // Draw the chart area
- if (gridLines.drawOnChartArea) {
- context.moveTo(chartArea.left, yLineValue);
- context.lineTo(chartArea.right, yLineValue);
- }
-
- // Need to stroke in the loop because we are potentially changing line widths & colours
- context.stroke();
- }
-
- if (optionTicks.display) {
- var xLabelValue;
- var yLabelValue = me.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)
-
- context.save();
-
- if (options.position === "left") {
- if (optionTicks.mirror) {
- xLabelValue = me.right + optionTicks.padding;
- context.textAlign = "left";
- } else {
- xLabelValue = me.right - optionTicks.padding;
- context.textAlign = "right";
- }
- } else {
- // right side
- if (optionTicks.mirror) {
- xLabelValue = me.left - optionTicks.padding;
- context.textAlign = "right";
- } else {
- xLabelValue = me.left + optionTicks.padding;
- context.textAlign = "left";
- }
- }
-
- context.translate(xLabelValue, yLabelValue + optionTicks.labelOffset);
- context.rotate(labelRotationRadians * -1);
- context.font = tickLabelFont;
- context.textBaseline = "middle";
- context.fillText(label, 0, 0);
- context.restore();
- }
- }, me);
-
- if (scaleLabel.display) {
- // Draw the scale label
- scaleLabelX = options.position === 'left' ? me.left + (scaleLabelFontSize / 2) : me.right - (scaleLabelFontSize / 2);
- scaleLabelY = me.top + ((me.bottom - me.top) / 2);
- var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;
-
- context.save();
- context.translate(scaleLabelX, scaleLabelY);
- context.rotate(rotation);
- context.textAlign = "center";
- context.fillStyle = scaleLabelFontColor; // render in correct colour
- context.font = scaleLabelFont;
- context.textBaseline = 'middle';
- context.fillText(scaleLabel.labelString, 0, 0);
- context.restore();
- }
- }
-
- if (gridLines.drawBorder) {
- // Draw the line at the edge of the axis
- context.lineWidth = gridLines.lineWidth;
- context.strokeStyle = gridLines.color;
- var x1 = me.left,
- x2 = me.right,
- y1 = me.top,
- y2 = me.bottom;
-
- var aliasPixel = helpers.aliasPixel(context.lineWidth);
- if (me.isHorizontal()) {
- y1 = y2 = options.position === 'top' ? me.bottom : me.top;
- y1 += aliasPixel;
- y2 += aliasPixel;
- } else {
- x1 = x2 = options.position === 'left' ? me.right : me.left;
- x1 += aliasPixel;
- x2 += aliasPixel;
- }
-
- context.beginPath();
- context.moveTo(x1, y1);
- context.lineTo(x2, y2);
- context.stroke();
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.scale = {\r
+ display: true,\r
+ position: "left",\r
+\r
+ // grid line settings\r
+ gridLines: {\r
+ display: true,\r
+ color: "rgba(0, 0, 0, 0.1)",\r
+ lineWidth: 1,\r
+ drawBorder: true,\r
+ drawOnChartArea: true,\r
+ drawTicks: true,\r
+ tickMarkLength: 10,\r
+ zeroLineWidth: 1,\r
+ zeroLineColor: "rgba(0,0,0,0.25)",\r
+ offsetGridLines: false\r
+ },\r
+\r
+ // scale label\r
+ scaleLabel: {\r
+ // actual label\r
+ labelString: '',\r
+\r
+ // display property\r
+ display: false\r
+ },\r
+\r
+ // label settings\r
+ ticks: {\r
+ beginAtZero: false,\r
+ minRotation: 0,\r
+ maxRotation: 50,\r
+ mirror: false,\r
+ padding: 10,\r
+ reverse: false,\r
+ display: true,\r
+ autoSkip: true,\r
+ autoSkipPadding: 0,\r
+ labelOffset: 0,\r
+ callback: function(value) {\r
+ return '' + value;\r
+ }\r
+ }\r
+ };\r
+\r
+ Chart.Scale = Chart.Element.extend({\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+ // Any function defined here is inherited by all scale types.\r
+ // Any function can be extended by the scale type\r
+\r
+ beforeUpdate: function() {\r
+ helpers.callCallback(this.options.beforeUpdate, [this]);\r
+ },\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = helpers.extend({\r
+ left: 0,\r
+ right: 0,\r
+ top: 0,\r
+ bottom: 0\r
+ }, margins);\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+\r
+ // Data min/max\r
+ this.beforeDataLimits();\r
+ this.determineDataLimits();\r
+ this.afterDataLimits();\r
+\r
+ // Ticks\r
+ this.beforeBuildTicks();\r
+ this.buildTicks();\r
+ this.afterBuildTicks();\r
+\r
+ this.beforeTickToLabelConversion();\r
+ this.convertTicksToLabels();\r
+ this.afterTickToLabelConversion();\r
+\r
+ // Tick Rotation\r
+ this.beforeCalculateTickRotation();\r
+ this.calculateTickRotation();\r
+ this.afterCalculateTickRotation();\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+\r
+ },\r
+ afterUpdate: function() {\r
+ helpers.callCallback(this.options.afterUpdate, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeSetDimensions: function() {\r
+ helpers.callCallback(this.options.beforeSetDimensions, [this]);\r
+ },\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+ },\r
+ afterSetDimensions: function() {\r
+ helpers.callCallback(this.options.afterSetDimensions, [this]);\r
+ },\r
+\r
+ // Data limits\r
+ beforeDataLimits: function() {\r
+ helpers.callCallback(this.options.beforeDataLimits, [this]);\r
+ },\r
+ determineDataLimits: helpers.noop,\r
+ afterDataLimits: function() {\r
+ helpers.callCallback(this.options.afterDataLimits, [this]);\r
+ },\r
+\r
+ //\r
+ beforeBuildTicks: function() {\r
+ helpers.callCallback(this.options.beforeBuildTicks, [this]);\r
+ },\r
+ buildTicks: helpers.noop,\r
+ afterBuildTicks: function() {\r
+ helpers.callCallback(this.options.afterBuildTicks, [this]);\r
+ },\r
+\r
+ beforeTickToLabelConversion: function() {\r
+ helpers.callCallback(this.options.beforeTickToLabelConversion, [this]);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ // Convert ticks to strings\r
+ this.ticks = this.ticks.map(function(numericalTick, index, ticks) {\r
+ if (this.options.ticks.userCallback) {\r
+ return this.options.ticks.userCallback(numericalTick, index, ticks);\r
+ }\r
+ return this.options.ticks.callback(numericalTick, index, ticks);\r
+ },\r
+ this);\r
+ },\r
+ afterTickToLabelConversion: function() {\r
+ helpers.callCallback(this.options.afterTickToLabelConversion, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeCalculateTickRotation: function() {\r
+ helpers.callCallback(this.options.beforeCalculateTickRotation, [this]);\r
+ },\r
+ calculateTickRotation: function() {\r
+ var context = this.ctx;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var optionTicks = this.options.ticks;\r
+\r
+ //Get the width of each grid by calculating the difference\r
+ //between x offsets between 0 and 1.\r
+ var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ context.font = tickLabelFont;\r
+\r
+ var firstWidth = context.measureText(this.ticks[0]).width;\r
+ var lastWidth = context.measureText(this.ticks[this.ticks.length - 1]).width;\r
+ var firstRotated;\r
+\r
+ this.labelRotation = optionTicks.minRotation || 0;\r
+ this.paddingRight = 0;\r
+ this.paddingLeft = 0;\r
+\r
+ if (this.options.display) {\r
+ if (this.isHorizontal()) {\r
+ this.paddingRight = lastWidth / 2 + 3;\r
+ this.paddingLeft = firstWidth / 2 + 3;\r
+\r
+ if (!this.longestTextCache) {\r
+ this.longestTextCache = {};\r
+ }\r
+ var originalLabelWidth = helpers.longestText(context, tickLabelFont, this.ticks, this.longestTextCache);\r
+ var labelWidth = originalLabelWidth;\r
+ var cosRotation;\r
+ var sinRotation;\r
+\r
+ // Allow 3 pixels x2 padding either side for label readability\r
+ // only the index matters for a dataset scale, but we want a consistent interface between scales\r
+ var tickWidth = this.getPixelForTick(1) - this.getPixelForTick(0) - 6;\r
+\r
+ //Max label rotation can be set or default to 90 - also act as a loop counter\r
+ while (labelWidth > tickWidth && this.labelRotation < optionTicks.maxRotation) {\r
+ cosRotation = Math.cos(helpers.toRadians(this.labelRotation));\r
+ sinRotation = Math.sin(helpers.toRadians(this.labelRotation));\r
+\r
+ firstRotated = cosRotation * firstWidth;\r
+\r
+ // We're right aligning the text now.\r
+ if (firstRotated + tickFontSize / 2 > this.yLabelWidth) {\r
+ this.paddingLeft = firstRotated + tickFontSize / 2;\r
+ }\r
+\r
+ this.paddingRight = tickFontSize / 2;\r
+\r
+ if (sinRotation * originalLabelWidth > this.maxHeight) {\r
+ // go back one step\r
+ this.labelRotation--;\r
+ break;\r
+ }\r
+\r
+ this.labelRotation++;\r
+ labelWidth = cosRotation * originalLabelWidth;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (this.margins) {\r
+ this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);\r
+ this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);\r
+ }\r
+ },\r
+ afterCalculateTickRotation: function() {\r
+ helpers.callCallback(this.options.afterCalculateTickRotation, [this]);\r
+ },\r
+\r
+ //\r
+\r
+ beforeFit: function() {\r
+ helpers.callCallback(this.options.beforeFit, [this]);\r
+ },\r
+ fit: function() {\r
+ // Reset\r
+ var minSize = this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+\r
+ var opts = this.options;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var tickOpts = opts.ticks;\r
+ var scaleLabelOpts = opts.scaleLabel;\r
+ var display = opts.display;\r
+ var isHorizontal = this.isHorizontal();\r
+\r
+ var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+\r
+ var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);\r
+ var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);\r
+ var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);\r
+ var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);\r
+\r
+ var tickMarkLength = opts.gridLines.tickMarkLength;\r
+\r
+ // Width\r
+ if (isHorizontal) {\r
+ // subtract the margins to line up with the chartArea if we are a full width scale\r
+ minSize.width = this.isFullWidth() ? this.maxWidth - this.margins.left - this.margins.right : this.maxWidth;\r
+ } else {\r
+ minSize.width = display ? tickMarkLength : 0;\r
+ }\r
+\r
+ // height\r
+ if (isHorizontal) {\r
+ minSize.height = display ? tickMarkLength : 0;\r
+ } else {\r
+ minSize.height = this.maxHeight; // fill all the height\r
+ }\r
+\r
+ // Are we showing a title for the scale?\r
+ if (scaleLabelOpts.display && display) {\r
+ if (isHorizontal) {\r
+ minSize.height += (scaleLabelFontSize * 1.5);\r
+ } else {\r
+ minSize.width += (scaleLabelFontSize * 1.5);\r
+ }\r
+ }\r
+\r
+ if (tickOpts.display && display) {\r
+ // Don't bother fitting the ticks if we are not showing them\r
+ if (!this.longestTextCache) {\r
+ this.longestTextCache = {};\r
+ }\r
+\r
+ var largestTextWidth = helpers.longestText(this.ctx, tickLabelFont, this.ticks, this.longestTextCache);\r
+\r
+ if (isHorizontal) {\r
+ // A horizontal axis is more constrained by the height.\r
+ this.longestLabelWidth = largestTextWidth;\r
+\r
+ // TODO - improve this calculation\r
+ var labelHeight = (Math.sin(helpers.toRadians(this.labelRotation)) * this.longestLabelWidth) + 1.5 * tickFontSize;\r
+\r
+ minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight);\r
+ this.ctx.font = tickLabelFont;\r
+\r
+ var firstLabelWidth = this.ctx.measureText(this.ticks[0]).width;\r
+ var lastLabelWidth = this.ctx.measureText(this.ticks[this.ticks.length - 1]).width;\r
+\r
+ // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned which means that the right padding is dominated\r
+ // by the font height\r
+ var cosRotation = Math.cos(helpers.toRadians(this.labelRotation));\r
+ var sinRotation = Math.sin(helpers.toRadians(this.labelRotation));\r
+ this.paddingLeft = this.labelRotation !== 0 ? (cosRotation * firstLabelWidth) + 3 : firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges\r
+ this.paddingRight = this.labelRotation !== 0 ? (sinRotation * (tickFontSize / 2)) + 3 : lastLabelWidth / 2 + 3; // when rotated\r
+ } else {\r
+ // A vertical axis is more constrained by the width. Labels are the dominant factor here, so get that length first\r
+ var maxLabelWidth = this.maxWidth - minSize.width;\r
+\r
+ // Account for padding\r
+ var mirror = tickOpts.mirror;\r
+ if (!mirror) {\r
+ largestTextWidth += this.options.ticks.padding;\r
+ } else {\r
+ // If mirrored text is on the inside so don't expand\r
+ largestTextWidth = 0;\r
+ }\r
+\r
+ if (largestTextWidth < maxLabelWidth) {\r
+ // We don't need all the room\r
+ minSize.width += largestTextWidth;\r
+ } else {\r
+ // Expand to max size\r
+ minSize.width = this.maxWidth;\r
+ }\r
+\r
+ this.paddingTop = tickFontSize / 2;\r
+ this.paddingBottom = tickFontSize / 2;\r
+ }\r
+ }\r
+\r
+ if (this.margins) {\r
+ this.paddingLeft = Math.max(this.paddingLeft - this.margins.left, 0);\r
+ this.paddingTop = Math.max(this.paddingTop - this.margins.top, 0);\r
+ this.paddingRight = Math.max(this.paddingRight - this.margins.right, 0);\r
+ this.paddingBottom = Math.max(this.paddingBottom - this.margins.bottom, 0);\r
+ }\r
+\r
+ this.width = minSize.width;\r
+ this.height = minSize.height;\r
+\r
+ },\r
+ afterFit: function() {\r
+ helpers.callCallback(this.options.afterFit, [this]);\r
+ },\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ return this.options.position === "top" || this.options.position === "bottom";\r
+ },\r
+ isFullWidth: function() {\r
+ return (this.options.fullWidth);\r
+ },\r
+\r
+ // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not\r
+ getRightValue: function getRightValue(rawValue) {\r
+ // Null and undefined values first\r
+ if (rawValue === null || typeof(rawValue) === 'undefined') {\r
+ return NaN;\r
+ }\r
+ // isNaN(object) returns true, so make sure NaN is checking for a number\r
+ if (typeof(rawValue) === 'number' && isNaN(rawValue)) {\r
+ return NaN;\r
+ }\r
+ // If it is in fact an object, dive in one more level\r
+ if (typeof(rawValue) === "object") {\r
+ if ((rawValue instanceof Date) || (rawValue.isValid)) {\r
+ return rawValue;\r
+ } else {\r
+ return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);\r
+ }\r
+ }\r
+\r
+ // Value is good, return it\r
+ return rawValue;\r
+ },\r
+\r
+ // Used to get the value to display in the tooltip for the data at the given index\r
+ // function getLabelForIndex(index, datasetIndex)\r
+ getLabelForIndex: helpers.noop,\r
+\r
+ // Used to get data value locations. Value can either be an index or a numerical value\r
+ getPixelForValue: helpers.noop,\r
+\r
+ // Used to get the data value from a given pixel. This is the inverse of getPixelForValue\r
+ getValueForPixel: helpers.noop,\r
+\r
+ // Used for tick location, should\r
+ getPixelForTick: function(index, includeOffset) {\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var tickWidth = innerWidth / Math.max((this.ticks.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+ var pixel = (tickWidth * index) + this.paddingLeft;\r
+\r
+ if (includeOffset) {\r
+ pixel += tickWidth / 2;\r
+ }\r
+\r
+ var finalVal = this.left + Math.round(pixel);\r
+ finalVal += this.isFullWidth() ? this.margins.left : 0;\r
+ return finalVal;\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ return this.top + (index * (innerHeight / (this.ticks.length - 1)));\r
+ }\r
+ },\r
+\r
+ // Utility for getting the pixel location of a percentage of scale\r
+ getPixelForDecimal: function(decimal /*, includeOffset*/ ) {\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueOffset = (innerWidth * decimal) + this.paddingLeft;\r
+\r
+ var finalVal = this.left + Math.round(valueOffset);\r
+ finalVal += this.isFullWidth() ? this.margins.left : 0;\r
+ return finalVal;\r
+ } else {\r
+ return this.top + (decimal * this.height);\r
+ }\r
+ },\r
+\r
+ getBasePixel: function() {\r
+ var me = this;\r
+ var min = me.min;\r
+ var max = me.max;\r
+\r
+ return me.getPixelForValue(\r
+ me.beginAtZero? 0:\r
+ min < 0 && max < 0? max :\r
+ min > 0 && max > 0? min :\r
+ 0);\r
+ },\r
+\r
+ // Actualy draw the scale on the canvas\r
+ // @param {rectangle} chartArea : the area of the chart to draw full grid lines on\r
+ draw: function(chartArea) {\r
+ var options = this.options;\r
+ if (!options.display) {\r
+ return;\r
+ }\r
+\r
+ var context = this.ctx;\r
+ var globalDefaults = Chart.defaults.global;\r
+ var optionTicks = options.ticks;\r
+ var gridLines = options.gridLines;\r
+ var scaleLabel = options.scaleLabel;\r
+\r
+ var setContextLineSettings;\r
+ var isRotated = this.labelRotation !== 0;\r
+ var skipRatio;\r
+ var scaleLabelX;\r
+ var scaleLabelY;\r
+ var useAutoskipper = optionTicks.autoSkip;\r
+\r
+ // figure out the maximum number of gridlines to show\r
+ var maxTicks;\r
+ if (optionTicks.maxTicksLimit) {\r
+ maxTicks = optionTicks.maxTicksLimit;\r
+ }\r
+\r
+ var tickFontColor = helpers.getValueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor);\r
+ var tickFontSize = helpers.getValueOrDefault(optionTicks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(optionTicks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(optionTicks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ var tl = gridLines.tickMarkLength;\r
+\r
+ var scaleLabelFontColor = helpers.getValueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor);\r
+ var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabel.fontSize, globalDefaults.defaultFontSize);\r
+ var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabel.fontStyle, globalDefaults.defaultFontStyle);\r
+ var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabel.fontFamily, globalDefaults.defaultFontFamily);\r
+ var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);\r
+\r
+ var labelRotationRadians = helpers.toRadians(this.labelRotation);\r
+ var cosRotation = Math.cos(labelRotationRadians);\r
+ var sinRotation = Math.sin(labelRotationRadians);\r
+ var longestRotatedLabel = this.longestLabelWidth * cosRotation;\r
+ var rotatedLabelHeight = tickFontSize * sinRotation;\r
+\r
+ // Make sure we draw text in the correct color and font\r
+ context.fillStyle = tickFontColor;\r
+\r
+ if (this.isHorizontal()) {\r
+ setContextLineSettings = true;\r
+ var yTickStart = options.position === "bottom" ? this.top : this.bottom - tl;\r
+ var yTickEnd = options.position === "bottom" ? this.top + tl : this.bottom;\r
+ skipRatio = false;\r
+\r
+ // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation\r
+ // See #2584\r
+ if (isRotated) {\r
+ longestRotatedLabel /= 2;\r
+ }\r
+\r
+ if ((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length > (this.width - (this.paddingLeft + this.paddingRight))) {\r
+ skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * this.ticks.length) / (this.width - (this.paddingLeft + this.paddingRight)));\r
+ }\r
+\r
+ // if they defined a max number of optionTicks,\r
+ // increase skipRatio until that number is met\r
+ if (maxTicks && this.ticks.length > maxTicks) {\r
+ while (!skipRatio || this.ticks.length / (skipRatio || 1) > maxTicks) {\r
+ if (!skipRatio) {\r
+ skipRatio = 1;\r
+ }\r
+ skipRatio += 1;\r
+ }\r
+ }\r
+\r
+ if (!useAutoskipper) {\r
+ skipRatio = false;\r
+ }\r
+\r
+ helpers.each(this.ticks, function (label, index) {\r
+ // Blank optionTicks\r
+ var isLastTick = this.ticks.length === index + 1;\r
+\r
+ // Since we always show the last tick,we need may need to hide the last shown one before\r
+ var shouldSkip = (skipRatio > 1 && index % skipRatio > 0) || (index % skipRatio === 0 && index + skipRatio >= this.ticks.length);\r
+ if (shouldSkip && !isLastTick || (label === undefined || label === null)) {\r
+ return;\r
+ }\r
+ var xLineValue = this.getPixelForTick(index); // xvalues for grid lines\r
+ var xLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)\r
+\r
+ if (gridLines.display) {\r
+ if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {\r
+ // Draw the first index specially\r
+ context.lineWidth = gridLines.zeroLineWidth;\r
+ context.strokeStyle = gridLines.zeroLineColor;\r
+ setContextLineSettings = true; // reset next time\r
+ } else if (setContextLineSettings) {\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ setContextLineSettings = false;\r
+ }\r
+\r
+ xLineValue += helpers.aliasPixel(context.lineWidth);\r
+\r
+ // Draw the label area\r
+ context.beginPath();\r
+\r
+ if (gridLines.drawTicks) {\r
+ context.moveTo(xLineValue, yTickStart);\r
+ context.lineTo(xLineValue, yTickEnd);\r
+ }\r
+\r
+ // Draw the chart area\r
+ if (gridLines.drawOnChartArea) {\r
+ context.moveTo(xLineValue, chartArea.top);\r
+ context.lineTo(xLineValue, chartArea.bottom);\r
+ }\r
+\r
+ // Need to stroke in the loop because we are potentially changing line widths & colours\r
+ context.stroke();\r
+ }\r
+\r
+ if (optionTicks.display) {\r
+ context.save();\r
+ context.translate(xLabelValue + optionTicks.labelOffset, (isRotated) ? this.top + 12 : options.position === "top" ? this.bottom - tl : this.top + tl);\r
+ context.rotate(labelRotationRadians * -1);\r
+ context.font = tickLabelFont;\r
+ context.textAlign = (isRotated) ? "right" : "center";\r
+ context.textBaseline = (isRotated) ? "middle" : options.position === "top" ? "bottom" : "top";\r
+ context.fillText(label, 0, 0);\r
+ context.restore();\r
+ }\r
+ }, this);\r
+\r
+ if (scaleLabel.display) {\r
+ // Draw the scale label\r
+ context.textAlign = "center";\r
+ context.textBaseline = 'middle';\r
+ context.fillStyle = scaleLabelFontColor; // render in correct colour\r
+ context.font = scaleLabelFont;\r
+\r
+ scaleLabelX = this.left + ((this.right - this.left) / 2); // midpoint of the width\r
+ scaleLabelY = options.position === 'bottom' ? this.bottom - (scaleLabelFontSize / 2) : this.top + (scaleLabelFontSize / 2);\r
+\r
+ context.fillText(scaleLabel.labelString, scaleLabelX, scaleLabelY);\r
+ }\r
+\r
+ } else {\r
+ setContextLineSettings = true;\r
+ var xTickStart = options.position === "right" ? this.left : this.right - 5;\r
+ var xTickEnd = options.position === "right" ? this.left + 5 : this.right;\r
+\r
+ helpers.each(this.ticks, function (label, index) {\r
+ // If the callback returned a null or undefined value, do not draw this line\r
+ if (label === undefined || label === null) {\r
+ return;\r
+ }\r
+\r
+ var yLineValue = this.getPixelForTick(index); // xvalues for grid lines\r
+\r
+ if (gridLines.display) {\r
+ if (index === (typeof this.zeroLineIndex !== 'undefined' ? this.zeroLineIndex : 0)) {\r
+ // Draw the first index specially\r
+ context.lineWidth = gridLines.zeroLineWidth;\r
+ context.strokeStyle = gridLines.zeroLineColor;\r
+ setContextLineSettings = true; // reset next time\r
+ } else if (setContextLineSettings) {\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ setContextLineSettings = false;\r
+ }\r
+\r
+ yLineValue += helpers.aliasPixel(context.lineWidth);\r
+\r
+ // Draw the label area\r
+ context.beginPath();\r
+\r
+ if (gridLines.drawTicks) {\r
+ context.moveTo(xTickStart, yLineValue);\r
+ context.lineTo(xTickEnd, yLineValue);\r
+ }\r
+\r
+ // Draw the chart area\r
+ if (gridLines.drawOnChartArea) {\r
+ context.moveTo(chartArea.left, yLineValue);\r
+ context.lineTo(chartArea.right, yLineValue);\r
+ }\r
+\r
+ // Need to stroke in the loop because we are potentially changing line widths & colours\r
+ context.stroke();\r
+ }\r
+\r
+ if (optionTicks.display) {\r
+ var xLabelValue;\r
+ var yLabelValue = this.getPixelForTick(index, gridLines.offsetGridLines); // x values for optionTicks (need to consider offsetLabel option)\r
+\r
+ context.save();\r
+\r
+ if (options.position === "left") {\r
+ if (optionTicks.mirror) {\r
+ xLabelValue = this.right + optionTicks.padding;\r
+ context.textAlign = "left";\r
+ } else {\r
+ xLabelValue = this.right - optionTicks.padding;\r
+ context.textAlign = "right";\r
+ }\r
+ } else {\r
+ // right side\r
+ if (optionTicks.mirror) {\r
+ xLabelValue = this.left - optionTicks.padding;\r
+ context.textAlign = "right";\r
+ } else {\r
+ xLabelValue = this.left + optionTicks.padding;\r
+ context.textAlign = "left";\r
+ }\r
+ }\r
+\r
+ context.translate(xLabelValue, yLabelValue + optionTicks.labelOffset);\r
+ context.rotate(labelRotationRadians * -1);\r
+ context.font = tickLabelFont;\r
+ context.textBaseline = "middle";\r
+ context.fillText(label, 0, 0);\r
+ context.restore();\r
+ }\r
+ }, this);\r
+\r
+ if (scaleLabel.display) {\r
+ // Draw the scale label\r
+ scaleLabelX = options.position === 'left' ? this.left + (scaleLabelFontSize / 2) : this.right - (scaleLabelFontSize / 2);\r
+ scaleLabelY = this.top + ((this.bottom - this.top) / 2);\r
+ var rotation = options.position === 'left' ? -0.5 * Math.PI : 0.5 * Math.PI;\r
+\r
+ context.save();\r
+ context.translate(scaleLabelX, scaleLabelY);\r
+ context.rotate(rotation);\r
+ context.textAlign = "center";\r
+ context.fillStyle = scaleLabelFontColor; // render in correct colour\r
+ context.font = scaleLabelFont;\r
+ context.textBaseline = 'middle';\r
+ context.fillText(scaleLabel.labelString, 0, 0);\r
+ context.restore();\r
+ }\r
+ }\r
+\r
+ if (gridLines.drawBorder) {\r
+ // Draw the line at the edge of the axis\r
+ context.lineWidth = gridLines.lineWidth;\r
+ context.strokeStyle = gridLines.color;\r
+ var x1 = this.left,\r
+ x2 = this.right,\r
+ y1 = this.top,\r
+ y2 = this.bottom;\r
+\r
+ var aliasPixel = helpers.aliasPixel(context.lineWidth);\r
+ if (this.isHorizontal()) {\r
+ y1 = y2 = options.position === 'top' ? this.bottom : this.top;\r
+ y1 += aliasPixel;\r
+ y2 += aliasPixel;\r
+ } else {\r
+ x1 = x2 = options.position === 'left' ? this.right : this.left;\r
+ x1 += aliasPixel;\r
+ x2 += aliasPixel;\r
+ }\r
+\r
+ context.beginPath();\r
+ context.moveTo(x1, y1);\r
+ context.lineTo(x2, y2);\r
+ context.stroke();\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],31:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.scaleService = {
- // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then
- // use the new chart options to grab the correct scale
- constructors: {},
- // Use a registration function so that we can move to an ES6 map when we no longer need to support
- // old browsers
-
- // Scale config defaults
- defaults: {},
- registerScaleType: function(type, scaleConstructor, defaults) {
- this.constructors[type] = scaleConstructor;
- this.defaults[type] = helpers.clone(defaults);
- },
- getScaleConstructor: function(type) {
- return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
- },
- getScaleDefaults: function(type) {
- // Return the scale defaults merged with the global settings so that we always use the latest ones
- return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};
- },
- updateScaleDefaults: function(type, additions) {
- var defaults = this.defaults;
- if (defaults.hasOwnProperty(type)) {
- defaults[type] = helpers.extend(defaults[type], additions);
- }
- },
- addScalesToLayout: function(chartInstance) {
- // Adds each scale to the chart.boxes array to be sized accordingly
- helpers.each(chartInstance.scales, function(scale) {
- Chart.layoutService.addBox(chartInstance, scale);
- });
- }
- };
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.scaleService = {\r
+ // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then\r
+ // use the new chart options to grab the correct scale\r
+ constructors: {},\r
+ // Use a registration function so that we can move to an ES6 map when we no longer need to support\r
+ // old browsers\r
+\r
+ // Scale config defaults\r
+ defaults: {},\r
+ registerScaleType: function(type, scaleConstructor, defaults) {\r
+ this.constructors[type] = scaleConstructor;\r
+ this.defaults[type] = helpers.clone(defaults);\r
+ },\r
+ getScaleConstructor: function(type) {\r
+ return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;\r
+ },\r
+ getScaleDefaults: function(type) {\r
+ // Return the scale defaults merged with the global settings so that we always use the latest ones\r
+ return this.defaults.hasOwnProperty(type) ? helpers.scaleMerge(Chart.defaults.scale, this.defaults[type]) : {};\r
+ },\r
+ updateScaleDefaults: function(type, additions) {\r
+ var defaults = this.defaults;\r
+ if (defaults.hasOwnProperty(type)) {\r
+ defaults[type] = helpers.extend(defaults[type], additions);\r
+ }\r
+ },\r
+ addScalesToLayout: function(chartInstance) {\r
+ // Adds each scale to the chart.boxes array to be sized accordingly\r
+ helpers.each(chartInstance.scales, function(scale) {\r
+ Chart.layoutService.addBox(chartInstance, scale);\r
+ });\r
+ }\r
+ };\r
};
},{}],32:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.title = {
- display: false,
- position: 'top',
- fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
-
- fontStyle: 'bold',
- padding: 10,
-
- // actual title
- text: ''
- };
-
- var noop = helpers.noop;
- Chart.Title = Chart.Element.extend({
-
- initialize: function(config) {
- var me = this;
- helpers.extend(me, config);
- me.options = helpers.configMerge(Chart.defaults.global.title, config.options);
-
- // Contains hit boxes for each dataset (in dataset order)
- me.legendHitBoxes = [];
- },
-
- // These methods are ordered by lifecyle. Utilities then follow.
-
- beforeUpdate: function () {
- var chartOpts = this.chart.options;
- if (chartOpts && chartOpts.title) {
- this.options = helpers.configMerge(Chart.defaults.global.title, chartOpts.title);
- }
- },
- update: function(maxWidth, maxHeight, margins) {
- var me = this;
-
- // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)
- me.beforeUpdate();
-
- // Absorb the master measurements
- me.maxWidth = maxWidth;
- me.maxHeight = maxHeight;
- me.margins = margins;
-
- // Dimensions
- me.beforeSetDimensions();
- me.setDimensions();
- me.afterSetDimensions();
- // Labels
- me.beforeBuildLabels();
- me.buildLabels();
- me.afterBuildLabels();
-
- // Fit
- me.beforeFit();
- me.fit();
- me.afterFit();
- //
- me.afterUpdate();
-
- return me.minSize;
-
- },
- afterUpdate: noop,
-
- //
-
- beforeSetDimensions: noop,
- setDimensions: function() {
- var me = this;
- // Set the unconstrained dimension before label rotation
- if (me.isHorizontal()) {
- // Reset position before calculating rotation
- me.width = me.maxWidth;
- me.left = 0;
- me.right = me.width;
- } else {
- me.height = me.maxHeight;
-
- // Reset position before calculating rotation
- me.top = 0;
- me.bottom = me.height;
- }
-
- // Reset padding
- me.paddingLeft = 0;
- me.paddingTop = 0;
- me.paddingRight = 0;
- me.paddingBottom = 0;
-
- // Reset minSize
- me.minSize = {
- width: 0,
- height: 0
- };
- },
- afterSetDimensions: noop,
-
- //
-
- beforeBuildLabels: noop,
- buildLabels: noop,
- afterBuildLabels: noop,
-
- //
-
- beforeFit: noop,
- fit: function() {
-
- var me = this,
- ctx = me.ctx,
- valueOrDefault = helpers.getValueOrDefault,
- opts = me.options,
- globalDefaults = Chart.defaults.global,
- display = opts.display,
- fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
- minSize = me.minSize;
-
- if (me.isHorizontal()) {
- minSize.width = me.maxWidth; // fill all the width
- minSize.height = display ? fontSize + (opts.padding * 2) : 0;
- } else {
- minSize.width = display ? fontSize + (opts.padding * 2) : 0;
- minSize.height = me.maxHeight; // fill all the height
- }
-
- me.width = minSize.width;
- me.height = minSize.height;
-
- },
- afterFit: noop,
-
- // Shared Methods
- isHorizontal: function() {
- var pos = this.options.position;
- return pos === "top" || pos === "bottom";
- },
-
- // Actualy draw the title block on the canvas
- draw: function() {
- var me = this,
- ctx = me.ctx,
- valueOrDefault = helpers.getValueOrDefault,
- opts = me.options,
- globalDefaults = Chart.defaults.global;
-
- if (opts.display) {
- var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
- fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),
- fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),
- titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),
- rotation = 0,
- titleX,
- titleY,
- top = me.top,
- left = me.left,
- bottom = me.bottom,
- right = me.right;
-
- ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour
- ctx.font = titleFont;
-
- // Horizontal
- if (me.isHorizontal()) {
- titleX = left + ((right - left) / 2); // midpoint of the width
- titleY = top + ((bottom - top) / 2); // midpoint of the height
- } else {
- titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);
- titleY = top + ((bottom - top) / 2);
- rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);
- }
-
- ctx.save();
- ctx.translate(titleX, titleY);
- ctx.rotate(rotation);
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- ctx.fillText(opts.text, 0, 0);
- ctx.restore();
- }
- }
- });
-
- // Register the title plugin
- Chart.pluginService.register({
- beforeInit: function(chartInstance) {
- var opts = chartInstance.options;
- var titleOpts = opts.title;
-
- if (titleOpts) {
- chartInstance.titleBlock = new Chart.Title({
- ctx: chartInstance.chart.ctx,
- options: titleOpts,
- chart: chartInstance
- });
-
- Chart.layoutService.addBox(chartInstance, chartInstance.titleBlock);
- }
- }
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.title = {\r
+ display: false,\r
+ position: 'top',\r
+ fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)\r
+\r
+ fontStyle: 'bold',\r
+ padding: 10,\r
+\r
+ // actual title\r
+ text: ''\r
+ };\r
+\r
+ var noop = helpers.noop;\r
+ Chart.Title = Chart.Element.extend({\r
+\r
+ initialize: function(config) {\r
+ helpers.extend(this, config);\r
+ this.options = helpers.configMerge(Chart.defaults.global.title, config.options);\r
+\r
+ // Contains hit boxes for each dataset (in dataset order)\r
+ this.legendHitBoxes = [];\r
+ },\r
+\r
+ // These methods are ordered by lifecyle. Utilities then follow.\r
+\r
+ beforeUpdate: noop,\r
+ update: function(maxWidth, maxHeight, margins) {\r
+\r
+ // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;)\r
+ this.beforeUpdate();\r
+\r
+ // Absorb the master measurements\r
+ this.maxWidth = maxWidth;\r
+ this.maxHeight = maxHeight;\r
+ this.margins = margins;\r
+\r
+ // Dimensions\r
+ this.beforeSetDimensions();\r
+ this.setDimensions();\r
+ this.afterSetDimensions();\r
+ // Labels\r
+ this.beforeBuildLabels();\r
+ this.buildLabels();\r
+ this.afterBuildLabels();\r
+\r
+ // Fit\r
+ this.beforeFit();\r
+ this.fit();\r
+ this.afterFit();\r
+ //\r
+ this.afterUpdate();\r
+\r
+ return this.minSize;\r
+\r
+ },\r
+ afterUpdate: noop,\r
+\r
+ //\r
+\r
+ beforeSetDimensions: noop,\r
+ setDimensions: function() {\r
+ // Set the unconstrained dimension before label rotation\r
+ if (this.isHorizontal()) {\r
+ // Reset position before calculating rotation\r
+ this.width = this.maxWidth;\r
+ this.left = 0;\r
+ this.right = this.width;\r
+ } else {\r
+ this.height = this.maxHeight;\r
+\r
+ // Reset position before calculating rotation\r
+ this.top = 0;\r
+ this.bottom = this.height;\r
+ }\r
+\r
+ // Reset padding\r
+ this.paddingLeft = 0;\r
+ this.paddingTop = 0;\r
+ this.paddingRight = 0;\r
+ this.paddingBottom = 0;\r
+\r
+ // Reset minSize\r
+ this.minSize = {\r
+ width: 0,\r
+ height: 0\r
+ };\r
+ },\r
+ afterSetDimensions: noop,\r
+\r
+ //\r
+\r
+ beforeBuildLabels: noop,\r
+ buildLabels: noop,\r
+ afterBuildLabels: noop,\r
+\r
+ //\r
+\r
+ beforeFit: noop,\r
+ fit: function() {\r
+\r
+ var _this = this,\r
+ ctx = _this.ctx,\r
+ valueOrDefault = helpers.getValueOrDefault,\r
+ opts = _this.options,\r
+ globalDefaults = Chart.defaults.global,\r
+ display = opts.display,\r
+ fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),\r
+ minSize = _this.minSize;\r
+\r
+ if (_this.isHorizontal()) {\r
+ minSize.width = _this.maxWidth; // fill all the width\r
+ minSize.height = display ? fontSize + (opts.padding * 2) : 0;\r
+ } else {\r
+ minSize.width = display ? fontSize + (opts.padding * 2) : 0;\r
+ minSize.height = _this.maxHeight; // fill all the height\r
+ }\r
+\r
+ _this.width = minSize.width;\r
+ _this.height = minSize.height;\r
+\r
+ },\r
+ afterFit: noop,\r
+\r
+ // Shared Methods\r
+ isHorizontal: function() {\r
+ var pos = this.options.position;\r
+ return pos === "top" || pos === "bottom";\r
+ },\r
+\r
+ // Actualy draw the title block on the canvas\r
+ draw: function() {\r
+ var _this = this,\r
+ ctx = _this.ctx,\r
+ valueOrDefault = helpers.getValueOrDefault,\r
+ opts = _this.options,\r
+ globalDefaults = Chart.defaults.global;\r
+\r
+ if (opts.display) {\r
+ var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),\r
+ fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle),\r
+ fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily),\r
+ titleFont = helpers.fontString(fontSize, fontStyle, fontFamily),\r
+ rotation = 0,\r
+ titleX, \r
+ titleY,\r
+ top = _this.top,\r
+ left = _this.left,\r
+ bottom = _this.bottom,\r
+ right = _this.right;\r
+\r
+ ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour\r
+ ctx.font = titleFont;\r
+\r
+ // Horizontal\r
+ if (_this.isHorizontal()) {\r
+ titleX = left + ((right - left) / 2); // midpoint of the width\r
+ titleY = top + ((bottom - top) / 2); // midpoint of the height\r
+ } else {\r
+ titleX = opts.position === 'left' ? left + (fontSize / 2) : right - (fontSize / 2);\r
+ titleY = top + ((bottom - top) / 2);\r
+ rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5);\r
+ }\r
+\r
+ ctx.save();\r
+ ctx.translate(titleX, titleY);\r
+ ctx.rotate(rotation);\r
+ ctx.textAlign = 'center';\r
+ ctx.textBaseline = 'middle';\r
+ ctx.fillText(opts.text, 0, 0);\r
+ ctx.restore();\r
+ }\r
+ }\r
+ });\r
};
-
},{}],33:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- Chart.defaults.global.tooltips = {
- enabled: true,
- custom: null,
- mode: 'single',
- backgroundColor: "rgba(0,0,0,0.8)",
- titleFontStyle: "bold",
- titleSpacing: 2,
- titleMarginBottom: 6,
- titleColor: "#fff",
- titleAlign: "left",
- bodySpacing: 2,
- bodyColor: "#fff",
- bodyAlign: "left",
- footerFontStyle: "bold",
- footerSpacing: 2,
- footerMarginTop: 6,
- footerColor: "#fff",
- footerAlign: "left",
- yPadding: 6,
- xPadding: 6,
- yAlign : 'center',
- xAlign : 'center',
- caretSize: 5,
- cornerRadius: 6,
- multiKeyBackground: '#fff',
- callbacks: {
- // Args are: (tooltipItems, data)
- beforeTitle: helpers.noop,
- title: function(tooltipItems, data) {
- // Pick first xLabel for now
- var title = '';
- var labels = data.labels;
- var labelCount = labels ? labels.length : 0;
-
- if (tooltipItems.length > 0) {
- var item = tooltipItems[0];
-
- if (item.xLabel) {
- title = item.xLabel;
- } else if (labelCount > 0 && item.index < labelCount) {
- title = labels[item.index];
- }
- }
-
- return title;
- },
- afterTitle: helpers.noop,
-
- // Args are: (tooltipItems, data)
- beforeBody: helpers.noop,
-
- // Args are: (tooltipItem, data)
- beforeLabel: helpers.noop,
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- return datasetLabel + ': ' + tooltipItem.yLabel;
- },
- labelColor: function(tooltipItem, chartInstance) {
- var meta = chartInstance.getDatasetMeta(tooltipItem.datasetIndex);
- var activeElement = meta.data[tooltipItem.index];
- var view = activeElement._view;
- return {
- borderColor: view.borderColor,
- backgroundColor: view.backgroundColor
- };
- },
- afterLabel: helpers.noop,
-
- // Args are: (tooltipItems, data)
- afterBody: helpers.noop,
-
- // Args are: (tooltipItems, data)
- beforeFooter: helpers.noop,
- footer: helpers.noop,
- afterFooter: helpers.noop
- }
- };
-
- // Helper to push or concat based on if the 2nd parameter is an array or not
- function pushOrConcat(base, toPush) {
- if (toPush) {
- if (helpers.isArray(toPush)) {
- base = base.concat(toPush);
- } else {
- base.push(toPush);
- }
- }
-
- return base;
- }
-
- function getAveragePosition(elements) {
- if (!elements.length) {
- return false;
- }
-
- var i, len;
- var xPositions = [];
- var yPositions = [];
-
- for (i = 0, len = elements.length; i < len; ++i) {
- var el = elements[i];
- if (el && el.hasValue()){
- var pos = el.tooltipPosition();
- xPositions.push(pos.x);
- yPositions.push(pos.y);
- }
- }
-
- var x = 0,
- y = 0;
- for (i = 0, len - xPositions.length; i < len; ++i) {
- x += xPositions[i];
- y += yPositions[i];
- }
-
- return {
- x: Math.round(x / xPositions.length),
- y: Math.round(y / xPositions.length)
- };
- }
-
- // Private helper to create a tooltip iteam model
- // @param element : the chart element (point, arc, bar) to create the tooltip item for
- // @return : new tooltip item
- function createTooltipItem(element) {
- var xScale = element._xScale;
- var yScale = element._yScale || element._scale; // handle radar || polarArea charts
- var index = element._index,
- datasetIndex = element._datasetIndex;
-
- return {
- xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '',
- yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '',
- index: index,
- datasetIndex: datasetIndex
- };
- }
-
- Chart.Tooltip = Chart.Element.extend({
- initialize: function() {
- var me = this;
- var globalDefaults = Chart.defaults.global;
- var tooltipOpts = me._options;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- helpers.extend(me, {
- _model: {
- // Positioning
- xPadding: tooltipOpts.xPadding,
- yPadding: tooltipOpts.yPadding,
- xAlign : tooltipOpts.yAlign,
- yAlign : tooltipOpts.xAlign,
-
- // Body
- bodyColor: tooltipOpts.bodyColor,
- _bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
- _bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
- _bodyAlign: tooltipOpts.bodyAlign,
- bodyFontSize: getValueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize),
- bodySpacing: tooltipOpts.bodySpacing,
-
- // Title
- titleColor: tooltipOpts.titleColor,
- _titleFontFamily: getValueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily),
- _titleFontStyle: getValueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle),
- titleFontSize: getValueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize),
- _titleAlign: tooltipOpts.titleAlign,
- titleSpacing: tooltipOpts.titleSpacing,
- titleMarginBottom: tooltipOpts.titleMarginBottom,
-
- // Footer
- footerColor: tooltipOpts.footerColor,
- _footerFontFamily: getValueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily),
- _footerFontStyle: getValueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle),
- footerFontSize: getValueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize),
- _footerAlign: tooltipOpts.footerAlign,
- footerSpacing: tooltipOpts.footerSpacing,
- footerMarginTop: tooltipOpts.footerMarginTop,
-
- // Appearance
- caretSize: tooltipOpts.caretSize,
- cornerRadius: tooltipOpts.cornerRadius,
- backgroundColor: tooltipOpts.backgroundColor,
- opacity: 0,
- legendColorBackground: tooltipOpts.multiKeyBackground
- }
- });
- },
-
- // Get the title
- // Args are: (tooltipItem, data)
- getTitle: function() {
- var me = this;
- var opts = me._options;
- var callbacks = opts.callbacks;
-
- var beforeTitle = callbacks.beforeTitle.apply(me, arguments),
- title = callbacks.title.apply(me, arguments),
- afterTitle = callbacks.afterTitle.apply(me, arguments);
-
- var lines = [];
- lines = pushOrConcat(lines, beforeTitle);
- lines = pushOrConcat(lines, title);
- lines = pushOrConcat(lines, afterTitle);
-
- return lines;
- },
-
- // Args are: (tooltipItem, data)
- getBeforeBody: function() {
- var lines = this._options.callbacks.beforeBody.apply(this, arguments);
- return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
- },
-
- // Args are: (tooltipItem, data)
- getBody: function(tooltipItems, data) {
- var me = this;
- var callbacks = me._options.callbacks;
- var bodyItems = [];
-
- helpers.each(tooltipItems, function(tooltipItem) {
- var bodyItem = {
- before: [],
- lines: [],
- after: []
- };
- pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data));
- pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data));
- pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data));
-
- bodyItems.push(bodyItem);
- });
-
- return bodyItems;
- },
-
- // Args are: (tooltipItem, data)
- getAfterBody: function() {
- var lines = this._options.callbacks.afterBody.apply(this, arguments);
- return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];
- },
-
- // Get the footer and beforeFooter and afterFooter lines
- // Args are: (tooltipItem, data)
- getFooter: function() {
- var me = this;
- var callbacks = me._options.callbacks;
-
- var beforeFooter = callbacks.beforeFooter.apply(me, arguments);
- var footer = callbacks.footer.apply(me, arguments);
- var afterFooter = callbacks.afterFooter.apply(me, arguments);
-
- var lines = [];
- lines = pushOrConcat(lines, beforeFooter);
- lines = pushOrConcat(lines, footer);
- lines = pushOrConcat(lines, afterFooter);
-
- return lines;
- },
-
- update: function(changed) {
- var me = this;
- var opts = me._options;
- var model = me._model;
- var active = me._active;
-
- var data = me._data;
- var chartInstance = me._chartInstance;
-
- var i, len;
-
- if (active.length) {
- model.opacity = 1;
-
- var labelColors = [],
- tooltipPosition = getAveragePosition(active);
-
- var tooltipItems = [];
- for (i = 0, len = active.length; i < len; ++i) {
- tooltipItems.push(createTooltipItem(active[i]));
- }
-
- // If the user provided a sorting function, use it to modify the tooltip items
- if (opts.itemSort) {
- tooltipItems = tooltipItems.sort(opts.itemSort);
- }
-
- // If there is more than one item, show color items
- if (active.length > 1) {
- helpers.each(tooltipItems, function(tooltipItem) {
- labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, chartInstance));
- });
- }
-
- // Build the Text Lines
- helpers.extend(model, {
- title: me.getTitle(tooltipItems, data),
- beforeBody: me.getBeforeBody(tooltipItems, data),
- body: me.getBody(tooltipItems, data),
- afterBody: me.getAfterBody(tooltipItems, data),
- footer: me.getFooter(tooltipItems, data),
- x: Math.round(tooltipPosition.x),
- y: Math.round(tooltipPosition.y),
- caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),
- labelColors: labelColors
- });
-
- // We need to determine alignment of
- var tooltipSize = me.getTooltipSize(model);
- me.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas
-
- helpers.extend(model, me.getBackgroundPoint(model, tooltipSize));
- } else {
- me._model.opacity = 0;
- }
-
- if (changed && opts.custom) {
- opts.custom.call(me, model);
- }
-
- return me;
- },
- getTooltipSize: function getTooltipSize(vm) {
- var ctx = this._chart.ctx;
-
- var size = {
- height: vm.yPadding * 2, // Tooltip Padding
- width: 0
- };
-
- // Count of all lines in the body
- var body = vm.body;
- var combinedBodyLength = body.reduce(function(count, bodyItem) {
- return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length;
- }, 0);
- combinedBodyLength += vm.beforeBody.length + vm.afterBody.length;
-
- var titleLineCount = vm.title.length;
- var footerLineCount = vm.footer.length;
- var titleFontSize = vm.titleFontSize,
- bodyFontSize = vm.bodyFontSize,
- footerFontSize = vm.footerFontSize;
-
- size.height += titleLineCount * titleFontSize; // Title Lines
- size.height += (titleLineCount - 1) * vm.titleSpacing; // Title Line Spacing
- size.height += titleLineCount ? vm.titleMarginBottom : 0; // Title's bottom Margin
- size.height += combinedBodyLength * bodyFontSize; // Body Lines
- size.height += combinedBodyLength ? (combinedBodyLength - 1) * vm.bodySpacing : 0; // Body Line Spacing
- size.height += footerLineCount ? vm.footerMarginTop : 0; // Footer Margin
- size.height += footerLineCount * (footerFontSize); // Footer Lines
- size.height += footerLineCount ? (footerLineCount - 1) * vm.footerSpacing : 0; // Footer Line Spacing
-
- // Title width
- var widthPadding = 0;
- var maxLineWidth = function(line) {
- size.width = Math.max(size.width, ctx.measureText(line).width + widthPadding);
- };
-
- ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
- helpers.each(vm.title, maxLineWidth);
-
- // Body width
- ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
- helpers.each(vm.beforeBody.concat(vm.afterBody), maxLineWidth);
-
- // Body lines may include some extra width due to the color box
- widthPadding = body.length > 1 ? (bodyFontSize + 2) : 0;
- helpers.each(body, function(bodyItem) {
- helpers.each(bodyItem.before, maxLineWidth);
- helpers.each(bodyItem.lines, maxLineWidth);
- helpers.each(bodyItem.after, maxLineWidth);
- });
-
- // Reset back to 0
- widthPadding = 0;
-
- // Footer width
- ctx.font = helpers.fontString(footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
- helpers.each(vm.footer, maxLineWidth);
-
- // Add padding
- size.width += 2 * vm.xPadding;
-
- return size;
- },
- determineAlignment: function determineAlignment(size) {
- var me = this;
- var model = me._model;
- var chart = me._chart;
- var chartArea = me._chartInstance.chartArea;
-
- if (model.y < size.height) {
- model.yAlign = 'top';
- } else if (model.y > (chart.height - size.height)) {
- model.yAlign = 'bottom';
- }
-
- var lf, rf; // functions to determine left, right alignment
- var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart
- var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges
- var midX = (chartArea.left + chartArea.right) / 2;
- var midY = (chartArea.top + chartArea.bottom) / 2;
-
- if (model.yAlign === 'center') {
- lf = function(x) {
- return x <= midX;
- };
- rf = function(x) {
- return x > midX;
- };
- } else {
- lf = function(x) {
- return x <= (size.width / 2);
- };
- rf = function(x) {
- return x >= (chart.width - (size.width / 2));
- };
- }
-
- olf = function(x) {
- return x + size.width > chart.width;
- };
- orf = function(x) {
- return x - size.width < 0;
- };
- yf = function(y) {
- return y <= midY ? 'top' : 'bottom';
- };
-
- if (lf(model.x)) {
- model.xAlign = 'left';
-
- // Is tooltip too wide and goes over the right side of the chart.?
- if (olf(model.x)) {
- model.xAlign = 'center';
- model.yAlign = yf(model.y);
- }
- } else if (rf(model.x)) {
- model.xAlign = 'right';
-
- // Is tooltip too wide and goes outside left edge of canvas?
- if (orf(model.x)) {
- model.xAlign = 'center';
- model.yAlign = yf(model.y);
- }
- }
- },
- getBackgroundPoint: function getBackgroundPoint(vm, size) {
- // Background Position
- var pt = {
- x: vm.x,
- y: vm.y
- };
-
- var caretSize = vm.caretSize,
- caretPadding = vm.caretPadding,
- cornerRadius = vm.cornerRadius,
- xAlign = vm.xAlign,
- yAlign = vm.yAlign,
- paddingAndSize = caretSize + caretPadding,
- radiusAndPadding = cornerRadius + caretPadding;
-
- if (xAlign === 'right') {
- pt.x -= size.width;
- } else if (xAlign === 'center') {
- pt.x -= (size.width / 2);
- }
-
- if (yAlign === 'top') {
- pt.y += paddingAndSize;
- } else if (yAlign === 'bottom') {
- pt.y -= size.height + paddingAndSize;
- } else {
- pt.y -= (size.height / 2);
- }
-
- if (yAlign === 'center') {
- if (xAlign === 'left') {
- pt.x += paddingAndSize;
- } else if (xAlign === 'right') {
- pt.x -= paddingAndSize;
- }
- } else {
- if (xAlign === 'left') {
- pt.x -= radiusAndPadding;
- } else if (xAlign === 'right') {
- pt.x += radiusAndPadding;
- }
- }
-
- return pt;
- },
- drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {
- var vm = this._view;
- var ctx = this._chart.ctx;
- var x1, x2, x3;
- var y1, y2, y3;
- var caretSize = vm.caretSize;
- var cornerRadius = vm.cornerRadius;
- var xAlign = vm.xAlign,
- yAlign = vm.yAlign;
- var ptX = tooltipPoint.x,
- ptY = tooltipPoint.y;
- var width = size.width,
- height = size.height;
-
- if (yAlign === 'center') {
- // Left or right side
- if (xAlign === 'left') {
- x1 = ptX;
- x2 = x1 - caretSize;
- x3 = x1;
- } else {
- x1 = ptX + width;
- x2 = x1 + caretSize;
- x3 = x1;
- }
-
- y2 = ptY + (height / 2);
- y1 = y2 - caretSize;
- y3 = y2 + caretSize;
- } else {
- if (xAlign === 'left') {
- x1 = ptX + cornerRadius;
- x2 = x1 + caretSize;
- x3 = x2 + caretSize;
- } else if (xAlign === 'right') {
- x1 = ptX + width - cornerRadius;
- x2 = x1 - caretSize;
- x3 = x2 - caretSize;
- } else {
- x2 = ptX + (width / 2);
- x1 = x2 - caretSize;
- x3 = x2 + caretSize;
- }
-
- if (yAlign === 'top') {
- y1 = ptY;
- y2 = y1 - caretSize;
- y3 = y1;
- } else {
- y1 = ptY + height;
- y2 = y1 + caretSize;
- y3 = y1;
- }
- }
-
- var bgColor = helpers.color(vm.backgroundColor);
- ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();
- ctx.beginPath();
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.lineTo(x3, y3);
- ctx.closePath();
- ctx.fill();
- },
- drawTitle: function drawTitle(pt, vm, ctx, opacity) {
- var title = vm.title;
-
- if (title.length) {
- ctx.textAlign = vm._titleAlign;
- ctx.textBaseline = "top";
-
- var titleFontSize = vm.titleFontSize,
- titleSpacing = vm.titleSpacing;
-
- var titleColor = helpers.color(vm.titleColor);
- ctx.fillStyle = titleColor.alpha(opacity * titleColor.alpha()).rgbString();
- ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily);
-
- var i, len;
- for (i = 0, len = title.length; i < len; ++i) {
- ctx.fillText(title[i], pt.x, pt.y);
- pt.y += titleFontSize + titleSpacing; // Line Height and spacing
-
- if (i + 1 === title.length) {
- pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
- }
- }
- }
- },
- drawBody: function drawBody(pt, vm, ctx, opacity) {
- var bodyFontSize = vm.bodyFontSize;
- var bodySpacing = vm.bodySpacing;
- var body = vm.body;
-
- ctx.textAlign = vm._bodyAlign;
- ctx.textBaseline = "top";
-
- var bodyColor = helpers.color(vm.bodyColor);
- var textColor = bodyColor.alpha(opacity * bodyColor.alpha()).rgbString();
- ctx.fillStyle = textColor;
- ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);
-
- // Before Body
- var xLinePadding = 0;
- var fillLineOfText = function(line) {
- ctx.fillText(line, pt.x + xLinePadding, pt.y);
- pt.y += bodyFontSize + bodySpacing;
- };
-
- // Before body lines
- helpers.each(vm.beforeBody, fillLineOfText);
-
- var drawColorBoxes = body.length > 1;
- xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0;
-
- // Draw body lines now
- helpers.each(body, function(bodyItem, i) {
- helpers.each(bodyItem.before, fillLineOfText);
-
- helpers.each(bodyItem.lines, function(line) {
- // Draw Legend-like boxes if needed
- if (drawColorBoxes) {
- // Fill a white rect so that colours merge nicely if the opacity is < 1
- ctx.fillStyle = helpers.color(vm.legendColorBackground).alpha(opacity).rgbaString();
- ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
-
- // Border
- ctx.strokeStyle = helpers.color(vm.labelColors[i].borderColor).alpha(opacity).rgbaString();
- ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize);
-
- // Inner square
- ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(opacity).rgbaString();
- ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2);
-
- ctx.fillStyle = textColor;
- }
-
- fillLineOfText(line);
- });
-
- helpers.each(bodyItem.after, fillLineOfText);
- });
-
- // Reset back to 0 for after body
- xLinePadding = 0;
-
- // After body lines
- helpers.each(vm.afterBody, fillLineOfText);
- pt.y -= bodySpacing; // Remove last body spacing
- },
- drawFooter: function drawFooter(pt, vm, ctx, opacity) {
- var footer = vm.footer;
-
- if (footer.length) {
- pt.y += vm.footerMarginTop;
-
- ctx.textAlign = vm._footerAlign;
- ctx.textBaseline = "top";
-
- var footerColor = helpers.color(vm.footerColor);
- ctx.fillStyle = footerColor.alpha(opacity * footerColor.alpha()).rgbString();
- ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);
-
- helpers.each(footer, function(line) {
- ctx.fillText(line, pt.x, pt.y);
- pt.y += vm.footerFontSize + vm.footerSpacing;
- });
- }
- },
- draw: function draw() {
- var ctx = this._chart.ctx;
- var vm = this._view;
-
- if (vm.opacity === 0) {
- return;
- }
-
- var tooltipSize = this.getTooltipSize(vm);
- var pt = {
- x: vm.x,
- y: vm.y
- };
-
- // IE11/Edge does not like very small opacities, so snap to 0
- var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
-
- if (this._options.enabled) {
- // Draw Background
- var bgColor = helpers.color(vm.backgroundColor);
- ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();
- helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);
- ctx.fill();
-
- // Draw Caret
- this.drawCaret(pt, tooltipSize, opacity, vm.caretPadding);
-
- // Draw Title, Body, and Footer
- pt.x += vm.xPadding;
- pt.y += vm.yPadding;
-
- // Titles
- this.drawTitle(pt, vm, ctx, opacity);
-
- // Body
- this.drawBody(pt, vm, ctx, opacity);
-
- // Footer
- this.drawFooter(pt, vm, ctx, opacity);
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ Chart.defaults.global.tooltips = {\r
+ enabled: true,\r
+ custom: null,\r
+ mode: 'single',\r
+ backgroundColor: "rgba(0,0,0,0.8)",\r
+ titleFontStyle: "bold",\r
+ titleSpacing: 2,\r
+ titleMarginBottom: 6,\r
+ titleColor: "#fff",\r
+ titleAlign: "left",\r
+ bodySpacing: 2,\r
+ bodyColor: "#fff",\r
+ bodyAlign: "left",\r
+ footerFontStyle: "bold",\r
+ footerSpacing: 2,\r
+ footerMarginTop: 6,\r
+ footerColor: "#fff",\r
+ footerAlign: "left",\r
+ yPadding: 6,\r
+ xPadding: 6,\r
+ yAlign : 'center',\r
+ xAlign : 'center',\r
+ caretSize: 5,\r
+ cornerRadius: 6,\r
+ multiKeyBackground: '#fff',\r
+ callbacks: {\r
+ // Args are: (tooltipItems, data)\r
+ beforeTitle: helpers.noop,\r
+ title: function(tooltipItems, data) {\r
+ // Pick first xLabel for now\r
+ var title = '';\r
+\r
+ if (tooltipItems.length > 0) {\r
+ if (tooltipItems[0].xLabel) {\r
+ title = tooltipItems[0].xLabel;\r
+ } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\r
+ title = data.labels[tooltipItems[0].index];\r
+ }\r
+ }\r
+\r
+ return title;\r
+ },\r
+ afterTitle: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ beforeBody: helpers.noop,\r
+\r
+ // Args are: (tooltipItem, data)\r
+ beforeLabel: helpers.noop,\r
+ label: function(tooltipItem, data) {\r
+ var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\r
+ return datasetLabel + ': ' + tooltipItem.yLabel;\r
+ },\r
+ afterLabel: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ afterBody: helpers.noop,\r
+\r
+ // Args are: (tooltipItems, data)\r
+ beforeFooter: helpers.noop,\r
+ footer: helpers.noop,\r
+ afterFooter: helpers.noop\r
+ }\r
+ };\r
+\r
+ // Helper to push or concat based on if the 2nd parameter is an array or not\r
+ function pushOrConcat(base, toPush) {\r
+ if (toPush) {\r
+ if (helpers.isArray(toPush)) {\r
+ base = base.concat(toPush);\r
+ } else {\r
+ base.push(toPush);\r
+ }\r
+ }\r
+\r
+ return base;\r
+ }\r
+\r
+ Chart.Tooltip = Chart.Element.extend({\r
+ initialize: function() {\r
+ var globalDefaults = Chart.defaults.global;\r
+ var options = this._options;\r
+ var tooltips = options.tooltips;\r
+\r
+ helpers.extend(this, {\r
+ _model: {\r
+ // Positioning\r
+ xPadding: tooltips.xPadding,\r
+ yPadding: tooltips.yPadding,\r
+ xAlign : tooltips.yAlign,\r
+ yAlign : tooltips.xAlign,\r
+\r
+ // Body\r
+ bodyColor: tooltips.bodyColor,\r
+ _bodyFontFamily: helpers.getValueOrDefault(tooltips.bodyFontFamily, globalDefaults.defaultFontFamily),\r
+ _bodyFontStyle: helpers.getValueOrDefault(tooltips.bodyFontStyle, globalDefaults.defaultFontStyle),\r
+ _bodyAlign: tooltips.bodyAlign,\r
+ bodyFontSize: helpers.getValueOrDefault(tooltips.bodyFontSize, globalDefaults.defaultFontSize),\r
+ bodySpacing: tooltips.bodySpacing,\r
+\r
+ // Title\r
+ titleColor: tooltips.titleColor,\r
+ _titleFontFamily: helpers.getValueOrDefault(tooltips.titleFontFamily, globalDefaults.defaultFontFamily),\r
+ _titleFontStyle: helpers.getValueOrDefault(tooltips.titleFontStyle, globalDefaults.defaultFontStyle),\r
+ titleFontSize: helpers.getValueOrDefault(tooltips.titleFontSize, globalDefaults.defaultFontSize),\r
+ _titleAlign: tooltips.titleAlign,\r
+ titleSpacing: tooltips.titleSpacing,\r
+ titleMarginBottom: tooltips.titleMarginBottom,\r
+\r
+ // Footer\r
+ footerColor: tooltips.footerColor,\r
+ _footerFontFamily: helpers.getValueOrDefault(tooltips.footerFontFamily, globalDefaults.defaultFontFamily),\r
+ _footerFontStyle: helpers.getValueOrDefault(tooltips.footerFontStyle, globalDefaults.defaultFontStyle),\r
+ footerFontSize: helpers.getValueOrDefault(tooltips.footerFontSize, globalDefaults.defaultFontSize),\r
+ _footerAlign: tooltips.footerAlign,\r
+ footerSpacing: tooltips.footerSpacing,\r
+ footerMarginTop: tooltips.footerMarginTop,\r
+\r
+ // Appearance\r
+ caretSize: tooltips.caretSize,\r
+ cornerRadius: tooltips.cornerRadius,\r
+ backgroundColor: tooltips.backgroundColor,\r
+ opacity: 0,\r
+ legendColorBackground: tooltips.multiKeyBackground\r
+ }\r
+ });\r
+ },\r
+\r
+ // Get the title\r
+ // Args are: (tooltipItem, data)\r
+ getTitle: function() {\r
+ var beforeTitle = this._options.tooltips.callbacks.beforeTitle.apply(this, arguments),\r
+ title = this._options.tooltips.callbacks.title.apply(this, arguments),\r
+ afterTitle = this._options.tooltips.callbacks.afterTitle.apply(this, arguments);\r
+\r
+ var lines = [];\r
+ lines = pushOrConcat(lines, beforeTitle);\r
+ lines = pushOrConcat(lines, title);\r
+ lines = pushOrConcat(lines, afterTitle);\r
+\r
+ return lines;\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getBeforeBody: function() {\r
+ var lines = this._options.tooltips.callbacks.beforeBody.apply(this, arguments);\r
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getBody: function(tooltipItems, data) {\r
+ var lines = [];\r
+\r
+ helpers.each(tooltipItems, function(bodyItem) {\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.beforeLabel.call(this, bodyItem, data), lines);\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.label.call(this, bodyItem, data), lines);\r
+ helpers.pushAllIfDefined(this._options.tooltips.callbacks.afterLabel.call(this, bodyItem, data), lines);\r
+ }, this);\r
+\r
+ return lines;\r
+ },\r
+\r
+ // Args are: (tooltipItem, data)\r
+ getAfterBody: function() {\r
+ var lines = this._options.tooltips.callbacks.afterBody.apply(this, arguments);\r
+ return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : [];\r
+ },\r
+\r
+ // Get the footer and beforeFooter and afterFooter lines\r
+ // Args are: (tooltipItem, data)\r
+ getFooter: function() {\r
+ var beforeFooter = this._options.tooltips.callbacks.beforeFooter.apply(this, arguments);\r
+ var footer = this._options.tooltips.callbacks.footer.apply(this, arguments);\r
+ var afterFooter = this._options.tooltips.callbacks.afterFooter.apply(this, arguments);\r
+\r
+ var lines = [];\r
+ lines = pushOrConcat(lines, beforeFooter);\r
+ lines = pushOrConcat(lines, footer);\r
+ lines = pushOrConcat(lines, afterFooter);\r
+\r
+ return lines;\r
+ },\r
+\r
+ getAveragePosition: function(elements) {\r
+\r
+ if (!elements.length) {\r
+ return false;\r
+ }\r
+\r
+ var xPositions = [];\r
+ var yPositions = [];\r
+\r
+ helpers.each(elements, function(el) {\r
+ if (el && el.hasValue()){\r
+ var pos = el.tooltipPosition();\r
+ xPositions.push(pos.x);\r
+ yPositions.push(pos.y);\r
+ }\r
+ });\r
+\r
+ var x = 0,\r
+ y = 0;\r
+ for (var i = 0; i < xPositions.length; i++) {\r
+ x += xPositions[i];\r
+ y += yPositions[i];\r
+ }\r
+\r
+ return {\r
+ x: Math.round(x / xPositions.length),\r
+ y: Math.round(y / xPositions.length)\r
+ };\r
+\r
+ },\r
+\r
+ update: function(changed) {\r
+ if (this._active.length) {\r
+ this._model.opacity = 1;\r
+\r
+ var element = this._active[0],\r
+ labelColors = [],\r
+ tooltipPosition;\r
+\r
+ var tooltipItems = [];\r
+\r
+ if (this._options.tooltips.mode === 'single') {\r
+ var yScale = element._yScale || element._scale; // handle radar || polarArea charts\r
+ tooltipItems.push({\r
+ xLabel: element._xScale ? element._xScale.getLabelForIndex(element._index, element._datasetIndex) : '',\r
+ yLabel: yScale ? yScale.getLabelForIndex(element._index, element._datasetIndex) : '',\r
+ index: element._index,\r
+ datasetIndex: element._datasetIndex\r
+ });\r
+ tooltipPosition = this.getAveragePosition(this._active);\r
+ } else {\r
+ helpers.each(this._data.datasets, function(dataset, datasetIndex) {\r
+ if (!this._chartInstance.isDatasetVisible(datasetIndex)) {\r
+ return;\r
+ }\r
+\r
+ var meta = this._chartInstance.getDatasetMeta(datasetIndex);\r
+ var currentElement = meta.data[element._index];\r
+ if (currentElement) {\r
+ var yScale = element._yScale || element._scale; // handle radar || polarArea charts\r
+\r
+ tooltipItems.push({\r
+ xLabel: currentElement._xScale ? currentElement._xScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',\r
+ yLabel: yScale ? yScale.getLabelForIndex(currentElement._index, currentElement._datasetIndex) : '',\r
+ index: element._index,\r
+ datasetIndex: datasetIndex\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ helpers.each(this._active, function(active) {\r
+ if (active) {\r
+ labelColors.push({\r
+ borderColor: active._view.borderColor,\r
+ backgroundColor: active._view.backgroundColor\r
+ });\r
+ }\r
+ }, null);\r
+\r
+ tooltipPosition = this.getAveragePosition(this._active);\r
+ }\r
+\r
+ // Build the Text Lines\r
+ helpers.extend(this._model, {\r
+ title: this.getTitle(tooltipItems, this._data),\r
+ beforeBody: this.getBeforeBody(tooltipItems, this._data),\r
+ body: this.getBody(tooltipItems, this._data),\r
+ afterBody: this.getAfterBody(tooltipItems, this._data),\r
+ footer: this.getFooter(tooltipItems, this._data)\r
+ });\r
+\r
+ helpers.extend(this._model, {\r
+ x: Math.round(tooltipPosition.x),\r
+ y: Math.round(tooltipPosition.y),\r
+ caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),\r
+ labelColors: labelColors\r
+ });\r
+\r
+ // We need to determine alignment of\r
+ var tooltipSize = this.getTooltipSize(this._model);\r
+ this.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas\r
+\r
+ helpers.extend(this._model, this.getBackgroundPoint(this._model, tooltipSize));\r
+ } else {\r
+ this._model.opacity = 0;\r
+ }\r
+\r
+ if (changed && this._options.tooltips.custom) {\r
+ this._options.tooltips.custom.call(this, this._model);\r
+ }\r
+\r
+ return this;\r
+ },\r
+ getTooltipSize: function getTooltipSize(vm) {\r
+ var ctx = this._chart.ctx;\r
+\r
+ var size = {\r
+ height: vm.yPadding * 2, // Tooltip Padding\r
+ width: 0\r
+ };\r
+ var combinedBodyLength = vm.body.length + vm.beforeBody.length + vm.afterBody.length;\r
+\r
+ size.height += vm.title.length * vm.titleFontSize; // Title Lines\r
+ size.height += (vm.title.length - 1) * vm.titleSpacing; // Title Line Spacing\r
+ size.height += vm.title.length ? vm.titleMarginBottom : 0; // Title's bottom Margin\r
+ size.height += combinedBodyLength * vm.bodyFontSize; // Body Lines\r
+ size.height += combinedBodyLength ? (combinedBodyLength - 1) * vm.bodySpacing : 0; // Body Line Spacing\r
+ size.height += vm.footer.length ? vm.footerMarginTop : 0; // Footer Margin\r
+ size.height += vm.footer.length * (vm.footerFontSize); // Footer Lines\r
+ size.height += vm.footer.length ? (vm.footer.length - 1) * vm.footerSpacing : 0; // Footer Line Spacing\r
+\r
+ // Width\r
+ ctx.font = helpers.fontString(vm.titleFontSize, vm._titleFontStyle, vm._titleFontFamily);\r
+ helpers.each(vm.title, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+\r
+ ctx.font = helpers.fontString(vm.bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);\r
+ helpers.each(vm.beforeBody.concat(vm.afterBody), function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+ helpers.each(vm.body, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width + (this._options.tooltips.mode !== 'single' ? (vm.bodyFontSize + 2) : 0));\r
+ }, this);\r
+\r
+ ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);\r
+ helpers.each(vm.footer, function(line) {\r
+ size.width = Math.max(size.width, ctx.measureText(line).width);\r
+ });\r
+ size.width += 2 * vm.xPadding;\r
+\r
+ return size;\r
+ },\r
+ determineAlignment: function determineAlignment(size) {\r
+ if (this._model.y < size.height) {\r
+ this._model.yAlign = 'top';\r
+ } else if (this._model.y > (this._chart.height - size.height)) {\r
+ this._model.yAlign = 'bottom';\r
+ }\r
+\r
+ var lf, rf; // functions to determine left, right alignment\r
+ var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart\r
+ var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges\r
+ var _this = this;\r
+ var midX = (this._chartInstance.chartArea.left + this._chartInstance.chartArea.right) / 2;\r
+ var midY = (this._chartInstance.chartArea.top + this._chartInstance.chartArea.bottom) / 2;\r
+\r
+ if (this._model.yAlign === 'center') {\r
+ lf = function(x) {\r
+ return x <= midX;\r
+ };\r
+ rf = function(x) {\r
+ return x > midX;\r
+ };\r
+ } else {\r
+ lf = function(x) {\r
+ return x <= (size.width / 2);\r
+ };\r
+ rf = function(x) {\r
+ return x >= (_this._chart.width - (size.width / 2));\r
+ };\r
+ }\r
+\r
+ olf = function(x) {\r
+ return x + size.width > _this._chart.width;\r
+ };\r
+ orf = function(x) {\r
+ return x - size.width < 0;\r
+ };\r
+ yf = function(y) {\r
+ return y <= midY ? 'top' : 'bottom';\r
+ };\r
+\r
+ if (lf(this._model.x)) {\r
+ this._model.xAlign = 'left';\r
+\r
+ // Is tooltip too wide and goes over the right side of the chart.?\r
+ if (olf(this._model.x)) {\r
+ this._model.xAlign = 'center';\r
+ this._model.yAlign = yf(this._model.y);\r
+ }\r
+ } else if (rf(this._model.x)) {\r
+ this._model.xAlign = 'right';\r
+\r
+ // Is tooltip too wide and goes outside left edge of canvas?\r
+ if (orf(this._model.x)) {\r
+ this._model.xAlign = 'center';\r
+ this._model.yAlign = yf(this._model.y);\r
+ }\r
+ }\r
+ },\r
+ getBackgroundPoint: function getBackgroundPoint(vm, size) {\r
+ // Background Position\r
+ var pt = {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+\r
+ if (vm.xAlign === 'right') {\r
+ pt.x -= size.width;\r
+ } else if (vm.xAlign === 'center') {\r
+ pt.x -= (size.width / 2);\r
+ }\r
+\r
+ if (vm.yAlign === 'top') {\r
+ pt.y += vm.caretPadding + vm.caretSize;\r
+ } else if (vm.yAlign === 'bottom') {\r
+ pt.y -= size.height + vm.caretPadding + vm.caretSize;\r
+ } else {\r
+ pt.y -= (size.height / 2);\r
+ }\r
+\r
+ if (vm.yAlign === 'center') {\r
+ if (vm.xAlign === 'left') {\r
+ pt.x += vm.caretPadding + vm.caretSize;\r
+ } else if (vm.xAlign === 'right') {\r
+ pt.x -= vm.caretPadding + vm.caretSize;\r
+ }\r
+ } else {\r
+ if (vm.xAlign === 'left') {\r
+ pt.x -= vm.cornerRadius + vm.caretPadding;\r
+ } else if (vm.xAlign === 'right') {\r
+ pt.x += vm.cornerRadius + vm.caretPadding;\r
+ }\r
+ }\r
+\r
+ return pt;\r
+ },\r
+ drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var x1, x2, x3;\r
+ var y1, y2, y3;\r
+\r
+ if (vm.yAlign === 'center') {\r
+ // Left or right side\r
+ if (vm.xAlign === 'left') {\r
+ x1 = tooltipPoint.x;\r
+ x2 = x1 - vm.caretSize;\r
+ x3 = x1;\r
+ } else {\r
+ x1 = tooltipPoint.x + size.width;\r
+ x2 = x1 + vm.caretSize;\r
+ x3 = x1;\r
+ }\r
+\r
+ y2 = tooltipPoint.y + (size.height / 2);\r
+ y1 = y2 - vm.caretSize;\r
+ y3 = y2 + vm.caretSize;\r
+ } else {\r
+ if (vm.xAlign === 'left') {\r
+ x1 = tooltipPoint.x + vm.cornerRadius;\r
+ x2 = x1 + vm.caretSize;\r
+ x3 = x2 + vm.caretSize;\r
+ } else if (vm.xAlign === 'right') {\r
+ x1 = tooltipPoint.x + size.width - vm.cornerRadius;\r
+ x2 = x1 - vm.caretSize;\r
+ x3 = x2 - vm.caretSize;\r
+ } else {\r
+ x2 = tooltipPoint.x + (size.width / 2);\r
+ x1 = x2 - vm.caretSize;\r
+ x3 = x2 + vm.caretSize;\r
+ }\r
+\r
+ if (vm.yAlign === 'top') {\r
+ y1 = tooltipPoint.y;\r
+ y2 = y1 - vm.caretSize;\r
+ y3 = y1;\r
+ } else {\r
+ y1 = tooltipPoint.y + size.height;\r
+ y2 = y1 + vm.caretSize;\r
+ y3 = y1;\r
+ }\r
+ }\r
+\r
+ var bgColor = helpers.color(vm.backgroundColor);\r
+ ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();\r
+ ctx.beginPath();\r
+ ctx.moveTo(x1, y1);\r
+ ctx.lineTo(x2, y2);\r
+ ctx.lineTo(x3, y3);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ },\r
+ drawTitle: function drawTitle(pt, vm, ctx, opacity) {\r
+ if (vm.title.length) {\r
+ ctx.textAlign = vm._titleAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var titleColor = helpers.color(vm.titleColor);\r
+ ctx.fillStyle = titleColor.alpha(opacity * titleColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.titleFontSize, vm._titleFontStyle, vm._titleFontFamily);\r
+\r
+ helpers.each(vm.title, function(title, i) {\r
+ ctx.fillText(title, pt.x, pt.y);\r
+ pt.y += vm.titleFontSize + vm.titleSpacing; // Line Height and spacing\r
+\r
+ if (i + 1 === vm.title.length) {\r
+ pt.y += vm.titleMarginBottom - vm.titleSpacing; // If Last, add margin, remove spacing\r
+ }\r
+ });\r
+ }\r
+ },\r
+ drawBody: function drawBody(pt, vm, ctx, opacity) {\r
+ ctx.textAlign = vm._bodyAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var bodyColor = helpers.color(vm.bodyColor);\r
+ ctx.fillStyle = bodyColor.alpha(opacity * bodyColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily);\r
+\r
+ // Before Body\r
+ helpers.each(vm.beforeBody, function(beforeBody) {\r
+ ctx.fillText(beforeBody, pt.x, pt.y);\r
+ pt.y += vm.bodyFontSize + vm.bodySpacing;\r
+ });\r
+\r
+ helpers.each(vm.body, function(body, i) {\r
+ // Draw Legend-like boxes if needed\r
+ if (this._options.tooltips.mode !== 'single') {\r
+ // Fill a white rect so that colours merge nicely if the opacity is < 1\r
+ ctx.fillStyle = helpers.color(vm.legendColorBackground).alpha(opacity).rgbaString();\r
+ ctx.fillRect(pt.x, pt.y, vm.bodyFontSize, vm.bodyFontSize);\r
+\r
+ // Border\r
+ ctx.strokeStyle = helpers.color(vm.labelColors[i].borderColor).alpha(opacity).rgbaString();\r
+ ctx.strokeRect(pt.x, pt.y, vm.bodyFontSize, vm.bodyFontSize);\r
+\r
+ // Inner square\r
+ ctx.fillStyle = helpers.color(vm.labelColors[i].backgroundColor).alpha(opacity).rgbaString();\r
+ ctx.fillRect(pt.x + 1, pt.y + 1, vm.bodyFontSize - 2, vm.bodyFontSize - 2);\r
+\r
+ ctx.fillStyle = helpers.color(vm.bodyColor).alpha(opacity).rgbaString(); // Return fill style for text\r
+ }\r
+\r
+ // Body Line\r
+ ctx.fillText(body, pt.x + (this._options.tooltips.mode !== 'single' ? (vm.bodyFontSize + 2) : 0), pt.y);\r
+\r
+ pt.y += vm.bodyFontSize + vm.bodySpacing;\r
+ }, this);\r
+\r
+ // After Body\r
+ helpers.each(vm.afterBody, function(afterBody) {\r
+ ctx.fillText(afterBody, pt.x, pt.y);\r
+ pt.y += vm.bodyFontSize;\r
+ });\r
+\r
+ pt.y -= vm.bodySpacing; // Remove last body spacing\r
+ },\r
+ drawFooter: function drawFooter(pt, vm, ctx, opacity) {\r
+ if (vm.footer.length) {\r
+ pt.y += vm.footerMarginTop;\r
+\r
+ ctx.textAlign = vm._footerAlign;\r
+ ctx.textBaseline = "top";\r
+\r
+ var footerColor = helpers.color(vm.footerColor);\r
+ ctx.fillStyle = footerColor.alpha(opacity * footerColor.alpha()).rgbString();\r
+ ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily);\r
+\r
+ helpers.each(vm.footer, function(footer) {\r
+ ctx.fillText(footer, pt.x, pt.y);\r
+ pt.y += vm.footerFontSize + vm.footerSpacing;\r
+ });\r
+ }\r
+ },\r
+ draw: function draw() {\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ if (vm.opacity === 0) {\r
+ return;\r
+ }\r
+\r
+ var caretPadding = vm.caretPadding;\r
+ var tooltipSize = this.getTooltipSize(vm);\r
+ var pt = {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+\r
+ // IE11/Edge does not like very small opacities, so snap to 0\r
+ var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;\r
+\r
+ if (this._options.tooltips.enabled) {\r
+ // Draw Background\r
+ var bgColor = helpers.color(vm.backgroundColor);\r
+ ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();\r
+ helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);\r
+ ctx.fill();\r
+\r
+ // Draw Caret\r
+ this.drawCaret(pt, tooltipSize, opacity, caretPadding);\r
+\r
+ // Draw Title, Body, and Footer\r
+ pt.x += vm.xPadding;\r
+ pt.y += vm.yPadding;\r
+\r
+ // Titles\r
+ this.drawTitle(pt, vm, ctx, opacity);\r
+\r
+ // Body\r
+ this.drawBody(pt, vm, ctx, opacity);\r
+\r
+ // Footer\r
+ this.drawFooter(pt, vm, ctx, opacity);\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],34:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart, moment) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global;
-
- globalOpts.elements.arc = {
- backgroundColor: globalOpts.defaultColor,
- borderColor: "#fff",
- borderWidth: 2
- };
-
- Chart.elements.Arc = Chart.Element.extend({
- inLabelRange: function(mouseX) {
- var vm = this._view;
-
- if (vm) {
- return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));
- } else {
- return false;
- }
- },
- inRange: function(chartX, chartY) {
- var vm = this._view;
-
- if (vm) {
- var pointRelativePosition = helpers.getAngleFromPoint(vm, {
- x: chartX,
- y: chartY
- }),
- angle = pointRelativePosition.angle,
- distance = pointRelativePosition.distance;
-
- //Sanitise angle range
- var startAngle = vm.startAngle;
- var endAngle = vm.endAngle;
- while (endAngle < startAngle) {
- endAngle += 2.0 * Math.PI;
- }
- while (angle > endAngle) {
- angle -= 2.0 * Math.PI;
- }
- while (angle < startAngle) {
- angle += 2.0 * Math.PI;
- }
-
- //Check if within the range of the open/close angle
- var betweenAngles = (angle >= startAngle && angle <= endAngle),
- withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);
-
- return (betweenAngles && withinRadius);
- } else {
- return false;
- }
- },
- tooltipPosition: function() {
- var vm = this._view;
-
- var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2),
- rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;
- return {
- x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),
- y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)
- };
- },
- draw: function() {
-
- var ctx = this._chart.ctx,
- vm = this._view,
- sA = vm.startAngle,
- eA = vm.endAngle;
-
- ctx.beginPath();
-
- ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);
- ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);
-
- ctx.closePath();
- ctx.strokeStyle = vm.borderColor;
- ctx.lineWidth = vm.borderWidth;
-
- ctx.fillStyle = vm.backgroundColor;
-
- ctx.fill();
- ctx.lineJoin = 'bevel';
-
- if (vm.borderWidth) {
- ctx.stroke();
- }
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart, moment) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global;\r
+\r
+ globalOpts.elements.arc = {\r
+ backgroundColor: globalOpts.defaultColor,\r
+ borderColor: "#fff",\r
+ borderWidth: 2\r
+ };\r
+\r
+ Chart.elements.Arc = Chart.Element.extend({\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+\r
+ if (vm) {\r
+ return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2));\r
+ } else {\r
+ return false;\r
+ }\r
+ },\r
+ inRange: function(chartX, chartY) {\r
+ var vm = this._view;\r
+\r
+ if (vm) {\r
+ var pointRelativePosition = helpers.getAngleFromPoint(vm, {\r
+ x: chartX,\r
+ y: chartY\r
+ }),\r
+ angle = pointRelativePosition.angle,\r
+ distance = pointRelativePosition.distance;\r
+\r
+ //Sanitise angle range\r
+ var startAngle = vm.startAngle;\r
+ var endAngle = vm.endAngle;\r
+ while (endAngle < startAngle) {\r
+ endAngle += 2.0 * Math.PI;\r
+ }\r
+ while (angle > endAngle) {\r
+ angle -= 2.0 * Math.PI;\r
+ }\r
+ while (angle < startAngle) {\r
+ angle += 2.0 * Math.PI;\r
+ }\r
+\r
+ //Check if within the range of the open/close angle\r
+ var betweenAngles = (angle >= startAngle && angle <= endAngle),\r
+ withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius);\r
+\r
+ return (betweenAngles && withinRadius);\r
+ } else {\r
+ return false;\r
+ }\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+\r
+ var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2),\r
+ rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius;\r
+ return {\r
+ x: vm.x + (Math.cos(centreAngle) * rangeFromCentre),\r
+ y: vm.y + (Math.sin(centreAngle) * rangeFromCentre)\r
+ };\r
+ },\r
+ draw: function() {\r
+\r
+ var ctx = this._chart.ctx,\r
+ vm = this._view,\r
+ sA = vm.startAngle,\r
+ eA = vm.endAngle;\r
+\r
+ ctx.beginPath();\r
+\r
+ ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA);\r
+ ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true);\r
+\r
+ ctx.closePath();\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ ctx.fillStyle = vm.backgroundColor;\r
+\r
+ ctx.fill();\r
+ ctx.lineJoin = 'bevel';\r
+\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ }\r
+ });\r
+};\r
},{}],35:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var globalDefaults = Chart.defaults.global;
-
- Chart.defaults.global.elements.line = {
- tension: 0.4,
- backgroundColor: globalDefaults.defaultColor,
- borderWidth: 3,
- borderColor: globalDefaults.defaultColor,
- borderCapStyle: 'butt',
- borderDash: [],
- borderDashOffset: 0.0,
- borderJoinStyle: 'miter',
- fill: true // do we fill in the area between the line and its base axis
- };
-
- Chart.elements.Line = Chart.Element.extend({
- lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
- var me = this;
- var ctx = me._chart.ctx;
- var spanGaps = me._view ? me._view.spanGaps : false;
-
- if (point._view.skip && !spanGaps) {
- skipHandler.call(me, previousPoint, point, nextPoint);
- } else if (previousPoint._view.skip && !spanGaps) {
- previousSkipHandler.call(me, previousPoint, point, nextPoint);
- } else if (point._view.tension === 0) {
- ctx.lineTo(point._view.x, point._view.y);
- } else {
- // Line between points
- ctx.bezierCurveTo(
- previousPoint._view.controlPointNextX,
- previousPoint._view.controlPointNextY,
- point._view.controlPointPreviousX,
- point._view.controlPointPreviousY,
- point._view.x,
- point._view.y
- );
- }
- },
-
- draw: function() {
- var me = this;
-
- var vm = me._view;
- var ctx = me._chart.ctx;
- var first = me._children[0];
- var last = me._children[me._children.length - 1];
-
- function loopBackToStart(drawLineToCenter) {
- if (!first._view.skip && !last._view.skip) {
- // Draw a bezier line from last to first
- ctx.bezierCurveTo(
- last._view.controlPointNextX,
- last._view.controlPointNextY,
- first._view.controlPointPreviousX,
- first._view.controlPointPreviousY,
- first._view.x,
- first._view.y
- );
- } else if (drawLineToCenter) {
- // Go to center
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
- }
- }
-
- ctx.save();
-
- // If we had points and want to fill this line, do so.
- if (me._children.length > 0 && vm.fill) {
- // Draw the background first (so the border is always on top)
- ctx.beginPath();
-
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
-
- // First point moves to it's starting position no matter what
- if (index === 0) {
- if (me._loop) {
- ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
- } else {
- ctx.moveTo(point._view.x, vm.scaleZero);
- }
-
- if (point._view.skip) {
- if (!me._loop) {
- ctx.moveTo(next._view.x, me._view.scaleZero);
- }
- } else {
- ctx.lineTo(point._view.x, point._view.y);
- }
- } else {
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
- if (me._loop) {
- // Go to center
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
- } else {
- ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
- ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
- }
- }, function(previousPoint, point) {
- // If we skipped the last point, draw a line to ourselves so that the fill is nice
- ctx.lineTo(point._view.x, point._view.y);
- });
- }
- }, me);
-
- // For radial scales, loop back around to the first point
- if (me._loop) {
- loopBackToStart(true);
- } else {
- //Round off the line by going to the base of the chart, back to the start, then fill.
- ctx.lineTo(me._children[me._children.length - 1]._view.x, vm.scaleZero);
- ctx.lineTo(me._children[0]._view.x, vm.scaleZero);
- }
-
- ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
- ctx.closePath();
- ctx.fill();
- }
-
- var globalOptionLineElements = globalDefaults.elements.line;
- // Now draw the line between all the points with any borders
- ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
-
- // IE 9 and 10 do not support line dash
- if (ctx.setLineDash) {
- ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);
- }
-
- ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
- ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
- ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
- ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
- ctx.beginPath();
-
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
-
- if (index === 0) {
- ctx.moveTo(point._view.x, point._view.y);
- } else {
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
- ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
- }, function(previousPoint, point) {
- // If we skipped the last point, move up to our point preventing a line from being drawn
- ctx.moveTo(point._view.x, point._view.y);
- });
- }
- }, me);
-
- if (me._loop && me._children.length > 0) {
- loopBackToStart();
- }
-
- ctx.stroke();
- ctx.restore();
- }
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var globalDefaults = Chart.defaults.global;\r
+\r
+ Chart.defaults.global.elements.line = {\r
+ tension: 0.4,\r
+ backgroundColor: globalDefaults.defaultColor,\r
+ borderWidth: 3,\r
+ borderColor: globalDefaults.defaultColor,\r
+ borderCapStyle: 'butt',\r
+ borderDash: [],\r
+ borderDashOffset: 0.0,\r
+ borderJoinStyle: 'miter',\r
+ fill: true // do we fill in the area between the line and its base axis\r
+ };\r
+\r
+ Chart.elements.Line = Chart.Element.extend({\r
+ lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {\r
+ var ctx = this._chart.ctx;\r
+\r
+ if (point._view.skip) {\r
+ skipHandler.call(this, previousPoint, point, nextPoint);\r
+ } else if (previousPoint._view.skip) {\r
+ previousSkipHandler.call(this, previousPoint, point, nextPoint);\r
+ } else if (point._view.tension === 0) {\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ } else {\r
+ // Line between points\r
+ ctx.bezierCurveTo(\r
+ previousPoint._view.controlPointNextX,\r
+ previousPoint._view.controlPointNextY,\r
+ point._view.controlPointPreviousX,\r
+ point._view.controlPointPreviousY,\r
+ point._view.x,\r
+ point._view.y\r
+ );\r
+ }\r
+ },\r
+\r
+ draw: function() {\r
+ var _this = this;\r
+\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var first = this._children[0];\r
+ var last = this._children[this._children.length - 1];\r
+\r
+ function loopBackToStart(drawLineToCenter) {\r
+ if (!first._view.skip && !last._view.skip) {\r
+ // Draw a bezier line from last to first\r
+ ctx.bezierCurveTo(\r
+ last._view.controlPointNextX,\r
+ last._view.controlPointNextY,\r
+ first._view.controlPointPreviousX,\r
+ first._view.controlPointPreviousY,\r
+ first._view.x,\r
+ first._view.y\r
+ );\r
+ } else if (drawLineToCenter) {\r
+ // Go to center\r
+ ctx.lineTo(_this._view.scaleZero.x, _this._view.scaleZero.y);\r
+ }\r
+ }\r
+\r
+ ctx.save();\r
+\r
+ // If we had points and want to fill this line, do so.\r
+ if (this._children.length > 0 && vm.fill) {\r
+ // Draw the background first (so the border is always on top)\r
+ ctx.beginPath();\r
+\r
+ helpers.each(this._children, function(point, index) {\r
+ var previous = helpers.previousItem(this._children, index);\r
+ var next = helpers.nextItem(this._children, index);\r
+\r
+ // First point moves to it's starting position no matter what\r
+ if (index === 0) {\r
+ if (this._loop) {\r
+ ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);\r
+ } else {\r
+ ctx.moveTo(point._view.x, vm.scaleZero);\r
+ }\r
+\r
+ if (point._view.skip) {\r
+ if (!this._loop) {\r
+ ctx.moveTo(next._view.x, this._view.scaleZero);\r
+ }\r
+ } else {\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ }\r
+ } else {\r
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {\r
+ if (this._loop) {\r
+ // Go to center\r
+ ctx.lineTo(this._view.scaleZero.x, this._view.scaleZero.y);\r
+ } else {\r
+ ctx.lineTo(previousPoint._view.x, this._view.scaleZero);\r
+ ctx.moveTo(nextPoint._view.x, this._view.scaleZero);\r
+ }\r
+ }, function(previousPoint, point) {\r
+ // If we skipped the last point, draw a line to ourselves so that the fill is nice\r
+ ctx.lineTo(point._view.x, point._view.y);\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ // For radial scales, loop back around to the first point\r
+ if (this._loop) {\r
+ loopBackToStart(true);\r
+ } else {\r
+ //Round off the line by going to the base of the chart, back to the start, then fill.\r
+ ctx.lineTo(this._children[this._children.length - 1]._view.x, vm.scaleZero);\r
+ ctx.lineTo(this._children[0]._view.x, vm.scaleZero);\r
+ }\r
+\r
+ ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ }\r
+\r
+ var globalOptionLineElements = globalDefaults.elements.line;\r
+ // Now draw the line between all the points with any borders\r
+ ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;\r
+\r
+ // IE 9 and 10 do not support line dash\r
+ if (ctx.setLineDash) {\r
+ ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash);\r
+ }\r
+\r
+ ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;\r
+ ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;\r
+ ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;\r
+ ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;\r
+ ctx.beginPath();\r
+\r
+ helpers.each(this._children, function(point, index) {\r
+ var previous = helpers.previousItem(this._children, index);\r
+ var next = helpers.nextItem(this._children, index);\r
+\r
+ if (index === 0) {\r
+ ctx.moveTo(point._view.x, point._view.y);\r
+ } else {\r
+ this.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {\r
+ ctx.moveTo(nextPoint._view.x, nextPoint._view.y);\r
+ }, function(previousPoint, point) {\r
+ // If we skipped the last point, move up to our point preventing a line from being drawn\r
+ ctx.moveTo(point._view.x, point._view.y);\r
+ });\r
+ }\r
+ }, this);\r
+\r
+ if (this._loop && this._children.length > 0) {\r
+ loopBackToStart();\r
+ }\r
+\r
+ ctx.stroke();\r
+ ctx.restore();\r
+ }\r
+ });\r
};
},{}],36:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global,
- defaultColor = globalOpts.defaultColor;
-
- globalOpts.elements.point = {
- radius: 3,
- pointStyle: 'circle',
- backgroundColor: defaultColor,
- borderWidth: 1,
- borderColor: defaultColor,
- // Hover
- hitRadius: 1,
- hoverRadius: 4,
- hoverBorderWidth: 1
- };
-
- Chart.elements.Point = Chart.Element.extend({
- inRange: function(mouseX, mouseY) {
- var vm = this._view;
- return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;
- },
- inLabelRange: function(mouseX) {
- var vm = this._view;
- return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;
- },
- tooltipPosition: function() {
- var vm = this._view;
- return {
- x: vm.x,
- y: vm.y,
- padding: vm.radius + vm.borderWidth
- };
- },
- draw: function() {
- var vm = this._view;
- var ctx = this._chart.ctx;
- var pointStyle = vm.pointStyle;
- var radius = vm.radius;
- var x = vm.x;
- var y = vm.y;
- var type, edgeLength, xOffset, yOffset, height, size;
-
- if (vm.skip) {
- return;
- }
-
- if (typeof pointStyle === 'object') {
- type = pointStyle.toString();
- if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
- ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);
- return;
- }
- }
-
- if (isNaN(radius) || radius <= 0) {
- return;
- }
-
- ctx.strokeStyle = vm.borderColor || defaultColor;
- ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);
- ctx.fillStyle = vm.backgroundColor || defaultColor;
-
- switch (pointStyle) {
- // Default includes circle
- default:
- ctx.beginPath();
- ctx.arc(x, y, radius, 0, Math.PI * 2);
- ctx.closePath();
- ctx.fill();
- break;
- case 'triangle':
- ctx.beginPath();
- edgeLength = 3 * radius / Math.sqrt(3);
- height = edgeLength * Math.sqrt(3) / 2;
- ctx.moveTo(x - edgeLength / 2, y + height / 3);
- ctx.lineTo(x + edgeLength / 2, y + height / 3);
- ctx.lineTo(x, y - 2 * height / 3);
- ctx.closePath();
- ctx.fill();
- break;
- case 'rect':
- size = 1 / Math.SQRT2 * radius;
- ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
- ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
- break;
- case 'rectRot':
- size = 1 / Math.SQRT2 * radius;
- ctx.beginPath();
- ctx.moveTo(x - size, y);
- ctx.lineTo(x, y + size);
- ctx.lineTo(x + size, y);
- ctx.lineTo(x, y - size);
- ctx.closePath();
- ctx.fill();
- break;
- case 'cross':
- ctx.beginPath();
- ctx.moveTo(x, y + radius);
- ctx.lineTo(x, y - radius);
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- case 'crossRot':
- ctx.beginPath();
- xOffset = Math.cos(Math.PI / 4) * radius;
- yOffset = Math.sin(Math.PI / 4) * radius;
- ctx.moveTo(x - xOffset, y - yOffset);
- ctx.lineTo(x + xOffset, y + yOffset);
- ctx.moveTo(x - xOffset, y + yOffset);
- ctx.lineTo(x + xOffset, y - yOffset);
- ctx.closePath();
- break;
- case 'star':
- ctx.beginPath();
- ctx.moveTo(x, y + radius);
- ctx.lineTo(x, y - radius);
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- xOffset = Math.cos(Math.PI / 4) * radius;
- yOffset = Math.sin(Math.PI / 4) * radius;
- ctx.moveTo(x - xOffset, y - yOffset);
- ctx.lineTo(x + xOffset, y + yOffset);
- ctx.moveTo(x - xOffset, y + yOffset);
- ctx.lineTo(x + xOffset, y - yOffset);
- ctx.closePath();
- break;
- case 'line':
- ctx.beginPath();
- ctx.moveTo(x - radius, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- case 'dash':
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(x + radius, y);
- ctx.closePath();
- break;
- }
-
- ctx.stroke();
- }
- });
-};
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global,\r
+ defaultColor = globalOpts.defaultColor;\r
+\r
+ globalOpts.elements.point = {\r
+ radius: 3,\r
+ pointStyle: 'circle',\r
+ backgroundColor: defaultColor,\r
+ borderWidth: 1,\r
+ borderColor: defaultColor,\r
+ // Hover\r
+ hitRadius: 1,\r
+ hoverRadius: 4,\r
+ hoverBorderWidth: 1\r
+ };\r
+\r
+ Chart.elements.Point = Chart.Element.extend({\r
+ inRange: function(mouseX, mouseY) {\r
+ var vm = this._view;\r
+ return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false;\r
+ },\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+ return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false;\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+ return {\r
+ x: vm.x,\r
+ y: vm.y,\r
+ padding: vm.radius + vm.borderWidth\r
+ };\r
+ },\r
+ draw: function() {\r
+ var vm = this._view;\r
+ var ctx = this._chart.ctx;\r
+ var pointStyle = vm.pointStyle;\r
+ var radius = vm.radius;\r
+ var x = vm.x;\r
+ var y = vm.y;\r
+ var type, edgeLength, xOffset, yOffset, height, size;\r
+\r
+ if (vm.skip) {\r
+ return;\r
+ }\r
+\r
+ if (typeof pointStyle === 'object') {\r
+ type = pointStyle.toString();\r
+ if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\r
+ ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);\r
+ return;\r
+ }\r
+ }\r
+\r
+ if (isNaN(radius) || radius <= 0) {\r
+ return;\r
+ }\r
+\r
+ ctx.strokeStyle = vm.borderColor || defaultColor;\r
+ ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);\r
+ ctx.fillStyle = vm.backgroundColor || defaultColor;\r
+\r
+ switch (pointStyle) {\r
+ // Default includes circle\r
+ default:\r
+ ctx.beginPath();\r
+ ctx.arc(x, y, radius, 0, Math.PI * 2);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ break;\r
+ case 'triangle':\r
+ ctx.beginPath();\r
+ edgeLength = 3 * radius / Math.sqrt(3);\r
+ height = edgeLength * Math.sqrt(3) / 2;\r
+ ctx.moveTo(x - edgeLength / 2, y + height / 3);\r
+ ctx.lineTo(x + edgeLength / 2, y + height / 3);\r
+ ctx.lineTo(x, y - 2 * height / 3);\r
+ ctx.closePath();\r
+ ctx.fill();\r
+ break;\r
+ case 'rect':\r
+ size = 1 / Math.SQRT2 * radius;\r
+ ctx.fillRect(x - size, y - size, 2 * size, 2 * size);\r
+ ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);\r
+ break;\r
+ case 'rectRot':\r
+ ctx.translate(x, y);\r
+ ctx.rotate(Math.PI / 4);\r
+ size = 1 / Math.SQRT2 * radius;\r
+ ctx.fillRect(-size, -size, 2 * size, 2 * size);\r
+ ctx.strokeRect(-size, -size, 2 * size, 2 * size);\r
+ ctx.setTransform(1, 0, 0, 1, 0, 0);\r
+ break;\r
+ case 'cross':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y + radius);\r
+ ctx.lineTo(x, y - radius);\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ case 'crossRot':\r
+ ctx.beginPath();\r
+ xOffset = Math.cos(Math.PI / 4) * radius;\r
+ yOffset = Math.sin(Math.PI / 4) * radius;\r
+ ctx.moveTo(x - xOffset, y - yOffset);\r
+ ctx.lineTo(x + xOffset, y + yOffset);\r
+ ctx.moveTo(x - xOffset, y + yOffset);\r
+ ctx.lineTo(x + xOffset, y - yOffset);\r
+ ctx.closePath();\r
+ break;\r
+ case 'star':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y + radius);\r
+ ctx.lineTo(x, y - radius);\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ xOffset = Math.cos(Math.PI / 4) * radius;\r
+ yOffset = Math.sin(Math.PI / 4) * radius;\r
+ ctx.moveTo(x - xOffset, y - yOffset);\r
+ ctx.lineTo(x + xOffset, y + yOffset);\r
+ ctx.moveTo(x - xOffset, y + yOffset);\r
+ ctx.lineTo(x + xOffset, y - yOffset);\r
+ ctx.closePath();\r
+ break;\r
+ case 'line':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x - radius, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ case 'dash':\r
+ ctx.beginPath();\r
+ ctx.moveTo(x, y);\r
+ ctx.lineTo(x + radius, y);\r
+ ctx.closePath();\r
+ break;\r
+ }\r
+\r
+ ctx.stroke();\r
+ }\r
+ });\r
+};\r
},{}],37:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global;
-
- globalOpts.elements.rectangle = {
- backgroundColor: globalOpts.defaultColor,
- borderWidth: 0,
- borderColor: globalOpts.defaultColor,
- borderSkipped: 'bottom'
- };
-
- Chart.elements.Rectangle = Chart.Element.extend({
- draw: function() {
- var ctx = this._chart.ctx;
- var vm = this._view;
-
- var halfWidth = vm.width / 2,
- leftX = vm.x - halfWidth,
- rightX = vm.x + halfWidth,
- top = vm.base - (vm.base - vm.y),
- 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) {
- leftX += halfStroke;
- rightX -= halfStroke;
- top += 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 = [
- [leftX, vm.base],
- [leftX, top],
- [rightX, top],
- [rightX, vm.base]
- ];
-
- // 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(index) {
- return corners[(startCorner + index) % 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();
- }
- },
- height: function() {
- var vm = this._view;
- return vm.base - vm.y;
- },
- inRange: function(mouseX, mouseY) {
- var vm = this._view;
- return vm ?
- (vm.y < vm.base ?
- (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base) :
- (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y)) :
- false;
- },
- inLabelRange: function(mouseX) {
- var vm = this._view;
- return vm ? (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) : false;
- },
- tooltipPosition: function() {
- var vm = this._view;
- return {
- x: vm.x,
- y: vm.y
- };
- }
- });
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers,\r
+ globalOpts = Chart.defaults.global;\r
+\r
+ globalOpts.elements.rectangle = {\r
+ backgroundColor: globalOpts.defaultColor,\r
+ borderWidth: 0,\r
+ borderColor: globalOpts.defaultColor,\r
+ borderSkipped: 'bottom'\r
+ };\r
+\r
+ Chart.elements.Rectangle = Chart.Element.extend({\r
+ draw: function() {\r
+ var ctx = this._chart.ctx;\r
+ var vm = this._view;\r
+\r
+ var halfWidth = vm.width / 2,\r
+ leftX = vm.x - halfWidth,\r
+ rightX = vm.x + halfWidth,\r
+ top = vm.base - (vm.base - vm.y),\r
+ halfStroke = vm.borderWidth / 2;\r
+\r
+ // Canvas doesn't allow us to stroke inside the width so we can\r
+ // adjust the sizes to fit if we're setting a stroke on the line\r
+ if (vm.borderWidth) {\r
+ leftX += halfStroke;\r
+ rightX -= halfStroke;\r
+ top += halfStroke;\r
+ }\r
+\r
+ ctx.beginPath();\r
+ ctx.fillStyle = vm.backgroundColor;\r
+ ctx.strokeStyle = vm.borderColor;\r
+ ctx.lineWidth = vm.borderWidth;\r
+\r
+ // Corner points, from bottom-left to bottom-right clockwise\r
+ // | 1 2 |\r
+ // | 0 3 |\r
+ var corners = [\r
+ [leftX, vm.base],\r
+ [leftX, top],\r
+ [rightX, top],\r
+ [rightX, vm.base]\r
+ ];\r
+\r
+ // Find first (starting) corner with fallback to 'bottom' \r
+ var borders = ['bottom', 'left', 'top', 'right'];\r
+ var startCorner = borders.indexOf(vm.borderSkipped, 0);\r
+ if (startCorner === -1)\r
+ startCorner = 0;\r
+\r
+ function cornerAt(index) {\r
+ return corners[(startCorner + index) % 4];\r
+ }\r
+\r
+ // Draw rectangle from 'startCorner'\r
+ ctx.moveTo.apply(ctx, cornerAt(0));\r
+ for (var i = 1; i < 4; i++)\r
+ ctx.lineTo.apply(ctx, cornerAt(i));\r
+\r
+ ctx.fill();\r
+ if (vm.borderWidth) {\r
+ ctx.stroke();\r
+ }\r
+ },\r
+ height: function() {\r
+ var vm = this._view;\r
+ return vm.base - vm.y;\r
+ },\r
+ inRange: function(mouseX, mouseY) {\r
+ var vm = this._view;\r
+ return vm ? \r
+ (vm.y < vm.base ? \r
+ (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.y && mouseY <= vm.base) :\r
+ (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) && (mouseY >= vm.base && mouseY <= vm.y)) :\r
+ false;\r
+ },\r
+ inLabelRange: function(mouseX) {\r
+ var vm = this._view;\r
+ return vm ? (mouseX >= vm.x - vm.width / 2 && mouseX <= vm.x + vm.width / 2) : false;\r
+ },\r
+ tooltipPosition: function() {\r
+ var vm = this._view;\r
+ return {\r
+ x: vm.x,\r
+ y: vm.y\r
+ };\r
+ }\r
+ });\r
+\r
};
},{}],38:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- // Default config for a category scale
- var defaultConfig = {
- position: "bottom"
- };
-
- var DatasetScale = Chart.Scale.extend({
- // Implement this so that
- determineDataLimits: function() {
- var me = this;
- me.minIndex = 0;
- me.maxIndex = me.chart.data.labels.length - 1;
- var findIndex;
-
- if (me.options.ticks.min !== undefined) {
- // user specified min value
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.min);
- me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
- }
-
- if (me.options.ticks.max !== undefined) {
- // user specified max value
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.max);
- me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
- }
-
- me.min = me.chart.data.labels[me.minIndex];
- me.max = me.chart.data.labels[me.maxIndex];
- },
-
- buildTicks: function(index) {
- var me = this;
- // If we are viewing some subset of labels, slice the original array
- me.ticks = (me.minIndex === 0 && me.maxIndex === me.chart.data.labels.length - 1) ? me.chart.data.labels : me.chart.data.labels.slice(me.minIndex, me.maxIndex + 1);
- },
-
- getLabelForIndex: function(index, datasetIndex) {
- return this.ticks[index];
- },
-
- // Used to get data value locations. Value can either be an index or a numerical value
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- // 1 is added because we need the length but we have the indexes
- var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
-
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueWidth = innerWidth / offsetAmt;
- var widthOffset = (valueWidth * (index - me.minIndex)) + me.paddingLeft;
-
- if (me.options.gridLines.offsetGridLines && includeOffset) {
- widthOffset += (valueWidth / 2);
- }
-
- return me.left + Math.round(widthOffset);
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- var valueHeight = innerHeight / offsetAmt;
- var heightOffset = (valueHeight * (index - me.minIndex)) + me.paddingTop;
-
- if (me.options.gridLines.offsetGridLines && includeOffset) {
- heightOffset += (valueHeight / 2);
- }
-
- return me.top + Math.round(heightOffset);
- }
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset);
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var value;
- var offsetAmt = Math.max((me.ticks.length - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
- var horz = me.isHorizontal();
- var innerDimension = horz ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
- var valueDimension = innerDimension / offsetAmt;
-
- if (me.options.gridLines.offsetGridLines) {
- pixel -= (valueDimension / 2);
- }
- pixel -= horz ? me.paddingLeft : me.paddingTop;
-
- if (pixel <= 0) {
- value = 0;
- } else {
- value = Math.round(pixel / valueDimension);
- }
-
- return value;
- }
- });
-
- Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ // Default config for a category scale\r
+ var defaultConfig = {\r
+ position: "bottom"\r
+ };\r
+\r
+ var DatasetScale = Chart.Scale.extend({\r
+ // Implement this so that \r
+ determineDataLimits: function() {\r
+ this.minIndex = 0;\r
+ this.maxIndex = this.chart.data.labels.length - 1;\r
+ var findIndex;\r
+\r
+ if (this.options.ticks.min !== undefined) {\r
+ // user specified min value\r
+ findIndex = helpers.indexOf(this.chart.data.labels, this.options.ticks.min);\r
+ this.minIndex = findIndex !== -1 ? findIndex : this.minIndex;\r
+ }\r
+\r
+ if (this.options.ticks.max !== undefined) {\r
+ // user specified max value\r
+ findIndex = helpers.indexOf(this.chart.data.labels, this.options.ticks.max);\r
+ this.maxIndex = findIndex !== -1 ? findIndex : this.maxIndex;\r
+ }\r
+\r
+ this.min = this.chart.data.labels[this.minIndex];\r
+ this.max = this.chart.data.labels[this.maxIndex];\r
+ },\r
+\r
+ buildTicks: function(index) {\r
+ // If we are viewing some subset of labels, slice the original array\r
+ this.ticks = (this.minIndex === 0 && this.maxIndex === this.chart.data.labels.length - 1) ? this.chart.data.labels : this.chart.data.labels.slice(this.minIndex, this.maxIndex + 1);\r
+ },\r
+\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return this.ticks[index];\r
+ },\r
+\r
+ // Used to get data value locations. Value can either be an index or a numerical value\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ // 1 is added because we need the length but we have the indexes\r
+ var offsetAmt = Math.max((this.maxIndex + 1 - this.minIndex - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueWidth = innerWidth / offsetAmt;\r
+ var widthOffset = (valueWidth * (index - this.minIndex)) + this.paddingLeft;\r
+\r
+ if (this.options.gridLines.offsetGridLines && includeOffset) {\r
+ widthOffset += (valueWidth / 2);\r
+ }\r
+\r
+ return this.left + Math.round(widthOffset);\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueHeight = innerHeight / offsetAmt;\r
+ var heightOffset = (valueHeight * (index - this.minIndex)) + this.paddingTop;\r
+\r
+ if (this.options.gridLines.offsetGridLines && includeOffset) {\r
+ heightOffset += (valueHeight / 2);\r
+ }\r
+\r
+ return this.top + Math.round(heightOffset);\r
+ }\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.ticks[index], index + this.minIndex, null, includeOffset);\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var value\r
+; var offsetAmt = Math.max((this.ticks.length - ((this.options.gridLines.offsetGridLines) ? 0 : 1)), 1);\r
+ var horz = this.isHorizontal();\r
+ var innerDimension = horz ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueDimension = innerDimension / offsetAmt;\r
+\r
+ if (this.options.gridLines.offsetGridLines) {\r
+ pixel -= (valueDimension / 2);\r
+ }\r
+ pixel -= horz ? this.paddingLeft : this.paddingTop;\r
+\r
+ if (pixel <= 0) {\r
+ value = 0;\r
+ } else {\r
+ value = Math.round(pixel / valueDimension);\r
+ }\r
+\r
+ return value;\r
+ }\r
+ });\r
+\r
+ Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);\r
+\r
};
},{}],39:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- var defaultConfig = {
- position: "left",
- ticks: {
- callback: function(tickValue, index, ticks) {
- // If we have lots of ticks, don't use the ones
- var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
-
- // If we have a number like 2.5 as the delta, figure out how many decimal places we need
- if (Math.abs(delta) > 1) {
- if (tickValue !== Math.floor(tickValue)) {
- // not an integer
- delta = tickValue - Math.floor(tickValue);
- }
- }
-
- var logDelta = helpers.log10(Math.abs(delta));
- var tickString = '';
-
- if (tickValue !== 0) {
- var numDecimal = -1 * Math.floor(logDelta);
- numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
- tickString = tickValue.toFixed(numDecimal);
- } else {
- tickString = '0'; // never show decimal places for 0
- }
-
- return tickString;
- }
- }
- };
-
- var LinearScale = Chart.LinearScaleBase.extend({
- determineDataLimits: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var chart = me.chart;
- var data = chart.data;
- var datasets = data.datasets;
- var isHorizontal = me.isHorizontal();
-
- function IDMatches(meta) {
- return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
- }
-
- // First Calculate the range
- me.min = null;
- me.max = null;
-
- if (opts.stacked) {
- var valuesPerType = {};
- var hasPositiveValues = false;
- var hasNegativeValues = false;
-
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (valuesPerType[meta.type] === undefined) {
- valuesPerType[meta.type] = {
- positiveValues: [],
- negativeValues: []
- };
- }
-
- // Store these per type
- var positiveValues = valuesPerType[meta.type].positiveValues;
- var negativeValues = valuesPerType[meta.type].negativeValues;
-
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- positiveValues[index] = positiveValues[index] || 0;
- negativeValues[index] = negativeValues[index] || 0;
-
- if (opts.relativePoints) {
- positiveValues[index] = 100;
- } else {
- if (value < 0) {
- hasNegativeValues = true;
- negativeValues[index] += value;
- } else {
- hasPositiveValues = true;
- positiveValues[index] += value;
- }
- }
- });
- }
- });
-
- helpers.each(valuesPerType, function(valuesForType) {
- var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
- var minVal = helpers.min(values);
- var maxVal = helpers.max(values);
- me.min = me.min === null ? minVal : Math.min(me.min, minVal);
- me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
- });
-
- } else {
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
- }
-
- // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
- this.handleTickRangeOptions();
- },
- getTickLimit: function() {
- var maxTicks;
- var me = this;
- var tickOpts = me.options.ticks;
-
- if (me.isHorizontal()) {
- maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
- } else {
- // The factor of 2 used to scale the font size has been experimentally determined.
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);
- maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
- }
-
- return maxTicks;
- },
- // Called after the ticks are built. We need
- handleDirectionalChanges: function() {
- if (!this.isHorizontal()) {
- // We are in a vertical orientation. The top value is the highest. So reverse the array
- this.ticks.reverse();
- }
- },
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- // Utils
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- // This must be called after fit has been run so that
- // this.left, this.top, this.right, and this.bottom have been defined
- var me = this;
- var paddingLeft = me.paddingLeft;
- var paddingBottom = me.paddingBottom;
- var start = me.start;
-
- var rightValue = +me.getRightValue(value);
- var pixel;
- var innerDimension;
- var range = me.end - start;
-
- if (me.isHorizontal()) {
- innerDimension = me.width - (paddingLeft + me.paddingRight);
- pixel = me.left + (innerDimension / range * (rightValue - start));
- return Math.round(pixel + paddingLeft);
- } else {
- innerDimension = me.height - (me.paddingTop + paddingBottom);
- pixel = (me.bottom - paddingBottom) - (innerDimension / range * (rightValue - start));
- return Math.round(pixel);
- }
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var isHorizontal = me.isHorizontal();
- var paddingLeft = me.paddingLeft;
- var paddingBottom = me.paddingBottom;
- var innerDimension = isHorizontal ? me.width - (paddingLeft + me.paddingRight) : me.height - (me.paddingTop + paddingBottom);
- var offset = (isHorizontal ? pixel - me.left - paddingLeft : me.bottom - paddingBottom - pixel) / innerDimension;
- return me.start + ((me.end - me.start) * offset);
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);
- }
- });
- Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ var defaultConfig = {\r
+ position: "left",\r
+ ticks: {\r
+ callback: function(tickValue, index, ticks) {\r
+ // If we have lots of ticks, don't use the ones\r
+ var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];\r
+\r
+ // If we have a number like 2.5 as the delta, figure out how many decimal places we need\r
+ if (Math.abs(delta) > 1) {\r
+ if (tickValue !== Math.floor(tickValue)) {\r
+ // not an integer\r
+ delta = tickValue - Math.floor(tickValue);\r
+ }\r
+ }\r
+\r
+ var logDelta = helpers.log10(Math.abs(delta));\r
+ var tickString = '';\r
+\r
+ if (tickValue !== 0) {\r
+ var numDecimal = -1 * Math.floor(logDelta);\r
+ numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places\r
+ tickString = tickValue.toFixed(numDecimal);\r
+ } else {\r
+ tickString = '0'; // never show decimal places for 0\r
+ }\r
+\r
+ return tickString;\r
+ }\r
+ }\r
+ };\r
+\r
+ var LinearScale = Chart.Scale.extend({\r
+ determineDataLimits: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var chart = _this.chart;\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var isHorizontal = _this.isHorizontal();\r
+\r
+ function IDMatches(meta) {\r
+ return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;\r
+ }\r
+\r
+ // First Calculate the range\r
+ _this.min = null;\r
+ _this.max = null;\r
+\r
+ if (opts.stacked) {\r
+ var valuesPerType = {};\r
+ var hasPositiveValues = false;\r
+ var hasNegativeValues = false;\r
+\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (valuesPerType[meta.type] === undefined) {\r
+ valuesPerType[meta.type] = {\r
+ positiveValues: [],\r
+ negativeValues: []\r
+ };\r
+ }\r
+\r
+ // Store these per type\r
+ var positiveValues = valuesPerType[meta.type].positiveValues;\r
+ var negativeValues = valuesPerType[meta.type].negativeValues;\r
+\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ positiveValues[index] = positiveValues[index] || 0;\r
+ negativeValues[index] = negativeValues[index] || 0;\r
+\r
+ if (opts.relativePoints) {\r
+ positiveValues[index] = 100;\r
+ } else {\r
+ if (value < 0) {\r
+ hasNegativeValues = true;\r
+ negativeValues[index] += value;\r
+ } else {\r
+ hasPositiveValues = true;\r
+ positiveValues[index] += value;\r
+ }\r
+ }\r
+ });\r
+ }\r
+ });\r
+\r
+ helpers.each(valuesPerType, function(valuesForType) {\r
+ var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);\r
+ var minVal = helpers.min(values);\r
+ var maxVal = helpers.max(values);\r
+ _this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);\r
+ _this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);\r
+ });\r
+\r
+ } else {\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (_this.min === null) {\r
+ _this.min = value;\r
+ } else if (value < _this.min) {\r
+ _this.min = value;\r
+ }\r
+\r
+ if (_this.max === null) {\r
+ _this.max = value;\r
+ } else if (value > _this.max) {\r
+ _this.max = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ }\r
+\r
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,\r
+ // do nothing since that would make the chart weird. If the user really wants a weird chart\r
+ // axis, they can manually override it\r
+ if (tickOpts.beginAtZero) {\r
+ var minSign = helpers.sign(_this.min);\r
+ var maxSign = helpers.sign(_this.max);\r
+\r
+ if (minSign < 0 && maxSign < 0) {\r
+ // move the top up to 0\r
+ _this.max = 0;\r
+ } else if (minSign > 0 && maxSign > 0) {\r
+ // move the botttom down to 0\r
+ _this.min = 0;\r
+ }\r
+ }\r
+\r
+ if (tickOpts.min !== undefined) {\r
+ _this.min = tickOpts.min;\r
+ } else if (tickOpts.suggestedMin !== undefined) {\r
+ _this.min = Math.min(_this.min, tickOpts.suggestedMin);\r
+ }\r
+\r
+ if (tickOpts.max !== undefined) {\r
+ _this.max = tickOpts.max;\r
+ } else if (tickOpts.suggestedMax !== undefined) {\r
+ _this.max = Math.max(_this.max, tickOpts.suggestedMax);\r
+ }\r
+\r
+ if (_this.min === _this.max) {\r
+ _this.max++;\r
+\r
+ if (!tickOpts.beginAtZero) {\r
+ _this.min--;\r
+ }\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+ var isHorizontal = _this.isHorizontal();\r
+\r
+ var ticks = _this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+\r
+ var maxTicks;\r
+\r
+ if (isHorizontal) {\r
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.width / 50));\r
+ } else {\r
+ // The factor of 2 used to scale the font size has been experimentally determined.\r
+ var tickFontSize = getValueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);\r
+ maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(_this.height / (2 * tickFontSize)));\r
+ }\r
+\r
+ // Make sure we always have at least 2 ticks\r
+ maxTicks = Math.max(2, maxTicks);\r
+\r
+ // To get a "nice" value for the tick spacing, we will use the appropriately named\r
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks\r
+ // for details.\r
+\r
+ var spacing;\r
+ var fixedStepSizeSet = (tickOpts.fixedStepSize && tickOpts.fixedStepSize > 0) || (tickOpts.stepSize && tickOpts.stepSize > 0);\r
+ if (fixedStepSizeSet) {\r
+ spacing = getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize);\r
+ } else {\r
+ var niceRange = helpers.niceNum(_this.max - _this.min, false);\r
+ spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);\r
+ }\r
+ var niceMin = Math.floor(_this.min / spacing) * spacing;\r
+ var niceMax = Math.ceil(_this.max / spacing) * spacing;\r
+ var numSpaces = (niceMax - niceMin) / spacing;\r
+\r
+ // If very close to our rounded value, use it.\r
+ if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {\r
+ numSpaces = Math.round(numSpaces);\r
+ } else {\r
+ numSpaces = Math.ceil(numSpaces);\r
+ }\r
+\r
+ // Put the values into the ticks array\r
+ ticks.push(tickOpts.min !== undefined ? tickOpts.min : niceMin);\r
+ for (var j = 1; j < numSpaces; ++j) {\r
+ ticks.push(niceMin + (j * spacing));\r
+ }\r
+ ticks.push(tickOpts.max !== undefined ? tickOpts.max : niceMax);\r
+\r
+ if (!isHorizontal) {\r
+ // We are in a vertical orientation. The top value is the highest. So reverse the array\r
+ ticks.reverse();\r
+ }\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ _this.max = helpers.max(ticks);\r
+ _this.min = helpers.min(ticks);\r
+\r
+ if (tickOpts.reverse) {\r
+ ticks.reverse();\r
+\r
+ _this.start = _this.max;\r
+ _this.end = _this.min;\r
+ } else {\r
+ _this.start = _this.min;\r
+ _this.end = _this.max;\r
+ }\r
+ },\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ var _this = this;\r
+ _this.ticksAsNumbers = _this.ticks.slice();\r
+ _this.zeroLineIndex = _this.ticks.indexOf(0);\r
+\r
+ Chart.Scale.prototype.convertTicksToLabels.call(_this);\r
+ },\r
+ // Utils\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ // This must be called after fit has been run so that\r
+ // this.left, this.top, this.right, and this.bottom have been defined\r
+ var _this = this;\r
+ var paddingLeft = _this.paddingLeft;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var start = _this.start;\r
+\r
+ var rightValue = +_this.getRightValue(value);\r
+ var pixel;\r
+ var innerDimension;\r
+ var range = _this.end - start;\r
+\r
+ if (_this.isHorizontal()) {\r
+ innerDimension = _this.width - (paddingLeft + _this.paddingRight);\r
+ pixel = _this.left + (innerDimension / range * (rightValue - start));\r
+ return Math.round(pixel + paddingLeft);\r
+ } else {\r
+ innerDimension = _this.height - (_this.paddingTop + paddingBottom);\r
+ pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (rightValue - start));\r
+ return Math.round(pixel);\r
+ }\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var _this = this;\r
+ var isHorizontal = _this.isHorizontal();\r
+ var paddingLeft = _this.paddingLeft;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var innerDimension = isHorizontal ? _this.width - (paddingLeft + _this.paddingRight) : _this.height - (_this.paddingTop + paddingBottom);\r
+ var offset = (isHorizontal ? pixel - _this.left - paddingLeft : _this.bottom - paddingBottom - pixel) / innerDimension;\r
+ return _this.start + ((_this.end - _this.start) * offset);\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);\r
+\r
};
},{}],40:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers,
- noop = helpers.noop;
-
- Chart.LinearScaleBase = Chart.Scale.extend({
- handleTickRangeOptions: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
-
- // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,
- // do nothing since that would make the chart weird. If the user really wants a weird chart
- // axis, they can manually override it
- if (tickOpts.beginAtZero) {
- var minSign = helpers.sign(me.min);
- var maxSign = helpers.sign(me.max);
-
- if (minSign < 0 && maxSign < 0) {
- // move the top up to 0
- me.max = 0;
- } else if (minSign > 0 && maxSign > 0) {
- // move the botttom down to 0
- me.min = 0;
- }
- }
-
- if (tickOpts.min !== undefined) {
- me.min = tickOpts.min;
- } else if (tickOpts.suggestedMin !== undefined) {
- me.min = Math.min(me.min, tickOpts.suggestedMin);
- }
-
- if (tickOpts.max !== undefined) {
- me.max = tickOpts.max;
- } else if (tickOpts.suggestedMax !== undefined) {
- me.max = Math.max(me.max, tickOpts.suggestedMax);
- }
-
- if (me.min === me.max) {
- me.max++;
-
- if (!tickOpts.beginAtZero) {
- me.min--;
- }
- }
- },
- getTickLimit: noop,
- handleDirectionalChanges: noop,
-
- buildTicks: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var getValueOrDefault = helpers.getValueOrDefault;
- var isHorizontal = me.isHorizontal();
-
- var ticks = me.ticks = [];
-
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
-
- var maxTicks = me.getTickLimit();
-
- // Make sure we always have at least 2 ticks
- maxTicks = Math.max(2, maxTicks);
-
- // To get a "nice" value for the tick spacing, we will use the appropriately named
- // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
- // for details.
-
- var spacing;
- var fixedStepSizeSet = (tickOpts.fixedStepSize && tickOpts.fixedStepSize > 0) || (tickOpts.stepSize && tickOpts.stepSize > 0);
- if (fixedStepSizeSet) {
- spacing = getValueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize);
- } else {
- var niceRange = helpers.niceNum(me.max - me.min, false);
- spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);
- }
- var niceMin = Math.floor(me.min / spacing) * spacing;
- var niceMax = Math.ceil(me.max / spacing) * spacing;
- var numSpaces = (niceMax - niceMin) / spacing;
-
- // If very close to our rounded value, use it.
- if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
- numSpaces = Math.round(numSpaces);
- } else {
- numSpaces = Math.ceil(numSpaces);
- }
-
- // Put the values into the ticks array
- ticks.push(tickOpts.min !== undefined ? tickOpts.min : niceMin);
- for (var j = 1; j < numSpaces; ++j) {
- ticks.push(niceMin + (j * spacing));
- }
- ticks.push(tickOpts.max !== undefined ? tickOpts.max : niceMax);
-
- me.handleDirectionalChanges();
-
- // At this point, we need to update our max and min given the tick values since we have expanded the
- // range of the scale
- me.max = helpers.max(ticks);
- me.min = helpers.min(ticks);
-
- if (tickOpts.reverse) {
- ticks.reverse();
-
- me.start = me.max;
- me.end = me.min;
- } else {
- me.start = me.min;
- me.end = me.max;
- }
- },
- convertTicksToLabels: function() {
- var me = this;
- me.ticksAsNumbers = me.ticks.slice();
- me.zeroLineIndex = me.ticks.indexOf(0);
-
- Chart.Scale.prototype.convertTicksToLabels.call(me);
- },
- });
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+\r
+ var defaultConfig = {\r
+ position: "left",\r
+\r
+ // label settings\r
+ ticks: {\r
+ callback: function(value, index, arr) {\r
+ var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));\r
+\r
+ if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {\r
+ return value.toExponential();\r
+ } else {\r
+ return '';\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ var LogarithmicScale = Chart.Scale.extend({\r
+ determineDataLimits: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var chart = _this.chart;\r
+ var data = chart.data;\r
+ var datasets = data.datasets;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+ var isHorizontal = _this.isHorizontal();\r
+ function IDMatches(meta) {\r
+ return isHorizontal ? meta.xAxisID === _this.id : meta.yAxisID === _this.id;\r
+ }\r
+\r
+ // Calculate Range\r
+ _this.min = null;\r
+ _this.max = null;\r
+\r
+ if (opts.stacked) {\r
+ var valuesPerType = {};\r
+\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ if (valuesPerType[meta.type] === undefined) {\r
+ valuesPerType[meta.type] = [];\r
+ }\r
+\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var values = valuesPerType[meta.type];\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ values[index] = values[index] || 0;\r
+\r
+ if (opts.relativePoints) {\r
+ values[index] = 100;\r
+ } else {\r
+ // Don't need to split positive and negative since the log scale can't handle a 0 crossing\r
+ values[index] += value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+\r
+ helpers.each(valuesPerType, function(valuesForType) {\r
+ var minVal = helpers.min(valuesForType);\r
+ var maxVal = helpers.max(valuesForType);\r
+ _this.min = _this.min === null ? minVal : Math.min(_this.min, minVal);\r
+ _this.max = _this.max === null ? maxVal : Math.max(_this.max, maxVal);\r
+ });\r
+\r
+ } else {\r
+ helpers.each(datasets, function(dataset, datasetIndex) {\r
+ var meta = chart.getDatasetMeta(datasetIndex);\r
+ if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +_this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (_this.min === null) {\r
+ _this.min = value;\r
+ } else if (value < _this.min) {\r
+ _this.min = value;\r
+ }\r
+\r
+ if (_this.max === null) {\r
+ _this.max = value;\r
+ } else if (value > _this.max) {\r
+ _this.max = value;\r
+ }\r
+ });\r
+ }\r
+ });\r
+ }\r
+\r
+ _this.min = getValueOrDefault(tickOpts.min, _this.min);\r
+ _this.max = getValueOrDefault(tickOpts.max, _this.max);\r
+\r
+ if (_this.min === _this.max) {\r
+ if (_this.min !== 0 && _this.min !== null) {\r
+ _this.min = Math.pow(10, Math.floor(helpers.log10(_this.min)) - 1);\r
+ _this.max = Math.pow(10, Math.floor(helpers.log10(_this.max)) + 1);\r
+ } else {\r
+ _this.min = 1;\r
+ _this.max = 10;\r
+ }\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+ var _this = this;\r
+ var opts = _this.options;\r
+ var tickOpts = opts.ticks;\r
+ var getValueOrDefault = helpers.getValueOrDefault;\r
+\r
+ // Reset the ticks array. Later on, we will draw a grid line at these positions\r
+ // The array simply contains the numerical value of the spots where ticks will be\r
+ var ticks = _this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+\r
+ var tickVal = getValueOrDefault(tickOpts.min, Math.pow(10, Math.floor(helpers.log10(_this.min))));\r
+\r
+ while (tickVal < _this.max) {\r
+ ticks.push(tickVal);\r
+\r
+ var exp = Math.floor(helpers.log10(tickVal));\r
+ var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;\r
+\r
+ if (significand === 10) {\r
+ significand = 1;\r
+ ++exp;\r
+ }\r
+\r
+ tickVal = significand * Math.pow(10, exp);\r
+ }\r
+\r
+ var lastTick = getValueOrDefault(tickOpts.max, tickVal);\r
+ ticks.push(lastTick);\r
+\r
+ if (!_this.isHorizontal()) {\r
+ // We are in a vertical orientation. The top value is the highest. So reverse the array\r
+ ticks.reverse();\r
+ }\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ _this.max = helpers.max(ticks);\r
+ _this.min = helpers.min(ticks);\r
+\r
+ if (tickOpts.reverse) {\r
+ ticks.reverse();\r
+\r
+ _this.start = _this.max;\r
+ _this.end = _this.min;\r
+ } else {\r
+ _this.start = _this.min;\r
+ _this.end = _this.max;\r
+ }\r
+ },\r
+ convertTicksToLabels: function() {\r
+ this.tickValues = this.ticks.slice();\r
+\r
+ Chart.Scale.prototype.convertTicksToLabels.call(this);\r
+ },\r
+ // Get the correct tooltip label\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);\r
+ },\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ var _this = this;\r
+ var innerDimension;\r
+ var pixel;\r
+\r
+ var start = _this.start;\r
+ var newVal = +_this.getRightValue(value);\r
+ var range = helpers.log10(_this.end) - helpers.log10(start);\r
+ var paddingTop = _this.paddingTop;\r
+ var paddingBottom = _this.paddingBottom;\r
+ var paddingLeft = _this.paddingLeft;\r
+\r
+ if (_this.isHorizontal()) {\r
+\r
+ if (newVal === 0) {\r
+ pixel = _this.left + paddingLeft;\r
+ } else {\r
+ innerDimension = _this.width - (paddingLeft + _this.paddingRight);\r
+ pixel = _this.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));\r
+ pixel += paddingLeft;\r
+ }\r
+ } else {\r
+ // Bottom - top since pixels increase downard on a screen\r
+ if (newVal === 0) {\r
+ pixel = _this.top + paddingTop;\r
+ } else {\r
+ innerDimension = _this.height - (paddingTop + paddingBottom);\r
+ pixel = (_this.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));\r
+ }\r
+ }\r
+\r
+ return pixel;\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var _this = this;\r
+ var offset;\r
+ var range = helpers.log10(_this.end) - helpers.log10(_this.start);\r
+ var value;\r
+ var innerDimension;\r
+\r
+ if (_this.isHorizontal()) {\r
+ innerDimension = _this.width - (_this.paddingLeft + _this.paddingRight);\r
+ value = _this.start * Math.pow(10, (pixel - _this.left - _this.paddingLeft) * range / innerDimension);\r
+ } else {\r
+ innerDimension = _this.height - (_this.paddingTop + _this.paddingBottom);\r
+ value = Math.pow(10, (_this.bottom - _this.paddingBottom - pixel) * range / innerDimension) / _this.start;\r
+ }\r
+\r
+ return value;\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);\r
+\r
};
},{}],41:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
-
- var defaultConfig = {
- position: "left",
-
- // label settings
- ticks: {
- callback: function(value, index, arr) {
- var remain = value / (Math.pow(10, Math.floor(helpers.log10(value))));
-
- if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === arr.length - 1) {
- return value.toExponential();
- } else {
- return '';
- }
- }
- }
- };
-
- var LogarithmicScale = Chart.Scale.extend({
- determineDataLimits: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var chart = me.chart;
- var data = chart.data;
- var datasets = data.datasets;
- var getValueOrDefault = helpers.getValueOrDefault;
- var isHorizontal = me.isHorizontal();
- function IDMatches(meta) {
- return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
- }
-
- // Calculate Range
- me.min = null;
- me.max = null;
-
- if (opts.stacked) {
- var valuesPerType = {};
-
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- if (valuesPerType[meta.type] === undefined) {
- valuesPerType[meta.type] = [];
- }
-
- helpers.each(dataset.data, function(rawValue, index) {
- var values = valuesPerType[meta.type];
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- values[index] = values[index] || 0;
-
- if (opts.relativePoints) {
- values[index] = 100;
- } else {
- // Don't need to split positive and negative since the log scale can't handle a 0 crossing
- values[index] += value;
- }
- });
- }
- });
-
- helpers.each(valuesPerType, function(valuesForType) {
- var minVal = helpers.min(valuesForType);
- var maxVal = helpers.max(valuesForType);
- me.min = me.min === null ? minVal : Math.min(me.min, minVal);
- me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
- });
-
- } else {
- helpers.each(datasets, function(dataset, datasetIndex) {
- var meta = chart.getDatasetMeta(datasetIndex);
- if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
- }
-
- me.min = getValueOrDefault(tickOpts.min, me.min);
- me.max = getValueOrDefault(tickOpts.max, me.max);
-
- if (me.min === me.max) {
- if (me.min !== 0 && me.min !== null) {
- me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1);
- me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1);
- } else {
- me.min = 1;
- me.max = 10;
- }
- }
- },
- buildTicks: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- // Reset the ticks array. Later on, we will draw a grid line at these positions
- // The array simply contains the numerical value of the spots where ticks will be
- var ticks = me.ticks = [];
-
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
-
- var tickVal = getValueOrDefault(tickOpts.min, Math.pow(10, Math.floor(helpers.log10(me.min))));
-
- while (tickVal < me.max) {
- ticks.push(tickVal);
-
- var exp = Math.floor(helpers.log10(tickVal));
- var significand = Math.floor(tickVal / Math.pow(10, exp)) + 1;
-
- if (significand === 10) {
- significand = 1;
- ++exp;
- }
-
- tickVal = significand * Math.pow(10, exp);
- }
-
- var lastTick = getValueOrDefault(tickOpts.max, tickVal);
- ticks.push(lastTick);
-
- if (!me.isHorizontal()) {
- // We are in a vertical orientation. The top value is the highest. So reverse the array
- ticks.reverse();
- }
-
- // At this point, we need to update our max and min given the tick values since we have expanded the
- // range of the scale
- me.max = helpers.max(ticks);
- me.min = helpers.min(ticks);
-
- if (tickOpts.reverse) {
- ticks.reverse();
-
- me.start = me.max;
- me.end = me.min;
- } else {
- me.start = me.min;
- me.end = me.max;
- }
- },
- convertTicksToLabels: function() {
- this.tickValues = this.ticks.slice();
-
- Chart.Scale.prototype.convertTicksToLabels.call(this);
- },
- // Get the correct tooltip label
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);
- },
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- var innerDimension;
- var pixel;
-
- var start = me.start;
- var newVal = +me.getRightValue(value);
- var range = helpers.log10(me.end) - helpers.log10(start);
- var paddingTop = me.paddingTop;
- var paddingBottom = me.paddingBottom;
- var paddingLeft = me.paddingLeft;
-
- if (me.isHorizontal()) {
-
- if (newVal === 0) {
- pixel = me.left + paddingLeft;
- } else {
- innerDimension = me.width - (paddingLeft + me.paddingRight);
- pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
- pixel += paddingLeft;
- }
- } else {
- // Bottom - top since pixels increase downard on a screen
- if (newVal === 0) {
- pixel = me.top + paddingTop;
- } else {
- innerDimension = me.height - (paddingTop + paddingBottom);
- pixel = (me.bottom - paddingBottom) - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start)));
- }
- }
-
- return pixel;
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var offset;
- var range = helpers.log10(me.end) - helpers.log10(me.start);
- var value;
- var innerDimension;
-
- if (me.isHorizontal()) {
- innerDimension = me.width - (me.paddingLeft + me.paddingRight);
- value = me.start * Math.pow(10, (pixel - me.left - me.paddingLeft) * range / innerDimension);
- } else {
- innerDimension = me.height - (me.paddingTop + me.paddingBottom);
- value = Math.pow(10, (me.bottom - me.paddingBottom - pixel) * range / innerDimension) / me.start;
- }
-
- return value;
- }
- });
- Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);
-
+"use strict";\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var globalDefaults = Chart.defaults.global;\r
+\r
+ var defaultConfig = {\r
+ display: true,\r
+\r
+ //Boolean - Whether to animate scaling the chart from the centre\r
+ animate: true,\r
+ lineArc: false,\r
+ position: "chartArea",\r
+\r
+ angleLines: {\r
+ display: true,\r
+ color: "rgba(0, 0, 0, 0.1)",\r
+ lineWidth: 1\r
+ },\r
+\r
+ // label settings\r
+ ticks: {\r
+ //Boolean - Show a backdrop to the scale label\r
+ showLabelBackdrop: true,\r
+\r
+ //String - The colour of the label backdrop\r
+ backdropColor: "rgba(255,255,255,0.75)",\r
+\r
+ //Number - The backdrop padding above & below the label in pixels\r
+ backdropPaddingY: 2,\r
+\r
+ //Number - The backdrop padding to the side of the label in pixels\r
+ backdropPaddingX: 2\r
+ },\r
+\r
+ pointLabels: {\r
+ //Number - Point label font size in pixels\r
+ fontSize: 10,\r
+\r
+ //Function - Used to convert point labels\r
+ callback: function(label) {\r
+ return label;\r
+ }\r
+ }\r
+ };\r
+\r
+ var LinearRadialScale = Chart.Scale.extend({\r
+ getValueCount: function() {\r
+ return this.chart.data.labels.length;\r
+ },\r
+ setDimensions: function() {\r
+ var options = this.options;\r
+ // Set the unconstrained dimension before label rotation\r
+ this.width = this.maxWidth;\r
+ this.height = this.maxHeight;\r
+ this.xCenter = Math.round(this.width / 2);\r
+ this.yCenter = Math.round(this.height / 2);\r
+\r
+ var minSize = helpers.min([this.height, this.width]);\r
+ var tickFontSize = helpers.getValueOrDefault(options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ this.drawingArea = (options.display) ? (minSize / 2) - (tickFontSize / 2 + options.ticks.backdropPaddingY) : (minSize / 2);\r
+ },\r
+ determineDataLimits: function() {\r
+ this.min = null;\r
+ this.max = null;\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ if (this.chart.isDatasetVisible(datasetIndex)) {\r
+ var meta = this.chart.getDatasetMeta(datasetIndex);\r
+ helpers.each(dataset.data, function(rawValue, index) {\r
+ var value = +this.getRightValue(rawValue);\r
+ if (isNaN(value) || meta.data[index].hidden) {\r
+ return;\r
+ }\r
+\r
+ if (this.min === null) {\r
+ this.min = value;\r
+ } else if (value < this.min) {\r
+ this.min = value;\r
+ }\r
+\r
+ if (this.max === null) {\r
+ this.max = value;\r
+ } else if (value > this.max) {\r
+ this.max = value;\r
+ }\r
+ }, this);\r
+ }\r
+ }, this);\r
+\r
+ // If we are forcing it to begin at 0, but 0 will already be rendered on the chart,\r
+ // do nothing since that would make the chart weird. If the user really wants a weird chart\r
+ // axis, they can manually override it\r
+ if (this.options.ticks.beginAtZero) {\r
+ var minSign = helpers.sign(this.min);\r
+ var maxSign = helpers.sign(this.max);\r
+\r
+ if (minSign < 0 && maxSign < 0) {\r
+ // move the top up to 0\r
+ this.max = 0;\r
+ } else if (minSign > 0 && maxSign > 0) {\r
+ // move the botttom down to 0\r
+ this.min = 0;\r
+ }\r
+ }\r
+\r
+ if (this.options.ticks.min !== undefined) {\r
+ this.min = this.options.ticks.min;\r
+ } else if (this.options.ticks.suggestedMin !== undefined) {\r
+ this.min = Math.min(this.min, this.options.ticks.suggestedMin);\r
+ }\r
+\r
+ if (this.options.ticks.max !== undefined) {\r
+ this.max = this.options.ticks.max;\r
+ } else if (this.options.ticks.suggestedMax !== undefined) {\r
+ this.max = Math.max(this.max, this.options.ticks.suggestedMax);\r
+ }\r
+\r
+ if (this.min === this.max) {\r
+ this.min--;\r
+ this.max++;\r
+ }\r
+ },\r
+ buildTicks: function() {\r
+\r
+\r
+ this.ticks = [];\r
+\r
+ // Figure out what the max number of ticks we can support it is based on the size of\r
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50\r
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on\r
+ // the graph\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ var maxTicks = Math.min(this.options.ticks.maxTicksLimit ? this.options.ticks.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));\r
+ maxTicks = Math.max(2, maxTicks); // Make sure we always have at least 2 ticks\r
+\r
+ // To get a "nice" value for the tick spacing, we will use the appropriately named\r
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks\r
+ // for details.\r
+\r
+ var niceRange = helpers.niceNum(this.max - this.min, false);\r
+ var spacing = helpers.niceNum(niceRange / (maxTicks - 1), true);\r
+ var niceMin = Math.floor(this.min / spacing) * spacing;\r
+ var niceMax = Math.ceil(this.max / spacing) * spacing;\r
+\r
+ var numSpaces = Math.ceil((niceMax - niceMin) / spacing);\r
+\r
+ // Put the values into the ticks array\r
+ this.ticks.push(this.options.ticks.min !== undefined ? this.options.ticks.min : niceMin);\r
+ for (var j = 1; j < numSpaces; ++j) {\r
+ this.ticks.push(niceMin + (j * spacing));\r
+ }\r
+ this.ticks.push(this.options.ticks.max !== undefined ? this.options.ticks.max : niceMax);\r
+\r
+ // At this point, we need to update our max and min given the tick values since we have expanded the\r
+ // range of the scale\r
+ this.max = helpers.max(this.ticks);\r
+ this.min = helpers.min(this.ticks);\r
+\r
+ if (this.options.ticks.reverse) {\r
+ this.ticks.reverse();\r
+\r
+ this.start = this.max;\r
+ this.end = this.min;\r
+ } else {\r
+ this.start = this.min;\r
+ this.end = this.max;\r
+ }\r
+\r
+ this.zeroLineIndex = this.ticks.indexOf(0);\r
+ },\r
+ convertTicksToLabels: function() {\r
+ Chart.Scale.prototype.convertTicksToLabels.call(this);\r
+\r
+ // Point labels\r
+ this.pointLabels = this.chart.data.labels.map(this.options.pointLabels.callback, this);\r
+ },\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ },\r
+ fit: function() {\r
+ /*\r
+ * Right, this is really confusing and there is a lot of maths going on here\r
+ * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9\r
+ *\r
+ * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif\r
+ *\r
+ * Solution:\r
+ *\r
+ * We assume the radius of the polygon is half the size of the canvas at first\r
+ * at each index we check if the text overlaps.\r
+ *\r
+ * Where it does, we store that angle and that index.\r
+ *\r
+ * After finding the largest index and angle we calculate how much we need to remove\r
+ * from the shape radius to move the point inwards by that x.\r
+ *\r
+ * We average the left and right distances to get the maximum shape radius that can fit in the box\r
+ * along with labels.\r
+ *\r
+ * Once we have that, we can find the centre point for the chart, by taking the x text protrusion\r
+ * on each side, removing that from the size, halving it and adding the left x protrusion width.\r
+ *\r
+ * This will mean we have a shape fitted to the canvas, as large as it can be with the labels\r
+ * and position it in the most space efficient manner\r
+ *\r
+ * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif\r
+ */\r
+\r
+ var pointLabels = this.options.pointLabels;\r
+ var pointLabelFontSize = helpers.getValueOrDefault(pointLabels.fontSize, globalDefaults.defaultFontSize);\r
+ var pointLabeFontStyle = helpers.getValueOrDefault(pointLabels.fontStyle, globalDefaults.defaultFontStyle);\r
+ var pointLabeFontFamily = helpers.getValueOrDefault(pointLabels.fontFamily, globalDefaults.defaultFontFamily);\r
+ var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);\r
+\r
+ // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.\r
+ // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points\r
+ var largestPossibleRadius = helpers.min([(this.height / 2 - pointLabelFontSize - 5), this.width / 2]),\r
+ pointPosition,\r
+ i,\r
+ textWidth,\r
+ halfTextWidth,\r
+ furthestRight = this.width,\r
+ furthestRightIndex,\r
+ furthestRightAngle,\r
+ furthestLeft = 0,\r
+ furthestLeftIndex,\r
+ furthestLeftAngle,\r
+ xProtrusionLeft,\r
+ xProtrusionRight,\r
+ radiusReductionRight,\r
+ radiusReductionLeft,\r
+ maxWidthRadius;\r
+ this.ctx.font = pointLabeFont;\r
+\r
+ for (i = 0; i < this.getValueCount(); i++) {\r
+ // 5px to space the text slightly out - similar to what we do in the draw function.\r
+ pointPosition = this.getPointPosition(i, largestPossibleRadius);\r
+ textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;\r
+ if (i === 0 || i === this.getValueCount() / 2) {\r
+ // If we're at index zero, or exactly the middle, we're at exactly the top/bottom\r
+ // of the radar chart, so text will be aligned centrally, so we'll half it and compare\r
+ // w/left and right text sizes\r
+ halfTextWidth = textWidth / 2;\r
+ if (pointPosition.x + halfTextWidth > furthestRight) {\r
+ furthestRight = pointPosition.x + halfTextWidth;\r
+ furthestRightIndex = i;\r
+ }\r
+ if (pointPosition.x - halfTextWidth < furthestLeft) {\r
+ furthestLeft = pointPosition.x - halfTextWidth;\r
+ furthestLeftIndex = i;\r
+ }\r
+ } else if (i < this.getValueCount() / 2) {\r
+ // Less than half the values means we'll left align the text\r
+ if (pointPosition.x + textWidth > furthestRight) {\r
+ furthestRight = pointPosition.x + textWidth;\r
+ furthestRightIndex = i;\r
+ }\r
+ } else if (i > this.getValueCount() / 2) {\r
+ // More than half the values means we'll right align the text\r
+ if (pointPosition.x - textWidth < furthestLeft) {\r
+ furthestLeft = pointPosition.x - textWidth;\r
+ furthestLeftIndex = i;\r
+ }\r
+ }\r
+ }\r
+\r
+ xProtrusionLeft = furthestLeft;\r
+ xProtrusionRight = Math.ceil(furthestRight - this.width);\r
+\r
+ furthestRightAngle = this.getIndexAngle(furthestRightIndex);\r
+ furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);\r
+\r
+ radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI / 2);\r
+ radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI / 2);\r
+\r
+ // Ensure we actually need to reduce the size of the chart\r
+ radiusReductionRight = (helpers.isNumber(radiusReductionRight)) ? radiusReductionRight : 0;\r
+ radiusReductionLeft = (helpers.isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;\r
+\r
+ this.drawingArea = Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2);\r
+ this.setCenterPoint(radiusReductionLeft, radiusReductionRight);\r
+ },\r
+ setCenterPoint: function(leftMovement, rightMovement) {\r
+\r
+ var maxRight = this.width - rightMovement - this.drawingArea,\r
+ maxLeft = leftMovement + this.drawingArea;\r
+\r
+ this.xCenter = Math.round(((maxLeft + maxRight) / 2) + this.left);\r
+ // Always vertically in the centre as the text height doesn't change\r
+ this.yCenter = Math.round((this.height / 2) + this.top);\r
+ },\r
+\r
+ getIndexAngle: function(index) {\r
+ var angleMultiplier = (Math.PI * 2) / this.getValueCount();\r
+ // Start from the top instead of right, so remove a quarter of the circle\r
+\r
+ return index * angleMultiplier - (Math.PI / 2);\r
+ },\r
+ getDistanceFromCenterForValue: function(value) {\r
+ if (value === null) {\r
+ return 0; // null always in center\r
+ }\r
+\r
+ // Take into account half font size + the yPadding of the top value\r
+ var scalingFactor = this.drawingArea / (this.max - this.min);\r
+ if (this.options.reverse) {\r
+ return (this.max - value) * scalingFactor;\r
+ } else {\r
+ return (value - this.min) * scalingFactor;\r
+ }\r
+ },\r
+ getPointPosition: function(index, distanceFromCenter) {\r
+ var thisAngle = this.getIndexAngle(index);\r
+ return {\r
+ x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + this.xCenter,\r
+ y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + this.yCenter\r
+ };\r
+ },\r
+ getPointPositionForValue: function(index, value) {\r
+ return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));\r
+ },\r
+\r
+ getBasePosition: function() {\r
+ var me = this;\r
+ var min = me.min;\r
+ var max = me.max;\r
+\r
+ return me.getPointPositionForValue(0,\r
+ me.beginAtZero? 0:\r
+ min < 0 && max < 0? max :\r
+ min > 0 && max > 0? min :\r
+ 0);\r
+ },\r
+\r
+ draw: function() {\r
+ if (this.options.display) {\r
+ var ctx = this.ctx;\r
+ helpers.each(this.ticks, function(label, index) {\r
+ // Don't draw a centre value (if it is minimum)\r
+ if (index > 0 || this.options.reverse) {\r
+ var yCenterOffset = this.getDistanceFromCenterForValue(this.ticks[index]);\r
+ var yHeight = this.yCenter - yCenterOffset;\r
+\r
+ // Draw circular lines around the scale\r
+ if (this.options.gridLines.display) {\r
+ ctx.strokeStyle = this.options.gridLines.color;\r
+ ctx.lineWidth = this.options.gridLines.lineWidth;\r
+\r
+ if (this.options.lineArc) {\r
+ // Draw circular arcs between the points\r
+ ctx.beginPath();\r
+ ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI * 2);\r
+ ctx.closePath();\r
+ ctx.stroke();\r
+ } else {\r
+ // Draw straight lines connecting each index\r
+ ctx.beginPath();\r
+ for (var i = 0; i < this.getValueCount(); i++) {\r
+ var pointPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.ticks[index]));\r
+ if (i === 0) {\r
+ ctx.moveTo(pointPosition.x, pointPosition.y);\r
+ } else {\r
+ ctx.lineTo(pointPosition.x, pointPosition.y);\r
+ }\r
+ }\r
+ ctx.closePath();\r
+ ctx.stroke();\r
+ }\r
+ }\r
+\r
+ if (this.options.ticks.display) {\r
+ var tickFontColor = helpers.getValueOrDefault(this.options.ticks.fontColor, globalDefaults.defaultFontColor);\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, globalDefaults.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, globalDefaults.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, globalDefaults.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ ctx.font = tickLabelFont;\r
+\r
+ if (this.options.ticks.showLabelBackdrop) {\r
+ var labelWidth = ctx.measureText(label).width;\r
+ ctx.fillStyle = this.options.ticks.backdropColor;\r
+ ctx.fillRect(\r
+ this.xCenter - labelWidth / 2 - this.options.ticks.backdropPaddingX,\r
+ yHeight - tickFontSize / 2 - this.options.ticks.backdropPaddingY,\r
+ labelWidth + this.options.ticks.backdropPaddingX * 2,\r
+ tickFontSize + this.options.ticks.backdropPaddingY * 2\r
+ );\r
+ }\r
+\r
+ ctx.textAlign = 'center';\r
+ ctx.textBaseline = "middle";\r
+ ctx.fillStyle = tickFontColor;\r
+ ctx.fillText(label, this.xCenter, yHeight);\r
+ }\r
+ }\r
+ }, this);\r
+\r
+ if (!this.options.lineArc) {\r
+ ctx.lineWidth = this.options.angleLines.lineWidth;\r
+ ctx.strokeStyle = this.options.angleLines.color;\r
+\r
+ for (var i = this.getValueCount() - 1; i >= 0; i--) {\r
+ if (this.options.angleLines.display) {\r
+ var outerPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max));\r
+ ctx.beginPath();\r
+ ctx.moveTo(this.xCenter, this.yCenter);\r
+ ctx.lineTo(outerPosition.x, outerPosition.y);\r
+ ctx.stroke();\r
+ ctx.closePath();\r
+ }\r
+ // Extra 3px out for some label spacing\r
+ var pointLabelPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.options.reverse ? this.min : this.max) + 5);\r
+\r
+ var pointLabelFontColor = helpers.getValueOrDefault(this.options.pointLabels.fontColor, globalDefaults.defaultFontColor);\r
+ var pointLabelFontSize = helpers.getValueOrDefault(this.options.pointLabels.fontSize, globalDefaults.defaultFontSize);\r
+ var pointLabeFontStyle = helpers.getValueOrDefault(this.options.pointLabels.fontStyle, globalDefaults.defaultFontStyle);\r
+ var pointLabeFontFamily = helpers.getValueOrDefault(this.options.pointLabels.fontFamily, globalDefaults.defaultFontFamily);\r
+ var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);\r
+\r
+ ctx.font = pointLabeFont;\r
+ ctx.fillStyle = pointLabelFontColor;\r
+\r
+ var labelsCount = this.pointLabels.length,\r
+ halfLabelsCount = this.pointLabels.length / 2,\r
+ quarterLabelsCount = halfLabelsCount / 2,\r
+ upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),\r
+ exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);\r
+ if (i === 0) {\r
+ ctx.textAlign = 'center';\r
+ } else if (i === halfLabelsCount) {\r
+ ctx.textAlign = 'center';\r
+ } else if (i < halfLabelsCount) {\r
+ ctx.textAlign = 'left';\r
+ } else {\r
+ ctx.textAlign = 'right';\r
+ }\r
+\r
+ // Set the correct text baseline based on outer positioning\r
+ if (exactQuarter) {\r
+ ctx.textBaseline = 'middle';\r
+ } else if (upperHalf) {\r
+ ctx.textBaseline = 'bottom';\r
+ } else {\r
+ ctx.textBaseline = 'top';\r
+ }\r
+\r
+ ctx.fillText(this.pointLabels[i] ? this.pointLabels[i] : '', pointLabelPosition.x, pointLabelPosition.y);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("radialLinear", LinearRadialScale, defaultConfig);\r
+\r
};
},{}],42:[function(require,module,exports){
-"use strict";
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var globalDefaults = Chart.defaults.global;
-
- var defaultConfig = {
- display: true,
-
- //Boolean - Whether to animate scaling the chart from the centre
- animate: true,
- lineArc: false,
- position: "chartArea",
-
- angleLines: {
- display: true,
- color: "rgba(0, 0, 0, 0.1)",
- lineWidth: 1
- },
-
- // label settings
- ticks: {
- //Boolean - Show a backdrop to the scale label
- showLabelBackdrop: true,
-
- //String - The colour of the label backdrop
- backdropColor: "rgba(255,255,255,0.75)",
-
- //Number - The backdrop padding above & below the label in pixels
- backdropPaddingY: 2,
-
- //Number - The backdrop padding to the side of the label in pixels
- backdropPaddingX: 2
- },
-
- pointLabels: {
- //Number - Point label font size in pixels
- fontSize: 10,
-
- //Function - Used to convert point labels
- callback: function(label) {
- return label;
- }
- }
- };
-
- var LinearRadialScale = Chart.LinearScaleBase.extend({
- getValueCount: function() {
- return this.chart.data.labels.length;
- },
- setDimensions: function() {
- var me = this;
- var opts = me.options;
- var tickOpts = opts.ticks;
- // Set the unconstrained dimension before label rotation
- me.width = me.maxWidth;
- me.height = me.maxHeight;
- me.xCenter = Math.round(me.width / 2);
- me.yCenter = Math.round(me.height / 2);
-
- var minSize = helpers.min([me.height, me.width]);
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2);
- },
- determineDataLimits: function() {
- var me = this;
- var chart = me.chart;
- me.min = null;
- me.max = null;
-
-
- helpers.each(chart.data.datasets, function(dataset, datasetIndex) {
- if (chart.isDatasetVisible(datasetIndex)) {
- var meta = chart.getDatasetMeta(datasetIndex);
-
- helpers.each(dataset.data, function(rawValue, index) {
- var value = +me.getRightValue(rawValue);
- if (isNaN(value) || meta.data[index].hidden) {
- return;
- }
-
- if (me.min === null) {
- me.min = value;
- } else if (value < me.min) {
- me.min = value;
- }
-
- if (me.max === null) {
- me.max = value;
- } else if (value > me.max) {
- me.max = value;
- }
- });
- }
- });
-
- // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
- me.handleTickRangeOptions();
- },
- getTickLimit: function() {
- var tickOpts = this.options.ticks;
- var tickFontSize = helpers.getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize)));
- },
- convertTicksToLabels: function() {
- var me = this;
- Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me);
-
- // Point labels
- me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me);
- },
- getLabelForIndex: function(index, datasetIndex) {
- return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
- },
- fit: function() {
- /*
- * Right, this is really confusing and there is a lot of maths going on here
- * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9
- *
- * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif
- *
- * Solution:
- *
- * We assume the radius of the polygon is half the size of the canvas at first
- * at each index we check if the text overlaps.
- *
- * Where it does, we store that angle and that index.
- *
- * After finding the largest index and angle we calculate how much we need to remove
- * from the shape radius to move the point inwards by that x.
- *
- * We average the left and right distances to get the maximum shape radius that can fit in the box
- * along with labels.
- *
- * Once we have that, we can find the centre point for the chart, by taking the x text protrusion
- * on each side, removing that from the size, halving it and adding the left x protrusion width.
- *
- * This will mean we have a shape fitted to the canvas, as large as it can be with the labels
- * and position it in the most space efficient manner
- *
- * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif
- */
-
- var pointLabels = this.options.pointLabels;
- var pointLabelFontSize = helpers.getValueOrDefault(pointLabels.fontSize, globalDefaults.defaultFontSize);
- var pointLabeFontStyle = helpers.getValueOrDefault(pointLabels.fontStyle, globalDefaults.defaultFontStyle);
- var pointLabeFontFamily = helpers.getValueOrDefault(pointLabels.fontFamily, globalDefaults.defaultFontFamily);
- var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
-
- // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width.
- // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points
- var largestPossibleRadius = helpers.min([(this.height / 2 - pointLabelFontSize - 5), this.width / 2]),
- pointPosition,
- i,
- textWidth,
- halfTextWidth,
- furthestRight = this.width,
- furthestRightIndex,
- furthestRightAngle,
- furthestLeft = 0,
- furthestLeftIndex,
- furthestLeftAngle,
- xProtrusionLeft,
- xProtrusionRight,
- radiusReductionRight,
- radiusReductionLeft,
- maxWidthRadius;
- this.ctx.font = pointLabeFont;
-
- for (i = 0; i < this.getValueCount(); i++) {
- // 5px to space the text slightly out - similar to what we do in the draw function.
- pointPosition = this.getPointPosition(i, largestPossibleRadius);
- textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;
- if (i === 0 || i === this.getValueCount() / 2) {
- // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
- // of the radar chart, so text will be aligned centrally, so we'll half it and compare
- // w/left and right text sizes
- halfTextWidth = textWidth / 2;
- if (pointPosition.x + halfTextWidth > furthestRight) {
- furthestRight = pointPosition.x + halfTextWidth;
- furthestRightIndex = i;
- }
- if (pointPosition.x - halfTextWidth < furthestLeft) {
- furthestLeft = pointPosition.x - halfTextWidth;
- furthestLeftIndex = i;
- }
- } else if (i < this.getValueCount() / 2) {
- // Less than half the values means we'll left align the text
- if (pointPosition.x + textWidth > furthestRight) {
- furthestRight = pointPosition.x + textWidth;
- furthestRightIndex = i;
- }
- } else if (i > this.getValueCount() / 2) {
- // More than half the values means we'll right align the text
- if (pointPosition.x - textWidth < furthestLeft) {
- furthestLeft = pointPosition.x - textWidth;
- furthestLeftIndex = i;
- }
- }
- }
-
- xProtrusionLeft = furthestLeft;
- xProtrusionRight = Math.ceil(furthestRight - this.width);
-
- furthestRightAngle = this.getIndexAngle(furthestRightIndex);
- furthestLeftAngle = this.getIndexAngle(furthestLeftIndex);
-
- radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI / 2);
- radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI / 2);
-
- // Ensure we actually need to reduce the size of the chart
- radiusReductionRight = (helpers.isNumber(radiusReductionRight)) ? radiusReductionRight : 0;
- radiusReductionLeft = (helpers.isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0;
-
- this.drawingArea = Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2);
- this.setCenterPoint(radiusReductionLeft, radiusReductionRight);
- },
- setCenterPoint: function(leftMovement, rightMovement) {
- var me = this;
- var maxRight = me.width - rightMovement - me.drawingArea,
- maxLeft = leftMovement + me.drawingArea;
-
- me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left);
- // Always vertically in the centre as the text height doesn't change
- me.yCenter = Math.round((me.height / 2) + me.top);
- },
-
- getIndexAngle: function(index) {
- var angleMultiplier = (Math.PI * 2) / this.getValueCount();
- // Start from the top instead of right, so remove a quarter of the circle
-
- return index * angleMultiplier - (Math.PI / 2);
- },
- getDistanceFromCenterForValue: function(value) {
- var me = this;
-
- if (value === null) {
- return 0; // null always in center
- }
-
- // Take into account half font size + the yPadding of the top value
- var scalingFactor = me.drawingArea / (me.max - me.min);
- if (me.options.reverse) {
- return (me.max - value) * scalingFactor;
- } else {
- return (value - me.min) * scalingFactor;
- }
- },
- getPointPosition: function(index, distanceFromCenter) {
- var me = this;
- var thisAngle = me.getIndexAngle(index);
- return {
- x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter,
- y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter
- };
- },
- getPointPositionForValue: function(index, value) {
- return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
- },
-
- getBasePosition: function() {
- var me = this;
- var min = me.min;
- var max = me.max;
-
- return me.getPointPositionForValue(0,
- me.beginAtZero? 0:
- min < 0 && max < 0? max :
- min > 0 && max > 0? min :
- 0);
- },
-
- draw: function() {
- var me = this;
- var opts = me.options;
- var gridLineOpts = opts.gridLines;
- var tickOpts = opts.ticks;
- var angleLineOpts = opts.angleLines;
- var pointLabelOpts = opts.pointLabels;
- var getValueOrDefault = helpers.getValueOrDefault;
-
- if (opts.display) {
- var ctx = me.ctx;
-
- // Tick Font
- var tickFontSize = getValueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize);
- var tickFontStyle = getValueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle);
- var tickFontFamily = getValueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
-
- helpers.each(me.ticks, function(label, index) {
- // Don't draw a centre value (if it is minimum)
- if (index > 0 || opts.reverse) {
- var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]);
- var yHeight = me.yCenter - yCenterOffset;
-
- // Draw circular lines around the scale
- if (gridLineOpts.display) {
- ctx.strokeStyle = gridLineOpts.color;
- ctx.lineWidth = gridLineOpts.lineWidth;
-
- if (opts.lineArc) {
- // Draw circular arcs between the points
- ctx.beginPath();
- ctx.arc(me.xCenter, me.yCenter, yCenterOffset, 0, Math.PI * 2);
- ctx.closePath();
- ctx.stroke();
- } else {
- // Draw straight lines connecting each index
- ctx.beginPath();
- for (var i = 0; i < me.getValueCount(); i++) {
- var pointPosition = me.getPointPosition(i, yCenterOffset);
- if (i === 0) {
- ctx.moveTo(pointPosition.x, pointPosition.y);
- } else {
- ctx.lineTo(pointPosition.x, pointPosition.y);
- }
- }
- ctx.closePath();
- ctx.stroke();
- }
- }
-
- if (tickOpts.display) {
- var tickFontColor = getValueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor);
- ctx.font = tickLabelFont;
-
- if (tickOpts.showLabelBackdrop) {
- var labelWidth = ctx.measureText(label).width;
- ctx.fillStyle = tickOpts.backdropColor;
- ctx.fillRect(
- me.xCenter - labelWidth / 2 - tickOpts.backdropPaddingX,
- yHeight - tickFontSize / 2 - tickOpts.backdropPaddingY,
- labelWidth + tickOpts.backdropPaddingX * 2,
- tickFontSize + tickOpts.backdropPaddingY * 2
- );
- }
-
- ctx.textAlign = 'center';
- ctx.textBaseline = "middle";
- ctx.fillStyle = tickFontColor;
- ctx.fillText(label, me.xCenter, yHeight);
- }
- }
- });
-
- if (!opts.lineArc) {
- ctx.lineWidth = angleLineOpts.lineWidth;
- ctx.strokeStyle = angleLineOpts.color;
-
- var outerDistance = me.getDistanceFromCenterForValue(opts.reverse ? me.min : me.max);
-
- // Point Label Font
- var pointLabelFontSize = getValueOrDefault(pointLabelOpts.fontSize, globalDefaults.defaultFontSize);
- var pointLabeFontStyle = getValueOrDefault(pointLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
- var pointLabeFontFamily = getValueOrDefault(pointLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
- var pointLabeFont = helpers.fontString(pointLabelFontSize, pointLabeFontStyle, pointLabeFontFamily);
-
- for (var i = me.getValueCount() - 1; i >= 0; i--) {
- if (angleLineOpts.display) {
- var outerPosition = me.getPointPosition(i, outerDistance);
- ctx.beginPath();
- ctx.moveTo(me.xCenter, me.yCenter);
- ctx.lineTo(outerPosition.x, outerPosition.y);
- ctx.stroke();
- ctx.closePath();
- }
- // Extra 3px out for some label spacing
- var pointLabelPosition = me.getPointPosition(i, outerDistance + 5);
-
- // Keep this in loop since we may support array properties here
- var pointLabelFontColor = getValueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor);
- ctx.font = pointLabeFont;
- ctx.fillStyle = pointLabelFontColor;
-
- var pointLabels = me.pointLabels,
- labelsCount = pointLabels.length,
- halfLabelsCount = pointLabels.length / 2,
- quarterLabelsCount = halfLabelsCount / 2,
- upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
- exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
- if (i === 0) {
- ctx.textAlign = 'center';
- } else if (i === halfLabelsCount) {
- ctx.textAlign = 'center';
- } else if (i < halfLabelsCount) {
- ctx.textAlign = 'left';
- } else {
- ctx.textAlign = 'right';
- }
-
- // Set the correct text baseline based on outer positioning
- if (exactQuarter) {
- ctx.textBaseline = 'middle';
- } else if (upperHalf) {
- ctx.textBaseline = 'bottom';
- } else {
- ctx.textBaseline = 'top';
- }
-
- ctx.fillText(pointLabels[i] ? pointLabels[i] : '', pointLabelPosition.x, pointLabelPosition.y);
- }
- }
- }
- }
- });
- Chart.scaleService.registerScaleType("radialLinear", LinearRadialScale, defaultConfig);
-
-};
-
-},{}],43:[function(require,module,exports){
-/*global window: false */
-"use strict";
-
-var moment = require(1);
-moment = typeof(moment) === 'function' ? moment : window.moment;
-
-module.exports = function(Chart) {
-
- var helpers = Chart.helpers;
- var time = {
- units: [{
- name: 'millisecond',
- steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]
- }, {
- name: 'second',
- steps: [1, 2, 5, 10, 30]
- }, {
- name: 'minute',
- steps: [1, 2, 5, 10, 30]
- }, {
- name: 'hour',
- steps: [1, 2, 3, 6, 12]
- }, {
- name: 'day',
- steps: [1, 2, 5]
- }, {
- name: 'week',
- maxStep: 4
- }, {
- name: 'month',
- maxStep: 3
- }, {
- name: 'quarter',
- maxStep: 4
- }, {
- name: 'year',
- maxStep: false
- }]
- };
-
- var defaultConfig = {
- position: "bottom",
-
- time: {
- parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
- format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/
- unit: false, // false == automatic or override with week, month, year, etc.
- round: false, // none, or override with week, month, year, etc.
- displayFormat: false, // DEPRECATED
- isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/
-
- // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/
- displayFormats: {
- 'millisecond': 'h:mm:ss.SSS a', // 11:20:01.123 AM,
- 'second': 'h:mm:ss a', // 11:20:01 AM
- 'minute': 'h:mm:ss a', // 11:20:01 AM
- 'hour': 'MMM D, hA', // Sept 4, 5PM
- 'day': 'll', // Sep 4 2015
- 'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?
- 'month': 'MMM YYYY', // Sept 2015
- 'quarter': '[Q]Q - YYYY', // Q3
- 'year': 'YYYY' // 2015
- }
- },
- ticks: {
- autoSkip: false
- }
- };
-
- var TimeScale = Chart.Scale.extend({
- initialize: function() {
- if (!moment) {
- throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');
- }
-
- Chart.Scale.prototype.initialize.call(this);
- },
- getLabelMoment: function(datasetIndex, index) {
- return this.labelMoments[datasetIndex][index];
- },
- getMomentStartOf: function(tick) {
- var me = this;
- if (me.options.time.unit === 'week' && me.options.time.isoWeekday !== false) {
- return tick.clone().startOf('isoWeek').isoWeekday(me.options.time.isoWeekday);
- } else {
- return tick.clone().startOf(me.tickUnit);
- }
- },
- determineDataLimits: function() {
- var me = this;
- me.labelMoments = [];
-
- // Only parse these once. If the dataset does not have data as x,y pairs, we will use
- // these
- var scaleLabelMoments = [];
- if (me.chart.data.labels && me.chart.data.labels.length > 0) {
- helpers.each(me.chart.data.labels, function(label, index) {
- var labelMoment = me.parseTime(label);
-
- if (labelMoment.isValid()) {
- if (me.options.time.round) {
- labelMoment.startOf(me.options.time.round);
- }
- scaleLabelMoments.push(labelMoment);
- }
- }, me);
-
- me.firstTick = moment.min.call(me, scaleLabelMoments);
- me.lastTick = moment.max.call(me, scaleLabelMoments);
- } else {
- me.firstTick = null;
- me.lastTick = null;
- }
-
- helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
- var momentsForDataset = [];
- var datasetVisible = me.chart.isDatasetVisible(datasetIndex);
-
- if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {
- helpers.each(dataset.data, function(value, index) {
- var labelMoment = me.parseTime(me.getRightValue(value));
-
- if (labelMoment.isValid()) {
- if (me.options.time.round) {
- labelMoment.startOf(me.options.time.round);
- }
- momentsForDataset.push(labelMoment);
-
- if (datasetVisible) {
- // May have gone outside the scale ranges, make sure we keep the first and last ticks updated
- me.firstTick = me.firstTick !== null ? moment.min(me.firstTick, labelMoment) : labelMoment;
- me.lastTick = me.lastTick !== null ? moment.max(me.lastTick, labelMoment) : labelMoment;
- }
- }
- }, me);
- } else {
- // We have no labels. Use the ones from the scale
- momentsForDataset = scaleLabelMoments;
- }
-
- me.labelMoments.push(momentsForDataset);
- }, me);
-
- // Set these after we've done all the data
- if (me.options.time.min) {
- me.firstTick = me.parseTime(me.options.time.min);
- }
-
- if (me.options.time.max) {
- me.lastTick = me.parseTime(me.options.time.max);
- }
-
- // We will modify these, so clone for later
- me.firstTick = (me.firstTick || moment()).clone();
- me.lastTick = (me.lastTick || moment()).clone();
- },
- buildTicks: function(index) {
- var me = this;
-
- me.ctx.save();
- var tickFontSize = helpers.getValueOrDefault(me.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);
- var tickFontStyle = helpers.getValueOrDefault(me.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);
- var tickFontFamily = helpers.getValueOrDefault(me.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);
- var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
- me.ctx.font = tickLabelFont;
-
- me.ticks = [];
- me.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step
- me.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc)
-
- // Set unit override if applicable
- if (me.options.time.unit) {
- me.tickUnit = me.options.time.unit || 'day';
- me.displayFormat = me.options.time.displayFormats[me.tickUnit];
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, 1);
- } else {
- // Determine the smallest needed unit of the time
- var innerWidth = me.isHorizontal() ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
-
- // Crude approximation of what the label length might be
- var tempFirstLabel = me.tickFormatFunction(me.firstTick, 0, []);
- var tickLabelWidth = me.ctx.measureText(tempFirstLabel).width;
- var cosRotation = Math.cos(helpers.toRadians(me.options.ticks.maxRotation));
- var sinRotation = Math.sin(helpers.toRadians(me.options.ticks.maxRotation));
- tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
- var labelCapacity = innerWidth / (tickLabelWidth);
-
- // Start as small as possible
- me.tickUnit = 'millisecond';
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- me.displayFormat = me.options.time.displayFormats[me.tickUnit];
-
- var unitDefinitionIndex = 0;
- var unitDefinition = time.units[unitDefinitionIndex];
-
- // While we aren't ideal and we don't have units left
- while (unitDefinitionIndex < time.units.length) {
- // Can we scale this unit. If `false` we can scale infinitely
- me.unitScale = 1;
-
- if (helpers.isArray(unitDefinition.steps) && Math.ceil(me.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) {
- // Use one of the prefedined steps
- for (var idx = 0; idx < unitDefinition.steps.length; ++idx) {
- if (unitDefinition.steps[idx] >= Math.ceil(me.scaleSizeInUnits / labelCapacity)) {
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, unitDefinition.steps[idx]);
- break;
- }
- }
-
- break;
- } else if ((unitDefinition.maxStep === false) || (Math.ceil(me.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) {
- // We have a max step. Scale this unit
- me.unitScale = helpers.getValueOrDefault(me.options.time.unitStepSize, Math.ceil(me.scaleSizeInUnits / labelCapacity));
- break;
- } else {
- // Move to the next unit up
- ++unitDefinitionIndex;
- unitDefinition = time.units[unitDefinitionIndex];
-
- me.tickUnit = unitDefinition.name;
- var leadingUnitBuffer = me.firstTick.diff(me.getMomentStartOf(me.firstTick), me.tickUnit, true);
- var trailingUnitBuffer = me.getMomentStartOf(me.lastTick.clone().add(1, me.tickUnit)).diff(me.lastTick, me.tickUnit, true);
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer;
- me.displayFormat = me.options.time.displayFormats[unitDefinition.name];
- }
- }
- }
-
- var roundedStart;
-
- // Only round the first tick if we have no hard minimum
- if (!me.options.time.min) {
- me.firstTick = me.getMomentStartOf(me.firstTick);
- roundedStart = me.firstTick;
- } else {
- roundedStart = me.getMomentStartOf(me.firstTick);
- }
-
- // Only round the last tick if we have no hard maximum
- if (!me.options.time.max) {
- var roundedEnd = me.getMomentStartOf(me.lastTick);
- if (roundedEnd.diff(me.lastTick, me.tickUnit, true) !== 0) {
- // Do not use end of because we need me to be in the next time unit
- me.lastTick = me.getMomentStartOf(me.lastTick.add(1, me.tickUnit));
- }
- }
-
- me.smallestLabelSeparation = me.width;
-
- helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
- for (var i = 1; i < me.labelMoments[datasetIndex].length; i++) {
- me.smallestLabelSeparation = Math.min(me.smallestLabelSeparation, me.labelMoments[datasetIndex][i].diff(me.labelMoments[datasetIndex][i - 1], me.tickUnit, true));
- }
- }, me);
-
- // Tick displayFormat override
- if (me.options.time.displayFormat) {
- me.displayFormat = me.options.time.displayFormat;
- }
-
- // first tick. will have been rounded correctly if options.time.min is not specified
- me.ticks.push(me.firstTick.clone());
-
- // For every unit in between the first and last moment, create a moment and add it to the ticks tick
- for (var i = 1; i <= me.scaleSizeInUnits; ++i) {
- var newTick = roundedStart.clone().add(i, me.tickUnit);
-
- // Are we greater than the max time
- if (me.options.time.max && newTick.diff(me.lastTick, me.tickUnit, true) >= 0) {
- break;
- }
-
- if (i % me.unitScale === 0) {
- me.ticks.push(newTick);
- }
- }
-
- // Always show the right tick
- var diff = me.ticks[me.ticks.length - 1].diff(me.lastTick, me.tickUnit);
- if (diff !== 0 || me.scaleSizeInUnits === 0) {
- // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart
- // but the last tick was not rounded.
- if (me.options.time.max) {
- me.ticks.push(me.lastTick.clone());
- me.scaleSizeInUnits = me.lastTick.diff(me.ticks[0], me.tickUnit, true);
- } else {
- me.ticks.push(me.lastTick.clone());
- me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
- }
- }
-
- me.ctx.restore();
- },
- // Get tooltip label
- getLabelForIndex: function(index, datasetIndex) {
- var me = this;
- var label = me.chart.data.labels && index < me.chart.data.labels.length ? me.chart.data.labels[index] : '';
-
- if (typeof me.chart.data.datasets[datasetIndex].data[0] === 'object') {
- label = me.getRightValue(me.chart.data.datasets[datasetIndex].data[index]);
- }
-
- // Format nicely
- if (me.options.time.tooltipFormat) {
- label = me.parseTime(label).format(me.options.time.tooltipFormat);
- }
-
- return label;
- },
- // Function to format an individual tick mark
- tickFormatFunction: function tickFormatFunction(tick, index, ticks) {
- var formattedTick = tick.format(this.displayFormat);
- var tickOpts = this.options.ticks;
- var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);
-
- if (callback) {
- return callback(formattedTick, index, ticks);
- } else {
- return formattedTick;
- }
- },
- convertTicksToLabels: function() {
- var me = this;
- me.tickMoments = me.ticks;
- me.ticks = me.ticks.map(me.tickFormatFunction, me);
- },
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
- var me = this;
- var labelMoment = value && value.isValid && value.isValid() ? value : me.getLabelMoment(datasetIndex, index);
-
- if (labelMoment) {
- var offset = labelMoment.diff(me.firstTick, me.tickUnit, true);
-
- var decimal = offset / me.scaleSizeInUnits;
-
- if (me.isHorizontal()) {
- var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
- var valueWidth = innerWidth / Math.max(me.ticks.length - 1, 1);
- var valueOffset = (innerWidth * decimal) + me.paddingLeft;
-
- return me.left + Math.round(valueOffset);
- } else {
- var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
- var valueHeight = innerHeight / Math.max(me.ticks.length - 1, 1);
- var heightOffset = (innerHeight * decimal) + me.paddingTop;
-
- return me.top + Math.round(heightOffset);
- }
- }
- },
- getPixelForTick: function(index, includeOffset) {
- return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);
- },
- getValueForPixel: function(pixel) {
- var me = this;
- var innerDimension = me.isHorizontal() ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
- var offset = (pixel - (me.isHorizontal() ? me.left + me.paddingLeft : me.top + me.paddingTop)) / innerDimension;
- offset *= me.scaleSizeInUnits;
- return me.firstTick.clone().add(moment.duration(offset, me.tickUnit).asSeconds(), 'seconds');
- },
- parseTime: function(label) {
- var me = this;
- if (typeof me.options.time.parser === 'string') {
- return moment(label, me.options.time.parser);
- }
- if (typeof me.options.time.parser === 'function') {
- return me.options.time.parser(label);
- }
- // Date objects
- if (typeof label.getMonth === 'function' || typeof label === 'number') {
- return moment(label);
- }
- // Moment support
- if (label.isValid && label.isValid()) {
- return label;
- }
- // Custom parsing (return an instance of moment)
- if (typeof me.options.time.format !== 'string' && me.options.time.format.call) {
- console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale");
- return me.options.time.format(label);
- }
- // Moment format parsing
- return moment(label, me.options.time.format);
- }
- });
- Chart.scaleService.registerScaleType("time", TimeScale, defaultConfig);
-
-};
+/*global window: false */\r
+"use strict";\r
+\r
+var moment = require('moment');\r
+moment = typeof(moment) === 'function' ? moment : window.moment;\r
+\r
+module.exports = function(Chart) {\r
+\r
+ var helpers = Chart.helpers;\r
+ var time = {\r
+ units: [{\r
+ name: 'millisecond',\r
+ steps: [1, 2, 5, 10, 20, 50, 100, 250, 500]\r
+ }, {\r
+ name: 'second',\r
+ steps: [1, 2, 5, 10, 30]\r
+ }, {\r
+ name: 'minute',\r
+ steps: [1, 2, 5, 10, 30]\r
+ }, {\r
+ name: 'hour',\r
+ steps: [1, 2, 3, 6, 12]\r
+ }, {\r
+ name: 'day',\r
+ steps: [1, 2, 5]\r
+ }, {\r
+ name: 'week',\r
+ maxStep: 4\r
+ }, {\r
+ name: 'month',\r
+ maxStep: 3\r
+ }, {\r
+ name: 'quarter',\r
+ maxStep: 4\r
+ }, {\r
+ name: 'year',\r
+ maxStep: false\r
+ }]\r
+ };\r
+\r
+ var defaultConfig = {\r
+ position: "bottom",\r
+\r
+ time: {\r
+ parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment\r
+ format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/\r
+ unit: false, // false == automatic or override with week, month, year, etc.\r
+ round: false, // none, or override with week, month, year, etc.\r
+ displayFormat: false, // DEPRECATED\r
+ isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/\r
+\r
+ // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/\r
+ displayFormats: {\r
+ 'millisecond': 'h:mm:ss.SSS a', // 11:20:01.123 AM,\r
+ 'second': 'h:mm:ss a', // 11:20:01 AM\r
+ 'minute': 'h:mm:ss a', // 11:20:01 AM\r
+ 'hour': 'MMM D, hA', // Sept 4, 5PM\r
+ 'day': 'll', // Sep 4 2015\r
+ 'week': 'll', // Week 46, or maybe "[W]WW - YYYY" ?\r
+ 'month': 'MMM YYYY', // Sept 2015\r
+ 'quarter': '[Q]Q - YYYY', // Q3\r
+ 'year': 'YYYY' // 2015\r
+ }\r
+ },\r
+ ticks: {\r
+ autoSkip: false\r
+ }\r
+ };\r
+\r
+ var TimeScale = Chart.Scale.extend({\r
+ initialize: function() {\r
+ if (!moment) {\r
+ throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com');\r
+ }\r
+\r
+ Chart.Scale.prototype.initialize.call(this);\r
+ },\r
+ getLabelMoment: function(datasetIndex, index) {\r
+ return this.labelMoments[datasetIndex][index];\r
+ },\r
+ getMomentStartOf: function(tick) {\r
+ if (this.options.time.unit === 'week' && this.options.time.isoWeekday !== false) {\r
+ return tick.clone().startOf('isoWeek').isoWeekday(this.options.time.isoWeekday);\r
+ } else {\r
+ return tick.clone().startOf(this.tickUnit);\r
+ }\r
+ },\r
+ determineDataLimits: function() {\r
+ this.labelMoments = [];\r
+\r
+ // Only parse these once. If the dataset does not have data as x,y pairs, we will use\r
+ // these\r
+ var scaleLabelMoments = [];\r
+ if (this.chart.data.labels && this.chart.data.labels.length > 0) {\r
+ helpers.each(this.chart.data.labels, function(label, index) {\r
+ var labelMoment = this.parseTime(label);\r
+\r
+ if (labelMoment.isValid()) {\r
+ if (this.options.time.round) {\r
+ labelMoment.startOf(this.options.time.round);\r
+ }\r
+ scaleLabelMoments.push(labelMoment);\r
+ }\r
+ }, this);\r
+\r
+ this.firstTick = moment.min.call(this, scaleLabelMoments);\r
+ this.lastTick = moment.max.call(this, scaleLabelMoments);\r
+ } else {\r
+ this.firstTick = null;\r
+ this.lastTick = null;\r
+ }\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ var momentsForDataset = [];\r
+ var datasetVisible = this.chart.isDatasetVisible(datasetIndex);\r
+\r
+ if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {\r
+ helpers.each(dataset.data, function(value, index) {\r
+ var labelMoment = this.parseTime(this.getRightValue(value));\r
+\r
+ if (labelMoment.isValid()) {\r
+ if (this.options.time.round) {\r
+ labelMoment.startOf(this.options.time.round);\r
+ }\r
+ momentsForDataset.push(labelMoment);\r
+\r
+ if (datasetVisible) {\r
+ // May have gone outside the scale ranges, make sure we keep the first and last ticks updated\r
+ this.firstTick = this.firstTick !== null ? moment.min(this.firstTick, labelMoment) : labelMoment;\r
+ this.lastTick = this.lastTick !== null ? moment.max(this.lastTick, labelMoment) : labelMoment;\r
+ }\r
+ }\r
+ }, this);\r
+ } else {\r
+ // We have no labels. Use the ones from the scale\r
+ momentsForDataset = scaleLabelMoments;\r
+ }\r
+\r
+ this.labelMoments.push(momentsForDataset);\r
+ }, this);\r
+\r
+ // Set these after we've done all the data\r
+ if (this.options.time.min) {\r
+ this.firstTick = this.parseTime(this.options.time.min);\r
+ }\r
+\r
+ if (this.options.time.max) {\r
+ this.lastTick = this.parseTime(this.options.time.max);\r
+ }\r
+\r
+ // We will modify these, so clone for later\r
+ this.firstTick = (this.firstTick || moment()).clone();\r
+ this.lastTick = (this.lastTick || moment()).clone();\r
+ },\r
+ buildTicks: function(index) {\r
+\r
+ this.ctx.save();\r
+ var tickFontSize = helpers.getValueOrDefault(this.options.ticks.fontSize, Chart.defaults.global.defaultFontSize);\r
+ var tickFontStyle = helpers.getValueOrDefault(this.options.ticks.fontStyle, Chart.defaults.global.defaultFontStyle);\r
+ var tickFontFamily = helpers.getValueOrDefault(this.options.ticks.fontFamily, Chart.defaults.global.defaultFontFamily);\r
+ var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);\r
+ this.ctx.font = tickLabelFont;\r
+\r
+ this.ticks = [];\r
+ this.unitScale = 1; // How much we scale the unit by, ie 2 means 2x unit per step\r
+ this.scaleSizeInUnits = 0; // How large the scale is in the base unit (seconds, minutes, etc)\r
+\r
+ // Set unit override if applicable\r
+ if (this.options.time.unit) {\r
+ this.tickUnit = this.options.time.unit || 'day';\r
+ this.displayFormat = this.options.time.displayFormats[this.tickUnit];\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, 1);\r
+ } else {\r
+ // Determine the smallest needed unit of the time\r
+ var innerWidth = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+\r
+ // Crude approximation of what the label length might be\r
+ var tempFirstLabel = this.tickFormatFunction(this.firstTick, 0, []);\r
+ var tickLabelWidth = this.ctx.measureText(tempFirstLabel).width;\r
+ var cosRotation = Math.cos(helpers.toRadians(this.options.ticks.maxRotation));\r
+ var sinRotation = Math.sin(helpers.toRadians(this.options.ticks.maxRotation));\r
+ tickLabelWidth = (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);\r
+ var labelCapacity = innerWidth / (tickLabelWidth);\r
+\r
+ // Start as small as possible\r
+ this.tickUnit = 'millisecond';\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ this.displayFormat = this.options.time.displayFormats[this.tickUnit];\r
+\r
+ var unitDefinitionIndex = 0;\r
+ var unitDefinition = time.units[unitDefinitionIndex];\r
+\r
+ // While we aren't ideal and we don't have units left\r
+ while (unitDefinitionIndex < time.units.length) {\r
+ // Can we scale this unit. If `false` we can scale infinitely\r
+ this.unitScale = 1;\r
+\r
+ if (helpers.isArray(unitDefinition.steps) && Math.ceil(this.scaleSizeInUnits / labelCapacity) < helpers.max(unitDefinition.steps)) {\r
+ // Use one of the prefedined steps\r
+ for (var idx = 0; idx < unitDefinition.steps.length; ++idx) {\r
+ if (unitDefinition.steps[idx] >= Math.ceil(this.scaleSizeInUnits / labelCapacity)) {\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, unitDefinition.steps[idx]);\r
+ break;\r
+ }\r
+ }\r
+\r
+ break;\r
+ } else if ((unitDefinition.maxStep === false) || (Math.ceil(this.scaleSizeInUnits / labelCapacity) < unitDefinition.maxStep)) {\r
+ // We have a max step. Scale this unit\r
+ this.unitScale = helpers.getValueOrDefault(this.options.time.unitStepSize, Math.ceil(this.scaleSizeInUnits / labelCapacity));\r
+ break;\r
+ } else {\r
+ // Move to the next unit up\r
+ ++unitDefinitionIndex;\r
+ unitDefinition = time.units[unitDefinitionIndex];\r
+\r
+ this.tickUnit = unitDefinition.name;\r
+ var leadingUnitBuffer = this.firstTick.diff(this.getMomentStartOf(this.firstTick), this.tickUnit, true);\r
+ var trailingUnitBuffer = this.getMomentStartOf(this.lastTick.clone().add(1, this.tickUnit)).diff(this.lastTick, this.tickUnit, true);\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true) + leadingUnitBuffer + trailingUnitBuffer;\r
+ this.displayFormat = this.options.time.displayFormats[unitDefinition.name];\r
+ }\r
+ }\r
+ }\r
+\r
+ var roundedStart;\r
+\r
+ // Only round the first tick if we have no hard minimum\r
+ if (!this.options.time.min) {\r
+ this.firstTick = this.getMomentStartOf(this.firstTick);\r
+ roundedStart = this.firstTick;\r
+ } else {\r
+ roundedStart = this.getMomentStartOf(this.firstTick);\r
+ }\r
+\r
+ // Only round the last tick if we have no hard maximum\r
+ if (!this.options.time.max) {\r
+ var roundedEnd = this.getMomentStartOf(this.lastTick);\r
+ if (roundedEnd.diff(this.lastTick, this.tickUnit, true) !== 0) {\r
+ // Do not use end of because we need this to be in the next time unit\r
+ this.lastTick = this.getMomentStartOf(this.lastTick.add(1, this.tickUnit));\r
+ }\r
+ }\r
+\r
+ this.smallestLabelSeparation = this.width;\r
+\r
+ helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {\r
+ for (var i = 1; i < this.labelMoments[datasetIndex].length; i++) {\r
+ this.smallestLabelSeparation = Math.min(this.smallestLabelSeparation, this.labelMoments[datasetIndex][i].diff(this.labelMoments[datasetIndex][i - 1], this.tickUnit, true));\r
+ }\r
+ }, this);\r
+\r
+ // Tick displayFormat override\r
+ if (this.options.time.displayFormat) {\r
+ this.displayFormat = this.options.time.displayFormat;\r
+ }\r
+\r
+ // first tick. will have been rounded correctly if options.time.min is not specified\r
+ this.ticks.push(this.firstTick.clone());\r
+\r
+ // For every unit in between the first and last moment, create a moment and add it to the ticks tick\r
+ for (var i = 1; i <= this.scaleSizeInUnits; ++i) {\r
+ var newTick = roundedStart.clone().add(i, this.tickUnit);\r
+\r
+ // Are we greater than the max time\r
+ if (this.options.time.max && newTick.diff(this.lastTick, this.tickUnit, true) >= 0) {\r
+ break;\r
+ }\r
+\r
+ if (i % this.unitScale === 0) {\r
+ this.ticks.push(newTick);\r
+ }\r
+ }\r
+\r
+ // Always show the right tick\r
+ var diff = this.ticks[this.ticks.length - 1].diff(this.lastTick, this.tickUnit);\r
+ if (diff !== 0 || this.scaleSizeInUnits === 0) {\r
+ // this is a weird case. If the <max> option is the same as the end option, we can't just diff the times because the tick was created from the roundedStart\r
+ // but the last tick was not rounded.\r
+ if (this.options.time.max) {\r
+ this.ticks.push(this.lastTick.clone());\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.ticks[0], this.tickUnit, true);\r
+ } else {\r
+ this.ticks.push(this.lastTick.clone());\r
+ this.scaleSizeInUnits = this.lastTick.diff(this.firstTick, this.tickUnit, true);\r
+ }\r
+ }\r
+\r
+ this.ctx.restore();\r
+ },\r
+ // Get tooltip label\r
+ getLabelForIndex: function(index, datasetIndex) {\r
+ var label = this.chart.data.labels && index < this.chart.data.labels.length ? this.chart.data.labels[index] : '';\r
+\r
+ if (typeof this.chart.data.datasets[datasetIndex].data[0] === 'object') {\r
+ label = this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);\r
+ }\r
+\r
+ // Format nicely\r
+ if (this.options.time.tooltipFormat) {\r
+ label = this.parseTime(label).format(this.options.time.tooltipFormat);\r
+ }\r
+\r
+ return label;\r
+ },\r
+ // Function to format an individual tick mark\r
+ tickFormatFunction: function tickFormatFunction(tick, index, ticks) {\r
+ var formattedTick = tick.format(this.displayFormat);\r
+ var tickOpts = this.options.ticks;\r
+ var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);\r
+\r
+ if (callback) {\r
+ return callback(formattedTick, index, ticks);\r
+ } else {\r
+ return formattedTick;\r
+ }\r
+ },\r
+ convertTicksToLabels: function() {\r
+ this.tickMoments = this.ticks;\r
+ this.ticks = this.ticks.map(this.tickFormatFunction, this);\r
+ },\r
+ getPixelForValue: function(value, index, datasetIndex, includeOffset) {\r
+ var labelMoment = value && value.isValid && value.isValid() ? value : this.getLabelMoment(datasetIndex, index);\r
+\r
+ if (labelMoment) {\r
+ var offset = labelMoment.diff(this.firstTick, this.tickUnit, true);\r
+\r
+ var decimal = offset / this.scaleSizeInUnits;\r
+\r
+ if (this.isHorizontal()) {\r
+ var innerWidth = this.width - (this.paddingLeft + this.paddingRight);\r
+ var valueWidth = innerWidth / Math.max(this.ticks.length - 1, 1);\r
+ var valueOffset = (innerWidth * decimal) + this.paddingLeft;\r
+\r
+ return this.left + Math.round(valueOffset);\r
+ } else {\r
+ var innerHeight = this.height - (this.paddingTop + this.paddingBottom);\r
+ var valueHeight = innerHeight / Math.max(this.ticks.length - 1, 1);\r
+ var heightOffset = (innerHeight * decimal) + this.paddingTop;\r
+\r
+ return this.top + Math.round(heightOffset);\r
+ }\r
+ }\r
+ },\r
+ getPixelForTick: function(index, includeOffset) {\r
+ return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);\r
+ },\r
+ getValueForPixel: function(pixel) {\r
+ var innerDimension = this.isHorizontal() ? this.width - (this.paddingLeft + this.paddingRight) : this.height - (this.paddingTop + this.paddingBottom);\r
+ var offset = (pixel - (this.isHorizontal() ? this.left + this.paddingLeft : this.top + this.paddingTop)) / innerDimension;\r
+ offset *= this.scaleSizeInUnits;\r
+ return this.firstTick.clone().add(moment.duration(offset, this.tickUnit).asSeconds(), 'seconds');\r
+ },\r
+ parseTime: function(label) {\r
+ if (typeof this.options.time.parser === 'string') {\r
+ return moment(label, this.options.time.parser);\r
+ }\r
+ if (typeof this.options.time.parser === 'function') {\r
+ return this.options.time.parser(label);\r
+ }\r
+ // Date objects\r
+ if (typeof label.getMonth === 'function' || typeof label === 'number') {\r
+ return moment(label);\r
+ }\r
+ // Moment support\r
+ if (label.isValid && label.isValid()) {\r
+ return label;\r
+ }\r
+ // Custom parsing (return an instance of moment)\r
+ if (typeof this.options.time.format !== 'string' && this.options.time.format.call) {\r
+ console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale");\r
+ return this.options.time.format(label);\r
+ }\r
+ // Moment format parsing\r
+ return moment(label, this.options.time.format);\r
+ }\r
+ });\r
+ Chart.scaleService.registerScaleType("time", TimeScale, defaultConfig);\r
+\r
+};\r
-},{"1":1}]},{},[7])(7)
-});
\ No newline at end of file
+},{"moment":1}]},{},[7]);
* Released under the MIT license
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
*/
-!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Chart=t()}}(function(){return function t(e,a,i){function n(r,l){if(!a[r]){if(!e[r]){var s="function"==typeof require&&require;if(!l&&s)return s(r,!0);if(o)return o(r,!0);var d=new Error("Cannot find module '"+r+"'");throw d.code="MODULE_NOT_FOUND",d}var u=a[r]={exports:{}};e[r][0].call(u.exports,function(t){var a=e[r][1][t];return n(a?a:t)},u,u.exports,t,e,a,i)}return a[r].exports}for(var o="function"==typeof require&&require,r=0;r<i.length;r++)n(i[r]);return n}({1:[function(t,e,a){},{}],2:[function(t,e,a){function i(t){if(t){var e=/^#([a-fA-F0-9]{3})$/,a=/^#([a-fA-F0-9]{6})$/,i=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,n=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,o=/(\w+)/,r=[0,0,0],l=1,s=t.match(e);if(s){s=s[1];for(var d=0;d<r.length;d++)r[d]=parseInt(s[d]+s[d],16)}else if(s=t.match(a)){s=s[1];for(var d=0;d<r.length;d++)r[d]=parseInt(s.slice(2*d,2*d+2),16)}else if(s=t.match(i)){for(var d=0;d<r.length;d++)r[d]=parseInt(s[d+1]);l=parseFloat(s[4])}else if(s=t.match(n)){for(var d=0;d<r.length;d++)r[d]=Math.round(2.55*parseFloat(s[d+1]));l=parseFloat(s[4])}else if(s=t.match(o)){if("transparent"==s[1])return[0,0,0,0];if(r=y[s[1]],!r)return}for(var d=0;d<r.length;d++)r[d]=v(r[d],0,255);return l=l||0==l?v(l,0,1):1,r[3]=l,r}}function n(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,a=t.match(e);if(a){var i=parseFloat(a[4]),n=v(parseInt(a[1]),0,360),o=v(parseFloat(a[2]),0,100),r=v(parseFloat(a[3]),0,100),l=v(isNaN(i)?1:i,0,1);return[n,o,r,l]}}}function o(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,a=t.match(e);if(a){var i=parseFloat(a[4]),n=v(parseInt(a[1]),0,360),o=v(parseFloat(a[2]),0,100),r=v(parseFloat(a[3]),0,100),l=v(isNaN(i)?1:i,0,1);return[n,o,r,l]}}}function r(t){var e=i(t);return e&&e.slice(0,3)}function l(t){var e=n(t);return e&&e.slice(0,3)}function s(t){var e=i(t);return e?e[3]:(e=n(t))?e[3]:(e=o(t))?e[3]:void 0}function d(t){return"#"+x(t[0])+x(t[1])+x(t[2])}function u(t,e){return 1>e||t[3]&&t[3]<1?c(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"}function c(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function h(t,e){if(1>e||t[3]&&t[3]<1)return f(t,e);var a=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),n=Math.round(t[2]/255*100);return"rgb("+a+"%, "+i+"%, "+n+"%)"}function f(t,e){var a=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),n=Math.round(t[2]/255*100);return"rgba("+a+"%, "+i+"%, "+n+"%, "+(e||t[3]||1)+")"}function g(t,e){return 1>e||t[3]&&t[3]<1?p(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"}function p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function m(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"}function b(t){return k[t.slice(0,3)]}function v(t,e,a){return Math.min(Math.max(e,t),a)}function x(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var y=t(6);e.exports={getRgba:i,getHsla:n,getRgb:r,getHsl:l,getHwb:o,getAlpha:s,hexString:d,rgbString:u,rgbaString:c,percentString:h,percentaString:f,hslString:g,hslaString:p,hwbString:m,keyword:b};var k={};for(var S in y)k[y[S]]=S},{6:6}],3:[function(t,e,a){var i=t(5),n=t(2),o=function(t){if(t instanceof o)return t;if(!(this instanceof o))return new o(t);this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;if("string"==typeof t)if(e=n.getRgba(t))this.setValues("rgb",e);else if(e=n.getHsla(t))this.setValues("hsl",e);else{if(!(e=n.getHwb(t)))throw new Error('Unable to parse color from string "'+t+'"');this.setValues("hwb",e)}else if("object"==typeof t)if(e=t,void 0!==e.r||void 0!==e.red)this.setValues("rgb",e);else if(void 0!==e.l||void 0!==e.lightness)this.setValues("hsl",e);else if(void 0!==e.v||void 0!==e.value)this.setValues("hsv",e);else if(void 0!==e.w||void 0!==e.whiteness)this.setValues("hwb",e);else{if(void 0===e.c&&void 0===e.cyan)throw new Error("Unable to parse color from object "+JSON.stringify(t));this.setValues("cmyk",e)}};o.prototype={rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=0>t?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return n.hexString(this.values.rgb)},rgbString:function(){return n.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return n.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return n.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return n.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return n.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return n.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return n.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],a=0;a<t.length;a++){var i=t[a]/255;e[a]=.03928>=i?i/12.92:Math.pow((i+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),a=t.luminosity();return e>a?(e+.05)/(a+.05):(a+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb,e=(299*t[0]+587*t[1]+114*t[2])/1e3;return 128>e},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;3>e;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,a=(e[0]+t)%360;return e[0]=0>a?360+a:a,this.setValues("hsl",e),this},mix:function(t,e){var a=this,i=t,n=void 0===e?.5:e,o=2*n-1,r=a.alpha()-i.alpha(),l=((o*r===-1?o:(o+r)/(1+o*r))+1)/2,s=1-l;return this.rgb(l*a.red()+s*i.red(),l*a.green()+s*i.green(),l*a.blue()+s*i.blue()).alpha(a.alpha()*n+i.alpha()*(1-n))},toJSON:function(){return this.rgb()},clone:function(){var t,e,a=new o,i=this.values,n=a.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],e={}.toString.call(t),"[object Array]"===e?n[r]=t.slice(0):"[object Number]"===e?n[r]=t:console.error("unexpected color value:",t));return a}},o.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},o.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},o.prototype.getValues=function(t){for(var e=this.values,a={},i=0;i<t.length;i++)a[t.charAt(i)]=e[t][i];return 1!==e.alpha&&(a.a=e.alpha),a},o.prototype.setValues=function(t,e){var a,n=this.values,o=this.spaces,r=this.maxes,l=1;if("alpha"===t)l=e;else if(e.length)n[t]=e.slice(0,t.length),l=e[t.length];else if(void 0!==e[t.charAt(0)]){for(a=0;a<t.length;a++)n[t][a]=e[t.charAt(a)];l=e.a}else if(void 0!==e[o[t][0]]){var s=o[t];for(a=0;a<t.length;a++)n[t][a]=e[s[a]];l=e.alpha}if(n.alpha=Math.max(0,Math.min(1,void 0===l?n.alpha:l)),"alpha"===t)return!1;var d;for(a=0;a<t.length;a++)d=Math.max(0,Math.min(r[t][a],n[t][a])),n[t][a]=Math.round(d);for(var u in o)u!==t&&(n[u]=i[t][u](n[t]));return!0},o.prototype.setSpace=function(t,e){var a=e[0];return void 0===a?this.getValues(t):("number"==typeof a&&(a=Array.prototype.slice.call(e)),this.setValues(t,a),this)},o.prototype.setChannel=function(t,e,a){var i=this.values[t];return void 0===a?i[e]:a===i[e]?this:(i[e]=a,this.setValues(t,i),this)},"undefined"!=typeof window&&(window.Color=o),e.exports=o},{2:2,5:5}],4:[function(t,e,a){function i(t){var e,a,i,n=t[0]/255,o=t[1]/255,r=t[2]/255,l=Math.min(n,o,r),s=Math.max(n,o,r),d=s-l;return s==l?e=0:n==s?e=(o-r)/d:o==s?e=2+(r-n)/d:r==s&&(e=4+(n-o)/d),e=Math.min(60*e,360),0>e&&(e+=360),i=(l+s)/2,a=s==l?0:.5>=i?d/(s+l):d/(2-s-l),[e,100*a,100*i]}function n(t){var e,a,i,n=t[0],o=t[1],r=t[2],l=Math.min(n,o,r),s=Math.max(n,o,r),d=s-l;return a=0==s?0:d/s*1e3/10,s==l?e=0:n==s?e=(o-r)/d:o==s?e=2+(r-n)/d:r==s&&(e=4+(n-o)/d),e=Math.min(60*e,360),0>e&&(e+=360),i=s/255*1e3/10,[e,a,i]}function o(t){var e=t[0],a=t[1],n=t[2],o=i(t)[0],r=1/255*Math.min(e,Math.min(a,n)),n=1-1/255*Math.max(e,Math.max(a,n));return[o,100*r,100*n]}function l(t){var e,a,i,n,o=t[0]/255,r=t[1]/255,l=t[2]/255;return n=Math.min(1-o,1-r,1-l),e=(1-o-n)/(1-n)||0,a=(1-r-n)/(1-n)||0,i=(1-l-n)/(1-n)||0,[100*e,100*a,100*i,100*n]}function s(t){return Q[JSON.stringify(t)]}function d(t){var e=t[0]/255,a=t[1]/255,i=t[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,a=a>.04045?Math.pow((a+.055)/1.055,2.4):a/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92;var n=.4124*e+.3576*a+.1805*i,o=.2126*e+.7152*a+.0722*i,r=.0193*e+.1192*a+.9505*i;return[100*n,100*o,100*r]}function u(t){var e,a,i,n=d(t),o=n[0],r=n[1],l=n[2];return o/=95.047,r/=100,l/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,l=l>.008856?Math.pow(l,1/3):7.787*l+16/116,e=116*r-16,a=500*(o-r),i=200*(r-l),[e,a,i]}function c(t){return W(u(t))}function h(t){var e,a,i,n,o,r=t[0]/360,l=t[1]/100,s=t[2]/100;if(0==l)return o=255*s,[o,o,o];a=.5>s?s*(1+l):s+l-s*l,e=2*s-a,n=[0,0,0];for(var d=0;3>d;d++)i=r+1/3*-(d-1),0>i&&i++,i>1&&i--,o=1>6*i?e+6*(a-e)*i:1>2*i?a:2>3*i?e+(a-e)*(2/3-i)*6:e,n[d]=255*o;return n}function f(t){var e,a,i=t[0],n=t[1]/100,o=t[2]/100;return 0===o?[0,0,0]:(o*=2,n*=1>=o?o:2-o,a=(o+n)/2,e=2*n/(o+n),[i,100*e,100*a])}function p(t){return o(h(t))}function m(t){return l(h(t))}function v(t){return s(h(t))}function x(t){var e=t[0]/60,a=t[1]/100,i=t[2]/100,n=Math.floor(e)%6,o=e-Math.floor(e),r=255*i*(1-a),l=255*i*(1-a*o),s=255*i*(1-a*(1-o)),i=255*i;switch(n){case 0:return[i,s,r];case 1:return[l,i,r];case 2:return[r,i,s];case 3:return[r,l,i];case 4:return[s,r,i];case 5:return[i,r,l]}}function y(t){var e,a,i=t[0],n=t[1]/100,o=t[2]/100;return a=(2-n)*o,e=n*o,e/=1>=a?a:2-a,e=e||0,a/=2,[i,100*e,100*a]}function k(t){return o(x(t))}function S(t){return l(x(t))}function w(t){return s(x(t))}function C(t){var e,a,i,n,o=t[0]/360,l=t[1]/100,s=t[2]/100,d=l+s;switch(d>1&&(l/=d,s/=d),e=Math.floor(6*o),a=1-s,i=6*o-e,0!=(1&e)&&(i=1-i),n=l+i*(a-l),e){default:case 6:case 0:r=a,g=n,b=l;break;case 1:r=n,g=a,b=l;break;case 2:r=l,g=a,b=n;break;case 3:r=l,g=n,b=a;break;case 4:r=n,g=l,b=a;break;case 5:r=a,g=l,b=n}return[255*r,255*g,255*b]}function M(t){return i(C(t))}function D(t){return n(C(t))}function A(t){return l(C(t))}function T(t){return s(C(t))}function I(t){var e,a,i,n=t[0]/100,o=t[1]/100,r=t[2]/100,l=t[3]/100;return e=1-Math.min(1,n*(1-l)+l),a=1-Math.min(1,o*(1-l)+l),i=1-Math.min(1,r*(1-l)+l),[255*e,255*a,255*i]}function P(t){return i(I(t))}function F(t){return n(I(t))}function _(t){return o(I(t))}function R(t){return s(I(t))}function V(t){var e,a,i,n=t[0]/100,o=t[1]/100,r=t[2]/100;return e=3.2406*n+-1.5372*o+r*-.4986,a=n*-.9689+1.8758*o+.0415*r,i=.0557*n+o*-.204+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e=12.92*e,a=a>.0031308?1.055*Math.pow(a,1/2.4)-.055:a=12.92*a,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i=12.92*i,e=Math.min(Math.max(0,e),1),a=Math.min(Math.max(0,a),1),i=Math.min(Math.max(0,i),1),[255*e,255*a,255*i]}function L(t){var e,a,i,n=t[0],o=t[1],r=t[2];return n/=95.047,o/=100,r/=108.883,n=n>.008856?Math.pow(n,1/3):7.787*n+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*o-16,a=500*(n-o),i=200*(o-r),[e,a,i]}function O(t){return W(L(t))}function B(t){var e,a,i,n,o=t[0],r=t[1],l=t[2];return 8>=o?(a=100*o/903.3,n=7.787*(a/100)+16/116):(a=100*Math.pow((o+16)/116,3),n=Math.pow(a/100,1/3)),e=.008856>=e/95.047?e=95.047*(r/500+n-16/116)/7.787:95.047*Math.pow(r/500+n,3),i=.008859>=i/108.883?i=108.883*(n-l/200-16/116)/7.787:108.883*Math.pow(n-l/200,3),[e,a,i]}function W(t){var e,a,i,n=t[0],o=t[1],r=t[2];return e=Math.atan2(r,o),a=360*e/2/Math.PI,0>a&&(a+=360),i=Math.sqrt(o*o+r*r),[n,i,a]}function z(t){return V(B(t))}function H(t){var e,a,i,n=t[0],o=t[1],r=t[2];return i=r/360*2*Math.PI,e=o*Math.cos(i),a=o*Math.sin(i),[n,e,a]}function N(t){return B(H(t))}function E(t){return z(H(t))}function U(t){return G[t]}function q(t){return i(U(t))}function j(t){return n(U(t))}function Y(t){return o(U(t))}function J(t){return l(U(t))}function X(t){return u(U(t))}function Z(t){return d(U(t))}e.exports={rgb2hsl:i,rgb2hsv:n,rgb2hwb:o,rgb2cmyk:l,rgb2keyword:s,rgb2xyz:d,rgb2lab:u,rgb2lch:c,hsl2rgb:h,hsl2hsv:f,hsl2hwb:p,hsl2cmyk:m,hsl2keyword:v,hsv2rgb:x,hsv2hsl:y,hsv2hwb:k,hsv2cmyk:S,hsv2keyword:w,hwb2rgb:C,hwb2hsl:M,hwb2hsv:D,hwb2cmyk:A,hwb2keyword:T,cmyk2rgb:I,cmyk2hsl:P,cmyk2hsv:F,cmyk2hwb:_,cmyk2keyword:R,keyword2rgb:U,keyword2hsl:q,keyword2hsv:j,keyword2hwb:Y,keyword2cmyk:J,keyword2lab:X,keyword2xyz:Z,xyz2rgb:V,xyz2lab:L,xyz2lch:O,lab2xyz:B,lab2rgb:z,lab2lch:W,lch2lab:H,lch2xyz:N,lch2rgb:E};var G={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},Q={};for(var $ in G)Q[JSON.stringify(G[$])]=$},{}],5:[function(t,e,a){var i=t(4),n=function(){return new d};for(var o in i){n[o+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(o);var r=/(\w+)2(\w+)/.exec(o),l=r[1],s=r[2];n[l]=n[l]||{},n[l][s]=n[o]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var a=i[t](e);if("string"==typeof a||void 0===a)return a;for(var n=0;n<a.length;n++)a[n]=Math.round(a[n]);return a}}(o)}var d=function(){this.convs={}};d.prototype.routeSpace=function(t,e){var a=e[0];return void 0===a?this.getValues(t):("number"==typeof a&&(a=Array.prototype.slice.call(e)),this.setValues(t,a))},d.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},d.prototype.getValues=function(t){var e=this.convs[t];if(!e){var a=this.space,i=this.convs[a];e=n[a][t](i),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){d.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=n},{4:4}],6:[function(t,e,a){e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,a){var i=t(26)();t(25)(i),t(24)(i),t(21)(i),t(22)(i),t(23)(i),t(27)(i),t(31)(i),t(29)(i),t(30)(i),t(32)(i),t(28)(i),t(33)(i),t(34)(i),t(35)(i),t(36)(i),t(37)(i),t(40)(i),t(38)(i),t(39)(i),t(41)(i),t(42)(i),t(43)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i),window.Chart=e.exports=i},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,34:34,35:35,36:36,37:37,38:38,39:39,40:40,41:41,42:42,43:43,8:8,9:9}],8:[function(t,e,a){"use strict";e.exports=function(t){t.Bar=function(e,a){return a.type="bar",new t(e,a)}}},{}],9:[function(t,e,a){"use strict";e.exports=function(t){t.Bubble=function(e,a){return a.type="bubble",new t(e,a)}}},{}],10:[function(t,e,a){"use strict";e.exports=function(t){t.Doughnut=function(e,a){return a.type="doughnut",new t(e,a)}}},{}],11:[function(t,e,a){"use strict";e.exports=function(t){t.Line=function(e,a){return a.type="line",new t(e,a)}}},{}],12:[function(t,e,a){"use strict";e.exports=function(t){t.PolarArea=function(e,a){return a.type="polarArea",new t(e,a)}}},{}],13:[function(t,e,a){"use strict";e.exports=function(t){t.Radar=function(e,a){return a.options=t.helpers.configMerge({aspectRatio:1},a.options),a.type="radar",new t(e,a)}}},{}],14:[function(t,e,a){"use strict";e.exports=function(t){var e={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){return"("+t.xLabel+", "+t.yLabel+")"}}}};t.defaults.scatter=e,t.controllers.scatter=t.controllers.line,t.Scatter=function(e,a){return a.type="scatter",new t(e,a)}}},{}],15:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(e,a){t.DatasetController.prototype.initialize.call(this,e,a),this.getMeta().bar=!0},getBarCount:function(){var t=this,a=0;return e.each(t.chart.data.datasets,function(e,i){var n=t.chart.getDatasetMeta(i);n.bar&&t.chart.isDatasetVisible(i)&&++a},t),a},update:function(t){var a=this;e.each(a.getMeta().data,function(e,i){a.updateElement(e,i,t)},a)},updateElement:function(t,a,i){var n=this,o=n.getMeta(),r=n.getScaleForId(o.xAxisID),l=n.getScaleForId(o.yAxisID),s=l.getBasePixel(),d=n.chart.options.elements.rectangle,u=t.custom||{},c=n.getDataset();e.extend(t,{_xScale:r,_yScale:l,_datasetIndex:n.index,_index:a,_model:{x:n.calculateBarX(a,n.index),y:i?s:n.calculateBarY(a,n.index),label:n.chart.data.labels[a],datasetLabel:c.label,base:i?s:n.calculateBarBase(n.index,a),width:n.calculateBarWidth(a),backgroundColor:u.backgroundColor?u.backgroundColor:e.getValueAtIndexOrDefault(c.backgroundColor,a,d.backgroundColor),borderSkipped:u.borderSkipped?u.borderSkipped:d.borderSkipped,borderColor:u.borderColor?u.borderColor:e.getValueAtIndexOrDefault(c.borderColor,a,d.borderColor),borderWidth:u.borderWidth?u.borderWidth:e.getValueAtIndexOrDefault(c.borderWidth,a,d.borderWidth)}}),t.pivot()},calculateBarBase:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=0;if(n.options.stacked){var r=a.chart,l=r.data.datasets,s=l[t].data[e];if(0>s)for(var d=0;t>d;d++){var u=l[d],c=r.getDatasetMeta(d);c.bar&&c.yAxisID===n.id&&r.isDatasetVisible(d)&&(o+=u.data[e]<0?u.data[e]:0)}else for(var h=0;t>h;h++){var f=l[h],g=r.getDatasetMeta(h);g.bar&&g.yAxisID===n.id&&r.isDatasetVisible(h)&&(o+=f.data[e]>0?f.data[e]:0)}return n.getPixelForValue(o)}return n.getBasePixel()},getRuler:function(t){var e,a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=a.getBarCount();e="category"===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var r=e*n.options.categoryPercentage,l=(e-e*n.options.categoryPercentage)/2,s=r/o;if(n.ticks.length!==a.chart.data.labels.length){var d=n.ticks.length/a.chart.data.labels.length;s*=d}var u=s*n.options.barPercentage,c=s-s*n.options.barPercentage;return{datasetCount:o,tickWidth:e,categoryWidth:r,categorySpacing:l,fullBarWidth:s,barWidth:u,barSpacing:c}},calculateBarWidth:function(t){var e=this.getScaleForId(this.getMeta().xAxisID),a=this.getRuler(t);return e.options.stacked?a.categoryWidth:a.barWidth},getBarIndex:function(t){var e,a,i=0;for(a=0;t>a;++a)e=this.chart.getDatasetMeta(a),e.bar&&this.chart.isDatasetVisible(a)&&++i;return i},calculateBarX:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=a.getBarIndex(e),r=a.getRuler(t),l=n.getPixelForValue(null,t,e,a.chart.isCombo);return l-=a.chart.isCombo?r.tickWidth/2:0,n.options.stacked?l+r.categoryWidth/2+r.categorySpacing:l+r.barWidth/2+r.categorySpacing+r.barWidth*o+r.barSpacing/2+r.barSpacing*o},calculateBarY:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=a.getDataset().data[t];if(n.options.stacked){for(var r=0,l=0,s=0;e>s;s++){var d=a.chart.data.datasets[s],u=a.chart.getDatasetMeta(s);u.bar&&u.yAxisID===n.id&&a.chart.isDatasetVisible(s)&&(d.data[t]<0?l+=d.data[t]||0:r+=d.data[t]||0)}return 0>o?n.getPixelForValue(l+o):n.getPixelForValue(r+o)}return n.getPixelForValue(o)},draw:function(t){var a=this,i=t||1;e.each(a.getMeta().data,function(t,e){var n=a.getDataset().data[e];null===n||void 0===n||isNaN(n)||t.transition(i).draw()},a)},setHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model;o.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:e.getValueAtIndexOrDefault(a.hoverBackgroundColor,i,e.getHoverColor(o.backgroundColor)),o.borderColor=n.hoverBorderColor?n.hoverBorderColor:e.getValueAtIndexOrDefault(a.hoverBorderColor,i,e.getHoverColor(o.borderColor)),o.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:e.getValueAtIndexOrDefault(a.hoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model,r=this.chart.options.elements.rectangle;o.backgroundColor=n.backgroundColor?n.backgroundColor:e.getValueAtIndexOrDefault(a.backgroundColor,i,r.backgroundColor),o.borderColor=n.borderColor?n.borderColor:e.getValueAtIndexOrDefault(a.borderColor,i,r.borderColor),o.borderWidth=n.borderWidth?n.borderWidth:e.getValueAtIndexOrDefault(a.borderWidth,i,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var a="";return t.length>0&&(t[0].yLabel?a=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(a=e.labels[t[0].index])),a},label:function(t,e){var a=e.datasets[t.datasetIndex].label||"";return a+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({updateElement:function(t,a,i,n){var o=this,r=o.getMeta(),l=o.getScaleForId(r.xAxisID),s=o.getScaleForId(r.yAxisID),d=l.getBasePixel(),u=t.custom||{},c=o.getDataset(),h=o.chart.options.elements.rectangle;e.extend(t,{_xScale:l,_yScale:s,_datasetIndex:o.index,_index:a,_model:{x:i?d:o.calculateBarX(a,o.index),y:o.calculateBarY(a,o.index),label:o.chart.data.labels[a],datasetLabel:c.label,base:i?d:o.calculateBarBase(o.index,a),height:o.calculateBarHeight(a),backgroundColor:u.backgroundColor?u.backgroundColor:e.getValueAtIndexOrDefault(c.backgroundColor,a,h.backgroundColor),borderSkipped:u.borderSkipped?u.borderSkipped:h.borderSkipped,borderColor:u.borderColor?u.borderColor:e.getValueAtIndexOrDefault(c.borderColor,a,h.borderColor),borderWidth:u.borderWidth?u.borderWidth:e.getValueAtIndexOrDefault(c.borderWidth,a,h.borderWidth)},draw:function(){function t(t){return s[(u+t)%4]}var e=this._chart.ctx,a=this._view,i=a.height/2,n=a.y-i,o=a.y+i,r=a.base-(a.base-a.x),l=a.borderWidth/2;a.borderWidth&&(n+=l,o-=l,r+=l),e.beginPath(),e.fillStyle=a.backgroundColor,e.strokeStyle=a.borderColor,e.lineWidth=a.borderWidth;var s=[[a.base,o],[a.base,n],[r,n],[r,o]],d=["bottom","left","top","right"],u=d.indexOf(a.borderSkipped,0);-1===u&&(u=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),a.borderWidth&&e.stroke()},inRange:function(t,e){var a=this._view,i=!1;return a&&(i=a.x<a.base?e>=a.y-a.height/2&&e<=a.y+a.height/2&&t>=a.x&&t<=a.base:e>=a.y-a.height/2&&e<=a.y+a.height/2&&t>=a.base&&t<=a.x),i}}),t.pivot()},calculateBarBase:function(t,e){
-var a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=0;if(n.options.stacked){var r=a.chart.data.datasets[t].data[e];if(0>r)for(var l=0;t>l;l++){var s=a.chart.data.datasets[l],d=a.chart.getDatasetMeta(l);d.bar&&d.xAxisID===n.id&&a.chart.isDatasetVisible(l)&&(o+=s.data[e]<0?s.data[e]:0)}else for(var u=0;t>u;u++){var c=a.chart.data.datasets[u],h=a.chart.getDatasetMeta(u);h.bar&&h.xAxisID===n.id&&a.chart.isDatasetVisible(u)&&(o+=c.data[e]>0?c.data[e]:0)}return n.getPixelForValue(o)}return n.getBasePixel()},getRuler:function(t){var e,a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=a.getBarCount();e="category"===n.options.type?n.getPixelForTick(t+1)-n.getPixelForTick(t):n.width/n.ticks.length;var r=e*n.options.categoryPercentage,l=(e-e*n.options.categoryPercentage)/2,s=r/o;if(n.ticks.length!==a.chart.data.labels.length){var d=n.ticks.length/a.chart.data.labels.length;s*=d}var u=s*n.options.barPercentage,c=s-s*n.options.barPercentage;return{datasetCount:o,tickHeight:e,categoryHeight:r,categorySpacing:l,fullBarHeight:s,barHeight:u,barSpacing:c}},calculateBarHeight:function(t){var e=this,a=e.getScaleForId(e.getMeta().yAxisID),i=e.getRuler(t);return a.options.stacked?i.categoryHeight:i.barHeight},calculateBarX:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.xAxisID),o=a.getDataset().data[t];if(n.options.stacked){for(var r=0,l=0,s=0;e>s;s++){var d=a.chart.data.datasets[s],u=a.chart.getDatasetMeta(s);u.bar&&u.xAxisID===n.id&&a.chart.isDatasetVisible(s)&&(d.data[t]<0?l+=d.data[t]||0:r+=d.data[t]||0)}return 0>o?n.getPixelForValue(l+o):n.getPixelForValue(r+o)}return n.getPixelForValue(o)},calculateBarY:function(t,e){var a=this,i=a.getMeta(),n=a.getScaleForId(i.yAxisID),o=a.getBarIndex(e),r=a.getRuler(t),l=n.getPixelForValue(null,t,e,a.chart.isCombo);return l-=a.chart.isCombo?r.tickHeight/2:0,n.options.stacked?l+r.categoryHeight/2+r.categorySpacing:l+r.barHeight/2+r.categorySpacing+r.barHeight*o+r.barSpacing/2+r.barSpacing*o}})}},{}],16:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){var a=e.datasets[t.datasetIndex].label||"",i=e.datasets[t.datasetIndex].data[t.index];return a+": ("+i.x+", "+i.y+", "+i.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var a=this,i=a.getMeta(),n=i.data;e.each(n,function(e,i){a.updateElement(e,i,t)})},updateElement:function(a,i,n){var o=this,r=o.getMeta(),l=o.getScaleForId(r.xAxisID),s=o.getScaleForId(r.yAxisID),d=a.custom||{},u=o.getDataset(),c=u.data[i],h=o.chart.options.elements.point,f=o.index;e.extend(a,{_xScale:l,_yScale:s,_datasetIndex:f,_index:i,_model:{x:n?l.getPixelForDecimal(.5):l.getPixelForValue(c,i,f,o.chart.isCombo),y:n?s.getBasePixel():s.getPixelForValue(c,i,f),radius:n?0:d.radius?d.radius:o.getRadius(c),hitRadius:d.hitRadius?d.hitRadius:e.getValueAtIndexOrDefault(u.hitRadius,i,h.hitRadius)}}),t.DatasetController.prototype.removeHoverStyle.call(o,a,h);var g=a._model;g.skip=d.skip?d.skip:isNaN(g.x)||isNaN(g.y),a.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(a){var i=this;t.DatasetController.prototype.setHoverStyle.call(i,a);var n=i.chart.data.datasets[a._datasetIndex],o=a._index,r=a.custom||{},l=a._model;l.radius=r.hoverRadius?r.hoverRadius:e.getValueAtIndexOrDefault(n.hoverRadius,o,i.chart.options.elements.point.hoverRadius)+i.getRadius(n.data[o])},removeHoverStyle:function(e){var a=this;t.DatasetController.prototype.removeHoverStyle.call(a,e,a.chart.options.elements.point);var i=a.chart.data.datasets[e._datasetIndex].data[e._index],n=e.custom||{},o=e._model;o.radius=n.radius?n.radius:a.getRadius(i)}})}},{}],17:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=t.defaults;a.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var a=t.data,i=a.datasets,n=a.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'"></span>'),n[o]&&e.push(n[o]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var a=t.data;return a.labels.length&&a.datasets.length?a.labels.map(function(i,n){var o=t.getDatasetMeta(0),r=a.datasets[0],l=o.data[n],s=l.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=s.backgroundColor?s.backgroundColor:d(r.backgroundColor,n,u.backgroundColor),h=s.borderColor?s.borderColor:d(r.borderColor,n,u.borderColor),f=s.borderWidth?s.borderWidth:d(r.borderWidth,n,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(r.data[n])||o.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var a,i,n,o=e.index,r=this.chart;for(a=0,i=(r.data.datasets||[]).length;i>a;++a)n=r.getDatasetMeta(a),n.data[o].hidden=!n.data[o].hidden;r.update()}},cutoutPercentage:50,rotation:Math.PI*-.5,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+e.datasets[t.datasetIndex].data[t.index]}}}},a.pie=e.clone(a.doughnut),e.extend(a.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,a=0;t>a;++a)this.chart.isDatasetVisible(a)&&++e;return e},update:function(t){var a=this,i=a.chart,n=i.chartArea,o=i.options,r=o.elements.arc,l=n.right-n.left-r.borderWidth,s=n.bottom-n.top-r.borderWidth,d=Math.min(l,s),u={x:0,y:0},c=a.getMeta(),h=o.cutoutPercentage,f=o.circumference;if(f<2*Math.PI){var g=o.rotation%(2*Math.PI);g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0);var p=g+f,m={x:Math.cos(g),y:Math.sin(g)},b={x:Math.cos(p),y:Math.sin(p)},v=0>=g&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,S=h/100,w={x:y?-1:Math.min(m.x*(m.x<0?1:S),b.x*(b.x<0?1:S)),y:k?-1:Math.min(m.y*(m.y<0?1:S),b.y*(b.y<0?1:S))},C={x:v?1:Math.max(m.x*(m.x>0?1:S),b.x*(b.x>0?1:S)),y:x?1:Math.max(m.y*(m.y>0?1:S),b.y*(b.y>0?1:S))},M={width:.5*(C.x-w.x),height:.5*(C.y-w.y)};d=Math.min(l/M.width,s/M.height),u={x:(C.x+w.x)*-.5,y:(C.y+w.y)*-.5}}i.outerRadius=Math.max(d/2,0),i.innerRadius=Math.max(h?i.outerRadius/100*h:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),i.offsetX=u.x*i.outerRadius,i.offsetY=u.y*i.outerRadius,c.total=a.calculateTotal(),a.outerRadius=i.outerRadius-i.radiusLength*a.getRingIndex(a.index),a.innerRadius=a.outerRadius-i.radiusLength,e.each(c.data,function(e,i){a.updateElement(e,i,t)})},updateElement:function(t,a,i){var n=this,o=n.chart,r=o.chartArea,l=o.options,s=l.animation,d=(l.elements.arc,(r.left+r.right)/2),u=(r.top+r.bottom)/2,c=l.rotation,h=l.rotation,f=n.getDataset(),g=i&&s.animateRotate?0:t.hidden?0:n.calculateCircumference(f.data[a])*(l.circumference/(2*Math.PI)),p=i&&s.animateScale?0:n.innerRadius,m=i&&s.animateScale?0:n.outerRadius,b=(t.custom||{},e.getValueAtIndexOrDefault);e.extend(t,{_datasetIndex:n.index,_index:a,_model:{x:d+o.offsetX,y:u+o.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:m,innerRadius:p,label:b(f.label,a,o.data.labels[a])}});var v=t._model;this.removeHoverStyle(t),i&&s.animateRotate||(0===a?v.startAngle=l.rotation:v.startAngle=n.getMeta().data[a-1]._model.endAngle,v.endAngle=v.startAngle+v.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,a=this.getDataset(),i=this.getMeta(),n=0;return e.each(i.data,function(e,i){t=a.data[i],isNaN(t)||e.hidden||(n+=Math.abs(t))}),n},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0}})}},{}],18:[function(t,e,a){"use strict";e.exports=function(t){function e(t,e){return a.getValueOrDefault(t.showLine,e.showLines)}var a=t.helpers;t.defaults.line={showLines:!0,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,addElementAndReset:function(a){var i=this,n=i.chart.options,o=i.getMeta();t.DatasetController.prototype.addElementAndReset.call(i,a),e(i.getDataset(),n)&&0!==o.dataset._model.tension&&i.updateBezierControlPoints()},update:function(t){var i,n,o,r=this,l=r.getMeta(),s=l.dataset,d=l.data||[],u=r.chart.options,c=u.elements.line,h=r.getScaleForId(l.yAxisID),f=r.getDataset(),g=e(f,u);for(g&&(o=s.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),s._scale=h,s._datasetIndex=r.index,s._children=d,s._model={spanGaps:f.spanGaps?f.spanGaps:!1,tension:o.tension?o.tension:a.getValueOrDefault(f.lineTension,c.tension),backgroundColor:o.backgroundColor?o.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:f.borderWidth||c.borderWidth,borderColor:o.borderColor?o.borderColor:f.borderColor||c.borderColor,borderCapStyle:o.borderCapStyle?o.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:o.borderDash?o.borderDash:f.borderDash||c.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:o.fill?o.fill:void 0!==f.fill?f.fill:c.fill,scaleTop:h.top,scaleBottom:h.bottom,scaleZero:h.getBasePixel()},s.pivot()),i=0,n=d.length;n>i;++i)r.updateElement(d[i],i,t);for(g&&0!==s._model.tension&&r.updateBezierControlPoints(),i=0,n=d.length;n>i;++i)d[i].pivot()},getPointBackgroundColor:function(t,e){var i=this.chart.options.elements.point.backgroundColor,n=this.getDataset(),o=t.custom||{};return o.backgroundColor?i=o.backgroundColor:n.pointBackgroundColor?i=a.getValueAtIndexOrDefault(n.pointBackgroundColor,e,i):n.backgroundColor&&(i=n.backgroundColor),i},getPointBorderColor:function(t,e){var i=this.chart.options.elements.point.borderColor,n=this.getDataset(),o=t.custom||{};return o.borderColor?i=o.borderColor:n.pointBorderColor?i=a.getValueAtIndexOrDefault(n.pointBorderColor,e,i):n.borderColor&&(i=n.borderColor),i},getPointBorderWidth:function(t,e){var i=this.chart.options.elements.point.borderWidth,n=this.getDataset(),o=t.custom||{};return o.borderWidth?i=o.borderWidth:n.pointBorderWidth?i=a.getValueAtIndexOrDefault(n.pointBorderWidth,e,i):n.borderWidth&&(i=n.borderWidth),i},updateElement:function(t,e,i){var n,o,r=this,l=r.getMeta(),s=t.custom||{},d=r.getDataset(),u=r.index,c=d.data[e],h=r.getScaleForId(l.yAxisID),f=r.getScaleForId(l.xAxisID),g=r.chart.options.elements.point;void 0!==d.radius&&void 0===d.pointRadius&&(d.pointRadius=d.radius),void 0!==d.hitRadius&&void 0===d.pointHitRadius&&(d.pointHitRadius=d.hitRadius),n=f.getPixelForValue(c,e,u,r.chart.isCombo),o=i?h.getBasePixel():r.calculatePointY(c,e,u,r.chart.isCombo),t._xScale=f,t._yScale=h,t._datasetIndex=u,t._index=e,t._model={x:n,y:o,skip:s.skip||isNaN(n)||isNaN(o),radius:s.radius||a.getValueAtIndexOrDefault(d.pointRadius,e,g.radius),pointStyle:s.pointStyle||a.getValueAtIndexOrDefault(d.pointStyle,e,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,e),borderColor:r.getPointBorderColor(t,e),borderWidth:r.getPointBorderWidth(t,e),tension:l.dataset._model?l.dataset._model.tension:0,hitRadius:s.hitRadius||a.getValueAtIndexOrDefault(d.pointHitRadius,e,g.hitRadius)}},calculatePointY:function(t,e,a,i){var n,o,r,l=this,s=l.chart,d=l.getMeta(),u=l.getScaleForId(d.yAxisID),c=0,h=0;if(u.options.stacked){for(n=0;a>n;n++)o=s.data.datasets[n],r=s.getDatasetMeta(n),"line"===r.type&&s.isDatasetVisible(n)&&(o.data[e]<0?h+=o.data[e]||0:c+=o.data[e]||0);return 0>t?u.getPixelForValue(h+t):u.getPixelForValue(c+t)}return u.getPixelForValue(t)},updateBezierControlPoints:function(){var t,e,i,n,o,r=this.getMeta(),l=this.chart.chartArea,s=r.data||[];for(t=0,e=s.length;e>t;++t)i=s[t],n=i._model,o=a.splineCurve(a.previousItem(s,t)._model,n,a.nextItem(s,t)._model,r.dataset._model.tension),n.controlPointPreviousX=Math.max(Math.min(o.previous.x,l.right),l.left),n.controlPointPreviousY=Math.max(Math.min(o.previous.y,l.bottom),l.top),n.controlPointNextX=Math.max(Math.min(o.next.x,l.right),l.left),n.controlPointNextY=Math.max(Math.min(o.next.y,l.bottom),l.top)},draw:function(t){var a,i,n=this,o=n.getMeta(),r=o.data||[],l=t||1;for(a=0,i=r.length;i>a;++a)r[a].transition(l);for(e(n.getDataset(),n.chart.options)&&o.dataset.transition(l).draw(),a=0,i=r.length;i>a;++a)r[a].draw()},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=t._model;o.radius=n.hoverRadius||a.getValueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),o.backgroundColor=n.hoverBackgroundColor||a.getValueAtIndexOrDefault(e.pointHoverBackgroundColor,i,a.getHoverColor(o.backgroundColor)),o.borderColor=n.hoverBorderColor||a.getValueAtIndexOrDefault(e.pointHoverBorderColor,i,a.getHoverColor(o.borderColor)),o.borderWidth=n.hoverBorderWidth||a.getValueAtIndexOrDefault(e.pointHoverBorderWidth,i,o.borderWidth)},removeHoverStyle:function(t){var e=this,i=e.chart.data.datasets[t._datasetIndex],n=t._index,o=t.custom||{},r=t._model;void 0!==i.radius&&void 0===i.pointRadius&&(i.pointRadius=i.radius),r.radius=o.radius||a.getValueAtIndexOrDefault(i.pointRadius,n,e.chart.options.elements.point.radius),r.backgroundColor=e.getPointBackgroundColor(t,n),r.borderColor=e.getPointBorderColor(t,n),r.borderWidth=e.getPointBorderWidth(t,n)}})}},{}],19:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",lineArc:!0},animation:{animateRotate:!0,animateScale:!0},aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var a=t.data,i=a.datasets,n=a.labels;if(i.length)for(var o=0;o<i[0].data.length;++o)e.push('<li><span style="background-color:'+i[0].backgroundColor[o]+'">'),n[o]&&e.push(n[o]),e.push("</span></li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var a=t.data;return a.labels.length&&a.datasets.length?a.labels.map(function(i,n){var o=t.getDatasetMeta(0),r=a.datasets[0],l=o.data[n],s=l.custom||{},d=e.getValueAtIndexOrDefault,u=t.options.elements.arc,c=s.backgroundColor?s.backgroundColor:d(r.backgroundColor,n,u.backgroundColor),h=s.borderColor?s.borderColor:d(r.borderColor,n,u.borderColor),f=s.borderWidth?s.borderWidth:d(r.borderWidth,n,u.borderWidth);return{text:i,fillStyle:c,strokeStyle:h,lineWidth:f,hidden:isNaN(r.data[n])||o.data[n].hidden,index:n}}):[]}},onClick:function(t,e){var a,i,n,o=e.index,r=this.chart;for(a=0,i=(r.data.datasets||[]).length;i>a;++a)n=r.getDatasetMeta(a),n.data[o].hidden=!n.data[o].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var a=this,i=a.chart,n=i.chartArea,o=a.getMeta(),r=i.options,l=r.elements.arc,s=Math.min(n.right-n.left,n.bottom-n.top);i.outerRadius=Math.max((s-l.borderWidth/2)/2,0),i.innerRadius=Math.max(r.cutoutPercentage?i.outerRadius/100*r.cutoutPercentage:1,0),i.radiusLength=(i.outerRadius-i.innerRadius)/i.getVisibleDatasetCount(),a.outerRadius=i.outerRadius-i.radiusLength*a.index,a.innerRadius=a.outerRadius-i.radiusLength,o.count=a.countVisibleElements(),e.each(o.data,function(e,i){a.updateElement(e,i,t)})},updateElement:function(t,a,i){for(var n=this,o=n.chart,r=o.chartArea,l=n.getDataset(),s=o.options,d=s.animation,u=(s.elements.arc,t.custom||{},o.scale),c=e.getValueAtIndexOrDefault,h=o.data.labels,f=n.calculateCircumference(l.data[a]),g=(r.left+r.right)/2,p=(r.top+r.bottom)/2,m=0,b=n.getMeta(),v=0;a>v;++v)isNaN(l.data[v])||b.data[v].hidden||++m;var x=-.5*Math.PI,y=t.hidden?0:u.getDistanceFromCenterForValue(l.data[a]),k=x+f*m,S=k+(t.hidden?0:f),w=d.animateScale?0:u.getDistanceFromCenterForValue(l.data[a]);e.extend(t,{_datasetIndex:n.index,_index:a,_scale:u,_model:{x:g,y:p,innerRadius:0,outerRadius:i?w:y,startAngle:i&&d.animateRotate?x:k,endAngle:i&&d.animateRotate?x:S,label:c(h,a,h[a])}}),n.removeHoverStyle(t),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),a=this.getMeta(),i=0;return e.each(a.data,function(e,a){isNaN(t.data[a])||e.hidden||i++}),i},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,addElementAndReset:function(e){t.DatasetController.prototype.addElementAndReset.call(this,e),this.updateBezierControlPoints()},update:function(t){var a=this,i=a.getMeta(),n=i.dataset,o=i.data,r=n.custom||{},l=a.getDataset(),s=a.chart.options.elements.line,d=a.chart.scale;void 0!==l.tension&&void 0===l.lineTension&&(l.lineTension=l.tension),e.extend(i.dataset,{_datasetIndex:a.index,_children:o,_loop:!0,_model:{tension:r.tension?r.tension:e.getValueOrDefault(l.lineTension,s.tension),backgroundColor:r.backgroundColor?r.backgroundColor:l.backgroundColor||s.backgroundColor,borderWidth:r.borderWidth?r.borderWidth:l.borderWidth||s.borderWidth,borderColor:r.borderColor?r.borderColor:l.borderColor||s.borderColor,fill:r.fill?r.fill:void 0!==l.fill?l.fill:s.fill,borderCapStyle:r.borderCapStyle?r.borderCapStyle:l.borderCapStyle||s.borderCapStyle,borderDash:r.borderDash?r.borderDash:l.borderDash||s.borderDash,borderDashOffset:r.borderDashOffset?r.borderDashOffset:l.borderDashOffset||s.borderDashOffset,borderJoinStyle:r.borderJoinStyle?r.borderJoinStyle:l.borderJoinStyle||s.borderJoinStyle,scaleTop:d.top,scaleBottom:d.bottom,scaleZero:d.getBasePosition()}}),i.dataset.pivot(),e.each(o,function(e,i){a.updateElement(e,i,t)},a),a.updateBezierControlPoints()},updateElement:function(t,a,i){var n=this,o=t.custom||{},r=n.getDataset(),l=n.chart.scale,s=n.chart.options.elements.point,d=l.getPointPositionForValue(a,r.data[a]);e.extend(t,{_datasetIndex:n.index,_index:a,_scale:l,_model:{x:i?l.xCenter:d.x,y:i?l.yCenter:d.y,tension:o.tension?o.tension:e.getValueOrDefault(r.tension,n.chart.options.elements.line.tension),radius:o.radius?o.radius:e.getValueAtIndexOrDefault(r.pointRadius,a,s.radius),backgroundColor:o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(r.pointBackgroundColor,a,s.backgroundColor),borderColor:o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(r.pointBorderColor,a,s.borderColor),borderWidth:o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(r.pointBorderWidth,a,s.borderWidth),pointStyle:o.pointStyle?o.pointStyle:e.getValueAtIndexOrDefault(r.pointStyle,a,s.pointStyle),hitRadius:o.hitRadius?o.hitRadius:e.getValueAtIndexOrDefault(r.hitRadius,a,s.hitRadius)}}),t._model.skip=o.skip?o.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,a=this.getMeta();e.each(a.data,function(i,n){var o=i._model,r=e.splineCurve(e.previousItem(a.data,n,!0)._model,o,e.nextItem(a.data,n,!0)._model,o.tension);o.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),o.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),o.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),o.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),i.pivot()})},draw:function(t){var a=this.getMeta(),i=t||1;e.each(a.data,function(t,e){t.transition(i)}),a.dataset.transition(i).draw(),e.each(a.data,function(t){t.draw()})},setHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,o=t._model;o.radius=i.hoverRadius?i.hoverRadius:e.getValueAtIndexOrDefault(a.pointHoverRadius,n,this.chart.options.elements.point.hoverRadius),o.backgroundColor=i.hoverBackgroundColor?i.hoverBackgroundColor:e.getValueAtIndexOrDefault(a.pointHoverBackgroundColor,n,e.getHoverColor(o.backgroundColor)),o.borderColor=i.hoverBorderColor?i.hoverBorderColor:e.getValueAtIndexOrDefault(a.pointHoverBorderColor,n,e.getHoverColor(o.borderColor)),o.borderWidth=i.hoverBorderWidth?i.hoverBorderWidth:e.getValueAtIndexOrDefault(a.pointHoverBorderWidth,n,o.borderWidth)},removeHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t.custom||{},n=t._index,o=t._model,r=this.chart.options.elements.point;o.radius=i.radius?i.radius:e.getValueAtIndexOrDefault(a.radius,n,r.radius),o.backgroundColor=i.backgroundColor?i.backgroundColor:e.getValueAtIndexOrDefault(a.pointBackgroundColor,n,r.backgroundColor),o.borderColor=i.borderColor?i.borderColor:e.getValueAtIndexOrDefault(a.pointBorderColor,n,r.borderColor),o.borderWidth=i.borderWidth?i.borderWidth:e.getValueAtIndexOrDefault(a.pointBorderWidth,n,r.borderWidth)}})}},{}],21:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({currentStep:null,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,a,i){var n=this;i||(t.animating=!0);for(var o=0;o<n.animations.length;++o)if(n.animations[o].chartInstance===t)return void(n.animations[o].animationObject=e);n.animations.push({chartInstance:t,animationObject:e}),1===n.animations.length&&n.requestAnimationFrame()},cancelAnimation:function(t){var a=e.findIndex(this.animations,function(e){return e.chartInstance===t});-1!==a&&(this.animations.splice(a,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=this,e=Date.now(),a=0;t.dropFrames>1&&(a=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1);for(var i=0;i<t.animations.length;)null===t.animations[i].animationObject.currentStep&&(t.animations[i].animationObject.currentStep=0),t.animations[i].animationObject.currentStep+=1+a,t.animations[i].animationObject.currentStep>t.animations[i].animationObject.numSteps&&(t.animations[i].animationObject.currentStep=t.animations[i].animationObject.numSteps),t.animations[i].animationObject.render(t.animations[i].chartInstance,t.animations[i].animationObject),t.animations[i].animationObject.onAnimationProgress&&t.animations[i].animationObject.onAnimationProgress.call&&t.animations[i].animationObject.onAnimationProgress.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].animationObject.currentStep===t.animations[i].animationObject.numSteps?(t.animations[i].animationObject.onAnimationComplete&&t.animations[i].animationObject.onAnimationComplete.call&&t.animations[i].animationObject.onAnimationComplete.call(t.animations[i].chartInstance,t.animations[i]),t.animations[i].chartInstance.animating=!1,t.animations.splice(i,1)):++i;var n=Date.now(),o=(n-e)/t.frameDuration;t.dropFrames+=o,t.animations.length>0&&t.requestAnimationFrame()}}}},{}],22:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.types={},t.instances={},t.controllers={},t.Controller=function(a){return this.chart=a,this.config=a.config,this.options=this.config.options=e.configMerge(t.defaults.global,t.defaults[this.config.type],this.config.options||{}),this.id=e.uid(),Object.defineProperty(this,"data",{get:function(){return this.config.data}}),t.instances[this.id]=this,this.options.responsive&&this.resize(!0),this.initialize(),this},e.extend(t.Controller.prototype,{initialize:function(){var e=this;return t.pluginService.notifyPlugins("beforeInit",[e]),e.bindEvents(),e.ensureScalesHaveIDs(),e.buildOrUpdateControllers(),e.buildScales(),e.updateLayout(),e.resetElements(),e.initToolTip(),e.update(),t.pluginService.notifyPlugins("afterInit",[e]),e},clear:function(){return e.clear(this.chart),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(a){var i=this,n=i.chart,o=n.canvas,r=e.getMaximumWidth(o),l=n.aspectRatio,s=i.options.maintainAspectRatio&&isNaN(l)===!1&&isFinite(l)&&0!==l?r/l:e.getMaximumHeight(o),d=n.width!==r||n.height!==s;if(!d)return i;o.width=n.width=r,o.height=n.height=s,e.retinaScale(n);var u={width:r,height:s};return t.pluginService.notifyPlugins("resize",[i,u]),i.options.onResize&&i.options.onResize(i,u),a||(i.stop(),i.update(i.options.responsiveAnimationDuration)),i},ensureScalesHaveIDs:function(){var t=this.options,a=t.scales||{},i=t.scale;e.each(a.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),e.each(a.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),i&&(i.id=i.id||"scale")},buildScales:function(){var a=this,i=a.options,n=a.scales={},o=[];i.scales&&(o=o.concat((i.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category"}}),(i.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear"}}))),i.scale&&o.push({options:i.scale,dtype:"radialLinear",isDefault:!0}),e.each(o,function(i,o){var r=i.options,l=e.getValueOrDefault(r.type,i.dtype),s=t.scaleService.getScaleConstructor(l);if(s){var d=new s({id:r.id,options:r,ctx:a.chart.ctx,chart:a});n[d.id]=d,i.isDefault&&(a.scale=d)}}),t.scaleService.addScalesToLayout(this)},updateLayout:function(){t.layoutService.update(this,this.chart.width,this.chart.height)},buildOrUpdateControllers:function(){var a=this,i=[],n=[];if(e.each(a.data.datasets,function(e,o){var r=a.getDatasetMeta(o);r.type||(r.type=e.type||a.config.type),i.push(r.type),r.controller?r.controller.updateIndex(o):(r.controller=new t.controllers[r.type](a,o),n.push(r.controller))},a),i.length>1)for(var o=1;o<i.length;o++)if(i[o]!==i[o-1]){a.isCombo=!0;break}return n},resetElements:function(){var t=this;e.each(t.data.datasets,function(e,a){t.getDatasetMeta(a).controller.reset()},t)},update:function(a,i){var n=this;t.pluginService.notifyPlugins("beforeUpdate",[n]),n.tooltip._data=n.data;var o=n.buildOrUpdateControllers();e.each(n.data.datasets,function(t,e){n.getDatasetMeta(e).controller.buildOrUpdateElements()},n),t.layoutService.update(n,n.chart.width,n.chart.height),t.pluginService.notifyPlugins("afterScaleUpdate",[n]),e.each(o,function(t){t.reset()}),e.each(n.data.datasets,function(t,e){n.getDatasetMeta(e).controller.update()},n),t.pluginService.notifyPlugins("afterUpdate",[n]),n.render(a,i)},render:function(a,i){var n=this;t.pluginService.notifyPlugins("beforeRender",[n]);var o=n.options.animation;if(o&&("undefined"!=typeof a&&0!==a||"undefined"==typeof a&&0!==o.duration)){var r=new t.Animation;r.numSteps=(a||o.duration)/16.66,r.easing=o.easing,r.render=function(t,a){var i=e.easingEffects[a.easing],n=a.currentStep/a.numSteps,o=i(n);t.draw(o,n,a.currentStep)},r.onAnimationProgress=o.onProgress,r.onAnimationComplete=o.onComplete,t.animationService.addAnimation(n,r,a,i)}else n.draw(),o&&o.onComplete&&o.onComplete.call&&o.onComplete.call(n);return n},draw:function(a){var i=this,n=a||1;i.clear(),t.pluginService.notifyPlugins("beforeDraw",[i,n]),e.each(i.boxes,function(t){t.draw(i.chartArea)},i),i.scale&&i.scale.draw(),t.pluginService.notifyPlugins("beforeDatasetDraw",[i,n]),e.each(i.data.datasets,function(t,e){i.isDatasetVisible(e)&&i.getDatasetMeta(e).controller.draw(a)},i,!0),t.pluginService.notifyPlugins("afterDatasetDraw",[i,n]),i.tooltip.transition(n).draw(),t.pluginService.notifyPlugins("afterDraw",[i,n])},getElementAtEvent:function(t){var a=this,i=e.getRelativePosition(t,a.chart),n=[];return e.each(a.data.datasets,function(t,o){if(a.isDatasetVisible(o)){var r=a.getDatasetMeta(o);e.each(r.data,function(t,e){return t.inRange(i.x,i.y)?(n.push(t),n):void 0})}}),n},getElementsAtEvent:function(t){var a=this,i=e.getRelativePosition(t,a.chart),n=[],o=function(){if(a.data.datasets)for(var t=0;t<a.data.datasets.length;t++){var e=a.getDatasetMeta(t);if(a.isDatasetVisible(t))for(var n=0;n<e.data.length;n++)if(e.data[n].inRange(i.x,i.y))return e.data[n]}}.call(a);return o?(e.each(a.data.datasets,function(t,e){if(a.isDatasetVisible(e)){var i=a.getDatasetMeta(e);n.push(i.data[o._index])}},a),n):n},getElementsAtEventForMode:function(t,e){var a=this;switch(e){case"single":return a.getElementAtEvent(t);case"label":return a.getElementsAtEvent(t);case"dataset":return a.getDatasetAtEvent(t);default:return t}},getDatasetAtEvent:function(t){var e=this.getElementAtEvent(t);return e.length>0&&(e=this.getDatasetMeta(e[0]._datasetIndex).data),e},getDatasetMeta:function(t){var e=this,a=e.data.datasets[t];a._meta||(a._meta={});var i=a._meta[e.id];return i||(i=a._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,a=this.data.datasets.length;a>e;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){var a=this;a.stop(),a.clear(),e.unbindEvents(a,a.events),e.removeResizeListener(a.chart.canvas.parentNode);var i=a.chart.canvas;i.width=a.chart.width,i.height=a.chart.height,void 0!==a.chart.originalDevicePixelRatio&&a.chart.ctx.scale(1/a.chart.originalDevicePixelRatio,1/a.chart.originalDevicePixelRatio),i.style.width=a.chart.originalCanvasStyleWidth,i.style.height=a.chart.originalCanvasStyleHeight,t.pluginService.notifyPlugins("destroy",[a]),delete t.instances[a.id]},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)},initToolTip:function(){var e=this;e.tooltip=new t.Tooltip({_chart:e.chart,_chartInstance:e,_data:e.data,_options:e.options.tooltips},e)},bindEvents:function(){var t=this;e.bindEvents(t,t.options.events,function(e){t.eventHandler(e)})},updateHoverStyle:function(t,e,a){var i,n,o,r=a?"setHoverStyle":"removeHoverStyle";switch(e){case"single":t=[t[0]];break;case"label":case"dataset":break;default:return}for(n=0,o=t.length;o>n;++n)i=t[n],i&&this.getDatasetMeta(i._datasetIndex).controller[r](i)},eventHandler:function(t){var a=this,i=a.tooltip,n=a.options||{},o=n.hover,r=n.tooltips;return a.lastActive=a.lastActive||[],a.lastTooltipActive=a.lastTooltipActive||[],"mouseout"===t.type?(a.active=[],a.tooltipActive=[]):(a.active=a.getElementsAtEventForMode(t,o.mode),a.tooltipActive=a.getElementsAtEventForMode(t,r.mode)),o.onHover&&o.onHover.call(a,a.active),("mouseup"===t.type||"click"===t.type)&&(n.onClick&&n.onClick.call(a,t,a.active),a.legend&&a.legend.handleEvent&&a.legend.handleEvent(t)),a.lastActive.length&&a.updateHoverStyle(a.lastActive,o.mode,!1),a.active.length&&o.mode&&a.updateHoverStyle(a.active,o.mode,!0),(r.enabled||r.custom)&&(i.initialize(),i._active=a.tooltipActive,i.update(!0)),i.pivot(),a.animating||e.arrayEquals(a.active,a.lastActive)&&e.arrayEquals(a.tooltipActive,a.lastTooltipActive)||(a.stop(),(r.enabled||r.custom)&&i.update(!0),a.render(o.animationDuration,!0)),a.lastActive=a.active,a.lastTooltipActive=a.tooltipActive,a}})}},{}],23:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=e.noop;t.DatasetController=function(t,e){this.initialize.call(this,t,e)},e.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var a=this;a.chart=t,a.index=e,a.linkScales(),a.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),a=t.getDataset();
-null===e.xAxisID&&(e.xAxisID=a.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=a.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,a=e.dataElementType;return a&&new a({_chart:e.chart.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,a=this,i=a.getMeta(),n=a.getDataset().data||[],o=i.data;for(t=0,e=n.length;e>t;++t)o[t]=o[t]||a.createMetaData(i,t);i.dataset=i.dataset||a.createMetaDataset()},addElementAndReset:function(t){var e=this,a=e.createMetaData(t);e.getMeta().data.splice(t,0,a),e.updateElement(a,t,!0)},buildOrUpdateElements:function(){var t=this.getMeta(),e=t.data,a=this.getDataset().data.length,i=e.length;if(i>a)e.splice(a,i-a);else if(a>i)for(var n=i;a>n;++n)this.addElementAndReset(n)},update:a,draw:function(t){var a=t||1;e.each(this.getMeta().data,function(t,e){t.transition(a).draw()})},removeHoverStyle:function(t,a){var i=this.chart.data.datasets[t._datasetIndex],n=t._index,o=t.custom||{},r=e.getValueAtIndexOrDefault,l=(e.color,t._model);l.backgroundColor=o.backgroundColor?o.backgroundColor:r(i.backgroundColor,n,a.backgroundColor),l.borderColor=o.borderColor?o.borderColor:r(i.borderColor,n,a.borderColor),l.borderWidth=o.borderWidth?o.borderWidth:r(i.borderWidth,n,a.borderWidth)},setHoverStyle:function(t){var a=this.chart.data.datasets[t._datasetIndex],i=t._index,n=t.custom||{},o=e.getValueAtIndexOrDefault,r=(e.color,e.getHoverColor),l=t._model;l.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:o(a.hoverBackgroundColor,i,r(l.backgroundColor)),l.borderColor=n.hoverBorderColor?n.hoverBorderColor:o(a.hoverBorderColor,i,r(l.borderColor)),l.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:o(a.hoverBorderWidth,i,l.borderWidth)}}),t.DatasetController.extend=e.inherits}},{}],24:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.elements={},t.Element=function(t){e.extend(this,t),this.initialize.apply(this,arguments)},e.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){var t=this;return t._view||(t._view=e.clone(t._model)),t._start=e.clone(t._view),t},transition:function(t){var a=this;return a._view||(a._view=e.clone(a._model)),1===t?(a._view=a._model,a._start=null,a):(a._start||a.pivot(),e.each(a._model,function(i,n){if("_"===n[0]);else if(a._view.hasOwnProperty(n))if(i===a._view[n]);else if("string"==typeof i)try{var o=e.color(a._model[n]).mix(e.color(a._start[n]),t);a._view[n]=o.rgbString()}catch(r){a._view[n]=i}else if("number"==typeof i){var l=void 0!==a._start[n]&&isNaN(a._start[n])===!1?a._start[n]:0;a._view[n]=(a._model[n]-l)*t+l}else a._view[n]=i;else"number"!=typeof i||isNaN(a._view[n])?a._view[n]=i:a._view[n]=i*t},a),a)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return e.isNumber(this._model.x)&&e.isNumber(this._model.y)}}),t.Element.extend=e.inherits}},{}],25:[function(t,e,a){"use strict";var i=t(3);e.exports=function(t){function e(t,e,a){var i;return"string"==typeof t?(i=parseInt(t,10),-1!=t.indexOf("%")&&(i=i/100*e.parentNode[a])):i=t,i}function a(t){return void 0!==t&&null!==t&&"none"!==t}function n(t,i,n){var o=document.defaultView,r=t.parentNode,l=o.getComputedStyle(t)[i],s=o.getComputedStyle(r)[i],d=a(l),u=a(s),c=Number.POSITIVE_INFINITY;return d||u?Math.min(d?e(l,t,n):c,u?e(s,r,n):c):"none"}var o=t.helpers={};o.each=function(t,e,a,i){var n,r;if(o.isArray(t))if(r=t.length,i)for(n=r-1;n>=0;n--)e.call(a,t[n],n);else for(n=0;r>n;n++)e.call(a,t[n],n);else if("object"==typeof t){var l=Object.keys(t);for(r=l.length,n=0;r>n;n++)e.call(a,t[l[n]],l[n])}},o.clone=function(t){var e={};return o.each(t,function(t,a){o.isArray(t)?e[a]=t.slice(0):"object"==typeof t&&null!==t?e[a]=o.clone(t):e[a]=t}),e},o.extend=function(t){for(var e=arguments.length,a=[],i=1;e>i;i++)a.push(arguments[i]);return o.each(a,function(e){o.each(e,function(e,a){t[a]=e})}),t},o.configMerge=function(e){var a=o.clone(e);return o.each(Array.prototype.slice.call(arguments,1),function(e){o.each(e,function(e,i){if("scales"===i)a[i]=o.scaleMerge(a.hasOwnProperty(i)?a[i]:{},e);else if("scale"===i)a[i]=o.configMerge(a.hasOwnProperty(i)?a[i]:{},t.scaleService.getScaleDefaults(e.type),e);else if(a.hasOwnProperty(i)&&o.isArray(a[i])&&o.isArray(e)){var n=a[i];o.each(e,function(t,e){e<n.length?"object"==typeof n[e]&&null!==n[e]&&"object"==typeof t&&null!==t?n[e]=o.configMerge(n[e],t):n[e]=t:n.push(t)})}else a.hasOwnProperty(i)&&"object"==typeof a[i]&&null!==a[i]&&"object"==typeof e?a[i]=o.configMerge(a[i],e):a[i]=e})}),a},o.extendDeep=function(t){function e(t){return o.each(arguments,function(a){a!==t&&o.each(a,function(a,i){t[i]&&t[i].constructor&&t[i].constructor===Object?e(t[i],a):t[i]=a})}),t}return e.apply(this,arguments)},o.scaleMerge=function(e,a){var i=o.clone(e);return o.each(a,function(e,a){"xAxes"===a||"yAxes"===a?i.hasOwnProperty(a)?o.each(e,function(e,n){var r=o.getValueOrDefault(e.type,"xAxes"===a?"category":"linear"),l=t.scaleService.getScaleDefaults(r);n>=i[a].length||!i[a][n].type?i[a].push(o.configMerge(l,e)):e.type&&e.type!==i[a][n].type?i[a][n]=o.configMerge(i[a][n],l,e):i[a][n]=o.configMerge(i[a][n],e)}):(i[a]=[],o.each(e,function(e){var n=o.getValueOrDefault(e.type,"xAxes"===a?"category":"linear");i[a].push(o.configMerge(t.scaleService.getScaleDefaults(n),e))})):i.hasOwnProperty(a)&&"object"==typeof i[a]&&null!==i[a]&&"object"==typeof e?i[a]=o.configMerge(i[a],e):i[a]=e}),i},o.getValueAtIndexOrDefault=function(t,e,a){return void 0===t||null===t?a:o.isArray(t)?e<t.length?t[e]:a:t},o.getValueOrDefault=function(t,e){return void 0===t?e:t},o.indexOf=function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var a=0;a<t.length;a++)if(t[a]===e)return a;return-1},o.where=function(t,e){if(o.isArray(t)&&Array.prototype.filter)return t.filter(e);var a=[];return o.each(t,function(t){e(t)&&a.push(t)}),a},o.findIndex=function(t,e,a){var i=-1;if(Array.prototype.findIndex)i=t.findIndex(e,a);else for(var n=0;n<t.length;++n)if(a=void 0!==a?a:t,e.call(a,t[n],n,t)){i=n;break}return i},o.findNextWhere=function(t,e,a){(void 0===a||null===a)&&(a=-1);for(var i=a+1;i<t.length;i++){var n=t[i];if(e(n))return n}},o.findPreviousWhere=function(t,e,a){(void 0===a||null===a)&&(a=t.length);for(var i=a-1;i>=0;i--){var n=t[i];if(e(n))return n}},o.inherits=function(t){var e=this,a=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=a};return i.prototype=e.prototype,a.prototype=new i,a.extend=o.inherits,t&&o.extend(a.prototype,t),a.__super__=e.prototype,a},o.noop=function(){},o.uid=function(){var t=0;return function(){return t++}}(),o.warn=function(t){console&&"function"==typeof console.warn&&console.warn(t)},o.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},o.almostEquals=function(t,e,a){return Math.abs(t-e)<a},o.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},o.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},o.sign=function(t){return Math.sign?Math.sign(t):(t=+t,0===t||isNaN(t)?t:t>0?1:-1)},o.log10=function(t){return Math.log10?Math.log10(t):Math.log(t)/Math.LN10},o.toRadians=function(t){return t*(Math.PI/180)},o.toDegrees=function(t){return t*(180/Math.PI)},o.getAngleFromPoint=function(t,e){var a=e.x-t.x,i=e.y-t.y,n=Math.sqrt(a*a+i*i),o=Math.atan2(i,a);return o<-.5*Math.PI&&(o+=2*Math.PI),{angle:o,distance:n}},o.aliasPixel=function(t){return t%2===0?0:.5},o.splineCurve=function(t,e,a,i){var n=t.skip?e:t,o=e,r=a.skip?e:a,l=Math.sqrt(Math.pow(o.x-n.x,2)+Math.pow(o.y-n.y,2)),s=Math.sqrt(Math.pow(r.x-o.x,2)+Math.pow(r.y-o.y,2)),d=l/(l+s),u=s/(l+s);d=isNaN(d)?0:d,u=isNaN(u)?0:u;var c=i*d,h=i*u;return{previous:{x:o.x-c*(r.x-n.x),y:o.y-c*(r.y-n.y)},next:{x:o.x+h*(r.x-n.x),y:o.y+h*(r.y-n.y)}}},o.nextItem=function(t,e,a){return a?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},o.previousItem=function(t,e,a){return a?0>=e?t[t.length-1]:t[e-1]:0>=e?t[0]:t[e-1]},o.niceNum=function(t,e){var a,i=Math.floor(o.log10(t)),n=t/Math.pow(10,i);return a=e?1.5>n?1:3>n?2:7>n?5:10:1>=n?1:2>=n?2:5>=n?5:10,a*Math.pow(10,i)};var r=o.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:1===(t/=1)?1:(a||(a=.3),i<Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),-(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)))},easeOutElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:1===(t/=1)?1:(a||(a=.3),i<Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/a)+1)},easeInOutElastic:function(t){var e=1.70158,a=0,i=1;return 0===t?0:2===(t/=.5)?1:(a||(a=1*(.3*1.5)),i<Math.abs(1)?(i=1,e=a/4):e=a/(2*Math.PI)*Math.asin(1/i),1>t?-.5*(i*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)):i*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/a)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};o.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),o.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),o.getRelativePosition=function(t,e){var a,i,n=t.originalEvent||t,r=t.currentTarget||t.srcElement,l=r.getBoundingClientRect(),s=n.touches;s&&s.length>0?(a=s[0].clientX,i=s[0].clientY):(a=n.clientX,i=n.clientY);var d=parseFloat(o.getStyle(r,"padding-left")),u=parseFloat(o.getStyle(r,"padding-top")),c=parseFloat(o.getStyle(r,"padding-right")),h=parseFloat(o.getStyle(r,"padding-bottom")),f=l.right-l.left-d-c,g=l.bottom-l.top-u-h;return a=Math.round((a-l.left-d)/f*r.width/e.currentDevicePixelRatio),i=Math.round((i-l.top-u)/g*r.height/e.currentDevicePixelRatio),{x:a,y:i}},o.addEvent=function(t,e,a){t.addEventListener?t.addEventListener(e,a):t.attachEvent?t.attachEvent("on"+e,a):t["on"+e]=a},o.removeEvent=function(t,e,a){t.removeEventListener?t.removeEventListener(e,a,!1):t.detachEvent?t.detachEvent("on"+e,a):t["on"+e]=o.noop},o.bindEvents=function(t,e,a){var i=t.events=t.events||{};o.each(e,function(e){i[e]=function(){a.apply(t,arguments)},o.addEvent(t.chart.canvas,e,i[e])})},o.unbindEvents=function(t,e){var a=t.chart.canvas;o.each(e,function(t,e){o.removeEvent(a,e,t)})},o.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},o.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},o.getMaximumWidth=function(t){var e=t.parentNode,a=parseInt(o.getStyle(e,"padding-left"))+parseInt(o.getStyle(e,"padding-right")),i=e.clientWidth-a,n=o.getConstraintWidth(t);return isNaN(n)?i:Math.min(i,n)},o.getMaximumHeight=function(t){var e=t.parentNode,a=parseInt(o.getStyle(e,"padding-top"))+parseInt(o.getStyle(e,"padding-bottom")),i=e.clientHeight-a,n=o.getConstraintHeight(t);return isNaN(n)?i:Math.min(i,n)},o.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},o.retinaScale=function(t){var e=t.ctx,a=t.canvas,i=a.width,n=a.height,o=t.currentDevicePixelRatio=window.devicePixelRatio||1;1!==o&&(a.height=n*o,a.width=i*o,e.scale(o,o),t.originalDevicePixelRatio=t.originalDevicePixelRatio||o),a.style.width=i+"px",a.style.height=n+"px"},o.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},o.fontString=function(t,e,a){return e+" "+t+"px "+a},o.longestText=function(t,e,a,i){i=i||{};var n=i.data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(n=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var l=0;o.each(a,function(e){void 0!==e&&null!==e&&o.isArray(e)!==!0?l=o.measureText(t,n,r,l,e):o.isArray(e)&&o.each(e,function(e){void 0===e||null===e||o.isArray(e)||(l=o.measureText(t,n,r,l,e))})});var s=r.length/2;if(s>a.length){for(var d=0;s>d;d++)delete n[r[d]];r.splice(0,s)}return l},o.measureText=function(t,e,a,i,n){var o=e[n];return o||(o=e[n]=t.measureText(n).width,a.push(n)),o>i&&(i=o),i},o.numberOfLabelLines=function(t){var e=1;return o.each(t,function(t){o.isArray(t)&&t.length>e&&(e=t.length)}),e},o.drawRoundedRectangle=function(t,e,a,i,n,o){t.beginPath(),t.moveTo(e+o,a),t.lineTo(e+i-o,a),t.quadraticCurveTo(e+i,a,e+i,a+o),t.lineTo(e+i,a+n-o),t.quadraticCurveTo(e+i,a+n,e+i-o,a+n),t.lineTo(e+o,a+n),t.quadraticCurveTo(e,a+n,e,a+n-o),t.lineTo(e,a+o),t.quadraticCurveTo(e,a,e+o,a),t.closePath()},o.color=function(e){return i?i(e instanceof CanvasGradient?t.defaults.global.defaultColor:e):(console.log("Color.js not found!"),e)},o.addResizeListener=function(t,e){var a=document.createElement("iframe"),i="chartjs-hidden-iframe";a.classlist?a.classlist.add(i):a.setAttribute("class",i);var n=a.style;n.width="100%",n.display="block",n.border=0,n.height=0,n.margin=0,n.position="absolute",n.left=0,n.right=0,n.top=0,n.bottom=0,t.insertBefore(a,t.firstChild),(a.contentWindow||a).onresize=function(){e&&e()}},o.removeResizeListener=function(t){var e=t.querySelector(".chartjs-hidden-iframe");e&&e.parentNode.removeChild(e)},o.isArray=function(t){return Array.isArray?Array.isArray(t):"[object Array]"===Object.prototype.toString.call(t)},o.arrayEquals=function(t,e){var a,i,n,r;if(!t||!e||t.length!=e.length)return!1;for(a=0,i=t.length;i>a;++a)if(n=t[a],r=e[a],n instanceof Array&&r instanceof Array){if(!o.arrayEquals(n,r))return!1}else if(n!=r)return!1;return!0},o.callCallback=function(t,e,a){t&&"function"==typeof t.call&&t.apply(a,e)},o.getHoverColor=function(t){return t instanceof CanvasPattern?t:o.color(t).saturate(.5).darken(.1).rgbString()}}},{3:3}],26:[function(t,e,a){"use strict";e.exports=function(){var t=function(e,a){var i=this,n=t.helpers;return i.config=a,e.length&&e[0].getContext&&(e=e[0]),e.getContext&&(e=e.getContext("2d")),i.ctx=e,i.canvas=e.canvas,e.canvas.style.display=e.canvas.style.display||"block",i.width=e.canvas.width||parseInt(n.getStyle(e.canvas,"width"),10)||n.getMaximumWidth(e.canvas),i.height=e.canvas.height||parseInt(n.getStyle(e.canvas,"height"),10)||n.getMaximumHeight(e.canvas),i.aspectRatio=i.width/i.height,(isNaN(i.aspectRatio)||isFinite(i.aspectRatio)===!1)&&(i.aspectRatio=void 0!==a.aspectRatio?a.aspectRatio:2),i.originalCanvasStyleWidth=e.canvas.style.width,i.originalCanvasStyleHeight=e.canvas.style.height,n.retinaScale(i),a&&(i.controller=new t.Controller(i)),n.addResizeListener(e.canvas.parentNode,function(){i.controller&&i.controller.config.options.responsive&&i.controller.resize()}),i.controller?i.controller:i};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"single",animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var a=0;a<t.data.datasets.length;a++)e.push('<li><span style="background-color:'+t.data.datasets[a].backgroundColor+'"></span>'),t.data.datasets[a].label&&e.push(t.data.datasets[a].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t.Chart=t,t}},{}],27:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),t.boxes.push(e)},removeBox:function(t,e){t.boxes&&t.boxes.splice(t.boxes.indexOf(e),1)},update:function(t,a,i){function n(t){var e,a=t.isHorizontal();a?(e=t.update(t.options.fullWidth?p:k,y),S-=e.height):(e=t.update(x,v),k-=e.width),w.push({horizontal:a,minSize:e,box:t})}function o(t){var a=e.findNextWhere(w,function(e){return e.box===t});if(a)if(t.isHorizontal()){var i={left:C,right:M,top:0,bottom:0};t.update(t.options.fullWidth?p:k,m/2,i)}else t.update(a.minSize.width,S)}function r(t){var a=e.findNextWhere(w,function(e){return e.box===t}),i={left:0,right:0,top:D,bottom:A};a&&t.update(a.minSize.width,S,i)}function l(t){t.isHorizontal()?(t.left=t.options.fullWidth?s:C,t.right=t.options.fullWidth?a-s:C+k,t.top=F,t.bottom=F+t.height,F=t.bottom):(t.left=P,t.right=P+t.width,t.top=D,t.bottom=D+S,P=t.right)}if(t){var s=0,d=0,u=e.where(t.boxes,function(t){return"left"===t.options.position}),c=e.where(t.boxes,function(t){return"right"===t.options.position}),h=e.where(t.boxes,function(t){return"top"===t.options.position}),f=e.where(t.boxes,function(t){return"bottom"===t.options.position}),g=e.where(t.boxes,function(t){return"chartArea"===t.options.position});h.sort(function(t,e){return(e.options.fullWidth?1:0)-(t.options.fullWidth?1:0)}),f.sort(function(t,e){return(t.options.fullWidth?1:0)-(e.options.fullWidth?1:0)});var p=a-2*s,m=i-2*d,b=p/2,v=m/2,x=(a-b)/(u.length+c.length),y=(i-v)/(h.length+f.length),k=p,S=m,w=[];e.each(u.concat(c,h,f),n);var C=s,M=s,D=d,A=d;e.each(u.concat(c),o),e.each(u,function(t){C+=t.width}),e.each(c,function(t){M+=t.width}),e.each(h.concat(f),o),e.each(h,function(t){D+=t.height}),e.each(f,function(t){A+=t.height}),e.each(u.concat(c),r),C=s,M=s,D=d,A=d,e.each(u,function(t){C+=t.width}),e.each(c,function(t){M+=t.width}),e.each(h,function(t){D+=t.height}),e.each(f,function(t){A+=t.height});var T=i-D-A,I=a-C-M;(I!==k||T!==S)&&(e.each(u,function(t){t.height=T}),e.each(c,function(t){t.height=T}),e.each(h,function(t){t.options.fullWidth||(t.width=I)}),e.each(f,function(t){t.options.fullWidth||(t.width=I)}),S=T,k=I);var P=s,F=d;e.each(u.concat(h),l),P+=k,F+=S,e.each(c,l),e.each(f,l),t.chartArea={left:C,top:D,right:C+k,bottom:D+S},e.each(g,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(k,S)})}}}}},{}],28:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=e.noop;t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,onClick:function(t,e){var a=e.datasetIndex,i=this.chart,n=i.getDatasetMeta(a);n.hidden=null===n.hidden?!i.data.datasets[a].hidden:null,i.update()},labels:{boxWidth:40,padding:10,generateLabels:function(t){var a=t.data;return e.isArray(a.datasets)?a.datasets.map(function(a,i){return{text:a.label,fillStyle:e.isArray(a.backgroundColor)?a.backgroundColor[0]:a.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:a.borderWidth,strokeStyle:a.borderColor,datasetIndex:i}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){e.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:a,update:function(t,e,a){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=a,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:a,beforeSetDimensions:a,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:a,beforeBuildLabels:a,buildLabels:function(){var t=this;t.legendItems=t.options.labels.generateLabels.call(t,t.chart),t.options.reverse&&t.legendItems.reverse()},afterBuildLabels:a,beforeFit:a,fit:function(){var a=this,i=a.options,n=i.labels,o=i.display,r=a.ctx,l=t.defaults.global,s=e.getValueOrDefault,d=s(n.fontSize,l.defaultFontSize),u=s(n.fontStyle,l.defaultFontStyle),c=s(n.fontFamily,l.defaultFontFamily),h=e.fontString(d,u,c),f=a.legendHitBoxes=[],g=a.minSize,p=a.isHorizontal();if(p?(g.width=a.maxWidth,g.height=o?10:0):(g.width=o?10:0,g.height=a.maxHeight),o&&p){var m=a.lineWidths=[0],b=a.legendItems.length?d+n.padding:0;r.textAlign="left",r.textBaseline="top",r.font=h,e.each(a.legendItems,function(t,e){var i=n.boxWidth+d/2+r.measureText(t.text).width;m[m.length-1]+i+n.padding>=a.width&&(b+=d+n.padding,m[m.length]=a.left),f[e]={left:0,top:0,width:i,height:d},m[m.length-1]+=i+n.padding},a),g.height+=b}a.width=g.width,a.height=g.height},afterFit:a,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var a=this,i=a.options,n=i.labels,o=t.defaults.global,r=o.elements.line,l=a.width,s=a.lineWidths;if(i.display){var d=a.ctx,u={x:a.left+(l-s[0])/2,y:a.top+n.padding,line:0},c=e.getValueOrDefault,h=c(n.fontColor,o.defaultFontColor),f=c(n.fontSize,o.defaultFontSize),g=c(n.fontStyle,o.defaultFontStyle),p=c(n.fontFamily,o.defaultFontFamily),m=e.fontString(f,g,p);if(a.isHorizontal()){d.textAlign="left",d.textBaseline="top",d.lineWidth=.5,d.strokeStyle=h,d.fillStyle=h,d.font=m;var b=n.boxWidth,v=a.legendHitBoxes;e.each(a.legendItems,function(t,e){var i=d.measureText(t.text).width,h=b+f/2+i,g=u.x,p=u.y;g+h>=l&&(p=u.y+=f+n.padding,u.line++,g=u.x=a.left+(l-s[u.line])/2),d.save(),d.fillStyle=c(t.fillStyle,o.defaultColor),d.lineCap=c(t.lineCap,r.borderCapStyle),d.lineDashOffset=c(t.lineDashOffset,r.borderDashOffset),d.lineJoin=c(t.lineJoin,r.borderJoinStyle),d.lineWidth=c(t.lineWidth,r.borderWidth),d.strokeStyle=c(t.strokeStyle,o.defaultColor),d.setLineDash&&d.setLineDash(c(t.lineDash,r.borderDash)),d.strokeRect(g,p,b,f),d.fillRect(g,p,b,f),d.restore(),v[e].left=g,v[e].top=p,d.fillText(t.text,b+f/2+g,p),t.hidden&&(d.beginPath(),d.lineWidth=2,d.moveTo(b+f/2+g,p+f/2),d.lineTo(b+f/2+g+i,p+f/2),d.stroke()),u.x+=h+n.padding},a)}}},handleEvent:function(t){var a=this,i=e.getRelativePosition(t,a.chart.chart),n=i.x,o=i.y,r=a.options;if(n>=a.left&&n<=a.right&&o>=a.top&&o<=a.bottom)for(var l=a.legendHitBoxes,s=0;s<l.length;++s){var d=l[s];if(n>=d.left&&n<=d.left+d.width&&o>=d.top&&o<=d.top+d.height){r.onClick&&r.onClick.call(a,t,a.legendItems[s]);break}}}}),t.pluginService.register({beforeInit:function(e){var a=e.options,i=a.legend;i&&(e.legend=new t.Legend({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.legend))}})}},{}],29:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.plugins=[],t.pluginService={register:function(e){var a=t.plugins;-1===a.indexOf(e)&&a.push(e)},remove:function(e){var a=t.plugins,i=a.indexOf(e);-1!==i&&a.splice(i,1)},notifyPlugins:function(a,i,n){e.each(t.plugins,function(t){t[a]&&"function"==typeof t[a]&&t[a].apply(n,i)},n)}};var a=e.noop;t.PluginBase=t.Element.extend({beforeInit:a,afterInit:a,beforeUpdate:a,afterUpdate:a,beforeDraw:a,afterDraw:a,destroy:a})}},{}],30:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",offsetGridLines:!1},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:10,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:function(t){return e.isArray(t)?t:""+t}}},t.Scale=t.Element.extend({beforeUpdate:function(){e.callCallback(this.options.beforeUpdate,[this])},update:function(t,a,i){var n=this;return n.beforeUpdate(),n.maxWidth=t,n.maxHeight=a,n.margins=e.extend({left:0,right:0,top:0,bottom:0},i),n.beforeSetDimensions(),n.setDimensions(),n.afterSetDimensions(),n.beforeDataLimits(),n.determineDataLimits(),n.afterDataLimits(),n.beforeBuildTicks(),n.buildTicks(),n.afterBuildTicks(),n.beforeTickToLabelConversion(),n.convertTicksToLabels(),n.afterTickToLabelConversion(),n.beforeCalculateTickRotation(),n.calculateTickRotation(),n.afterCalculateTickRotation(),n.beforeFit(),n.fit(),n.afterFit(),n.afterUpdate(),n.minSize},afterUpdate:function(){e.callCallback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){e.callCallback(this.options.beforeSetDimensions,[this])},setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0},afterSetDimensions:function(){e.callCallback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){e.callCallback(this.options.beforeDataLimits,[this])},determineDataLimits:e.noop,afterDataLimits:function(){e.callCallback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){e.callCallback(this.options.beforeBuildTicks,[this])},buildTicks:e.noop,afterBuildTicks:function(){e.callCallback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){e.callCallback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){var t=this;t.ticks=t.ticks.map(function(e,a,i){return t.options.ticks.userCallback?t.options.ticks.userCallback(e,a,i):t.options.ticks.callback(e,a,i)},t)},afterTickToLabelConversion:function(){e.callCallback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){e.callCallback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var a=this,i=a.ctx,n=t.defaults.global,o=a.options.ticks,r=e.getValueOrDefault(o.fontSize,n.defaultFontSize),l=e.getValueOrDefault(o.fontStyle,n.defaultFontStyle),s=e.getValueOrDefault(o.fontFamily,n.defaultFontFamily),d=e.fontString(r,l,s);i.font=d;var u,c=i.measureText(a.ticks[0]).width,h=i.measureText(a.ticks[a.ticks.length-1]).width;if(a.labelRotation=o.minRotation||0,a.paddingRight=0,a.paddingLeft=0,a.options.display&&a.isHorizontal()){a.paddingRight=h/2+3,a.paddingLeft=c/2+3,a.longestTextCache||(a.longestTextCache={});for(var f,g,p=e.longestText(i,d,a.ticks,a.longestTextCache),m=p,b=a.getPixelForTick(1)-a.getPixelForTick(0)-6;m>b&&a.labelRotation<o.maxRotation;){if(f=Math.cos(e.toRadians(a.labelRotation)),g=Math.sin(e.toRadians(a.labelRotation)),u=f*c,u+r/2>a.yLabelWidth&&(a.paddingLeft=u+r/2),a.paddingRight=r/2,g*p>a.maxHeight){a.labelRotation--;break}a.labelRotation++,m=f*p}}a.margins&&(a.paddingLeft=Math.max(a.paddingLeft-a.margins.left,0),a.paddingRight=Math.max(a.paddingRight-a.margins.right,0))},afterCalculateTickRotation:function(){e.callCallback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){e.callCallback(this.options.beforeFit,[this])},fit:function(){var a=this,i=a.minSize={width:0,height:0},n=a.options,o=t.defaults.global,r=n.ticks,l=n.scaleLabel,s=n.display,d=a.isHorizontal(),u=e.getValueOrDefault(r.fontSize,o.defaultFontSize),c=e.getValueOrDefault(r.fontStyle,o.defaultFontStyle),h=e.getValueOrDefault(r.fontFamily,o.defaultFontFamily),f=e.fontString(u,c,h),g=e.getValueOrDefault(l.fontSize,o.defaultFontSize),p=e.getValueOrDefault(l.fontStyle,o.defaultFontStyle),m=e.getValueOrDefault(l.fontFamily,o.defaultFontFamily),b=(e.fontString(g,p,m),n.gridLines.tickMarkLength);if(d?i.width=a.isFullWidth()?a.maxWidth-a.margins.left-a.margins.right:a.maxWidth:i.width=s?b:0,d?i.height=s?b:0:i.height=a.maxHeight,l.display&&s&&(d?i.height+=1.5*g:i.width+=1.5*g),r.display&&s){a.longestTextCache||(a.longestTextCache={});var v=e.longestText(a.ctx,f,a.ticks,a.longestTextCache),x=e.numberOfLabelLines(a.ticks),y=.5*u;if(d){a.longestLabelWidth=v;var k=Math.sin(e.toRadians(a.labelRotation))*a.longestLabelWidth+u*x+y*x;i.height=Math.min(a.maxHeight,i.height+k),a.ctx.font=f;var S=a.ctx.measureText(a.ticks[0]).width,w=a.ctx.measureText(a.ticks[a.ticks.length-1]).width,C=Math.cos(e.toRadians(a.labelRotation)),M=Math.sin(e.toRadians(a.labelRotation));a.paddingLeft=0!==a.labelRotation?C*S+3:S/2+3,a.paddingRight=0!==a.labelRotation?M*(u/2)+3:w/2+3}else{var D=a.maxWidth-i.width,A=r.mirror;A?v=0:v+=a.options.ticks.padding,D>v?i.width+=v:i.width=a.maxWidth,a.paddingTop=u/2,a.paddingBottom=u/2}}a.margins&&(a.paddingLeft=Math.max(a.paddingLeft-a.margins.left,0),a.paddingTop=Math.max(a.paddingTop-a.margins.top,0),a.paddingRight=Math.max(a.paddingRight-a.margins.right,0),a.paddingBottom=Math.max(a.paddingBottom-a.margins.bottom,0)),a.width=i.width,a.height=i.height},afterFit:function(){e.callCallback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function a(t){return null===t||"undefined"==typeof t?NaN:"number"==typeof t&&isNaN(t)?NaN:"object"==typeof t?t instanceof Date||t.isValid?t:a(this.isHorizontal()?t.x:t.y):t},getLabelForIndex:e.noop,getPixelForValue:e.noop,getValueForPixel:e.noop,getPixelForTick:function(t,e){var a=this;if(a.isHorizontal()){var i=a.width-(a.paddingLeft+a.paddingRight),n=i/Math.max(a.ticks.length-(a.options.gridLines.offsetGridLines?0:1),1),o=n*t+a.paddingLeft;e&&(o+=n/2);var r=a.left+Math.round(o);return r+=a.isFullWidth()?a.margins.left:0}var l=a.height-(a.paddingTop+a.paddingBottom);return a.top+t*(l/(a.ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var a=e.width-(e.paddingLeft+e.paddingRight),i=a*t+e.paddingLeft,n=e.left+Math.round(i);return n+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){var t=this,e=t.min,a=t.max;return t.getPixelForValue(t.beginAtZero?0:0>e&&0>a?a:e>0&&a>0?e:0)},draw:function(a){var i=this,n=i.options;if(n.display){var o,r,l,s,d,u=i.ctx,c=t.defaults.global,h=n.ticks,f=n.gridLines,g=n.scaleLabel,p=0!==i.labelRotation,m=h.autoSkip;h.maxTicksLimit&&(d=h.maxTicksLimit);var b=e.getValueOrDefault(h.fontColor,c.defaultFontColor),v=e.getValueOrDefault(h.fontSize,c.defaultFontSize),x=e.getValueOrDefault(h.fontStyle,c.defaultFontStyle),y=e.getValueOrDefault(h.fontFamily,c.defaultFontFamily),k=e.fontString(v,x,y),S=f.tickMarkLength,w=e.getValueOrDefault(g.fontColor,c.defaultFontColor),C=e.getValueOrDefault(g.fontSize,c.defaultFontSize),M=e.getValueOrDefault(g.fontStyle,c.defaultFontStyle),D=e.getValueOrDefault(g.fontFamily,c.defaultFontFamily),A=e.fontString(C,M,D),T=e.toRadians(i.labelRotation),I=Math.cos(T),P=(Math.sin(T),
-i.longestLabelWidth*I);if(u.fillStyle=b,i.isHorizontal()){o=!0;var F="bottom"===n.position?i.top:i.bottom-S,_="bottom"===n.position?i.top+S:i.bottom;if(r=!1,p&&(P/=2),(P+h.autoSkipPadding)*i.ticks.length>i.width-(i.paddingLeft+i.paddingRight)&&(r=1+Math.floor((P+h.autoSkipPadding)*i.ticks.length/(i.width-(i.paddingLeft+i.paddingRight)))),d&&i.ticks.length>d)for(;!r||i.ticks.length/(r||1)>d;)r||(r=1),r+=1;m||(r=!1),e.each(i.ticks,function(t,l){var s=i.ticks.length===l+1,d=r>1&&l%r>0||l%r===0&&l+r>=i.ticks.length;if((!d||s)&&void 0!==t&&null!==t){var c=i.getPixelForTick(l),g=i.getPixelForTick(l,f.offsetGridLines);if(f.display&&(l===("undefined"!=typeof i.zeroLineIndex?i.zeroLineIndex:0)?(u.lineWidth=f.zeroLineWidth,u.strokeStyle=f.zeroLineColor,o=!0):o&&(u.lineWidth=f.lineWidth,u.strokeStyle=f.color,o=!1),c+=e.aliasPixel(u.lineWidth),u.beginPath(),f.drawTicks&&(u.moveTo(c,F),u.lineTo(c,_)),f.drawOnChartArea&&(u.moveTo(c,a.top),u.lineTo(c,a.bottom)),u.stroke()),h.display){if(u.save(),u.translate(g+h.labelOffset,p?i.top+12:"top"===n.position?i.bottom-S:i.top+S),u.rotate(-1*T),u.font=k,u.textAlign=p?"right":"center",u.textBaseline=p?"middle":"top"===n.position?"bottom":"top",e.isArray(t))for(var m=0,b=0;m<t.length;++m)u.fillText(""+t[m],0,b),b+=1.5*v;else u.fillText(t,0,0);u.restore()}}},i),g.display&&(u.textAlign="center",u.textBaseline="middle",u.fillStyle=w,u.font=A,l=i.left+(i.right-i.left)/2,s="bottom"===n.position?i.bottom-C/2:i.top+C/2,u.fillText(g.labelString,l,s))}else{o=!0;var R="right"===n.position?i.left:i.right-5,V="right"===n.position?i.left+5:i.right;if(e.each(i.ticks,function(t,r){if(void 0!==t&&null!==t){var l=i.getPixelForTick(r);if(f.display&&(r===("undefined"!=typeof i.zeroLineIndex?i.zeroLineIndex:0)?(u.lineWidth=f.zeroLineWidth,u.strokeStyle=f.zeroLineColor,o=!0):o&&(u.lineWidth=f.lineWidth,u.strokeStyle=f.color,o=!1),l+=e.aliasPixel(u.lineWidth),u.beginPath(),f.drawTicks&&(u.moveTo(R,l),u.lineTo(V,l)),f.drawOnChartArea&&(u.moveTo(a.left,l),u.lineTo(a.right,l)),u.stroke()),h.display){var s,d=i.getPixelForTick(r,f.offsetGridLines);u.save(),"left"===n.position?h.mirror?(s=i.right+h.padding,u.textAlign="left"):(s=i.right-h.padding,u.textAlign="right"):h.mirror?(s=i.left-h.padding,u.textAlign="right"):(s=i.left+h.padding,u.textAlign="left"),u.translate(s,d+h.labelOffset),u.rotate(-1*T),u.font=k,u.textBaseline="middle",u.fillText(t,0,0),u.restore()}}},i),g.display){l="left"===n.position?i.left+C/2:i.right-C/2,s=i.top+(i.bottom-i.top)/2;var L="left"===n.position?-.5*Math.PI:.5*Math.PI;u.save(),u.translate(l,s),u.rotate(L),u.textAlign="center",u.fillStyle=w,u.font=A,u.textBaseline="middle",u.fillText(g.labelString,0,0),u.restore()}}if(f.drawBorder){u.lineWidth=f.lineWidth,u.strokeStyle=f.color;var O=i.left,B=i.right,W=i.top,z=i.bottom,H=e.aliasPixel(u.lineWidth);i.isHorizontal()?(W=z="top"===n.position?i.bottom:i.top,W+=H,z+=H):(O=B="left"===n.position?i.right:i.left,O+=H,B+=H),u.beginPath(),u.moveTo(O,W),u.lineTo(B,z),u.stroke()}}}})}},{}],31:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,a,i){this.constructors[t]=a,this.defaults[t]=e.clone(i)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(a){return this.defaults.hasOwnProperty(a)?e.scaleMerge(t.defaults.scale,this.defaults[a]):{}},updateScaleDefaults:function(t,a){var i=this.defaults;i.hasOwnProperty(t)&&(i[t]=e.extend(i[t],a))},addScalesToLayout:function(a){e.each(a.scales,function(e){t.layoutService.addBox(a,e)})}}}},{}],32:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.title={display:!1,position:"top",fullWidth:!0,fontStyle:"bold",padding:10,text:""};var a=e.noop;t.Title=t.Element.extend({initialize:function(a){var i=this;e.extend(i,a),i.options=e.configMerge(t.defaults.global.title,a.options),i.legendHitBoxes=[]},beforeUpdate:function(){var a=this.chart.options;a&&a.title&&(this.options=e.configMerge(t.defaults.global.title,a.title))},update:function(t,e,a){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=a,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:a,beforeSetDimensions:a,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:a,beforeBuildLabels:a,buildLabels:a,afterBuildLabels:a,beforeFit:a,fit:function(){var a=this,i=(a.ctx,e.getValueOrDefault),n=a.options,o=t.defaults.global,r=n.display,l=i(n.fontSize,o.defaultFontSize),s=a.minSize;a.isHorizontal()?(s.width=a.maxWidth,s.height=r?l+2*n.padding:0):(s.width=r?l+2*n.padding:0,s.height=a.maxHeight),a.width=s.width,a.height=s.height},afterFit:a,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var a=this,i=a.ctx,n=e.getValueOrDefault,o=a.options,r=t.defaults.global;if(o.display){var l,s,d=n(o.fontSize,r.defaultFontSize),u=n(o.fontStyle,r.defaultFontStyle),c=n(o.fontFamily,r.defaultFontFamily),h=e.fontString(d,u,c),f=0,g=a.top,p=a.left,m=a.bottom,b=a.right;i.fillStyle=n(o.fontColor,r.defaultFontColor),i.font=h,a.isHorizontal()?(l=p+(b-p)/2,s=g+(m-g)/2):(l="left"===o.position?p+d/2:b-d/2,s=g+(m-g)/2,f=Math.PI*("left"===o.position?-.5:.5)),i.save(),i.translate(l,s),i.rotate(f),i.textAlign="center",i.textBaseline="middle",i.fillText(o.text,0,0),i.restore()}}}),t.pluginService.register({beforeInit:function(e){var a=e.options,i=a.title;i&&(e.titleBlock=new t.Title({ctx:e.chart.ctx,options:i,chart:e}),t.layoutService.addBox(e,e.titleBlock))}})}},{}],33:[function(t,e,a){"use strict";e.exports=function(t){function e(t,e){return e&&(n.isArray(e)?t=t.concat(e):t.push(e)),t}function a(t){if(!t.length)return!1;var e,a,i=[],n=[];for(e=0,a=t.length;a>e;++e){var o=t[e];if(o&&o.hasValue()){var r=o.tooltipPosition();i.push(r.x),n.push(r.y)}}var l=0,s=0;for(e=0,a-i.length;a>e;++e)l+=i[e],s+=n[e];return{x:Math.round(l/i.length),y:Math.round(s/i.length)}}function i(t){var e=t._xScale,a=t._yScale||t._scale,i=t._index,n=t._datasetIndex;return{xLabel:e?e.getLabelForIndex(i,n):"",yLabel:a?a.getLabelForIndex(i,n):"",index:i,datasetIndex:n}}var n=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"single",backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleColor:"#fff",titleAlign:"left",bodySpacing:2,bodyColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,yAlign:"center",xAlign:"center",caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",callbacks:{beforeTitle:n.noop,title:function(t,e){var a="",i=e.labels,n=i?i.length:0;if(t.length>0){var o=t[0];o.xLabel?a=o.xLabel:n>0&&o.index<n&&(a=i[o.index])}return a},afterTitle:n.noop,beforeBody:n.noop,beforeLabel:n.noop,label:function(t,e){var a=e.datasets[t.datasetIndex].label||"";return a+": "+t.yLabel},labelColor:function(t,e){var a=e.getDatasetMeta(t.datasetIndex),i=a.data[t.index],n=i._view;return{borderColor:n.borderColor,backgroundColor:n.backgroundColor}},afterLabel:n.noop,afterBody:n.noop,beforeFooter:n.noop,footer:n.noop,afterFooter:n.noop}},t.Tooltip=t.Element.extend({initialize:function(){var e=this,a=t.defaults.global,i=e._options,o=n.getValueOrDefault;n.extend(e,{_model:{xPadding:i.xPadding,yPadding:i.yPadding,xAlign:i.yAlign,yAlign:i.xAlign,bodyColor:i.bodyColor,_bodyFontFamily:o(i.bodyFontFamily,a.defaultFontFamily),_bodyFontStyle:o(i.bodyFontStyle,a.defaultFontStyle),_bodyAlign:i.bodyAlign,bodyFontSize:o(i.bodyFontSize,a.defaultFontSize),bodySpacing:i.bodySpacing,titleColor:i.titleColor,_titleFontFamily:o(i.titleFontFamily,a.defaultFontFamily),_titleFontStyle:o(i.titleFontStyle,a.defaultFontStyle),titleFontSize:o(i.titleFontSize,a.defaultFontSize),_titleAlign:i.titleAlign,titleSpacing:i.titleSpacing,titleMarginBottom:i.titleMarginBottom,footerColor:i.footerColor,_footerFontFamily:o(i.footerFontFamily,a.defaultFontFamily),_footerFontStyle:o(i.footerFontStyle,a.defaultFontStyle),footerFontSize:o(i.footerFontSize,a.defaultFontSize),_footerAlign:i.footerAlign,footerSpacing:i.footerSpacing,footerMarginTop:i.footerMarginTop,caretSize:i.caretSize,cornerRadius:i.cornerRadius,backgroundColor:i.backgroundColor,opacity:0,legendColorBackground:i.multiKeyBackground}})},getTitle:function(){var t=this,a=t._options,i=a.callbacks,n=i.beforeTitle.apply(t,arguments),o=i.title.apply(t,arguments),r=i.afterTitle.apply(t,arguments),l=[];return l=e(l,n),l=e(l,o),l=e(l,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return n.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,a){var i=this,o=i._options.callbacks,r=[];return n.each(t,function(t){var n={before:[],lines:[],after:[]};e(n.before,o.beforeLabel.call(i,t,a)),e(n.lines,o.label.call(i,t,a)),e(n.after,o.afterLabel.call(i,t,a)),r.push(n)}),r},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return n.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,a=t._options.callbacks,i=a.beforeFooter.apply(t,arguments),n=a.footer.apply(t,arguments),o=a.afterFooter.apply(t,arguments),r=[];return r=e(r,i),r=e(r,n),r=e(r,o)},update:function(t){var e,o,r=this,l=r._options,s=r._model,d=r._active,u=r._data,c=r._chartInstance;if(d.length){s.opacity=1;var h=[],f=a(d),g=[];for(e=0,o=d.length;o>e;++e)g.push(i(d[e]));l.itemSort&&(g=g.sort(l.itemSort)),d.length>1&&n.each(g,function(t){h.push(l.callbacks.labelColor.call(r,t,c))}),n.extend(s,{title:r.getTitle(g,u),beforeBody:r.getBeforeBody(g,u),body:r.getBody(g,u),afterBody:r.getAfterBody(g,u),footer:r.getFooter(g,u),x:Math.round(f.x),y:Math.round(f.y),caretPadding:n.getValueOrDefault(f.padding,2),labelColors:h});var p=r.getTooltipSize(s);r.determineAlignment(p),n.extend(s,r.getBackgroundPoint(s,p))}else r._model.opacity=0;return t&&l.custom&&l.custom.call(r,s),r},getTooltipSize:function(t){var e=this._chart.ctx,a={height:2*t.yPadding,width:0},i=t.body,o=i.reduce(function(t,e){return t+e.before.length+e.lines.length+e.after.length},0);o+=t.beforeBody.length+t.afterBody.length;var r=t.title.length,l=t.footer.length,s=t.titleFontSize,d=t.bodyFontSize,u=t.footerFontSize;a.height+=r*s,a.height+=(r-1)*t.titleSpacing,a.height+=r?t.titleMarginBottom:0,a.height+=o*d,a.height+=o?(o-1)*t.bodySpacing:0,a.height+=l?t.footerMarginTop:0,a.height+=l*u,a.height+=l?(l-1)*t.footerSpacing:0;var c=0,h=function(t){a.width=Math.max(a.width,e.measureText(t).width+c)};return e.font=n.fontString(s,t._titleFontStyle,t._titleFontFamily),n.each(t.title,h),e.font=n.fontString(d,t._bodyFontStyle,t._bodyFontFamily),n.each(t.beforeBody.concat(t.afterBody),h),c=i.length>1?d+2:0,n.each(i,function(t){n.each(t.before,h),n.each(t.lines,h),n.each(t.after,h)}),c=0,e.font=n.fontString(u,t._footerFontStyle,t._footerFontFamily),n.each(t.footer,h),a.width+=2*t.xPadding,a},determineAlignment:function(t){var e=this,a=e._model,i=e._chart,n=e._chartInstance.chartArea;a.y<t.height?a.yAlign="top":a.y>i.height-t.height&&(a.yAlign="bottom");var o,r,l,s,d,u=(n.left+n.right)/2,c=(n.top+n.bottom)/2;"center"===a.yAlign?(o=function(t){return u>=t},r=function(t){return t>u}):(o=function(e){return e<=t.width/2},r=function(e){return e>=i.width-t.width/2}),l=function(e){return e+t.width>i.width},s=function(e){return e-t.width<0},d=function(t){return c>=t?"top":"bottom"},o(a.x)?(a.xAlign="left",l(a.x)&&(a.xAlign="center",a.yAlign=d(a.y))):r(a.x)&&(a.xAlign="right",s(a.x)&&(a.xAlign="center",a.yAlign=d(a.y)))},getBackgroundPoint:function(t,e){var a={x:t.x,y:t.y},i=t.caretSize,n=t.caretPadding,o=t.cornerRadius,r=t.xAlign,l=t.yAlign,s=i+n,d=o+n;return"right"===r?a.x-=e.width:"center"===r&&(a.x-=e.width/2),"top"===l?a.y+=s:"bottom"===l?a.y-=e.height+s:a.y-=e.height/2,"center"===l?"left"===r?a.x+=s:"right"===r&&(a.x-=s):"left"===r?a.x-=d:"right"===r&&(a.x+=d),a},drawCaret:function(t,e,a,i){var o,r,l,s,d,u,c=this._view,h=this._chart.ctx,f=c.caretSize,g=c.cornerRadius,p=c.xAlign,m=c.yAlign,b=t.x,v=t.y,x=e.width,y=e.height;"center"===m?("left"===p?(o=b,r=o-f,l=o):(o=b+x,r=o+f,l=o),d=v+y/2,s=d-f,u=d+f):("left"===p?(o=b+g,r=o+f,l=r+f):"right"===p?(o=b+x-g,r=o-f,l=r-f):(r=b+x/2,o=r-f,l=r+f),"top"===m?(s=v,d=s-f,u=s):(s=v+y,d=s+f,u=s));var k=n.color(c.backgroundColor);h.fillStyle=k.alpha(a*k.alpha()).rgbString(),h.beginPath(),h.moveTo(o,s),h.lineTo(r,d),h.lineTo(l,u),h.closePath(),h.fill()},drawTitle:function(t,e,a,i){var o=e.title;if(o.length){a.textAlign=e._titleAlign,a.textBaseline="top";var r=e.titleFontSize,l=e.titleSpacing,s=n.color(e.titleColor);a.fillStyle=s.alpha(i*s.alpha()).rgbString(),a.font=n.fontString(r,e._titleFontStyle,e._titleFontFamily);var d,u;for(d=0,u=o.length;u>d;++d)a.fillText(o[d],t.x,t.y),t.y+=r+l,d+1===o.length&&(t.y+=e.titleMarginBottom-l)}},drawBody:function(t,e,a,i){var o=e.bodyFontSize,r=e.bodySpacing,l=e.body;a.textAlign=e._bodyAlign,a.textBaseline="top";var s=n.color(e.bodyColor),d=s.alpha(i*s.alpha()).rgbString();a.fillStyle=d,a.font=n.fontString(o,e._bodyFontStyle,e._bodyFontFamily);var u=0,c=function(e){a.fillText(e,t.x+u,t.y),t.y+=o+r};n.each(e.beforeBody,c);var h=l.length>1;u=h?o+2:0,n.each(l,function(r,l){n.each(r.before,c),n.each(r.lines,function(r){h&&(a.fillStyle=n.color(e.legendColorBackground).alpha(i).rgbaString(),a.fillRect(t.x,t.y,o,o),a.strokeStyle=n.color(e.labelColors[l].borderColor).alpha(i).rgbaString(),a.strokeRect(t.x,t.y,o,o),a.fillStyle=n.color(e.labelColors[l].backgroundColor).alpha(i).rgbaString(),a.fillRect(t.x+1,t.y+1,o-2,o-2),a.fillStyle=d),c(r)}),n.each(r.after,c)}),u=0,n.each(e.afterBody,c),t.y-=r},drawFooter:function(t,e,a,i){var o=e.footer;if(o.length){t.y+=e.footerMarginTop,a.textAlign=e._footerAlign,a.textBaseline="top";var r=n.color(e.footerColor);a.fillStyle=r.alpha(i*r.alpha()).rgbString(),a.font=n.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),n.each(o,function(i){a.fillText(i,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing})}},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var a=this.getTooltipSize(e),i={x:e.x,y:e.y},o=Math.abs(e.opacity<.001)?0:e.opacity;if(this._options.enabled){var r=n.color(e.backgroundColor);t.fillStyle=r.alpha(o*r.alpha()).rgbString(),n.drawRoundedRectangle(t,i.x,i.y,a.width,a.height,e.cornerRadius),t.fill(),this.drawCaret(i,a,o,e.caretPadding),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,o),this.drawBody(i,e,t,o),this.drawFooter(i,e,t,o)}}}})}},{}],34:[function(t,e,a){"use strict";e.exports=function(t,e){var a=t.helpers,i=t.defaults.global;i.elements.arc={backgroundColor:i.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2):!1},inRange:function(t,e){var i=this._view;if(i){for(var n=a.getAngleFromPoint(i,{x:t,y:e}),o=n.angle,r=n.distance,l=i.startAngle,s=i.endAngle;l>s;)s+=2*Math.PI;for(;o>s;)o-=2*Math.PI;for(;l>o;)o+=2*Math.PI;var d=o>=l&&s>=o,u=r>=i.innerRadius&&r<=i.outerRadius;return d&&u}return!1},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,a=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*a,y:t.y+Math.sin(e)*a}},draw:function(){var t=this._chart.ctx,e=this._view,a=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,a,i),t.arc(e.x,e.y,e.innerRadius,i,a,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],35:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:a.defaultColor,borderWidth:3,borderColor:a.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",fill:!0},t.elements.Line=t.Element.extend({lineToNextPoint:function(t,e,a,i,n){var o=this,r=o._chart.ctx,l=o._view?o._view.spanGaps:!1;e._view.skip&&!l?i.call(o,t,e,a):t._view.skip&&!l?n.call(o,t,e,a):0===e._view.tension?r.lineTo(e._view.x,e._view.y):r.bezierCurveTo(t._view.controlPointNextX,t._view.controlPointNextY,e._view.controlPointPreviousX,e._view.controlPointPreviousY,e._view.x,e._view.y)},draw:function(){function t(t){r._view.skip||l._view.skip?t&&o.lineTo(i._view.scaleZero.x,i._view.scaleZero.y):o.bezierCurveTo(l._view.controlPointNextX,l._view.controlPointNextY,r._view.controlPointPreviousX,r._view.controlPointPreviousY,r._view.x,r._view.y)}var i=this,n=i._view,o=i._chart.ctx,r=i._children[0],l=i._children[i._children.length-1];o.save(),i._children.length>0&&n.fill&&(o.beginPath(),e.each(i._children,function(t,a){var r=e.previousItem(i._children,a),l=e.nextItem(i._children,a);0===a?(i._loop?o.moveTo(n.scaleZero.x,n.scaleZero.y):o.moveTo(t._view.x,n.scaleZero),t._view.skip?i._loop||o.moveTo(l._view.x,i._view.scaleZero):o.lineTo(t._view.x,t._view.y)):i.lineToNextPoint(r,t,l,function(t,e,a){i._loop?o.lineTo(i._view.scaleZero.x,i._view.scaleZero.y):(o.lineTo(t._view.x,i._view.scaleZero),o.moveTo(a._view.x,i._view.scaleZero))},function(t,e){o.lineTo(e._view.x,e._view.y)})},i),i._loop?t(!0):(o.lineTo(i._children[i._children.length-1]._view.x,n.scaleZero),o.lineTo(i._children[0]._view.x,n.scaleZero)),o.fillStyle=n.backgroundColor||a.defaultColor,o.closePath(),o.fill());var s=a.elements.line;o.lineCap=n.borderCapStyle||s.borderCapStyle,o.setLineDash&&o.setLineDash(n.borderDash||s.borderDash),o.lineDashOffset=n.borderDashOffset||s.borderDashOffset,o.lineJoin=n.borderJoinStyle||s.borderJoinStyle,o.lineWidth=n.borderWidth||s.borderWidth,o.strokeStyle=n.borderColor||a.defaultColor,o.beginPath(),e.each(i._children,function(t,a){var n=e.previousItem(i._children,a),r=e.nextItem(i._children,a);0===a?o.moveTo(t._view.x,t._view.y):i.lineToNextPoint(n,t,r,function(t,e,a){o.moveTo(a._view.x,a._view.y)},function(t,e){o.moveTo(e._view.x,e._view.y)})},i),i._loop&&i._children.length>0&&t(),o.stroke(),o.restore()}})}},{}],36:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=t.defaults.global,i=a.defaultColor;a.elements.point={radius:3,pointStyle:"circle",backgroundColor:i,borderWidth:1,borderColor:i,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var a=this._view;return a?Math.pow(t-a.x,2)+Math.pow(e-a.y,2)<Math.pow(a.hitRadius+a.radius,2):!1},inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2):!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(){var t,n,o,r,l,s,d=this._view,u=this._chart.ctx,c=d.pointStyle,h=d.radius,f=d.x,g=d.y;if(!d.skip){if("object"==typeof c&&(t=c.toString(),"[object HTMLImageElement]"===t||"[object HTMLCanvasElement]"===t))return void u.drawImage(c,f-c.width/2,g-c.height/2);if(!(isNaN(h)||0>=h)){switch(u.strokeStyle=d.borderColor||i,u.lineWidth=e.getValueOrDefault(d.borderWidth,a.elements.point.borderWidth),u.fillStyle=d.backgroundColor||i,c){default:u.beginPath(),u.arc(f,g,h,0,2*Math.PI),u.closePath(),u.fill();break;case"triangle":u.beginPath(),n=3*h/Math.sqrt(3),l=n*Math.sqrt(3)/2,u.moveTo(f-n/2,g+l/3),u.lineTo(f+n/2,g+l/3),u.lineTo(f,g-2*l/3),u.closePath(),u.fill();break;case"rect":s=1/Math.SQRT2*h,u.fillRect(f-s,g-s,2*s,2*s),u.strokeRect(f-s,g-s,2*s,2*s);break;case"rectRot":s=1/Math.SQRT2*h,u.beginPath(),u.moveTo(f-s,g),u.lineTo(f,g+s),u.lineTo(f+s,g),u.lineTo(f,g-s),u.closePath(),u.fill();break;case"cross":u.beginPath(),u.moveTo(f,g+h),u.lineTo(f,g-h),u.moveTo(f-h,g),u.lineTo(f+h,g),u.closePath();break;case"crossRot":u.beginPath(),o=Math.cos(Math.PI/4)*h,r=Math.sin(Math.PI/4)*h,u.moveTo(f-o,g-r),u.lineTo(f+o,g+r),u.moveTo(f-o,g+r),u.lineTo(f+o,g-r),u.closePath();break;case"star":u.beginPath(),u.moveTo(f,g+h),u.lineTo(f,g-h),u.moveTo(f-h,g),u.lineTo(f+h,g),o=Math.cos(Math.PI/4)*h,r=Math.sin(Math.PI/4)*h,u.moveTo(f-o,g-r),u.lineTo(f+o,g+r),u.moveTo(f-o,g+r),u.lineTo(f+o,g-r),u.closePath();break;case"line":u.beginPath(),u.moveTo(f-h,g),u.lineTo(f+h,g),u.closePath();break;case"dash":u.beginPath(),u.moveTo(f,g),u.lineTo(f+h,g),u.closePath()}u.stroke()}}}})}},{}],37:[function(t,e,a){"use strict";e.exports=function(t){var e=(t.helpers,t.defaults.global);e.elements.rectangle={backgroundColor:e.defaultColor,borderWidth:0,borderColor:e.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return s[(u+t)%4]}var e=this._chart.ctx,a=this._view,i=a.width/2,n=a.x-i,o=a.x+i,r=a.base-(a.base-a.y),l=a.borderWidth/2;a.borderWidth&&(n+=l,o-=l,r+=l),e.beginPath(),e.fillStyle=a.backgroundColor,e.strokeStyle=a.borderColor,e.lineWidth=a.borderWidth;var s=[[n,a.base],[n,r],[o,r],[o,a.base]],d=["bottom","left","top","right"],u=d.indexOf(a.borderSkipped,0);-1===u&&(u=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),a.borderWidth&&e.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var a=this._view;return a?a.y<a.base?t>=a.x-a.width/2&&t<=a.x+a.width/2&&e>=a.y&&e<=a.base:t>=a.x-a.width/2&&t<=a.x+a.width/2&&e>=a.base&&e<=a.y:!1},inLabelRange:function(t){var e=this._view;return e?t>=e.x-e.width/2&&t<=e.x+e.width/2:!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],38:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a={position:"bottom"},i=t.Scale.extend({determineDataLimits:function(){var t=this;t.minIndex=0,t.maxIndex=t.chart.data.labels.length-1;var a;void 0!==t.options.ticks.min&&(a=e.indexOf(t.chart.data.labels,t.options.ticks.min),t.minIndex=-1!==a?a:t.minIndex),void 0!==t.options.ticks.max&&(a=e.indexOf(t.chart.data.labels,t.options.ticks.max),t.maxIndex=-1!==a?a:t.maxIndex),t.min=t.chart.data.labels[t.minIndex],t.max=t.chart.data.labels[t.maxIndex]},buildTicks:function(t){var e=this;e.ticks=0===e.minIndex&&e.maxIndex===e.chart.data.labels.length-1?e.chart.data.labels:e.chart.data.labels.slice(e.minIndex,e.maxIndex+1)},getLabelForIndex:function(t,e){return this.ticks[t]},getPixelForValue:function(t,e,a,i){var n=this,o=Math.max(n.maxIndex+1-n.minIndex-(n.options.gridLines.offsetGridLines?0:1),1);if(n.isHorizontal()){var r=n.width-(n.paddingLeft+n.paddingRight),l=r/o,s=l*(e-n.minIndex)+n.paddingLeft;return n.options.gridLines.offsetGridLines&&i&&(s+=l/2),n.left+Math.round(s)}var d=n.height-(n.paddingTop+n.paddingBottom),u=d/o,c=u*(e-n.minIndex)+n.paddingTop;return n.options.gridLines.offsetGridLines&&i&&(c+=u/2),n.top+Math.round(c)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e,a=this,i=Math.max(a.ticks.length-(a.options.gridLines.offsetGridLines?0:1),1),n=a.isHorizontal(),o=n?a.width-(a.paddingLeft+a.paddingRight):a.height-(a.paddingTop+a.paddingBottom),r=o/i;return a.options.gridLines.offsetGridLines&&(t-=r/2),t-=n?a.paddingLeft:a.paddingTop,e=0>=t?0:Math.round(t/r)}});t.scaleService.registerScaleType("category",i,a)}},{}],39:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a={position:"left",ticks:{callback:function(t,a,i){var n=i.length>3?i[2]-i[1]:i[1]-i[0];Math.abs(n)>1&&t!==Math.floor(t)&&(n=t-Math.floor(t));var o=e.log10(Math.abs(n)),r="";if(0!==t){var l=-1*Math.floor(o);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r}}},i=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===a.id:t.yAxisID===a.id}var a=this,i=a.options,n=(i.ticks,a.chart),o=n.data,r=o.datasets,l=a.isHorizontal();if(a.min=null,a.max=null,i.stacked){var s={},d=!1,u=!1;e.each(r,function(o,r){var l=n.getDatasetMeta(r);void 0===s[l.type]&&(s[l.type]={positiveValues:[],negativeValues:[]});var c=s[l.type].positiveValues,h=s[l.type].negativeValues;n.isDatasetVisible(r)&&t(l)&&e.each(o.data,function(t,e){var n=+a.getRightValue(t);isNaN(n)||l.data[e].hidden||(c[e]=c[e]||0,h[e]=h[e]||0,i.relativePoints?c[e]=100:0>n?(u=!0,h[e]+=n):(d=!0,c[e]+=n))})}),e.each(s,function(t){var i=t.positiveValues.concat(t.negativeValues),n=e.min(i),o=e.max(i);a.min=null===a.min?n:Math.min(a.min,n),a.max=null===a.max?o:Math.max(a.max,o)})}else e.each(r,function(i,o){var r=n.getDatasetMeta(o);n.isDatasetVisible(o)&&t(r)&&e.each(i.data,function(t,e){var i=+a.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===a.min?a.min=i:i<a.min&&(a.min=i),null===a.max?a.max=i:i>a.max&&(a.max=i))})});this.handleTickRangeOptions()},getTickLimit:function(){var a,i=this,n=i.options.ticks;if(i.isHorizontal())a=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(i.width/50));else{var o=e.getValueOrDefault(n.fontSize,t.defaults.global.defaultFontSize);a=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(i.height/(2*o)))}return a},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t,e,a,i){var n,o,r=this,l=r.paddingLeft,s=r.paddingBottom,d=r.start,u=+r.getRightValue(t),c=r.end-d;return r.isHorizontal()?(o=r.width-(l+r.paddingRight),n=r.left+o/c*(u-d),Math.round(n+l)):(o=r.height-(r.paddingTop+s),n=r.bottom-s-o/c*(u-d),Math.round(n))},getValueForPixel:function(t){var e=this,a=e.isHorizontal(),i=e.paddingLeft,n=e.paddingBottom,o=a?e.width-(i+e.paddingRight):e.height-(e.paddingTop+n),r=(a?t-e.left-i:e.bottom-n-t)/o;return e.start+(e.end-e.start)*r},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticksAsNumbers[t],null,null,e)}});t.scaleService.registerScaleType("linear",i,a)}},{}],40:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=e.noop;t.LinearScaleBase=t.Scale.extend({handleTickRangeOptions:function(){var t=this,a=t.options,i=a.ticks;if(i.beginAtZero){var n=e.sign(t.min),o=e.sign(t.max);0>n&&0>o?t.max=0:n>0&&o>0&&(t.min=0)}void 0!==i.min?t.min=i.min:void 0!==i.suggestedMin&&(t.min=Math.min(t.min,i.suggestedMin)),void 0!==i.max?t.max=i.max:void 0!==i.suggestedMax&&(t.max=Math.max(t.max,i.suggestedMax)),t.min===t.max&&(t.max++,i.beginAtZero||t.min--)},getTickLimit:a,handleDirectionalChanges:a,buildTicks:function(){var t=this,a=t.options,i=a.ticks,n=e.getValueOrDefault,o=(t.isHorizontal(),t.ticks=[]),r=t.getTickLimit();r=Math.max(2,r);var l,s=i.fixedStepSize&&i.fixedStepSize>0||i.stepSize&&i.stepSize>0;if(s)l=n(i.fixedStepSize,i.stepSize);else{var d=e.niceNum(t.max-t.min,!1);l=e.niceNum(d/(r-1),!0)}var u=Math.floor(t.min/l)*l,c=Math.ceil(t.max/l)*l,h=(c-u)/l;h=e.almostEquals(h,Math.round(h),l/1e3)?Math.round(h):Math.ceil(h),o.push(void 0!==i.min?i.min:u);for(var f=1;h>f;++f)o.push(u+f*l);o.push(void 0!==i.max?i.max:c),t.handleDirectionalChanges(),t.max=e.max(o),t.min=e.min(o),i.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{}],41:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a={position:"left",ticks:{callback:function(t,a,i){var n=t/Math.pow(10,Math.floor(e.log10(t)));return 1===n||2===n||5===n||0===a||a===i.length-1?t.toExponential():""}}},i=t.Scale.extend({determineDataLimits:function(){function t(t){return d?t.xAxisID===a.id:t.yAxisID===a.id}var a=this,i=a.options,n=i.ticks,o=a.chart,r=o.data,l=r.datasets,s=e.getValueOrDefault,d=a.isHorizontal();if(a.min=null,a.max=null,i.stacked){var u={};e.each(l,function(n,r){var l=o.getDatasetMeta(r);o.isDatasetVisible(r)&&t(l)&&(void 0===u[l.type]&&(u[l.type]=[]),e.each(n.data,function(t,e){var n=u[l.type],o=+a.getRightValue(t);isNaN(o)||l.data[e].hidden||(n[e]=n[e]||0,i.relativePoints?n[e]=100:n[e]+=o)}))}),e.each(u,function(t){var i=e.min(t),n=e.max(t);a.min=null===a.min?i:Math.min(a.min,i),a.max=null===a.max?n:Math.max(a.max,n)})}else e.each(l,function(i,n){var r=o.getDatasetMeta(n);o.isDatasetVisible(n)&&t(r)&&e.each(i.data,function(t,e){var i=+a.getRightValue(t);isNaN(i)||r.data[e].hidden||(null===a.min?a.min=i:i<a.min&&(a.min=i),null===a.max?a.max=i:i>a.max&&(a.max=i))})});a.min=s(n.min,a.min),a.max=s(n.max,a.max),a.min===a.max&&(0!==a.min&&null!==a.min?(a.min=Math.pow(10,Math.floor(e.log10(a.min))-1),a.max=Math.pow(10,Math.floor(e.log10(a.max))+1)):(a.min=1,a.max=10))},buildTicks:function(){for(var t=this,a=t.options,i=a.ticks,n=e.getValueOrDefault,o=t.ticks=[],r=n(i.min,Math.pow(10,Math.floor(e.log10(t.min))));r<t.max;){o.push(r);var l=Math.floor(e.log10(r)),s=Math.floor(r/Math.pow(10,l))+1;10===s&&(s=1,++l),r=s*Math.pow(10,l)}var d=n(i.max,r);o.push(d),t.isHorizontal()||o.reverse(),t.max=e.max(o),t.min=e.min(o),i.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickValues[t],null,null,e)},getPixelForValue:function(t,a,i,n){var o,r,l=this,s=l.start,d=+l.getRightValue(t),u=e.log10(l.end)-e.log10(s),c=l.paddingTop,h=l.paddingBottom,f=l.paddingLeft;return l.isHorizontal()?0===d?r=l.left+f:(o=l.width-(f+l.paddingRight),r=l.left+o/u*(e.log10(d)-e.log10(s)),r+=f):0===d?r=l.top+c:(o=l.height-(c+h),r=l.bottom-h-o/u*(e.log10(d)-e.log10(s))),r},getValueForPixel:function(t){var a,i,n=this,o=e.log10(n.end)-e.log10(n.start);return n.isHorizontal()?(i=n.width-(n.paddingLeft+n.paddingRight),a=n.start*Math.pow(10,(t-n.left-n.paddingLeft)*o/i)):(i=n.height-(n.paddingTop+n.paddingBottom),a=Math.pow(10,(n.bottom-n.paddingBottom-t)*o/i)/n.start),a}});t.scaleService.registerScaleType("logarithmic",i,a)}},{}],42:[function(t,e,a){"use strict";e.exports=function(t){var e=t.helpers,a=t.defaults.global,i={display:!0,animate:!0,lineArc:!1,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2},pointLabels:{fontSize:10,callback:function(t){return t}}},n=t.LinearScaleBase.extend({getValueCount:function(){return this.chart.data.labels.length},setDimensions:function(){var t=this,i=t.options,n=i.ticks;t.width=t.maxWidth,t.height=t.maxHeight,t.xCenter=Math.round(t.width/2),t.yCenter=Math.round(t.height/2);var o=e.min([t.height,t.width]),r=e.getValueOrDefault(n.fontSize,a.defaultFontSize);t.drawingArea=i.display?o/2-(r/2+n.backdropPaddingY):o/2},determineDataLimits:function(){var t=this,a=t.chart;t.min=null,t.max=null,e.each(a.data.datasets,function(i,n){if(a.isDatasetVisible(n)){var o=a.getDatasetMeta(n);e.each(i.data,function(e,a){var i=+t.getRightValue(e);isNaN(i)||o.data[a].hidden||(null===t.min?t.min=i:i<t.min&&(t.min=i),null===t.max?t.max=i:i>t.max&&(t.max=i))})}}),t.handleTickRangeOptions()},getTickLimit:function(){var t=this.options.ticks,i=e.getValueOrDefault(t.fontSize,a.defaultFontSize);return Math.min(t.maxTicksLimit?t.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*i)))},convertTicksToLabels:function(){var e=this;t.LinearScaleBase.prototype.convertTicksToLabels.call(e),e.pointLabels=e.chart.data.labels.map(e.options.pointLabels.callback,e)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,i,n,o,r,l,s,d,u,c,h,f,g=this.options.pointLabels,p=e.getValueOrDefault(g.fontSize,a.defaultFontSize),m=e.getValueOrDefault(g.fontStyle,a.defaultFontStyle),b=e.getValueOrDefault(g.fontFamily,a.defaultFontFamily),v=e.fontString(p,m,b),x=e.min([this.height/2-p-5,this.width/2]),y=this.width,k=0;for(this.ctx.font=v,
-i=0;i<this.getValueCount();i++)t=this.getPointPosition(i,x),n=this.ctx.measureText(this.pointLabels[i]?this.pointLabels[i]:"").width+5,0===i||i===this.getValueCount()/2?(o=n/2,t.x+o>y&&(y=t.x+o,r=i),t.x-o<k&&(k=t.x-o,s=i)):i<this.getValueCount()/2?t.x+n>y&&(y=t.x+n,r=i):i>this.getValueCount()/2&&t.x-n<k&&(k=t.x-n,s=i);u=k,c=Math.ceil(y-this.width),l=this.getIndexAngle(r),d=this.getIndexAngle(s),h=c/Math.sin(l+Math.PI/2),f=u/Math.sin(d+Math.PI/2),h=e.isNumber(h)?h:0,f=e.isNumber(f)?f:0,this.drawingArea=Math.round(x-(f+h)/2),this.setCenterPoint(f,h)},setCenterPoint:function(t,e){var a=this,i=a.width-e-a.drawingArea,n=t+a.drawingArea;a.xCenter=Math.round((n+i)/2+a.left),a.yCenter=Math.round(a.height/2+a.top)},getIndexAngle:function(t){var e=2*Math.PI/this.getValueCount();return t*e-Math.PI/2},getDistanceFromCenterForValue:function(t){var e=this;if(null===t)return 0;var a=e.drawingArea/(e.max-e.min);return e.options.reverse?(e.max-t)*a:(t-e.min)*a},getPointPosition:function(t,e){var a=this,i=a.getIndexAngle(t);return{x:Math.round(Math.cos(i)*e)+a.xCenter,y:Math.round(Math.sin(i)*e)+a.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,a=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:0>e&&0>a?a:e>0&&a>0?e:0)},draw:function(){var t=this,i=t.options,n=i.gridLines,o=i.ticks,r=i.angleLines,l=i.pointLabels,s=e.getValueOrDefault;if(i.display){var d=t.ctx,u=s(o.fontSize,a.defaultFontSize),c=s(o.fontStyle,a.defaultFontStyle),h=s(o.fontFamily,a.defaultFontFamily),f=e.fontString(u,c,h);if(e.each(t.ticks,function(e,r){if(r>0||i.reverse){var l=t.getDistanceFromCenterForValue(t.ticksAsNumbers[r]),c=t.yCenter-l;if(n.display)if(d.strokeStyle=n.color,d.lineWidth=n.lineWidth,i.lineArc)d.beginPath(),d.arc(t.xCenter,t.yCenter,l,0,2*Math.PI),d.closePath(),d.stroke();else{d.beginPath();for(var h=0;h<t.getValueCount();h++){var g=t.getPointPosition(h,l);0===h?d.moveTo(g.x,g.y):d.lineTo(g.x,g.y)}d.closePath(),d.stroke()}if(o.display){var p=s(o.fontColor,a.defaultFontColor);if(d.font=f,o.showLabelBackdrop){var m=d.measureText(e).width;d.fillStyle=o.backdropColor,d.fillRect(t.xCenter-m/2-o.backdropPaddingX,c-u/2-o.backdropPaddingY,m+2*o.backdropPaddingX,u+2*o.backdropPaddingY)}d.textAlign="center",d.textBaseline="middle",d.fillStyle=p,d.fillText(e,t.xCenter,c)}}}),!i.lineArc){d.lineWidth=r.lineWidth,d.strokeStyle=r.color;for(var g=t.getDistanceFromCenterForValue(i.reverse?t.min:t.max),p=s(l.fontSize,a.defaultFontSize),m=s(l.fontStyle,a.defaultFontStyle),b=s(l.fontFamily,a.defaultFontFamily),v=e.fontString(p,m,b),x=t.getValueCount()-1;x>=0;x--){if(r.display){var y=t.getPointPosition(x,g);d.beginPath(),d.moveTo(t.xCenter,t.yCenter),d.lineTo(y.x,y.y),d.stroke(),d.closePath()}var k=t.getPointPosition(x,g+5),S=s(l.fontColor,a.defaultFontColor);d.font=v,d.fillStyle=S;var w=t.pointLabels,C=w.length,M=w.length/2,D=M/2,A=D>x||x>C-D,T=x===D||x===C-D;0===x?d.textAlign="center":x===M?d.textAlign="center":M>x?d.textAlign="left":d.textAlign="right",T?d.textBaseline="middle":A?d.textBaseline="bottom":d.textBaseline="top",d.fillText(w[x]?w[x]:"",k.x,k.y)}}}}});t.scaleService.registerScaleType("radialLinear",n,i)}},{}],43:[function(t,e,a){"use strict";var i=t(1);i="function"==typeof i?i:window.moment,e.exports=function(t){var e=t.helpers,a={units:[{name:"millisecond",steps:[1,2,5,10,20,50,100,250,500]},{name:"second",steps:[1,2,5,10,30]},{name:"minute",steps:[1,2,5,10,30]},{name:"hour",steps:[1,2,3,6,12]},{name:"day",steps:[1,2,5]},{name:"week",maxStep:4},{name:"month",maxStep:3},{name:"quarter",maxStep:4},{name:"year",maxStep:!1}]},n={position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}},o=t.Scale.extend({initialize:function(){if(!i)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");t.Scale.prototype.initialize.call(this)},getLabelMoment:function(t,e){return this.labelMoments[t][e]},getMomentStartOf:function(t){var e=this;return"week"===e.options.time.unit&&e.options.time.isoWeekday!==!1?t.clone().startOf("isoWeek").isoWeekday(e.options.time.isoWeekday):t.clone().startOf(e.tickUnit)},determineDataLimits:function(){var t=this;t.labelMoments=[];var a=[];t.chart.data.labels&&t.chart.data.labels.length>0?(e.each(t.chart.data.labels,function(e,i){var n=t.parseTime(e);n.isValid()&&(t.options.time.round&&n.startOf(t.options.time.round),a.push(n))},t),t.firstTick=i.min.call(t,a),t.lastTick=i.max.call(t,a)):(t.firstTick=null,t.lastTick=null),e.each(t.chart.data.datasets,function(n,o){var r=[],l=t.chart.isDatasetVisible(o);"object"==typeof n.data[0]&&null!==n.data[0]?e.each(n.data,function(e,a){var n=t.parseTime(t.getRightValue(e));n.isValid()&&(t.options.time.round&&n.startOf(t.options.time.round),r.push(n),l&&(t.firstTick=null!==t.firstTick?i.min(t.firstTick,n):n,t.lastTick=null!==t.lastTick?i.max(t.lastTick,n):n))},t):r=a,t.labelMoments.push(r)},t),t.options.time.min&&(t.firstTick=t.parseTime(t.options.time.min)),t.options.time.max&&(t.lastTick=t.parseTime(t.options.time.max)),t.firstTick=(t.firstTick||i()).clone(),t.lastTick=(t.lastTick||i()).clone()},buildTicks:function(i){var n=this;n.ctx.save();var o=e.getValueOrDefault(n.options.ticks.fontSize,t.defaults.global.defaultFontSize),r=e.getValueOrDefault(n.options.ticks.fontStyle,t.defaults.global.defaultFontStyle),l=e.getValueOrDefault(n.options.ticks.fontFamily,t.defaults.global.defaultFontFamily),s=e.fontString(o,r,l);if(n.ctx.font=s,n.ticks=[],n.unitScale=1,n.scaleSizeInUnits=0,n.options.time.unit)n.tickUnit=n.options.time.unit||"day",n.displayFormat=n.options.time.displayFormats[n.tickUnit],n.scaleSizeInUnits=n.lastTick.diff(n.firstTick,n.tickUnit,!0),n.unitScale=e.getValueOrDefault(n.options.time.unitStepSize,1);else{var d=n.isHorizontal()?n.width-(n.paddingLeft+n.paddingRight):n.height-(n.paddingTop+n.paddingBottom),u=n.tickFormatFunction(n.firstTick,0,[]),c=n.ctx.measureText(u).width,h=Math.cos(e.toRadians(n.options.ticks.maxRotation)),f=Math.sin(e.toRadians(n.options.ticks.maxRotation));c=c*h+o*f;var g=d/c;n.tickUnit="millisecond",n.scaleSizeInUnits=n.lastTick.diff(n.firstTick,n.tickUnit,!0),n.displayFormat=n.options.time.displayFormats[n.tickUnit];for(var p=0,m=a.units[p];p<a.units.length;){if(n.unitScale=1,e.isArray(m.steps)&&Math.ceil(n.scaleSizeInUnits/g)<e.max(m.steps)){for(var b=0;b<m.steps.length;++b)if(m.steps[b]>=Math.ceil(n.scaleSizeInUnits/g)){n.unitScale=e.getValueOrDefault(n.options.time.unitStepSize,m.steps[b]);break}break}if(m.maxStep===!1||Math.ceil(n.scaleSizeInUnits/g)<m.maxStep){n.unitScale=e.getValueOrDefault(n.options.time.unitStepSize,Math.ceil(n.scaleSizeInUnits/g));break}++p,m=a.units[p],n.tickUnit=m.name;var v=n.firstTick.diff(n.getMomentStartOf(n.firstTick),n.tickUnit,!0),x=n.getMomentStartOf(n.lastTick.clone().add(1,n.tickUnit)).diff(n.lastTick,n.tickUnit,!0);n.scaleSizeInUnits=n.lastTick.diff(n.firstTick,n.tickUnit,!0)+v+x,n.displayFormat=n.options.time.displayFormats[m.name]}}var y;if(n.options.time.min?y=n.getMomentStartOf(n.firstTick):(n.firstTick=n.getMomentStartOf(n.firstTick),y=n.firstTick),!n.options.time.max){var k=n.getMomentStartOf(n.lastTick);0!==k.diff(n.lastTick,n.tickUnit,!0)&&(n.lastTick=n.getMomentStartOf(n.lastTick.add(1,n.tickUnit)))}n.smallestLabelSeparation=n.width,e.each(n.chart.data.datasets,function(t,e){for(var a=1;a<n.labelMoments[e].length;a++)n.smallestLabelSeparation=Math.min(n.smallestLabelSeparation,n.labelMoments[e][a].diff(n.labelMoments[e][a-1],n.tickUnit,!0))},n),n.options.time.displayFormat&&(n.displayFormat=n.options.time.displayFormat),n.ticks.push(n.firstTick.clone());for(var S=1;S<=n.scaleSizeInUnits;++S){var w=y.clone().add(S,n.tickUnit);if(n.options.time.max&&w.diff(n.lastTick,n.tickUnit,!0)>=0)break;S%n.unitScale===0&&n.ticks.push(w)}var C=n.ticks[n.ticks.length-1].diff(n.lastTick,n.tickUnit);(0!==C||0===n.scaleSizeInUnits)&&(n.options.time.max?(n.ticks.push(n.lastTick.clone()),n.scaleSizeInUnits=n.lastTick.diff(n.ticks[0],n.tickUnit,!0)):(n.ticks.push(n.lastTick.clone()),n.scaleSizeInUnits=n.lastTick.diff(n.firstTick,n.tickUnit,!0))),n.ctx.restore()},getLabelForIndex:function(t,e){var a=this,i=a.chart.data.labels&&t<a.chart.data.labels.length?a.chart.data.labels[t]:"";return"object"==typeof a.chart.data.datasets[e].data[0]&&(i=a.getRightValue(a.chart.data.datasets[e].data[t])),a.options.time.tooltipFormat&&(i=a.parseTime(i).format(a.options.time.tooltipFormat)),i},tickFormatFunction:function(t,a,i){var n=t.format(this.displayFormat),o=this.options.ticks,r=e.getValueOrDefault(o.callback,o.userCallback);return r?r(n,a,i):n},convertTicksToLabels:function(){var t=this;t.tickMoments=t.ticks,t.ticks=t.ticks.map(t.tickFormatFunction,t)},getPixelForValue:function(t,e,a,i){var n=this,o=t&&t.isValid&&t.isValid()?t:n.getLabelMoment(a,e);if(o){var r=o.diff(n.firstTick,n.tickUnit,!0),l=r/n.scaleSizeInUnits;if(n.isHorizontal()){var s=n.width-(n.paddingLeft+n.paddingRight),d=(s/Math.max(n.ticks.length-1,1),s*l+n.paddingLeft);return n.left+Math.round(d)}var u=n.height-(n.paddingTop+n.paddingBottom),c=(u/Math.max(n.ticks.length-1,1),u*l+n.paddingTop);return n.top+Math.round(c)}},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickMoments[t],null,null,e)},getValueForPixel:function(t){var e=this,a=e.isHorizontal()?e.width-(e.paddingLeft+e.paddingRight):e.height-(e.paddingTop+e.paddingBottom),n=(t-(e.isHorizontal()?e.left+e.paddingLeft:e.top+e.paddingTop))/a;return n*=e.scaleSizeInUnits,e.firstTick.clone().add(i.duration(n,e.tickUnit).asSeconds(),"seconds")},parseTime:function(t){var e=this;return"string"==typeof e.options.time.parser?i(t,e.options.time.parser):"function"==typeof e.options.time.parser?e.options.time.parser(t):"function"==typeof t.getMonth||"number"==typeof t?i(t):t.isValid&&t.isValid()?t:"string"!=typeof e.options.time.format&&e.options.time.format.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale"),e.options.time.format(t)):i(t,e.options.time.format)}});t.scaleService.registerScaleType("time",o,n)}},{1:1}]},{},[7])(7)});
\ No newline at end of file
+!function t(e,i,a){function o(r,s){if(!i[r]){if(!e[r]){var l="function"==typeof require&&require;if(!s&&l)return l(r,!0);if(n)return n(r,!0);var h=new Error("Cannot find module '"+r+"'");throw h.code="MODULE_NOT_FOUND",h}var d=i[r]={exports:{}};e[r][0].call(d.exports,function(t){var i=e[r][1][t];return o(i?i:t)},d,d.exports,t,e,i,a)}return i[r].exports}for(var n="function"==typeof require&&require,r=0;r<a.length;r++)o(a[r]);return o}({1:[function(t,e,i){},{}],2:[function(t,e,i){function a(t){if(t){var e=/^#([a-fA-F0-9]{3})$/,i=/^#([a-fA-F0-9]{6})$/,a=/^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,o=/^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/,n=/(\w+)/,r=[0,0,0],s=1,l=t.match(e);if(l){l=l[1];for(var h=0;h<r.length;h++)r[h]=parseInt(l[h]+l[h],16)}else if(l=t.match(i)){l=l[1];for(var h=0;h<r.length;h++)r[h]=parseInt(l.slice(2*h,2*h+2),16)}else if(l=t.match(a)){for(var h=0;h<r.length;h++)r[h]=parseInt(l[h+1]);s=parseFloat(l[4])}else if(l=t.match(o)){for(var h=0;h<r.length;h++)r[h]=Math.round(2.55*parseFloat(l[h+1]));s=parseFloat(l[4])}else if(l=t.match(n)){if("transparent"==l[1])return[0,0,0,0];if(r=y[l[1]],!r)return}for(var h=0;h<r.length;h++)r[h]=v(r[h],0,255);return s=s||0==s?v(s,0,1):1,r[3]=s,r}}function o(t){if(t){var e=/^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,i=t.match(e);if(i){var a=parseFloat(i[4]),o=v(parseInt(i[1]),0,360),n=v(parseFloat(i[2]),0,100),r=v(parseFloat(i[3]),0,100),s=v(isNaN(a)?1:a,0,1);return[o,n,r,s]}}}function n(t){if(t){var e=/^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/,i=t.match(e);if(i){var a=parseFloat(i[4]),o=v(parseInt(i[1]),0,360),n=v(parseFloat(i[2]),0,100),r=v(parseFloat(i[3]),0,100),s=v(isNaN(a)?1:a,0,1);return[o,n,r,s]}}}function r(t){var e=a(t);return e&&e.slice(0,3)}function s(t){var e=o(t);return e&&e.slice(0,3)}function l(t){var e=a(t);return e?e[3]:(e=o(t))?e[3]:(e=n(t))?e[3]:void 0}function h(t){return"#"+x(t[0])+x(t[1])+x(t[2])}function d(t,e){return 1>e||t[3]&&t[3]<1?c(t,e):"rgb("+t[0]+", "+t[1]+", "+t[2]+")"}function c(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"rgba("+t[0]+", "+t[1]+", "+t[2]+", "+e+")"}function u(t,e){if(1>e||t[3]&&t[3]<1)return f(t,e);var i=Math.round(t[0]/255*100),a=Math.round(t[1]/255*100),o=Math.round(t[2]/255*100);return"rgb("+i+"%, "+a+"%, "+o+"%)"}function f(t,e){var i=Math.round(t[0]/255*100),a=Math.round(t[1]/255*100),o=Math.round(t[2]/255*100);return"rgba("+i+"%, "+a+"%, "+o+"%, "+(e||t[3]||1)+")"}function g(t,e){return 1>e||t[3]&&t[3]<1?p(t,e):"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"}function p(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hsla("+t[0]+", "+t[1]+"%, "+t[2]+"%, "+e+")"}function m(t,e){return void 0===e&&(e=void 0!==t[3]?t[3]:1),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"}function b(t){return k[t.slice(0,3)]}function v(t,e,i){return Math.min(Math.max(e,t),i)}function x(t){var e=t.toString(16).toUpperCase();return e.length<2?"0"+e:e}var y=t("color-name");e.exports={getRgba:a,getHsla:o,getRgb:r,getHsl:s,getHwb:n,getAlpha:l,hexString:h,rgbString:d,rgbaString:c,percentString:u,percentaString:f,hslString:g,hslaString:p,hwbString:m,keyword:b};var k={};for(var S in y)k[y[S]]=S},{"color-name":6}],3:[function(t,e,i){var a=t("color-convert"),o=t("chartjs-color-string"),n=function(t){if(t instanceof n)return t;if(!(this instanceof n))return new n(t);this.values={rgb:[0,0,0],hsl:[0,0,0],hsv:[0,0,0],hwb:[0,0,0],cmyk:[0,0,0,0],alpha:1};var e;if("string"==typeof t)if(e=o.getRgba(t))this.setValues("rgb",e);else if(e=o.getHsla(t))this.setValues("hsl",e);else{if(!(e=o.getHwb(t)))throw new Error('Unable to parse color from string "'+t+'"');this.setValues("hwb",e)}else if("object"==typeof t)if(e=t,void 0!==e.r||void 0!==e.red)this.setValues("rgb",e);else if(void 0!==e.l||void 0!==e.lightness)this.setValues("hsl",e);else if(void 0!==e.v||void 0!==e.value)this.setValues("hsv",e);else if(void 0!==e.w||void 0!==e.whiteness)this.setValues("hwb",e);else{if(void 0===e.c&&void 0===e.cyan)throw new Error("Unable to parse color from object "+JSON.stringify(t));this.setValues("cmyk",e)}};n.prototype={rgb:function(){return this.setSpace("rgb",arguments)},hsl:function(){return this.setSpace("hsl",arguments)},hsv:function(){return this.setSpace("hsv",arguments)},hwb:function(){return this.setSpace("hwb",arguments)},cmyk:function(){return this.setSpace("cmyk",arguments)},rgbArray:function(){return this.values.rgb},hslArray:function(){return this.values.hsl},hsvArray:function(){return this.values.hsv},hwbArray:function(){var t=this.values;return 1!==t.alpha?t.hwb.concat([t.alpha]):t.hwb},cmykArray:function(){return this.values.cmyk},rgbaArray:function(){var t=this.values;return t.rgb.concat([t.alpha])},hslaArray:function(){var t=this.values;return t.hsl.concat([t.alpha])},alpha:function(t){return void 0===t?this.values.alpha:(this.setValues("alpha",t),this)},red:function(t){return this.setChannel("rgb",0,t)},green:function(t){return this.setChannel("rgb",1,t)},blue:function(t){return this.setChannel("rgb",2,t)},hue:function(t){return t&&(t%=360,t=0>t?360+t:t),this.setChannel("hsl",0,t)},saturation:function(t){return this.setChannel("hsl",1,t)},lightness:function(t){return this.setChannel("hsl",2,t)},saturationv:function(t){return this.setChannel("hsv",1,t)},whiteness:function(t){return this.setChannel("hwb",1,t)},blackness:function(t){return this.setChannel("hwb",2,t)},value:function(t){return this.setChannel("hsv",2,t)},cyan:function(t){return this.setChannel("cmyk",0,t)},magenta:function(t){return this.setChannel("cmyk",1,t)},yellow:function(t){return this.setChannel("cmyk",2,t)},black:function(t){return this.setChannel("cmyk",3,t)},hexString:function(){return o.hexString(this.values.rgb)},rgbString:function(){return o.rgbString(this.values.rgb,this.values.alpha)},rgbaString:function(){return o.rgbaString(this.values.rgb,this.values.alpha)},percentString:function(){return o.percentString(this.values.rgb,this.values.alpha)},hslString:function(){return o.hslString(this.values.hsl,this.values.alpha)},hslaString:function(){return o.hslaString(this.values.hsl,this.values.alpha)},hwbString:function(){return o.hwbString(this.values.hwb,this.values.alpha)},keyword:function(){return o.keyword(this.values.rgb,this.values.alpha)},rgbNumber:function(){var t=this.values.rgb;return t[0]<<16|t[1]<<8|t[2]},luminosity:function(){for(var t=this.values.rgb,e=[],i=0;i<t.length;i++){var a=t[i]/255;e[i]=.03928>=a?a/12.92:Math.pow((a+.055)/1.055,2.4)}return.2126*e[0]+.7152*e[1]+.0722*e[2]},contrast:function(t){var e=this.luminosity(),i=t.luminosity();return e>i?(e+.05)/(i+.05):(i+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb,e=(299*t[0]+587*t[1]+114*t[2])/1e3;return 128>e},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;3>e;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,i=(e[0]+t)%360;return e[0]=0>i?360+i:i,this.setValues("hsl",e),this},mix:function(t,e){var i=this,a=t,o=void 0===e?.5:e,n=2*o-1,r=i.alpha()-a.alpha(),s=((n*r===-1?n:(n+r)/(1+n*r))+1)/2,l=1-s;return this.rgb(s*i.red()+l*a.red(),s*i.green()+l*a.green(),s*i.blue()+l*a.blue()).alpha(i.alpha()*o+a.alpha()*(1-o))},toJSON:function(){return this.rgb()},clone:function(){var t,e,i=new n,a=this.values,o=i.values;for(var r in a)a.hasOwnProperty(r)&&(t=a[r],e={}.toString.call(t),"[object Array]"===e?o[r]=t.slice(0):"[object Number]"===e?o[r]=t:console.error("unexpected color value:",t));return i}},n.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},n.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},n.prototype.getValues=function(t){for(var e=this.values,i={},a=0;a<t.length;a++)i[t.charAt(a)]=e[t][a];return 1!==e.alpha&&(i.a=e.alpha),i},n.prototype.setValues=function(t,e){var i,o=this.values,n=this.spaces,r=this.maxes,s=1;if("alpha"===t)s=e;else if(e.length)o[t]=e.slice(0,t.length),s=e[t.length];else if(void 0!==e[t.charAt(0)]){for(i=0;i<t.length;i++)o[t][i]=e[t.charAt(i)];s=e.a}else if(void 0!==e[n[t][0]]){var l=n[t];for(i=0;i<t.length;i++)o[t][i]=e[l[i]];s=e.alpha}if(o.alpha=Math.max(0,Math.min(1,void 0===s?o.alpha:s)),"alpha"===t)return!1;var h;for(i=0;i<t.length;i++)h=Math.max(0,Math.min(r[t][i],o[t][i])),o[t][i]=Math.round(h);for(var d in n)d!==t&&(o[d]=a[t][d](o[t]));return!0},n.prototype.setSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i),this)},n.prototype.setChannel=function(t,e,i){var a=this.values[t];return void 0===i?a[e]:i===a[e]?this:(a[e]=i,this.setValues(t,a),this)},"undefined"!=typeof window&&(window.Color=n),e.exports=n},{"chartjs-color-string":2,"color-convert":5}],4:[function(t,e,i){function a(t){var e,i,a,o=t[0]/255,n=t[1]/255,r=t[2]/255,s=Math.min(o,n,r),l=Math.max(o,n,r),h=l-s;return l==s?e=0:o==l?e=(n-r)/h:n==l?e=2+(r-o)/h:r==l&&(e=4+(o-n)/h),e=Math.min(60*e,360),0>e&&(e+=360),a=(s+l)/2,i=l==s?0:.5>=a?h/(l+s):h/(2-l-s),[e,100*i,100*a]}function o(t){var e,i,a,o=t[0],n=t[1],r=t[2],s=Math.min(o,n,r),l=Math.max(o,n,r),h=l-s;return i=0==l?0:h/l*1e3/10,l==s?e=0:o==l?e=(n-r)/h:n==l?e=2+(r-o)/h:r==l&&(e=4+(o-n)/h),e=Math.min(60*e,360),0>e&&(e+=360),a=l/255*1e3/10,[e,i,a]}function n(t){var e=t[0],i=t[1],o=t[2],n=a(t)[0],r=1/255*Math.min(e,Math.min(i,o)),o=1-1/255*Math.max(e,Math.max(i,o));return[n,100*r,100*o]}function s(t){var e,i,a,o,n=t[0]/255,r=t[1]/255,s=t[2]/255;return o=Math.min(1-n,1-r,1-s),e=(1-n-o)/(1-o)||0,i=(1-r-o)/(1-o)||0,a=(1-s-o)/(1-o)||0,[100*e,100*i,100*a,100*o]}function l(t){return G[JSON.stringify(t)]}function h(t){var e=t[0]/255,i=t[1]/255,a=t[2]/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92,a=a>.04045?Math.pow((a+.055)/1.055,2.4):a/12.92;var o=.4124*e+.3576*i+.1805*a,n=.2126*e+.7152*i+.0722*a,r=.0193*e+.1192*i+.9505*a;return[100*o,100*n,100*r]}function d(t){var e,i,a,o=h(t),n=o[0],r=o[1],s=o[2];return n/=95.047,r/=100,s/=108.883,n=n>.008856?Math.pow(n,1/3):7.787*n+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*r-16,i=500*(n-r),a=200*(r-s),[e,i,a]}function c(t){return B(d(t))}function u(t){var e,i,a,o,n,r=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return n=255*l,[n,n,n];i=.5>l?l*(1+s):l+s-l*s,e=2*l-i,o=[0,0,0];for(var h=0;3>h;h++)a=r+1/3*-(h-1),0>a&&a++,a>1&&a--,n=1>6*a?e+6*(i-e)*a:1>2*a?i:2>3*a?e+(i-e)*(2/3-a)*6:e,o[h]=255*n;return o}function f(t){var e,i,a=t[0],o=t[1]/100,n=t[2]/100;return 0===n?[0,0,0]:(n*=2,o*=1>=n?n:2-n,i=(n+o)/2,e=2*o/(n+o),[a,100*e,100*i])}function p(t){return n(u(t))}function m(t){return s(u(t))}function v(t){return l(u(t))}function x(t){var e=t[0]/60,i=t[1]/100,a=t[2]/100,o=Math.floor(e)%6,n=e-Math.floor(e),r=255*a*(1-i),s=255*a*(1-i*n),l=255*a*(1-i*(1-n)),a=255*a;switch(o){case 0:return[a,l,r];case 1:return[s,a,r];case 2:return[r,a,l];case 3:return[r,s,a];case 4:return[l,r,a];case 5:return[a,r,s]}}function y(t){var e,i,a=t[0],o=t[1]/100,n=t[2]/100;return i=(2-o)*n,e=o*n,e/=1>=i?i:2-i,e=e||0,i/=2,[a,100*e,100*i]}function k(t){return n(x(t))}function S(t){return s(x(t))}function C(t){return l(x(t))}function w(t){var e,i,a,o,n=t[0]/360,s=t[1]/100,l=t[2]/100,h=s+l;switch(h>1&&(s/=h,l/=h),e=Math.floor(6*n),i=1-l,a=6*n-e,0!=(1&e)&&(a=1-a),o=s+a*(i-s),e){default:case 6:case 0:r=i,g=o,b=s;break;case 1:r=o,g=i,b=s;break;case 2:r=s,g=i,b=o;break;case 3:r=s,g=o,b=i;break;case 4:r=o,g=s,b=i;break;case 5:r=i,g=s,b=o}return[255*r,255*g,255*b]}function M(t){return a(w(t))}function D(t){return o(w(t))}function A(t){return s(w(t))}function I(t){return l(w(t))}function F(t){var e,i,a,o=t[0]/100,n=t[1]/100,r=t[2]/100,s=t[3]/100;return e=1-Math.min(1,o*(1-s)+s),i=1-Math.min(1,n*(1-s)+s),a=1-Math.min(1,r*(1-s)+s),[255*e,255*i,255*a]}function _(t){return a(F(t))}function P(t){return o(F(t))}function T(t){return n(F(t))}function V(t){return l(F(t))}function R(t){var e,i,a,o=t[0]/100,n=t[1]/100,r=t[2]/100;return e=3.2406*o+-1.5372*n+r*-.4986,i=o*-.9689+1.8758*n+.0415*r,a=.0557*o+n*-.204+1.057*r,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e=12.92*e,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i=12.92*i,a=a>.0031308?1.055*Math.pow(a,1/2.4)-.055:a=12.92*a,e=Math.min(Math.max(0,e),1),i=Math.min(Math.max(0,i),1),a=Math.min(Math.max(0,a),1),[255*e,255*i,255*a]}function O(t){var e,i,a,o=t[0],n=t[1],r=t[2];return o/=95.047,n/=100,r/=108.883,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,n=n>.008856?Math.pow(n,1/3):7.787*n+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,e=116*n-16,i=500*(o-n),a=200*(n-r),[e,i,a]}function W(t){return B(O(t))}function L(t){var e,i,a,o,n=t[0],r=t[1],s=t[2];return 8>=n?(i=100*n/903.3,o=7.787*(i/100)+16/116):(i=100*Math.pow((n+16)/116,3),o=Math.pow(i/100,1/3)),e=.008856>=e/95.047?e=95.047*(r/500+o-16/116)/7.787:95.047*Math.pow(r/500+o,3),a=.008859>=a/108.883?a=108.883*(o-s/200-16/116)/7.787:108.883*Math.pow(o-s/200,3),[e,i,a]}function B(t){var e,i,a,o=t[0],n=t[1],r=t[2];return e=Math.atan2(r,n),i=360*e/2/Math.PI,0>i&&(i+=360),a=Math.sqrt(n*n+r*r),[o,a,i]}function z(t){return R(L(t))}function H(t){var e,i,a,o=t[0],n=t[1],r=t[2];return a=r/360*2*Math.PI,e=n*Math.cos(a),i=n*Math.sin(a),[o,e,i]}function N(t){return L(H(t))}function E(t){return z(H(t))}function U(t){return Q[t]}function j(t){return a(U(t))}function q(t){return o(U(t))}function Y(t){return n(U(t))}function J(t){return s(U(t))}function Z(t){return d(U(t))}function X(t){return h(U(t))}e.exports={rgb2hsl:a,rgb2hsv:o,rgb2hwb:n,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:h,rgb2lab:d,rgb2lch:c,hsl2rgb:u,hsl2hsv:f,hsl2hwb:p,hsl2cmyk:m,hsl2keyword:v,hsv2rgb:x,hsv2hsl:y,hsv2hwb:k,hsv2cmyk:S,hsv2keyword:C,hwb2rgb:w,hwb2hsl:M,hwb2hsv:D,hwb2cmyk:A,hwb2keyword:I,cmyk2rgb:F,cmyk2hsl:_,cmyk2hsv:P,cmyk2hwb:T,cmyk2keyword:V,keyword2rgb:U,keyword2hsl:j,keyword2hsv:q,keyword2hwb:Y,keyword2cmyk:J,keyword2lab:Z,keyword2xyz:X,xyz2rgb:R,xyz2lab:O,xyz2lch:W,lab2xyz:L,lab2rgb:z,lab2lch:B,lch2lab:H,lch2xyz:N,lch2rgb:E};var Q={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},G={};for(var $ in Q)G[JSON.stringify(Q[$])]=$},{}],5:[function(t,e,i){var a=t("./conversions"),o=function(){return new h};for(var n in a){o[n+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),a[t](e)}}(n);var r=/(\w+)2(\w+)/.exec(n),s=r[1],l=r[2];o[s]=o[s]||{},o[s][l]=o[n]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var i=a[t](e);if("string"==typeof i||void 0===i)return i;for(var o=0;o<i.length;o++)i[o]=Math.round(i[o]);return i}}(n)}var h=function(){this.convs={}};h.prototype.routeSpace=function(t,e){var i=e[0];return void 0===i?this.getValues(t):("number"==typeof i&&(i=Array.prototype.slice.call(e)),this.setValues(t,i))},h.prototype.setValues=function(t,e){return this.space=t,this.convs={},this.convs[t]=e,this},h.prototype.getValues=function(t){var e=this.convs[t];if(!e){var i=this.space,a=this.convs[i];e=o[i][t](a),this.convs[t]=e}return e},["rgb","hsl","hsv","cmyk","keyword"].forEach(function(t){h.prototype[t]=function(e){return this.routeSpace(t,arguments)}}),e.exports=o},{"./conversions":4}],6:[function(t,e,i){e.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}},{}],7:[function(t,e,i){var a=t("./core/core.js")();t("./core/core.helpers")(a),t("./core/core.element")(a),t("./core/core.animation")(a),t("./core/core.controller")(a),t("./core/core.datasetController")(a),t("./core/core.layoutService")(a),t("./core/core.legend")(a),t("./core/core.plugin.js")(a),t("./core/core.scale")(a),t("./core/core.scaleService")(a),t("./core/core.title")(a),t("./core/core.tooltip")(a),t("./elements/element.arc")(a),t("./elements/element.line")(a),t("./elements/element.point")(a),t("./elements/element.rectangle")(a),t("./scales/scale.category")(a),t("./scales/scale.linear")(a),t("./scales/scale.logarithmic")(a),t("./scales/scale.radialLinear")(a),t("./scales/scale.time")(a),t("./controllers/controller.bar")(a),t("./controllers/controller.bubble")(a),t("./controllers/controller.doughnut")(a),t("./controllers/controller.line")(a),t("./controllers/controller.polarArea")(a),t("./controllers/controller.radar")(a),t("./charts/Chart.Bar")(a),t("./charts/Chart.Bubble")(a),t("./charts/Chart.Doughnut")(a),t("./charts/Chart.Line")(a),t("./charts/Chart.PolarArea")(a),t("./charts/Chart.Radar")(a),t("./charts/Chart.Scatter")(a),window.Chart=e.exports=a},{"./charts/Chart.Bar":8,"./charts/Chart.Bubble":9,"./charts/Chart.Doughnut":10,"./charts/Chart.Line":11,"./charts/Chart.PolarArea":12,"./charts/Chart.Radar":13,"./charts/Chart.Scatter":14,"./controllers/controller.bar":15,"./controllers/controller.bubble":16,"./controllers/controller.doughnut":17,"./controllers/controller.line":18,"./controllers/controller.polarArea":19,"./controllers/controller.radar":20,"./core/core.animation":21,"./core/core.controller":22,"./core/core.datasetController":23,"./core/core.element":24,"./core/core.helpers":25,"./core/core.js":26,"./core/core.layoutService":27,"./core/core.legend":28,"./core/core.plugin.js":29,"./core/core.scale":30,"./core/core.scaleService":31,"./core/core.title":32,"./core/core.tooltip":33,"./elements/element.arc":34,"./elements/element.line":35,"./elements/element.point":36,"./elements/element.rectangle":37,"./scales/scale.category":38,"./scales/scale.linear":39,"./scales/scale.logarithmic":40,"./scales/scale.radialLinear":41,"./scales/scale.time":42}],8:[function(t,e,i){"use strict";e.exports=function(t){t.Bar=function(e,i){return i.type="bar",new t(e,i)}}},{}],9:[function(t,e,i){"use strict";e.exports=function(t){t.Bubble=function(e,i){return i.type="bubble",new t(e,i)}}},{}],10:[function(t,e,i){"use strict";e.exports=function(t){t.Doughnut=function(e,i){return i.type="doughnut",new t(e,i)}}},{}],11:[function(t,e,i){"use strict";e.exports=function(t){t.Line=function(e,i){return i.type="line",new t(e,i)}}},{}],12:[function(t,e,i){"use strict";e.exports=function(t){t.PolarArea=function(e,i){return i.type="polarArea",new t(e,i)}}},{}],13:[function(t,e,i){"use strict";e.exports=function(t){t.Radar=function(e,i){return i.options=t.helpers.configMerge({aspectRatio:1},i.options),i.type="radar",new t(e,i)}}},{}],14:[function(t,e,i){"use strict";e.exports=function(t){var e={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-1"}],yAxes:[{type:"linear",position:"left",id:"y-axis-1"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){return"("+t.xLabel+", "+t.yLabel+")"}}}};t.defaults.scatter=e,t.controllers.scatter=t.controllers.line,t.Scatter=function(e,i){return i.type="scatter",new t(e,i)}}},{}],15:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bar={hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}},t.controllers.bar=t.DatasetController.extend({dataElementType:t.elements.Rectangle,initialize:function(e,i){t.DatasetController.prototype.initialize.call(this,e,i),this.getMeta().bar=!0},getBarCount:function(){var t=0;return e.each(this.chart.data.datasets,function(e,i){var a=this.chart.getDatasetMeta(i);a.bar&&this.chart.isDatasetVisible(i)&&++t},this),t},update:function(t){e.each(this.getMeta().data,function(e,i){this.updateElement(e,i,t)},this)},updateElement:function(t,i,a){var o=this.getMeta(),n=this.getScaleForId(o.xAxisID),r=this.getScaleForId(o.yAxisID),s=r.getBasePixel(),l=this.chart.options.elements.rectangle,h=t.custom||{},d=this.getDataset();e.extend(t,{_xScale:n,_yScale:r,_datasetIndex:this.index,_index:i,_model:{x:this.calculateBarX(i,this.index),y:a?s:this.calculateBarY(i,this.index),label:this.chart.data.labels[i],datasetLabel:d.label,base:a?s:this.calculateBarBase(this.index,i),width:this.calculateBarWidth(i),backgroundColor:h.backgroundColor?h.backgroundColor:e.getValueAtIndexOrDefault(d.backgroundColor,i,l.backgroundColor),borderSkipped:h.borderSkipped?h.borderSkipped:l.borderSkipped,borderColor:h.borderColor?h.borderColor:e.getValueAtIndexOrDefault(d.borderColor,i,l.borderColor),borderWidth:h.borderWidth?h.borderWidth:e.getValueAtIndexOrDefault(d.borderWidth,i,l.borderWidth)}}),t.pivot()},calculateBarBase:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.yAxisID),o=0;if(a.options.stacked){var n=this.chart,r=n.data.datasets,s=r[t].data[e];if(0>s)for(var l=0;t>l;l++){var h=r[l],d=n.getDatasetMeta(l);d.bar&&d.yAxisID===a.id&&n.isDatasetVisible(l)&&(o+=h.data[e]<0?h.data[e]:0)}else for(var c=0;t>c;c++){var u=r[c],f=n.getDatasetMeta(c);f.bar&&f.yAxisID===a.id&&n.isDatasetVisible(c)&&(o+=u.data[e]>0?u.data[e]:0)}return a.getPixelForValue(o)}return a.getBasePixel()},getRuler:function(t){var e,i=this.getMeta(),a=this.getScaleForId(i.xAxisID),o=this.getBarCount();e="category"===a.options.type?a.getPixelForTick(t+1)-a.getPixelForTick(t):a.width/a.ticks.length;var n=e*a.options.categoryPercentage,r=(e-e*a.options.categoryPercentage)/2,s=n/o;if(a.ticks.length!==this.chart.data.labels.length){var l=a.ticks.length/this.chart.data.labels.length;s*=l}var h=s*a.options.barPercentage,d=s-s*a.options.barPercentage;return{datasetCount:o,tickWidth:e,categoryWidth:n,categorySpacing:r,fullBarWidth:s,barWidth:h,barSpacing:d}},calculateBarWidth:function(t){var e=this.getScaleForId(this.getMeta().xAxisID),i=this.getRuler(t);return e.options.stacked?i.categoryWidth:i.barWidth},getBarIndex:function(t){var e,i,a=0;for(i=0;t>i;++i)e=this.chart.getDatasetMeta(i),e.bar&&this.chart.isDatasetVisible(i)&&++a;return a},calculateBarX:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.xAxisID),o=this.getBarIndex(e),n=this.getRuler(t),r=a.getPixelForValue(null,t,e,this.chart.isCombo);return r-=this.chart.isCombo?n.tickWidth/2:0,a.options.stacked?r+n.categoryWidth/2+n.categorySpacing:r+n.barWidth/2+n.categorySpacing+n.barWidth*o+n.barSpacing/2+n.barSpacing*o},calculateBarY:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.yAxisID),o=this.getDataset().data[t];if(a.options.stacked){for(var n=0,r=0,s=0;e>s;s++){var l=this.chart.data.datasets[s],h=this.chart.getDatasetMeta(s);h.bar&&h.yAxisID===a.id&&this.chart.isDatasetVisible(s)&&(l.data[t]<0?r+=l.data[t]||0:n+=l.data[t]||0)}return 0>o?a.getPixelForValue(r+o):a.getPixelForValue(n+o)}return a.getPixelForValue(o)},draw:function(t){var i=t||1;e.each(this.getMeta().data,function(t,e){var a=this.getDataset().data[e];null===a||void 0===a||isNaN(a)||t.transition(i).draw()},this)},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=t._model;n.backgroundColor=o.hoverBackgroundColor?o.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.hoverBackgroundColor,a,e.getHoverColor(n.backgroundColor)),n.borderColor=o.hoverBorderColor?o.hoverBorderColor:e.getValueAtIndexOrDefault(i.hoverBorderColor,a,e.getHoverColor(n.borderColor)),n.borderWidth=o.hoverBorderWidth?o.hoverBorderWidth:e.getValueAtIndexOrDefault(i.hoverBorderWidth,a,n.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=t._model,r=this.chart.options.elements.rectangle;n.backgroundColor=o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(i.backgroundColor,a,r.backgroundColor),n.borderColor=o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(i.borderColor,a,r.borderColor),n.borderWidth=o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(i.borderWidth,a,r.borderWidth)}}),t.defaults.horizontalBar={hover:{mode:"label"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var i="";return t.length>0&&(t[0].yLabel?i=t[0].yLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i+": "+t.xLabel}}}},t.controllers.horizontalBar=t.controllers.bar.extend({updateElement:function(t,i,a,o){var n=this.getMeta(),r=this.getScaleForId(n.xAxisID),s=this.getScaleForId(n.yAxisID),l=r.getBasePixel(),h=t.custom||{},d=this.getDataset(),c=this.chart.options.elements.rectangle;
+e.extend(t,{_xScale:r,_yScale:s,_datasetIndex:this.index,_index:i,_model:{x:a?l:this.calculateBarX(i,this.index),y:this.calculateBarY(i,this.index),label:this.chart.data.labels[i],datasetLabel:d.label,base:a?l:this.calculateBarBase(this.index,i),height:this.calculateBarHeight(i),backgroundColor:h.backgroundColor?h.backgroundColor:e.getValueAtIndexOrDefault(d.backgroundColor,i,c.backgroundColor),borderSkipped:h.borderSkipped?h.borderSkipped:c.borderSkipped,borderColor:h.borderColor?h.borderColor:e.getValueAtIndexOrDefault(d.borderColor,i,c.borderColor),borderWidth:h.borderWidth?h.borderWidth:e.getValueAtIndexOrDefault(d.borderWidth,i,c.borderWidth)},draw:function(){function t(t){return l[(d+t)%4]}var e=this._chart.ctx,i=this._view,a=i.height/2,o=i.y-a,n=i.y+a,r=i.base-(i.base-i.x),s=i.borderWidth/2;i.borderWidth&&(o+=s,n-=s,r+=s),e.beginPath(),e.fillStyle=i.backgroundColor,e.strokeStyle=i.borderColor,e.lineWidth=i.borderWidth;var l=[[i.base,n],[i.base,o],[r,o],[r,n]],h=["bottom","left","top","right"],d=h.indexOf(i.borderSkipped,0);-1===d&&(d=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),i.borderWidth&&e.stroke()},inRange:function(t,e){var i=this._view,a=!1;return i&&(a=i.x<i.base?e>=i.y-i.height/2&&e<=i.y+i.height/2&&t>=i.x&&t<=i.base:e>=i.y-i.height/2&&e<=i.y+i.height/2&&t>=i.base&&t<=i.x),a}}),t.pivot()},calculateBarBase:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.xAxisID),o=0;if(a.options.stacked){var n=this.chart.data.datasets[t].data[e];if(0>n)for(var r=0;t>r;r++){var s=this.chart.data.datasets[r],l=this.chart.getDatasetMeta(r);l.bar&&l.xAxisID===a.id&&this.chart.isDatasetVisible(r)&&(o+=s.data[e]<0?s.data[e]:0)}else for(var h=0;t>h;h++){var d=this.chart.data.datasets[h],c=this.chart.getDatasetMeta(h);c.bar&&c.xAxisID===a.id&&this.chart.isDatasetVisible(h)&&(o+=d.data[e]>0?d.data[e]:0)}return a.getPixelForValue(o)}return a.getBasePixel()},getRuler:function(t){var e,i=this.getMeta(),a=this.getScaleForId(i.yAxisID),o=this.getBarCount();e="category"===a.options.type?a.getPixelForTick(t+1)-a.getPixelForTick(t):a.width/a.ticks.length;var n=e*a.options.categoryPercentage,r=(e-e*a.options.categoryPercentage)/2,s=n/o;if(a.ticks.length!==this.chart.data.labels.length){var l=a.ticks.length/this.chart.data.labels.length;s*=l}var h=s*a.options.barPercentage,d=s-s*a.options.barPercentage;return{datasetCount:o,tickHeight:e,categoryHeight:n,categorySpacing:r,fullBarHeight:s,barHeight:h,barSpacing:d}},calculateBarHeight:function(t){var e=this.getScaleForId(this.getMeta().yAxisID),i=this.getRuler(t);return e.options.stacked?i.categoryHeight:i.barHeight},calculateBarX:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.xAxisID),o=this.getDataset().data[t];if(a.options.stacked){for(var n=0,r=0,s=0;e>s;s++){var l=this.chart.data.datasets[s],h=this.chart.getDatasetMeta(s);h.bar&&h.xAxisID===a.id&&this.chart.isDatasetVisible(s)&&(l.data[t]<0?r+=l.data[t]||0:n+=l.data[t]||0)}return 0>o?a.getPixelForValue(r+o):a.getPixelForValue(n+o)}return a.getPixelForValue(o)},calculateBarY:function(t,e){var i=this.getMeta(),a=this.getScaleForId(i.yAxisID),o=this.getBarIndex(e),n=this.getRuler(t),r=a.getPixelForValue(null,t,e,this.chart.isCombo);return r-=this.chart.isCombo?n.tickHeight/2:0,a.options.stacked?r+n.categoryHeight/2+n.categorySpacing:r+n.barHeight/2+n.categorySpacing+n.barHeight*o+n.barSpacing/2+n.barSpacing*o}})}},{}],16:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.bubble={hover:{mode:"single"},scales:{xAxes:[{type:"linear",position:"bottom",id:"x-axis-0"}],yAxes:[{type:"linear",position:"left",id:"y-axis-0"}]},tooltips:{callbacks:{title:function(t,e){return""},label:function(t,e){var i=e.datasets[t.datasetIndex].label||"",a=e.datasets[t.datasetIndex].data[t.index];return i+": ("+a.x+", "+a.y+", "+a.r+")"}}}},t.controllers.bubble=t.DatasetController.extend({dataElementType:t.elements.Point,update:function(t){var i=this.getMeta(),a=i.data;e.each(a,function(e,i){this.updateElement(e,i,t)},this)},updateElement:function(t,i,a){var o=this.getMeta(),n=this.getScaleForId(o.xAxisID),r=this.getScaleForId(o.yAxisID),s=t.custom||{},l=this.getDataset(),h=l.data[i],d=this.chart.options.elements.point;e.extend(t,{_xScale:n,_yScale:r,_datasetIndex:this.index,_index:i,_model:{x:a?n.getPixelForDecimal(.5):n.getPixelForValue(h,i,this.index,this.chart.isCombo),y:a?r.getBasePixel():r.getPixelForValue(h,i,this.index),radius:a?0:s.radius?s.radius:this.getRadius(h),backgroundColor:s.backgroundColor?s.backgroundColor:e.getValueAtIndexOrDefault(l.backgroundColor,i,d.backgroundColor),borderColor:s.borderColor?s.borderColor:e.getValueAtIndexOrDefault(l.borderColor,i,d.borderColor),borderWidth:s.borderWidth?s.borderWidth:e.getValueAtIndexOrDefault(l.borderWidth,i,d.borderWidth),hitRadius:s.hitRadius?s.hitRadius:e.getValueAtIndexOrDefault(l.hitRadius,i,d.hitRadius)}});var c=t._model;c.skip=s.skip?s.skip:isNaN(c.x)||isNaN(c.y),t.pivot()},getRadius:function(t){return t.r||this.chart.options.elements.point.radius},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=t._model;n.radius=o.hoverRadius?o.hoverRadius:e.getValueAtIndexOrDefault(i.hoverRadius,a,this.chart.options.elements.point.hoverRadius)+this.getRadius(this.getDataset().data[t._index]),n.backgroundColor=o.hoverBackgroundColor?o.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.hoverBackgroundColor,a,e.getHoverColor(n.backgroundColor)),n.borderColor=o.hoverBorderColor?o.hoverBorderColor:e.getValueAtIndexOrDefault(i.hoverBorderColor,a,e.getHoverColor(n.borderColor)),n.borderWidth=o.hoverBorderWidth?o.hoverBorderWidth:e.getValueAtIndexOrDefault(i.hoverBorderWidth,a,n.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=t._model,r=this.chart.options.elements.point;n.radius=o.radius?o.radius:this.getRadius(i.data[t._index]),n.backgroundColor=o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(i.backgroundColor,a,r.backgroundColor),n.borderColor=o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(i.borderColor,a,r.borderColor),n.borderWidth=o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(i.borderWidth,a,r.borderWidth)}})}},{}],17:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults;i.doughnut={animation:{animateRotate:!0,animateScale:!1},aspectRatio:1,hover:{mode:"single"},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,a=i.datasets,o=i.labels;if(a.length)for(var n=0;n<a[0].data.length;++n)e.push('<li><span style="background-color:'+a[0].backgroundColor[n]+'"></span>'),o[n]&&e.push(o[n]),e.push("</li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var i=t.data;return i.labels.length&&i.datasets.length?i.labels.map(function(a,o){var n=t.getDatasetMeta(0),r=i.datasets[0],s=n.data[o],l=s.custom||{},h=e.getValueAtIndexOrDefault,d=t.options.elements.arc,c=l.backgroundColor?l.backgroundColor:h(r.backgroundColor,o,d.backgroundColor),u=l.borderColor?l.borderColor:h(r.borderColor,o,d.borderColor),f=l.borderWidth?l.borderWidth:h(r.borderWidth,o,d.borderWidth);return{text:a,fillStyle:c,strokeStyle:u,lineWidth:f,hidden:isNaN(r.data[o])||n.data[o].hidden,index:o}}):[]}},onClick:function(t,e){var i,a,o,n=e.index,r=this.chart;for(i=0,a=(r.data.datasets||[]).length;a>i;++i)o=r.getDatasetMeta(i),o.data[n].hidden=!o.data[n].hidden;r.update()}},cutoutPercentage:50,rotation:Math.PI*-.5,circumference:2*Math.PI,tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+e.datasets[t.datasetIndex].data[t.index]}}}},i.pie=e.clone(i.doughnut),e.extend(i.pie,{cutoutPercentage:0}),t.controllers.doughnut=t.controllers.pie=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,getRingIndex:function(t){for(var e=0,i=0;t>i;++i)this.chart.isDatasetVisible(i)&&++e;return e},update:function(t){var i=this,a=i.chart,o=a.chartArea,n=a.options,r=n.elements.arc,s=o.right-o.left-r.borderWidth,l=o.bottom-o.top-r.borderWidth,h=Math.min(s,l),d={x:0,y:0},c=i.getMeta(),u=n.cutoutPercentage,f=n.circumference;if(f<2*Math.PI){var g=n.rotation%(2*Math.PI);g+=2*Math.PI*(g>=Math.PI?-1:g<-Math.PI?1:0);var p=g+f,m={x:Math.cos(g),y:Math.sin(g)},b={x:Math.cos(p),y:Math.sin(p)},v=0>=g&&p>=0||g<=2*Math.PI&&2*Math.PI<=p,x=g<=.5*Math.PI&&.5*Math.PI<=p||g<=2.5*Math.PI&&2.5*Math.PI<=p,y=g<=-Math.PI&&-Math.PI<=p||g<=Math.PI&&Math.PI<=p,k=g<=.5*-Math.PI&&.5*-Math.PI<=p||g<=1.5*Math.PI&&1.5*Math.PI<=p,S=u/100,C={x:y?-1:Math.min(m.x*(m.x<0?1:S),b.x*(b.x<0?1:S)),y:k?-1:Math.min(m.y*(m.y<0?1:S),b.y*(b.y<0?1:S))},w={x:v?1:Math.max(m.x*(m.x>0?1:S),b.x*(b.x>0?1:S)),y:x?1:Math.max(m.y*(m.y>0?1:S),b.y*(b.y>0?1:S))},M={width:.5*(w.x-C.x),height:.5*(w.y-C.y)};h=Math.min(s/M.width,l/M.height),d={x:(w.x+C.x)*-.5,y:(w.y+C.y)*-.5}}a.outerRadius=Math.max(h/2,0),a.innerRadius=Math.max(u?a.outerRadius/100*u:1,0),a.radiusLength=(a.outerRadius-a.innerRadius)/a.getVisibleDatasetCount(),a.offsetX=d.x*a.outerRadius,a.offsetY=d.y*a.outerRadius,c.total=i.calculateTotal(),i.outerRadius=a.outerRadius-a.radiusLength*i.getRingIndex(i.index),i.innerRadius=i.outerRadius-a.radiusLength,e.each(c.data,function(e,a){i.updateElement(e,a,t)})},updateElement:function(t,i,a){var o=this,n=o.chart,r=n.chartArea,s=n.options,l=s.animation,h=s.elements.arc,d=(r.left+r.right)/2,c=(r.top+r.bottom)/2,u=s.rotation,f=s.rotation,g=o.getDataset(),p=a&&l.animateRotate?0:t.hidden?0:o.calculateCircumference(g.data[i])*(s.circumference/(2*Math.PI)),m=a&&l.animateScale?0:o.innerRadius,b=a&&l.animateScale?0:o.outerRadius,v=t.custom||{},x=e.getValueAtIndexOrDefault;e.extend(t,{_datasetIndex:o.index,_index:i,_model:{x:d+n.offsetX,y:c+n.offsetY,startAngle:u,endAngle:f,circumference:p,outerRadius:b,innerRadius:m,label:x(g.label,i,n.data.labels[i])}});var y=t._model;y.backgroundColor=v.backgroundColor?v.backgroundColor:x(g.backgroundColor,i,h.backgroundColor),y.hoverBackgroundColor=v.hoverBackgroundColor?v.hoverBackgroundColor:x(g.hoverBackgroundColor,i,h.hoverBackgroundColor),y.borderWidth=v.borderWidth?v.borderWidth:x(g.borderWidth,i,h.borderWidth),y.borderColor=v.borderColor?v.borderColor:x(g.borderColor,i,h.borderColor),a&&l.animateRotate||(0===i?y.startAngle=s.rotation:y.startAngle=o.getMeta().data[i-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,i=this.getDataset(),a=this.getMeta(),o=0;return e.each(a.data,function(e,a){t=i.data[a],isNaN(t)||e.hidden||(o+=Math.abs(t))}),o},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0}})}},{}],18:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.line={showLines:!0,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}},t.controllers.line=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,addElementAndReset:function(e){var i=this,a=i.chart.options;t.DatasetController.prototype.addElementAndReset.call(i,e),a.showLines&&0!==a.elements.line.tension&&i.updateBezierControlPoints()},update:function(t){var i,a,o,n,r=this,s=r.getMeta(),l=s.dataset,h=s.data||[],d=r.chart.options,c=d.elements.line,u=r.getScaleForId(s.yAxisID);for(d.showLines&&(o=r.getDataset(),n=l.custom||{},void 0!==o.tension&&void 0===o.lineTension&&(o.lineTension=o.tension),l._scale=u,l._datasetIndex=r.index,l._children=h,l._model={tension:n.tension?n.tension:e.getValueOrDefault(o.lineTension,c.tension),backgroundColor:n.backgroundColor?n.backgroundColor:o.backgroundColor||c.backgroundColor,borderWidth:n.borderWidth?n.borderWidth:o.borderWidth||c.borderWidth,borderColor:n.borderColor?n.borderColor:o.borderColor||c.borderColor,borderCapStyle:n.borderCapStyle?n.borderCapStyle:o.borderCapStyle||c.borderCapStyle,borderDash:n.borderDash?n.borderDash:o.borderDash||c.borderDash,borderDashOffset:n.borderDashOffset?n.borderDashOffset:o.borderDashOffset||c.borderDashOffset,borderJoinStyle:n.borderJoinStyle?n.borderJoinStyle:o.borderJoinStyle||c.borderJoinStyle,fill:n.fill?n.fill:void 0!==o.fill?o.fill:c.fill,scaleTop:u.top,scaleBottom:u.bottom,scaleZero:u.getBasePixel()},l.pivot()),i=0,a=h.length;a>i;++i)r.updateElement(h[i],i,t);d.showLines&&0!==c.tension&&r.updateBezierControlPoints()},getPointBackgroundColor:function(t,i){var a=this.chart.options.elements.point.backgroundColor,o=this.getDataset(),n=t.custom||{};return n.backgroundColor?a=n.backgroundColor:o.pointBackgroundColor?a=e.getValueAtIndexOrDefault(o.pointBackgroundColor,i,a):o.backgroundColor&&(a=o.backgroundColor),a},getPointBorderColor:function(t,i){var a=this.chart.options.elements.point.borderColor,o=this.getDataset(),n=t.custom||{};return n.borderColor?a=n.borderColor:o.pointBorderColor?a=e.getValueAtIndexOrDefault(o.pointBorderColor,i,a):o.borderColor&&(a=o.borderColor),a},getPointBorderWidth:function(t,i){var a=this.chart.options.elements.point.borderWidth,o=this.getDataset(),n=t.custom||{};return n.borderWidth?a=n.borderWidth:o.pointBorderWidth?a=e.getValueAtIndexOrDefault(o.pointBorderWidth,i,a):o.borderWidth&&(a=o.borderWidth),a},updateElement:function(t,i,a){var o,n,r=this,s=r.getMeta(),l=t.custom||{},h=r.getDataset(),d=r.index,c=h.data[i],u=r.getScaleForId(s.yAxisID),f=r.getScaleForId(s.xAxisID),g=r.chart.options.elements.point;void 0!==h.radius&&void 0===h.pointRadius&&(h.pointRadius=h.radius),void 0!==h.hitRadius&&void 0===h.pointHitRadius&&(h.pointHitRadius=h.hitRadius),o=f.getPixelForValue(c,i,d,r.chart.isCombo),n=a?u.getBasePixel():r.calculatePointY(c,i,d,r.chart.isCombo),t._xScale=f,t._yScale=u,t._datasetIndex=d,t._index=i,t._model={x:o,y:n,skip:l.skip||isNaN(o)||isNaN(n),radius:l.radius||e.getValueAtIndexOrDefault(h.pointRadius,i,g.radius),pointStyle:l.pointStyle||e.getValueAtIndexOrDefault(h.pointStyle,i,g.pointStyle),backgroundColor:r.getPointBackgroundColor(t,i),borderColor:r.getPointBorderColor(t,i),borderWidth:r.getPointBorderWidth(t,i),tension:s.dataset._model?s.dataset._model.tension:0,hitRadius:l.hitRadius||e.getValueAtIndexOrDefault(h.pointHitRadius,i,g.hitRadius)}},calculatePointY:function(t,e,i,a){var o,n,r,s=this,l=s.chart,h=s.getMeta(),d=s.getScaleForId(h.yAxisID),c=0,u=0;if(d.options.stacked){for(o=0;i>o;o++)n=l.data.datasets[o],r=l.getDatasetMeta(o),"line"===r.type&&l.isDatasetVisible(o)&&(n.data[e]<0?u+=n.data[e]||0:c+=n.data[e]||0);return 0>t?d.getPixelForValue(u+t):d.getPixelForValue(c+t)}return d.getPixelForValue(t)},updateBezierControlPoints:function(){var t,i,a,o,n,r=this.getMeta(),s=this.chart.chartArea,l=r.data||[];for(t=0,i=l.length;i>t;++t)a=l[t],o=a._model,n=e.splineCurve(e.previousItem(l,t)._model,o,e.nextItem(l,t)._model,r.dataset._model.tension),o.controlPointPreviousX=Math.max(Math.min(n.previous.x,s.right),s.left),o.controlPointPreviousY=Math.max(Math.min(n.previous.y,s.bottom),s.top),o.controlPointNextX=Math.max(Math.min(n.next.x,s.right),s.left),o.controlPointNextY=Math.max(Math.min(n.next.y,s.bottom),s.top),a.pivot()},draw:function(t){var e,i,a=this.getMeta(),o=a.data||[],n=t||1;for(e=0,i=o.length;i>e;++e)o[e].transition(n);for(this.chart.options.showLines&&a.dataset.transition(n).draw(),e=0,i=o.length;i>e;++e)o[e].draw()},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=t._model;n.radius=o.hoverRadius||e.getValueAtIndexOrDefault(i.pointHoverRadius,a,this.chart.options.elements.point.hoverRadius),n.backgroundColor=o.hoverBackgroundColor||e.getValueAtIndexOrDefault(i.pointHoverBackgroundColor,a,e.getHoverColor(n.backgroundColor)),n.borderColor=o.hoverBorderColor||e.getValueAtIndexOrDefault(i.pointHoverBorderColor,a,e.getHoverColor(n.borderColor)),n.borderWidth=o.hoverBorderWidth||e.getValueAtIndexOrDefault(i.pointHoverBorderWidth,a,n.borderWidth)},removeHoverStyle:function(t){var i=this,a=i.chart.data.datasets[t._datasetIndex],o=t._index,n=t.custom||{},r=t._model;void 0!==a.radius&&void 0===a.pointRadius&&(a.pointRadius=a.radius),r.radius=n.radius||e.getValueAtIndexOrDefault(a.pointRadius,o,i.chart.options.elements.point.radius),r.backgroundColor=i.getPointBackgroundColor(t,o),r.borderColor=i.getPointBorderColor(t,o),r.borderWidth=i.getPointBorderWidth(t,o)}})}},{}],19:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.polarArea={scale:{type:"radialLinear",lineArc:!0},animation:{animateRotate:!0,animateScale:!0},aspectRatio:1,legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');var i=t.data,a=i.datasets,o=i.labels;if(a.length)for(var n=0;n<a[0].data.length;++n)e.push('<li><span style="background-color:'+a[0].backgroundColor[n]+'">'),o[n]&&e.push(o[n]),e.push("</span></li>");return e.push("</ul>"),e.join("")},legend:{labels:{generateLabels:function(t){var i=t.data;return i.labels.length&&i.datasets.length?i.labels.map(function(a,o){var n=t.getDatasetMeta(0),r=i.datasets[0],s=n.data[o],l=s.custom||{},h=e.getValueAtIndexOrDefault,d=t.options.elements.arc,c=l.backgroundColor?l.backgroundColor:h(r.backgroundColor,o,d.backgroundColor),u=l.borderColor?l.borderColor:h(r.borderColor,o,d.borderColor),f=l.borderWidth?l.borderWidth:h(r.borderWidth,o,d.borderWidth);return{text:a,fillStyle:c,strokeStyle:u,lineWidth:f,hidden:isNaN(r.data[o])||n.data[o].hidden,index:o}}):[]}},onClick:function(t,e){var i,a,o,n=e.index,r=this.chart;for(i=0,a=(r.data.datasets||[]).length;a>i;++i)o=r.getDatasetMeta(i),o.data[n].hidden=!o.data[n].hidden;r.update()}},tooltips:{callbacks:{title:function(){return""},label:function(t,e){return e.labels[t.index]+": "+t.yLabel}}}},t.controllers.polarArea=t.DatasetController.extend({dataElementType:t.elements.Arc,linkScales:e.noop,update:function(t){var i=this,a=i.chart,o=a.chartArea,n=this.getMeta(),r=a.options,s=r.elements.arc,l=Math.min(o.right-o.left,o.bottom-o.top);a.outerRadius=Math.max((l-s.borderWidth/2)/2,0),a.innerRadius=Math.max(r.cutoutPercentage?a.outerRadius/100*r.cutoutPercentage:1,0),a.radiusLength=(a.outerRadius-a.innerRadius)/a.getVisibleDatasetCount(),i.outerRadius=a.outerRadius-a.radiusLength*i.index,i.innerRadius=i.outerRadius-a.radiusLength,n.count=i.countVisibleElements(),e.each(n.data,function(e,a){i.updateElement(e,a,t)})},updateElement:function(t,i,a){for(var o=this,n=o.chart,r=n.chartArea,s=o.getDataset(),l=n.options,h=l.animation,d=l.elements.arc,c=t.custom||{},u=n.scale,f=e.getValueAtIndexOrDefault,g=n.data.labels,p=o.calculateCircumference(s.data[i]),m=(r.left+r.right)/2,b=(r.top+r.bottom)/2,v=0,x=o.getMeta(),y=0;i>y;++y)isNaN(s.data[y])||x.data[y].hidden||++v;var k=t.hidden?0:u.getDistanceFromCenterForValue(s.data[i]),S=-.5*Math.PI+p*v,C=S+(t.hidden?0:p),w={x:m,y:b,innerRadius:0,outerRadius:h.animateScale?0:u.getDistanceFromCenterForValue(s.data[i]),startAngle:h.animateRotate?Math.PI*-.5:S,endAngle:h.animateRotate?Math.PI*-.5:C,backgroundColor:c.backgroundColor?c.backgroundColor:f(s.backgroundColor,i,d.backgroundColor),borderWidth:c.borderWidth?c.borderWidth:f(s.borderWidth,i,d.borderWidth),borderColor:c.borderColor?c.borderColor:f(s.borderColor,i,d.borderColor),label:f(g,i,g[i])};e.extend(t,{_datasetIndex:o.index,_index:i,_scale:u,_model:a?w:{x:m,y:b,innerRadius:0,outerRadius:k,startAngle:S,endAngle:C,backgroundColor:c.backgroundColor?c.backgroundColor:f(s.backgroundColor,i,d.backgroundColor),borderWidth:c.borderWidth?c.borderWidth:f(s.borderWidth,i,d.borderWidth),borderColor:c.borderColor?c.borderColor:f(s.borderColor,i,d.borderColor),label:f(g,i,g[i])}}),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},countVisibleElements:function(){var t=this.getDataset(),i=this.getMeta(),a=0;return e.each(i.data,function(e,i){isNaN(t.data[i])||e.hidden||a++}),a},calculateCircumference:function(t){var e=this.getMeta().count;return e>0&&!isNaN(t)?2*Math.PI/e:0}})}},{}],20:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.radar={scale:{type:"radialLinear"},elements:{line:{tension:0}}},t.controllers.radar=t.DatasetController.extend({datasetElementType:t.elements.Line,dataElementType:t.elements.Point,linkScales:e.noop,addElementAndReset:function(e){t.DatasetController.prototype.addElementAndReset.call(this,e),this.updateBezierControlPoints()},update:function(t){var i=this.getMeta(),a=i.dataset,o=i.data,n=a.custom||{},r=this.getDataset(),s=this.chart.options.elements.line,l=this.chart.scale;void 0!==r.tension&&void 0===r.lineTension&&(r.lineTension=r.tension),e.extend(i.dataset,{_datasetIndex:this.index,_children:o,_loop:!0,_model:{tension:n.tension?n.tension:e.getValueOrDefault(r.lineTension,s.tension),backgroundColor:n.backgroundColor?n.backgroundColor:r.backgroundColor||s.backgroundColor,borderWidth:n.borderWidth?n.borderWidth:r.borderWidth||s.borderWidth,borderColor:n.borderColor?n.borderColor:r.borderColor||s.borderColor,fill:n.fill?n.fill:void 0!==r.fill?r.fill:s.fill,borderCapStyle:n.borderCapStyle?n.borderCapStyle:r.borderCapStyle||s.borderCapStyle,borderDash:n.borderDash?n.borderDash:r.borderDash||s.borderDash,borderDashOffset:n.borderDashOffset?n.borderDashOffset:r.borderDashOffset||s.borderDashOffset,borderJoinStyle:n.borderJoinStyle?n.borderJoinStyle:r.borderJoinStyle||s.borderJoinStyle,scaleTop:l.top,scaleBottom:l.bottom,scaleZero:l.getBasePosition()}}),i.dataset.pivot(),e.each(o,function(e,i){this.updateElement(e,i,t)},this),this.updateBezierControlPoints()},updateElement:function(t,i,a){var o=t.custom||{},n=this.getDataset(),r=this.chart.scale,s=this.chart.options.elements.point,l=r.getPointPositionForValue(i,n.data[i]);e.extend(t,{_datasetIndex:this.index,_index:i,_scale:r,_model:{x:a?r.xCenter:l.x,y:a?r.yCenter:l.y,tension:o.tension?o.tension:e.getValueOrDefault(n.tension,this.chart.options.elements.line.tension),radius:o.radius?o.radius:e.getValueAtIndexOrDefault(n.pointRadius,i,s.radius),backgroundColor:o.backgroundColor?o.backgroundColor:e.getValueAtIndexOrDefault(n.pointBackgroundColor,i,s.backgroundColor),borderColor:o.borderColor?o.borderColor:e.getValueAtIndexOrDefault(n.pointBorderColor,i,s.borderColor),borderWidth:o.borderWidth?o.borderWidth:e.getValueAtIndexOrDefault(n.pointBorderWidth,i,s.borderWidth),pointStyle:o.pointStyle?o.pointStyle:e.getValueAtIndexOrDefault(n.pointStyle,i,s.pointStyle),hitRadius:o.hitRadius?o.hitRadius:e.getValueAtIndexOrDefault(n.hitRadius,i,s.hitRadius)}}),t._model.skip=o.skip?o.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,i=this.getMeta();e.each(i.data,function(a,o){var n=a._model,r=e.splineCurve(e.previousItem(i.data,o,!0)._model,n,e.nextItem(i.data,o,!0)._model,n.tension);n.controlPointPreviousX=Math.max(Math.min(r.previous.x,t.right),t.left),n.controlPointPreviousY=Math.max(Math.min(r.previous.y,t.bottom),t.top),n.controlPointNextX=Math.max(Math.min(r.next.x,t.right),t.left),n.controlPointNextY=Math.max(Math.min(r.next.y,t.bottom),t.top),a.pivot()},this)},draw:function(t){var i=this.getMeta(),a=t||1;e.each(i.data,function(t,e){t.transition(a)}),i.dataset.transition(a).draw(),e.each(i.data,function(t){t.draw()})},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t.custom||{},o=t._index,n=t._model;n.radius=a.hoverRadius?a.hoverRadius:e.getValueAtIndexOrDefault(i.pointHoverRadius,o,this.chart.options.elements.point.hoverRadius),n.backgroundColor=a.hoverBackgroundColor?a.hoverBackgroundColor:e.getValueAtIndexOrDefault(i.pointHoverBackgroundColor,o,e.getHoverColor(n.backgroundColor)),n.borderColor=a.hoverBorderColor?a.hoverBorderColor:e.getValueAtIndexOrDefault(i.pointHoverBorderColor,o,e.getHoverColor(n.borderColor)),n.borderWidth=a.hoverBorderWidth?a.hoverBorderWidth:e.getValueAtIndexOrDefault(i.pointHoverBorderWidth,o,n.borderWidth)},removeHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t.custom||{},o=t._index,n=t._model,r=this.chart.options.elements.point;n.radius=a.radius?a.radius:e.getValueAtIndexOrDefault(i.radius,o,r.radius),n.backgroundColor=a.backgroundColor?a.backgroundColor:e.getValueAtIndexOrDefault(i.pointBackgroundColor,o,r.backgroundColor),n.borderColor=a.borderColor?a.borderColor:e.getValueAtIndexOrDefault(i.pointBorderColor,o,r.borderColor),n.borderWidth=a.borderWidth?a.borderWidth:e.getValueAtIndexOrDefault(i.pointBorderWidth,o,r.borderWidth)}})}},{}],21:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.animation={duration:1e3,easing:"easeOutQuart",onProgress:e.noop,onComplete:e.noop},t.Animation=t.Element.extend({currentStep:null,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,i,a){a||(t.animating=!0);for(var o=0;o<this.animations.length;++o)if(this.animations[o].chartInstance===t)return void(this.animations[o].animationObject=e);this.animations.push({chartInstance:t,animationObject:e}),1===this.animations.length&&this.requestAnimationFrame()},cancelAnimation:function(t){var i=e.findIndex(this.animations,function(e){return e.chartInstance===t});-1!==i&&(this.animations.splice(i,1),t.animating=!1)},requestAnimationFrame:function(){var t=this;null===t.request&&(t.request=e.requestAnimFrame.call(window,function(){t.request=null,t.startDigest()}))},startDigest:function(){var t=Date.now(),e=0;this.dropFrames>1&&(e=Math.floor(this.dropFrames),this.dropFrames=this.dropFrames%1);for(var i=0;i<this.animations.length;)null===this.animations[i].animationObject.currentStep&&(this.animations[i].animationObject.currentStep=0),this.animations[i].animationObject.currentStep+=1+e,this.animations[i].animationObject.currentStep>this.animations[i].animationObject.numSteps&&(this.animations[i].animationObject.currentStep=this.animations[i].animationObject.numSteps),this.animations[i].animationObject.render(this.animations[i].chartInstance,this.animations[i].animationObject),this.animations[i].animationObject.onAnimationProgress&&this.animations[i].animationObject.onAnimationProgress.call&&this.animations[i].animationObject.onAnimationProgress.call(this.animations[i].chartInstance,this.animations[i]),this.animations[i].animationObject.currentStep===this.animations[i].animationObject.numSteps?(this.animations[i].animationObject.onAnimationComplete&&this.animations[i].animationObject.onAnimationComplete.call&&this.animations[i].animationObject.onAnimationComplete.call(this.animations[i].chartInstance,this.animations[i]),this.animations[i].chartInstance.animating=!1,this.animations.splice(i,1)):++i;var a=Date.now(),o=(a-t)/this.frameDuration;this.dropFrames+=o,this.animations.length>0&&this.requestAnimationFrame()}}}},{}],22:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.types={},t.instances={},t.controllers={},t.Controller=function(i){return this.chart=i,this.config=i.config,this.options=this.config.options=e.configMerge(t.defaults.global,t.defaults[this.config.type],this.config.options||{}),this.id=e.uid(),Object.defineProperty(this,"data",{get:function(){return this.config.data}}),t.instances[this.id]=this,this.options.responsive&&this.resize(!0),this.initialize(),this},e.extend(t.Controller.prototype,{initialize:function(){return t.pluginService.notifyPlugins("beforeInit",[this]),this.bindEvents(),this.ensureScalesHaveIDs(),this.buildOrUpdateControllers(),this.buildScales(),this.buildSurroundingItems(),this.updateLayout(),this.resetElements(),this.initToolTip(),this.update(),t.pluginService.notifyPlugins("afterInit",[this]),this},clear:function(){return e.clear(this.chart),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var i=this.chart.canvas,a=e.getMaximumWidth(this.chart.canvas),o=this.options.maintainAspectRatio&&isNaN(this.chart.aspectRatio)===!1&&isFinite(this.chart.aspectRatio)&&0!==this.chart.aspectRatio?a/this.chart.aspectRatio:e.getMaximumHeight(this.chart.canvas),n=this.chart.width!==a||this.chart.height!==o;return n?(i.width=this.chart.width=a,i.height=this.chart.height=o,e.retinaScale(this.chart),t||(this.stop(),this.update(this.options.responsiveAnimationDuration)),this):this},ensureScalesHaveIDs:function(){var t=this.options,i=t.scales||{},a=t.scale;e.each(i.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),e.each(i.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),a&&(a.id=a.id||"scale")},buildScales:function(){var i=this,a=i.options,o=i.scales={},n=[];a.scales&&(n=n.concat((a.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category"}}),(a.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear"}}))),a.scale&&n.push({options:a.scale,dtype:"radialLinear",isDefault:!0}),e.each(n,function(a,n){var r=a.options,s=e.getValueOrDefault(r.type,a.dtype),l=t.scaleService.getScaleConstructor(s);if(l){var h=new l({id:r.id,options:r,ctx:i.chart.ctx,chart:i});o[h.id]=h,a.isDefault&&(i.scale=h)}}),t.scaleService.addScalesToLayout(this)},buildSurroundingItems:function(){this.options.title&&(this.titleBlock=new t.Title({ctx:this.chart.ctx,options:this.options.title,chart:this}),t.layoutService.addBox(this,this.titleBlock)),this.options.legend&&(this.legend=new t.Legend({ctx:this.chart.ctx,options:this.options.legend,chart:this}),t.layoutService.addBox(this,this.legend))},updateLayout:function(){t.layoutService.update(this,this.chart.width,this.chart.height)},buildOrUpdateControllers:function(){var i=[],a=[];if(e.each(this.data.datasets,function(e,o){var n=this.getDatasetMeta(o);n.type||(n.type=e.type||this.config.type),i.push(n.type),n.controller?n.controller.updateIndex(o):(n.controller=new t.controllers[n.type](this,o),a.push(n.controller))},this),i.length>1)for(var o=1;o<i.length;o++)if(i[o]!==i[o-1]){this.isCombo=!0;break}return a},resetElements:function(){e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.reset()},this)},update:function(i,a){t.pluginService.notifyPlugins("beforeUpdate",[this]),this.tooltip._data=this.data;var o=this.buildOrUpdateControllers();e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.buildOrUpdateElements()},this),t.layoutService.update(this,this.chart.width,this.chart.height),t.pluginService.notifyPlugins("afterScaleUpdate",[this]),e.each(o,function(t){t.reset()}),e.each(this.data.datasets,function(t,e){this.getDatasetMeta(e).controller.update()},this),t.pluginService.notifyPlugins("afterUpdate",[this]),this.render(i,a)},render:function(i,a){t.pluginService.notifyPlugins("beforeRender",[this]);var o=this.options.animation;if(o&&("undefined"!=typeof i&&0!==i||"undefined"==typeof i&&0!==o.duration)){var n=new t.Animation;n.numSteps=(i||o.duration)/16.66,n.easing=o.easing,n.render=function(t,i){var a=e.easingEffects[i.easing],o=i.currentStep/i.numSteps,n=a(o);t.draw(n,o,i.currentStep)},n.onAnimationProgress=o.onProgress,n.onAnimationComplete=o.onComplete,t.animationService.addAnimation(this,n,i,a)}else this.draw(),o&&o.onComplete&&o.onComplete.call&&o.onComplete.call(this);return this},draw:function(i){var a=i||1;this.clear(),t.pluginService.notifyPlugins("beforeDraw",[this,a]),e.each(this.boxes,function(t){t.draw(this.chartArea)},this),this.scale&&this.scale.draw();var o=this.chart.ctx;o.save(),o.beginPath(),o.rect(this.chartArea.left,this.chartArea.top,this.chartArea.right-this.chartArea.left,this.chartArea.bottom-this.chartArea.top),o.clip(),e.each(this.data.datasets,function(t,e){this.isDatasetVisible(e)&&this.getDatasetMeta(e).controller.draw(i)},this,!0),o.restore(),this.tooltip.transition(a).draw(),t.pluginService.notifyPlugins("afterDraw",[this,a])},getElementAtEvent:function(t){var i=e.getRelativePosition(t,this.chart),a=[];return e.each(this.data.datasets,function(t,o){if(this.isDatasetVisible(o)){var n=this.getDatasetMeta(o);e.each(n.data,function(t,e){
+return t.inRange(i.x,i.y)?(a.push(t),a):void 0})}},this),a},getElementsAtEvent:function(t){var i=e.getRelativePosition(t,this.chart),a=[],o=function(){if(this.data.datasets)for(var t=0;t<this.data.datasets.length;t++){var e=this.getDatasetMeta(t);if(this.isDatasetVisible(t))for(var a=0;a<e.data.length;a++)if(e.data[a].inRange(i.x,i.y))return e.data[a]}}.call(this);return o?(e.each(this.data.datasets,function(t,e){if(this.isDatasetVisible(e)){var i=this.getDatasetMeta(e);a.push(i.data[o._index])}},this),a):a},getElementsAtEventForMode:function(t,e){var i=this;switch(e){case"single":return i.getElementAtEvent(t);case"label":return i.getElementsAtEvent(t);case"dataset":return i.getDatasetAtEvent(t);default:return t}},getDatasetAtEvent:function(t){var e=this.getElementAtEvent(t);return e.length>0&&(e=this.getDatasetMeta(e[0]._datasetIndex).data),e},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var i=e._meta[this.id];return i||(i=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,i=this.data.datasets.length;i>e;++e)this.isDatasetVisible(e)&&t++;return t},isDatasetVisible:function(t){var e=this.getDatasetMeta(t);return"boolean"==typeof e.hidden?!e.hidden:!this.data.datasets[t].hidden},generateLegend:function(){return this.options.legendCallback(this)},destroy:function(){this.clear(),e.unbindEvents(this,this.events),e.removeResizeListener(this.chart.canvas.parentNode);var i=this.chart.canvas;i.width=this.chart.width,i.height=this.chart.height,void 0!==this.chart.originalDevicePixelRatio&&this.chart.ctx.scale(1/this.chart.originalDevicePixelRatio,1/this.chart.originalDevicePixelRatio),i.style.width=this.chart.originalCanvasStyleWidth,i.style.height=this.chart.originalCanvasStyleHeight,t.pluginService.notifyPlugins("destroy",[this]),delete t.instances[this.id]},toBase64Image:function(){return this.chart.canvas.toDataURL.apply(this.chart.canvas,arguments)},initToolTip:function(){this.tooltip=new t.Tooltip({_chart:this.chart,_chartInstance:this,_data:this.data,_options:this.options},this)},bindEvents:function(){e.bindEvents(this,this.options.events,function(t){this.eventHandler(t)})},updateHoverStyle:function(t,e,i){var a,o,n,r=i?"setHoverStyle":"removeHoverStyle";switch(e){case"single":t=[t[0]];break;case"label":case"dataset":break;default:return}for(o=0,n=t.length;n>o;++o)a=t[o],a&&this.getDatasetMeta(a._datasetIndex).controller[r](a)},eventHandler:function(t){var i=this,a=i.tooltip,o=i.options||{},n=o.hover,r=o.tooltips;return i.lastActive=i.lastActive||[],i.lastTooltipActive=i.lastTooltipActive||[],"mouseout"===t.type?(i.active=[],i.tooltipActive=[]):(i.active=i.getElementsAtEventForMode(t,n.mode),i.tooltipActive=i.getElementsAtEventForMode(t,r.mode)),n.onHover&&n.onHover.call(i,i.active),("mouseup"===t.type||"click"===t.type)&&(o.onClick&&o.onClick.call(i,t,i.active),i.legend&&i.legend.handleEvent&&i.legend.handleEvent(t)),i.lastActive.length&&i.updateHoverStyle(i.lastActive,n.mode,!1),i.active.length&&n.mode&&i.updateHoverStyle(i.active,n.mode,!0),(r.enabled||r.custom)&&(a.initialize(),a._active=i.tooltipActive,a.update(!0)),a.pivot(),i.animating||e.arrayEquals(i.active,i.lastActive)&&e.arrayEquals(i.tooltipActive,i.lastTooltipActive)||(i.stop(),(r.enabled||r.custom)&&a.update(!0),i.render(n.animationDuration,!0)),i.lastActive=i.active,i.lastTooltipActive=i.tooltipActive,i}})}},{}],23:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=e.noop;t.DatasetController=function(t,e){this.initialize.call(this,t,e)},e.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){this.chart=t,this.index=e,this.linkScales(),this.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this.getMeta(),e=this.getDataset();null===t.xAxisID&&(t.xAxisID=e.xAxisID||this.chart.options.scales.xAxes[0].id),null===t.yAxisID&&(t.yAxisID=e.yAxisID||this.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,i=e.dataElementType;return i&&new i({_chart:e.chart.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,i=this,a=i.getMeta(),o=i.getDataset().data||[],n=a.data;for(t=0,e=o.length;e>t;++t)n[t]=n[t]||i.createMetaData(a,t);a.dataset=a.dataset||i.createMetaDataset()},addElementAndReset:function(t){var e=this,i=e.createMetaData(t);e.getMeta().data.splice(t,0,i),e.updateElement(i,t,!0)},buildOrUpdateElements:function(){var t=this.getMeta(),e=t.data,i=this.getDataset().data.length,a=e.length;if(a>i)e.splice(i,a-i);else if(i>a)for(var o=a;i>o;++o)this.addElementAndReset(o)},update:i,draw:function(t){var i=t||1;e.each(this.getMeta().data,function(t,e){t.transition(i).draw()})},removeHoverStyle:function(t,i){var a=this.chart.data.datasets[t._datasetIndex],o=t._index,n=t.custom||{},r=e.getValueAtIndexOrDefault,s=(e.color,t._model);s.backgroundColor=n.backgroundColor?n.backgroundColor:r(a.backgroundColor,o,i.backgroundColor),s.borderColor=n.borderColor?n.borderColor:r(a.borderColor,o,i.borderColor),s.borderWidth=n.borderWidth?n.borderWidth:r(a.borderWidth,o,i.borderWidth)},setHoverStyle:function(t){var i=this.chart.data.datasets[t._datasetIndex],a=t._index,o=t.custom||{},n=e.getValueAtIndexOrDefault,r=(e.color,e.getHoverColor),s=t._model;s.backgroundColor=o.hoverBackgroundColor?o.hoverBackgroundColor:n(i.hoverBackgroundColor,a,r(s.backgroundColor)),s.borderColor=o.hoverBorderColor?o.hoverBorderColor:n(i.hoverBorderColor,a,r(s.borderColor)),s.borderWidth=o.hoverBorderWidth?o.hoverBorderWidth:n(i.hoverBorderWidth,a,s.borderWidth)}}),t.DatasetController.extend=e.inherits}},{}],24:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.elements={},t.Element=function(t){e.extend(this,t),this.initialize.apply(this,arguments)},e.extend(t.Element.prototype,{initialize:function(){this.hidden=!1},pivot:function(){return this._view||(this._view=e.clone(this._model)),this._start=e.clone(this._view),this},transition:function(t){return this._view||(this._view=e.clone(this._model)),1===t?(this._view=this._model,this._start=null,this):(this._start||this.pivot(),e.each(this._model,function(i,a){if("_"===a[0]);else if(this._view.hasOwnProperty(a))if(i===this._view[a]);else if("string"==typeof i)try{var o=e.color(this._model[a]).mix(e.color(this._start[a]),t);this._view[a]=o.rgbString()}catch(n){this._view[a]=i}else if("number"==typeof i){var r=void 0!==this._start[a]&&isNaN(this._start[a])===!1?this._start[a]:0;this._view[a]=(this._model[a]-r)*t+r}else this._view[a]=i;else"number"!=typeof i||isNaN(this._view[a])?this._view[a]=i:this._view[a]=i*t},this),this)},tooltipPosition:function(){return{x:this._model.x,y:this._model.y}},hasValue:function(){return e.isNumber(this._model.x)&&e.isNumber(this._model.y)}}),t.Element.extend=e.inherits}},{}],25:[function(t,e,i){"use strict";var a=t("chartjs-color");e.exports=function(t){function e(t,e,i){var a;return"string"==typeof t?(a=parseInt(t,10),-1!=t.indexOf("%")&&(a=a/100*e.parentNode[i])):a=t,a}function i(t){return void 0!==t&&null!==t&&"none"!==t}function o(t,a,o){var n=document.defaultView,r=t.parentNode,s=n.getComputedStyle(t)[a],l=n.getComputedStyle(r)[a],h=i(s),d=i(l),c=Number.POSITIVE_INFINITY;return h||d?Math.min(h?e(s,t,o):c,d?e(l,r,o):c):"none"}var n=t.helpers={};n.each=function(t,e,i,a){var o,r;if(n.isArray(t))if(r=t.length,a)for(o=r-1;o>=0;o--)e.call(i,t[o],o);else for(o=0;r>o;o++)e.call(i,t[o],o);else if("object"==typeof t){var s=Object.keys(t);for(r=s.length,o=0;r>o;o++)e.call(i,t[s[o]],s[o])}},n.clone=function(t){var e={};return n.each(t,function(t,i){n.isArray(t)?e[i]=t.slice(0):"object"==typeof t&&null!==t?e[i]=n.clone(t):e[i]=t}),e},n.extend=function(t){for(var e=arguments.length,i=[],a=1;e>a;a++)i.push(arguments[a]);return n.each(i,function(e){n.each(e,function(e,i){t[i]=e})}),t},n.configMerge=function(e){var i=n.clone(e);return n.each(Array.prototype.slice.call(arguments,1),function(e){n.each(e,function(e,a){if("scales"===a)i[a]=n.scaleMerge(i.hasOwnProperty(a)?i[a]:{},e);else if("scale"===a)i[a]=n.configMerge(i.hasOwnProperty(a)?i[a]:{},t.scaleService.getScaleDefaults(e.type),e);else if(i.hasOwnProperty(a)&&n.isArray(i[a])&&n.isArray(e)){var o=i[a];n.each(e,function(t,e){e<o.length?"object"==typeof o[e]&&null!==o[e]&&"object"==typeof t&&null!==t?o[e]=n.configMerge(o[e],t):o[e]=t:o.push(t)})}else i.hasOwnProperty(a)&&"object"==typeof i[a]&&null!==i[a]&&"object"==typeof e?i[a]=n.configMerge(i[a],e):i[a]=e})}),i},n.extendDeep=function(t){function e(t){return n.each(arguments,function(i){i!==t&&n.each(i,function(i,a){t[a]&&t[a].constructor&&t[a].constructor===Object?e(t[a],i):t[a]=i})}),t}return e.apply(this,arguments)},n.scaleMerge=function(e,i){var a=n.clone(e);return n.each(i,function(e,i){"xAxes"===i||"yAxes"===i?a.hasOwnProperty(i)?n.each(e,function(e,o){var r=n.getValueOrDefault(e.type,"xAxes"===i?"category":"linear"),s=t.scaleService.getScaleDefaults(r);o>=a[i].length||!a[i][o].type?a[i].push(n.configMerge(s,e)):e.type&&e.type!==a[i][o].type?a[i][o]=n.configMerge(a[i][o],s,e):a[i][o]=n.configMerge(a[i][o],e)}):(a[i]=[],n.each(e,function(e){var o=n.getValueOrDefault(e.type,"xAxes"===i?"category":"linear");a[i].push(n.configMerge(t.scaleService.getScaleDefaults(o),e))})):a.hasOwnProperty(i)&&"object"==typeof a[i]&&null!==a[i]&&"object"==typeof e?a[i]=n.configMerge(a[i],e):a[i]=e}),a},n.getValueAtIndexOrDefault=function(t,e,i){return void 0===t||null===t?i:n.isArray(t)?e<t.length?t[e]:i:t},n.getValueOrDefault=function(t,e){return void 0===t?e:t},n.indexOf=function(t,e){if(Array.prototype.indexOf)return t.indexOf(e);for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1},n.where=function(t,e){if(n.isArray(t)&&Array.prototype.filter)return t.filter(e);var i=[];return n.each(t,function(t){e(t)&&i.push(t)}),i},n.findIndex=function(t,e,i){var a=-1;if(Array.prototype.findIndex)a=t.findIndex(e,i);else for(var o=0;o<t.length;++o)if(i=void 0!==i?i:t,e.call(i,t[o],o,t)){a=o;break}return a},n.findNextWhere=function(t,e,i){(void 0===i||null===i)&&(i=-1);for(var a=i+1;a<t.length;a++){var o=t[a];if(e(o))return o}},n.findPreviousWhere=function(t,e,i){(void 0===i||null===i)&&(i=t.length);for(var a=i-1;a>=0;a--){var o=t[a];if(e(o))return o}},n.inherits=function(t){var e=this,i=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},a=function(){this.constructor=i};return a.prototype=e.prototype,i.prototype=new a,i.extend=n.inherits,t&&n.extend(i.prototype,t),i.__super__=e.prototype,i},n.noop=function(){},n.uid=function(){var t=0;return function(){return t++}}(),n.warn=function(t){console&&"function"==typeof console.warn&&console.warn(t)},n.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},n.almostEquals=function(t,e,i){return Math.abs(t-e)<i},n.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},n.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},n.sign=function(t){return Math.sign?Math.sign(t):(t=+t,0===t||isNaN(t)?t:t>0?1:-1)},n.log10=function(t){return Math.log10?Math.log10(t):Math.log(t)/Math.LN10},n.toRadians=function(t){return t*(Math.PI/180)},n.toDegrees=function(t){return t*(180/Math.PI)},n.getAngleFromPoint=function(t,e){var i=e.x-t.x,a=e.y-t.y,o=Math.sqrt(i*i+a*a),n=Math.atan2(a,i);return n<-.5*Math.PI&&(n+=2*Math.PI),{angle:n,distance:o}},n.aliasPixel=function(t){return t%2===0?0:.5},n.splineCurve=function(t,e,i,a){var o=t.skip?e:t,n=e,r=i.skip?e:i,s=Math.sqrt(Math.pow(n.x-o.x,2)+Math.pow(n.y-o.y,2)),l=Math.sqrt(Math.pow(r.x-n.x,2)+Math.pow(r.y-n.y,2)),h=s/(s+l),d=l/(s+l);h=isNaN(h)?0:h,d=isNaN(d)?0:d;var c=a*h,u=a*d;return{previous:{x:n.x-c*(r.x-o.x),y:n.y-c*(r.y-o.y)},next:{x:n.x+u*(r.x-o.x),y:n.y+u*(r.y-o.y)}}},n.nextItem=function(t,e,i){return i?e>=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},n.previousItem=function(t,e,i){return i?0>=e?t[t.length-1]:t[e-1]:0>=e?t[0]:t[e-1]},n.niceNum=function(t,e){var i,a=Math.floor(n.log10(t)),o=t/Math.pow(10,a);return i=e?1.5>o?1:3>o?2:7>o?5:10:1>=o?1:2>=o?2:5>=o?5:10,i*Math.pow(10,a)};var r=n.easingEffects={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-1*t*(t-2)},easeInOutQuad:function(t){return(t/=.5)<1?.5*t*t:-0.5*(--t*(t-2)-1)},easeInCubic:function(t){return t*t*t},easeOutCubic:function(t){return 1*((t=t/1-1)*t*t+1)},easeInOutCubic:function(t){return(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},easeInQuart:function(t){return t*t*t*t},easeOutQuart:function(t){return-1*((t=t/1-1)*t*t*t-1)},easeInOutQuart:function(t){return(t/=.5)<1?.5*t*t*t*t:-0.5*((t-=2)*t*t*t-2)},easeInQuint:function(t){return 1*(t/=1)*t*t*t*t},easeOutQuint:function(t){return 1*((t=t/1-1)*t*t*t*t+1)},easeInOutQuint:function(t){return(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},easeInSine:function(t){return-1*Math.cos(t/1*(Math.PI/2))+1},easeOutSine:function(t){return 1*Math.sin(t/1*(Math.PI/2))},easeInOutSine:function(t){return-0.5*(Math.cos(Math.PI*t/1)-1)},easeInExpo:function(t){return 0===t?1:1*Math.pow(2,10*(t/1-1))},easeOutExpo:function(t){return 1===t?1:1*(-Math.pow(2,-10*t/1)+1)},easeInOutExpo:function(t){return 0===t?0:1===t?1:(t/=.5)<1?.5*Math.pow(2,10*(t-1)):.5*(-Math.pow(2,-10*--t)+2)},easeInCirc:function(t){return t>=1?t:-1*(Math.sqrt(1-(t/=1)*t)-1)},easeOutCirc:function(t){return 1*Math.sqrt(1-(t=t/1-1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-0.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,i=0,a=1;return 0===t?0:1===(t/=1)?1:(i||(i=.3),a<Math.abs(1)?(a=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/a),-(a*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)))},easeOutElastic:function(t){var e=1.70158,i=0,a=1;return 0===t?0:1===(t/=1)?1:(i||(i=.3),a<Math.abs(1)?(a=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/a),a*Math.pow(2,-10*t)*Math.sin((1*t-e)*(2*Math.PI)/i)+1)},easeInOutElastic:function(t){var e=1.70158,i=0,a=1;return 0===t?0:2===(t/=.5)?1:(i||(i=1*(.3*1.5)),a<Math.abs(1)?(a=1,e=i/4):e=i/(2*Math.PI)*Math.asin(1/a),1>t?-.5*(a*Math.pow(2,10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)):a*Math.pow(2,-10*(t-=1))*Math.sin((1*t-e)*(2*Math.PI)/i)*.5+1)},easeInBack:function(t){var e=1.70158;return 1*(t/=1)*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return 1*((t=t/1-1)*t*((e+1)*t+e)+1)},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?.5*(t*t*(((e*=1.525)+1)*t-e)):.5*((t-=2)*t*(((e*=1.525)+1)*t+e)+2)},easeInBounce:function(t){return 1-r.easeOutBounce(1-t)},easeOutBounce:function(t){return(t/=1)<1/2.75?1*(7.5625*t*t):2/2.75>t?1*(7.5625*(t-=1.5/2.75)*t+.75):2.5/2.75>t?1*(7.5625*(t-=2.25/2.75)*t+.9375):1*(7.5625*(t-=2.625/2.75)*t+.984375)},easeInOutBounce:function(t){return.5>t?.5*r.easeInBounce(2*t):.5*r.easeOutBounce(2*t-1)+.5}};n.requestAnimFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),n.cancelAnimFrame=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t,1e3/60)}}(),n.getRelativePosition=function(t,e){var i,a,o=t.originalEvent||t,r=t.currentTarget||t.srcElement,s=r.getBoundingClientRect(),l=o.touches;l&&l.length>0?(i=l[0].clientX,a=l[0].clientY):(i=o.clientX,a=o.clientY);var h=parseFloat(n.getStyle(r,"padding-left")),d=parseFloat(n.getStyle(r,"padding-top")),c=parseFloat(n.getStyle(r,"padding-right")),u=parseFloat(n.getStyle(r,"padding-bottom")),f=s.right-s.left-h-c,g=s.bottom-s.top-d-u;return i=Math.round((i-s.left-h)/f*r.width/e.currentDevicePixelRatio),a=Math.round((a-s.top-d)/g*r.height/e.currentDevicePixelRatio),{x:i,y:a}},n.addEvent=function(t,e,i){t.addEventListener?t.addEventListener(e,i):t.attachEvent?t.attachEvent("on"+e,i):t["on"+e]=i},n.removeEvent=function(t,e,i){t.removeEventListener?t.removeEventListener(e,i,!1):t.detachEvent?t.detachEvent("on"+e,i):t["on"+e]=n.noop},n.bindEvents=function(t,e,i){var a=t.events=t.events||{};n.each(e,function(e){a[e]=function(){i.apply(t,arguments)},n.addEvent(t.chart.canvas,e,a[e])})},n.unbindEvents=function(t,e){var i=t.chart.canvas;n.each(e,function(t,e){n.removeEvent(i,e,t)})},n.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},n.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},n.getMaximumWidth=function(t){var e=t.parentNode,i=parseInt(n.getStyle(e,"padding-left"))+parseInt(n.getStyle(e,"padding-right")),a=e.clientWidth-i,o=n.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},n.getMaximumHeight=function(t){var e=t.parentNode,i=parseInt(n.getStyle(e,"padding-top"))+parseInt(n.getStyle(e,"padding-bottom")),a=e.clientHeight-i,o=n.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},n.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},n.retinaScale=function(t){var e=t.ctx,i=t.canvas,a=i.width,o=i.height,n=t.currentDevicePixelRatio=window.devicePixelRatio||1;1!==n&&(i.height=o*n,i.width=a*n,e.scale(n,n),t.originalDevicePixelRatio=t.originalDevicePixelRatio||n),i.style.width=a+"px",i.style.height=o+"px"},n.clear=function(t){t.ctx.clearRect(0,0,t.width,t.height)},n.fontString=function(t,e,i){return e+" "+t+"px "+i},n.longestText=function(t,e,i,a){a=a||{};var o=a.data=a.data||{},r=a.garbageCollect=a.garbageCollect||[];a.font!==e&&(o=a.data={},r=a.garbageCollect=[],a.font=e),t.font=e;var s=0;n.each(i,function(e){if(void 0!==e&&null!==e){var i=o[e];i||(i=o[e]=t.measureText(e).width,r.push(e)),i>s&&(s=i)}});var l=r.length/2;if(l>i.length){for(var h=0;l>h;h++)delete o[r[h]];r.splice(0,l)}return s},n.drawRoundedRectangle=function(t,e,i,a,o,n){t.beginPath(),t.moveTo(e+n,i),t.lineTo(e+a-n,i),t.quadraticCurveTo(e+a,i,e+a,i+n),t.lineTo(e+a,i+o-n),t.quadraticCurveTo(e+a,i+o,e+a-n,i+o),t.lineTo(e+n,i+o),t.quadraticCurveTo(e,i+o,e,i+o-n),t.lineTo(e,i+n),t.quadraticCurveTo(e,i,e+n,i),t.closePath()},n.color=function(e){return a?a(e instanceof CanvasGradient?t.defaults.global.defaultColor:e):(console.log("Color.js not found!"),e)},n.addResizeListener=function(t,e){var i=document.createElement("iframe"),a="chartjs-hidden-iframe";i.classlist?i.classlist.add(a):i.setAttribute("class",a);var o=i.style;o.width="100%",o.display="block",o.border=0,o.height=0,o.margin=0,o.position="absolute",o.left=0,o.right=0,o.top=0,o.bottom=0,t.insertBefore(i,t.firstChild),(i.contentWindow||i).onresize=function(){e&&e()}},n.removeResizeListener=function(t){var e=t.querySelector(".chartjs-hidden-iframe");e&&e.parentNode.removeChild(e)},n.isArray=function(t){return Array.isArray?Array.isArray(t):"[object Array]"===Object.prototype.toString.call(t)},n.arrayEquals=function(t,e){var i,a,o,r;if(!t||!e||t.length!=e.length)return!1;for(i=0,a=t.length;a>i;++i)if(o=t[i],r=e[i],o instanceof Array&&r instanceof Array){if(!n.arrayEquals(o,r))return!1}else if(o!=r)return!1;return!0},n.pushAllIfDefined=function(t,e){"undefined"!=typeof t&&(n.isArray(t)?e.push.apply(e,t):e.push(t))},n.callCallback=function(t,e,i){t&&"function"==typeof t.call&&t.apply(i,e)},n.getHoverColor=function(t){return t instanceof CanvasPattern?t:n.color(t).saturate(.5).darken(.1).rgbString()}}},{"chartjs-color":3}],26:[function(t,e,i){"use strict";e.exports=function(){var t=function(e,i){this.config=i,e.length&&e[0].getContext&&(e=e[0]),e.getContext&&(e=e.getContext("2d")),this.ctx=e,this.canvas=e.canvas,this.width=e.canvas.width||parseInt(t.helpers.getStyle(e.canvas,"width"))||t.helpers.getMaximumWidth(e.canvas),this.height=e.canvas.height||parseInt(t.helpers.getStyle(e.canvas,"height"))||t.helpers.getMaximumHeight(e.canvas),this.aspectRatio=this.width/this.height,(isNaN(this.aspectRatio)||isFinite(this.aspectRatio)===!1)&&(this.aspectRatio=void 0!==i.aspectRatio?i.aspectRatio:2),this.originalCanvasStyleWidth=e.canvas.style.width,this.originalCanvasStyleHeight=e.canvas.style.height,t.helpers.retinaScale(this),i&&(this.controller=new t.Controller(this));var a=this;return t.helpers.addResizeListener(e.canvas.parentNode,function(){a.controller&&a.controller.config.options.responsive&&a.controller.resize()}),this.controller?this.controller:this};return t.defaults={global:{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"single",animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},legendCallback:function(t){var e=[];e.push('<ul class="'+t.id+'-legend">');for(var i=0;i<t.data.datasets.length;i++)e.push('<li><span style="background-color:'+t.data.datasets[i].backgroundColor+'"></span>'),t.data.datasets[i].label&&e.push(t.data.datasets[i].label),e.push("</li>");return e.push("</ul>"),e.join("")}}},t}},{}],27:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),t.boxes.push(e)},removeBox:function(t,e){t.boxes&&t.boxes.splice(t.boxes.indexOf(e),1)},update:function(t,i,a){function o(t){var e,i=t.isHorizontal();i?(e=t.update(t.options.fullWidth?p:k,y),S-=e.height):(e=t.update(x,v),k-=e.width),C.push({horizontal:i,minSize:e,box:t})}function n(t){var i=e.findNextWhere(C,function(e){return e.box===t});if(i)if(t.isHorizontal()){var a={left:w,right:M,top:0,bottom:0};t.update(t.options.fullWidth?p:k,m/2,a)}else t.update(i.minSize.width,S)}function r(t){var i=e.findNextWhere(C,function(e){return e.box===t}),a={left:0,right:0,top:D,bottom:A};i&&t.update(i.minSize.width,S,a)}function s(t){t.isHorizontal()?(t.left=t.options.fullWidth?l:w,t.right=t.options.fullWidth?i-l:w+k,t.top=P,t.bottom=P+t.height,P=t.bottom):(t.left=_,t.right=_+t.width,t.top=D,t.bottom=D+S,_=t.right)}if(t){var l=0,h=0,d=e.where(t.boxes,function(t){return"left"===t.options.position}),c=e.where(t.boxes,function(t){return"right"===t.options.position}),u=e.where(t.boxes,function(t){return"top"===t.options.position}),f=e.where(t.boxes,function(t){return"bottom"===t.options.position}),g=e.where(t.boxes,function(t){return"chartArea"===t.options.position});u.sort(function(t,e){return(e.options.fullWidth?1:0)-(t.options.fullWidth?1:0)}),f.sort(function(t,e){return(t.options.fullWidth?1:0)-(e.options.fullWidth?1:0)});var p=i-2*l,m=a-2*h,b=p/2,v=m/2,x=(i-b)/(d.length+c.length),y=(a-v)/(u.length+f.length),k=p,S=m,C=[];e.each(d.concat(c,u,f),o);var w=l,M=l,D=h,A=h;e.each(d.concat(c),n),e.each(d,function(t){w+=t.width}),e.each(c,function(t){M+=t.width}),e.each(u.concat(f),n),e.each(u,function(t){D+=t.height}),e.each(f,function(t){A+=t.height}),e.each(d.concat(c),r),w=l,M=l,D=h,A=h,e.each(d,function(t){w+=t.width}),e.each(c,function(t){M+=t.width}),e.each(u,function(t){D+=t.height}),e.each(f,function(t){A+=t.height});var I=a-D-A,F=i-w-M;(F!==k||I!==S)&&(e.each(d,function(t){t.height=I}),e.each(c,function(t){t.height=I}),e.each(u,function(t){t.options.fullWidth||(t.width=F)}),e.each(f,function(t){t.options.fullWidth||(t.width=F)}),S=I,k=F);var _=l,P=h;e.each(d.concat(u),s),_+=k,P+=S,e.each(c,s),e.each(f,s),t.chartArea={left:w,top:D,right:w+k,bottom:D+S},e.each(g,function(e){e.left=t.chartArea.left,e.top=t.chartArea.top,e.right=t.chartArea.right,e.bottom=t.chartArea.bottom,e.update(k,S)})}}}}},{}],28:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=e.noop;t.defaults.global.legend={display:!0,position:"top",fullWidth:!0,reverse:!1,onClick:function(t,e){var i=e.datasetIndex,a=this.chart,o=a.getDatasetMeta(i);o.hidden=null===o.hidden?!a.data.datasets[i].hidden:null,a.update()},labels:{boxWidth:40,padding:10,generateLabels:function(t){var i=t.data;return e.isArray(i.datasets)?i.datasets.map(function(e,i){return{text:e.label,fillStyle:e.backgroundColor,hidden:!t.isDatasetVisible(i),lineCap:e.borderCapStyle,lineDash:e.borderDash,lineDashOffset:e.borderDashOffset,lineJoin:e.borderJoinStyle,lineWidth:e.borderWidth,strokeStyle:e.borderColor,datasetIndex:i}},this):[]}}},t.Legend=t.Element.extend({initialize:function(t){e.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:i,update:function(t,e,i){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this.margins=i,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeBuildLabels(),this.buildLabels(),this.afterBuildLabels(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:i,beforeSetDimensions:i,setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0,this.minSize={width:0,height:0}},afterSetDimensions:i,beforeBuildLabels:i,buildLabels:function(){this.legendItems=this.options.labels.generateLabels.call(this,this.chart),this.options.reverse&&this.legendItems.reverse()},afterBuildLabels:i,beforeFit:i,fit:function(){var i=this.options,a=i.labels,o=i.display,n=this.ctx,r=t.defaults.global,s=e.getValueOrDefault,l=s(a.fontSize,r.defaultFontSize),h=s(a.fontStyle,r.defaultFontStyle),d=s(a.fontFamily,r.defaultFontFamily),c=e.fontString(l,h,d),u=this.legendHitBoxes=[],f=this.minSize,g=this.isHorizontal();if(g?(f.width=this.maxWidth,f.height=o?10:0):(f.width=o?10:0,f.height=this.maxHeight),o&&g){var p=this.lineWidths=[0],m=this.legendItems.length?l+a.padding:0;n.textAlign="left",n.textBaseline="top",n.font=c,e.each(this.legendItems,function(t,e){var i=a.boxWidth+l/2+n.measureText(t.text).width;p[p.length-1]+i+a.padding>=this.width&&(m+=l+a.padding,p[p.length]=this.left),u[e]={left:0,top:0,width:i,height:l},p[p.length-1]+=i+a.padding},this),f.height+=m}this.width=f.width,this.height=f.height},afterFit:i,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var i=this.options,a=i.labels,o=t.defaults.global,n=o.elements.line,r=this.width,s=this.lineWidths;if(i.display){var l=this.ctx,h={x:this.left+(r-s[0])/2,y:this.top+a.padding,line:0},d=e.getValueOrDefault,c=d(a.fontColor,o.defaultFontColor),u=d(a.fontSize,o.defaultFontSize),f=d(a.fontStyle,o.defaultFontStyle),g=d(a.fontFamily,o.defaultFontFamily),p=e.fontString(u,f,g);if(this.isHorizontal()){l.textAlign="left",l.textBaseline="top",l.lineWidth=.5,l.strokeStyle=c,l.fillStyle=c,l.font=p;var m=a.boxWidth,b=this.legendHitBoxes;e.each(this.legendItems,function(t,e){var i=l.measureText(t.text).width,c=m+u/2+i,f=h.x,g=h.y;f+c>=r&&(g=h.y+=u+a.padding,h.line++,f=h.x=this.left+(r-s[h.line])/2),l.save(),l.fillStyle=d(t.fillStyle,o.defaultColor),l.lineCap=d(t.lineCap,n.borderCapStyle),l.lineDashOffset=d(t.lineDashOffset,n.borderDashOffset),l.lineJoin=d(t.lineJoin,n.borderJoinStyle),l.lineWidth=d(t.lineWidth,n.borderWidth),l.strokeStyle=d(t.strokeStyle,o.defaultColor),l.setLineDash&&l.setLineDash(d(t.lineDash,n.borderDash)),l.strokeRect(f,g,m,u),l.fillRect(f,g,m,u),l.restore(),b[e].left=f,b[e].top=g,l.fillText(t.text,m+u/2+f,g),t.hidden&&(l.beginPath(),l.lineWidth=2,l.moveTo(m+u/2+f,g+u/2),l.lineTo(m+u/2+f+i,g+u/2),l.stroke()),h.x+=c+a.padding},this)}}},handleEvent:function(t){var i=e.getRelativePosition(t,this.chart.chart),a=i.x,o=i.y,n=this.options;if(a>=this.left&&a<=this.right&&o>=this.top&&o<=this.bottom)for(var r=this.legendHitBoxes,s=0;s<r.length;++s){var l=r[s];if(a>=l.left&&a<=l.left+l.width&&o>=l.top&&o<=l.top+l.height){n.onClick&&n.onClick.call(this,t,this.legendItems[s]);break}}}})}},{}],29:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.plugins=[],t.pluginService={register:function(e){var i=t.plugins;-1===i.indexOf(e)&&i.push(e)},remove:function(e){var i=t.plugins,a=i.indexOf(e);-1!==a&&i.splice(a,1)},notifyPlugins:function(i,a,o){e.each(t.plugins,function(t){t[i]&&"function"==typeof t[i]&&t[i].apply(o,a)},o)}};var i=e.noop;t.PluginBase=t.Element.extend({beforeInit:i,afterInit:i,beforeUpdate:i,afterUpdate:i,beforeDraw:i,afterDraw:i,destroy:i})}},{}],30:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.scale={display:!0,position:"left",gridLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickMarkLength:10,zeroLineWidth:1,zeroLineColor:"rgba(0,0,0,0.25)",offsetGridLines:!1},scaleLabel:{labelString:"",display:!1},ticks:{beginAtZero:!1,minRotation:0,maxRotation:50,mirror:!1,padding:10,reverse:!1,display:!0,autoSkip:!0,autoSkipPadding:0,labelOffset:0,callback:function(t){return""+t}}},t.Scale=t.Element.extend({beforeUpdate:function(){e.callCallback(this.options.beforeUpdate,[this])},update:function(t,i,a){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=i,this.margins=e.extend({left:0,right:0,top:0,bottom:0},a),this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this.beforeBuildTicks(),this.buildTicks(),this.afterBuildTicks(),this.beforeTickToLabelConversion(),this.convertTicksToLabels(),this.afterTickToLabelConversion(),this.beforeCalculateTickRotation(),this.calculateTickRotation(),this.afterCalculateTickRotation(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:function(){e.callCallback(this.options.afterUpdate,[this])},beforeSetDimensions:function(){e.callCallback(this.options.beforeSetDimensions,[this])},setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0},afterSetDimensions:function(){e.callCallback(this.options.afterSetDimensions,[this])},beforeDataLimits:function(){e.callCallback(this.options.beforeDataLimits,[this])},determineDataLimits:e.noop,afterDataLimits:function(){e.callCallback(this.options.afterDataLimits,[this])},beforeBuildTicks:function(){e.callCallback(this.options.beforeBuildTicks,[this])},buildTicks:e.noop,afterBuildTicks:function(){e.callCallback(this.options.afterBuildTicks,[this])},beforeTickToLabelConversion:function(){e.callCallback(this.options.beforeTickToLabelConversion,[this])},convertTicksToLabels:function(){this.ticks=this.ticks.map(function(t,e,i){return this.options.ticks.userCallback?this.options.ticks.userCallback(t,e,i):this.options.ticks.callback(t,e,i)},this)},afterTickToLabelConversion:function(){e.callCallback(this.options.afterTickToLabelConversion,[this])},beforeCalculateTickRotation:function(){e.callCallback(this.options.beforeCalculateTickRotation,[this])},calculateTickRotation:function(){var i=this.ctx,a=t.defaults.global,o=this.options.ticks,n=e.getValueOrDefault(o.fontSize,a.defaultFontSize),r=e.getValueOrDefault(o.fontStyle,a.defaultFontStyle),s=e.getValueOrDefault(o.fontFamily,a.defaultFontFamily),l=e.fontString(n,r,s);i.font=l;var h,d=i.measureText(this.ticks[0]).width,c=i.measureText(this.ticks[this.ticks.length-1]).width;if(this.labelRotation=o.minRotation||0,this.paddingRight=0,this.paddingLeft=0,this.options.display&&this.isHorizontal()){this.paddingRight=c/2+3,this.paddingLeft=d/2+3,this.longestTextCache||(this.longestTextCache={});for(var u,f,g=e.longestText(i,l,this.ticks,this.longestTextCache),p=g,m=this.getPixelForTick(1)-this.getPixelForTick(0)-6;p>m&&this.labelRotation<o.maxRotation;){
+if(u=Math.cos(e.toRadians(this.labelRotation)),f=Math.sin(e.toRadians(this.labelRotation)),h=u*d,h+n/2>this.yLabelWidth&&(this.paddingLeft=h+n/2),this.paddingRight=n/2,f*g>this.maxHeight){this.labelRotation--;break}this.labelRotation++,p=u*g}}this.margins&&(this.paddingLeft=Math.max(this.paddingLeft-this.margins.left,0),this.paddingRight=Math.max(this.paddingRight-this.margins.right,0))},afterCalculateTickRotation:function(){e.callCallback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){e.callCallback(this.options.beforeFit,[this])},fit:function(){var i=this.minSize={width:0,height:0},a=this.options,o=t.defaults.global,n=a.ticks,r=a.scaleLabel,s=a.display,l=this.isHorizontal(),h=e.getValueOrDefault(n.fontSize,o.defaultFontSize),d=e.getValueOrDefault(n.fontStyle,o.defaultFontStyle),c=e.getValueOrDefault(n.fontFamily,o.defaultFontFamily),u=e.fontString(h,d,c),f=e.getValueOrDefault(r.fontSize,o.defaultFontSize),g=e.getValueOrDefault(r.fontStyle,o.defaultFontStyle),p=e.getValueOrDefault(r.fontFamily,o.defaultFontFamily),m=(e.fontString(f,g,p),a.gridLines.tickMarkLength);if(l?i.width=this.isFullWidth()?this.maxWidth-this.margins.left-this.margins.right:this.maxWidth:i.width=s?m:0,l?i.height=s?m:0:i.height=this.maxHeight,r.display&&s&&(l?i.height+=1.5*f:i.width+=1.5*f),n.display&&s){this.longestTextCache||(this.longestTextCache={});var b=e.longestText(this.ctx,u,this.ticks,this.longestTextCache);if(l){this.longestLabelWidth=b;var v=Math.sin(e.toRadians(this.labelRotation))*this.longestLabelWidth+1.5*h;i.height=Math.min(this.maxHeight,i.height+v),this.ctx.font=u;var x=this.ctx.measureText(this.ticks[0]).width,y=this.ctx.measureText(this.ticks[this.ticks.length-1]).width,k=Math.cos(e.toRadians(this.labelRotation)),S=Math.sin(e.toRadians(this.labelRotation));this.paddingLeft=0!==this.labelRotation?k*x+3:x/2+3,this.paddingRight=0!==this.labelRotation?S*(h/2)+3:y/2+3}else{var C=this.maxWidth-i.width,w=n.mirror;w?b=0:b+=this.options.ticks.padding,C>b?i.width+=b:i.width=this.maxWidth,this.paddingTop=h/2,this.paddingBottom=h/2}}this.margins&&(this.paddingLeft=Math.max(this.paddingLeft-this.margins.left,0),this.paddingTop=Math.max(this.paddingTop-this.margins.top,0),this.paddingRight=Math.max(this.paddingRight-this.margins.right,0),this.paddingBottom=Math.max(this.paddingBottom-this.margins.bottom,0)),this.width=i.width,this.height=i.height},afterFit:function(){e.callCallback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function i(t){return null===t||"undefined"==typeof t?NaN:"number"==typeof t&&isNaN(t)?NaN:"object"==typeof t?t instanceof Date||t.isValid?t:i(this.isHorizontal()?t.x:t.y):t},getLabelForIndex:e.noop,getPixelForValue:e.noop,getValueForPixel:e.noop,getPixelForTick:function(t,e){if(this.isHorizontal()){var i=this.width-(this.paddingLeft+this.paddingRight),a=i/Math.max(this.ticks.length-(this.options.gridLines.offsetGridLines?0:1),1),o=a*t+this.paddingLeft;e&&(o+=a/2);var n=this.left+Math.round(o);return n+=this.isFullWidth()?this.margins.left:0}var r=this.height-(this.paddingTop+this.paddingBottom);return this.top+t*(r/(this.ticks.length-1))},getPixelForDecimal:function(t){if(this.isHorizontal()){var e=this.width-(this.paddingLeft+this.paddingRight),i=e*t+this.paddingLeft,a=this.left+Math.round(i);return a+=this.isFullWidth()?this.margins.left:0}return this.top+t*this.height},getBasePixel:function(){var t=this,e=t.min,i=t.max;return t.getPixelForValue(t.beginAtZero?0:0>e&&0>i?i:e>0&&i>0?e:0)},draw:function(i){var a=this.options;if(a.display){var o,n,r,s,l,h=this.ctx,d=t.defaults.global,c=a.ticks,u=a.gridLines,f=a.scaleLabel,g=0!==this.labelRotation,p=c.autoSkip;c.maxTicksLimit&&(l=c.maxTicksLimit);var m=e.getValueOrDefault(c.fontColor,d.defaultFontColor),b=e.getValueOrDefault(c.fontSize,d.defaultFontSize),v=e.getValueOrDefault(c.fontStyle,d.defaultFontStyle),x=e.getValueOrDefault(c.fontFamily,d.defaultFontFamily),y=e.fontString(b,v,x),k=u.tickMarkLength,S=e.getValueOrDefault(f.fontColor,d.defaultFontColor),C=e.getValueOrDefault(f.fontSize,d.defaultFontSize),w=e.getValueOrDefault(f.fontStyle,d.defaultFontStyle),M=e.getValueOrDefault(f.fontFamily,d.defaultFontFamily),D=e.fontString(C,w,M),A=e.toRadians(this.labelRotation),I=Math.cos(A),F=(Math.sin(A),this.longestLabelWidth*I);if(h.fillStyle=m,this.isHorizontal()){o=!0;var _="bottom"===a.position?this.top:this.bottom-k,P="bottom"===a.position?this.top+k:this.bottom;if(n=!1,g&&(F/=2),(F+c.autoSkipPadding)*this.ticks.length>this.width-(this.paddingLeft+this.paddingRight)&&(n=1+Math.floor((F+c.autoSkipPadding)*this.ticks.length/(this.width-(this.paddingLeft+this.paddingRight)))),l&&this.ticks.length>l)for(;!n||this.ticks.length/(n||1)>l;)n||(n=1),n+=1;p||(n=!1),e.each(this.ticks,function(t,r){var s=this.ticks.length===r+1,l=n>1&&r%n>0||r%n===0&&r+n>=this.ticks.length;if((!l||s)&&void 0!==t&&null!==t){var d=this.getPixelForTick(r),f=this.getPixelForTick(r,u.offsetGridLines);u.display&&(r===("undefined"!=typeof this.zeroLineIndex?this.zeroLineIndex:0)?(h.lineWidth=u.zeroLineWidth,h.strokeStyle=u.zeroLineColor,o=!0):o&&(h.lineWidth=u.lineWidth,h.strokeStyle=u.color,o=!1),d+=e.aliasPixel(h.lineWidth),h.beginPath(),u.drawTicks&&(h.moveTo(d,_),h.lineTo(d,P)),u.drawOnChartArea&&(h.moveTo(d,i.top),h.lineTo(d,i.bottom)),h.stroke()),c.display&&(h.save(),h.translate(f+c.labelOffset,g?this.top+12:"top"===a.position?this.bottom-k:this.top+k),h.rotate(-1*A),h.font=y,h.textAlign=g?"right":"center",h.textBaseline=g?"middle":"top"===a.position?"bottom":"top",h.fillText(t,0,0),h.restore())}},this),f.display&&(h.textAlign="center",h.textBaseline="middle",h.fillStyle=S,h.font=D,r=this.left+(this.right-this.left)/2,s="bottom"===a.position?this.bottom-C/2:this.top+C/2,h.fillText(f.labelString,r,s))}else{o=!0;var T="right"===a.position?this.left:this.right-5,V="right"===a.position?this.left+5:this.right;if(e.each(this.ticks,function(t,n){if(void 0!==t&&null!==t){var r=this.getPixelForTick(n);if(u.display&&(n===("undefined"!=typeof this.zeroLineIndex?this.zeroLineIndex:0)?(h.lineWidth=u.zeroLineWidth,h.strokeStyle=u.zeroLineColor,o=!0):o&&(h.lineWidth=u.lineWidth,h.strokeStyle=u.color,o=!1),r+=e.aliasPixel(h.lineWidth),h.beginPath(),u.drawTicks&&(h.moveTo(T,r),h.lineTo(V,r)),u.drawOnChartArea&&(h.moveTo(i.left,r),h.lineTo(i.right,r)),h.stroke()),c.display){var s,l=this.getPixelForTick(n,u.offsetGridLines);h.save(),"left"===a.position?c.mirror?(s=this.right+c.padding,h.textAlign="left"):(s=this.right-c.padding,h.textAlign="right"):c.mirror?(s=this.left-c.padding,h.textAlign="right"):(s=this.left+c.padding,h.textAlign="left"),h.translate(s,l+c.labelOffset),h.rotate(-1*A),h.font=y,h.textBaseline="middle",h.fillText(t,0,0),h.restore()}}},this),f.display){r="left"===a.position?this.left+C/2:this.right-C/2,s=this.top+(this.bottom-this.top)/2;var R="left"===a.position?-.5*Math.PI:.5*Math.PI;h.save(),h.translate(r,s),h.rotate(R),h.textAlign="center",h.fillStyle=S,h.font=D,h.textBaseline="middle",h.fillText(f.labelString,0,0),h.restore()}}if(u.drawBorder){h.lineWidth=u.lineWidth,h.strokeStyle=u.color;var O=this.left,W=this.right,L=this.top,B=this.bottom,z=e.aliasPixel(h.lineWidth);this.isHorizontal()?(L=B="top"===a.position?this.bottom:this.top,L+=z,B+=z):(O=W="left"===a.position?this.right:this.left,O+=z,W+=z),h.beginPath(),h.moveTo(O,L),h.lineTo(W,B),h.stroke()}}}})}},{}],31:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.scaleService={constructors:{},defaults:{},registerScaleType:function(t,i,a){this.constructors[t]=i,this.defaults[t]=e.clone(a)},getScaleConstructor:function(t){return this.constructors.hasOwnProperty(t)?this.constructors[t]:void 0},getScaleDefaults:function(i){return this.defaults.hasOwnProperty(i)?e.scaleMerge(t.defaults.scale,this.defaults[i]):{}},updateScaleDefaults:function(t,i){var a=this.defaults;a.hasOwnProperty(t)&&(a[t]=e.extend(a[t],i))},addScalesToLayout:function(i){e.each(i.scales,function(e){t.layoutService.addBox(i,e)})}}}},{}],32:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers;t.defaults.global.title={display:!1,position:"top",fullWidth:!0,fontStyle:"bold",padding:10,text:""};var i=e.noop;t.Title=t.Element.extend({initialize:function(i){e.extend(this,i),this.options=e.configMerge(t.defaults.global.title,i.options),this.legendHitBoxes=[]},beforeUpdate:i,update:function(t,e,i){return this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this.margins=i,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this.beforeBuildLabels(),this.buildLabels(),this.afterBuildLabels(),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate(),this.minSize},afterUpdate:i,beforeSetDimensions:i,setDimensions:function(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0,this.minSize={width:0,height:0}},afterSetDimensions:i,beforeBuildLabels:i,buildLabels:i,afterBuildLabels:i,beforeFit:i,fit:function(){var i=this,a=(i.ctx,e.getValueOrDefault),o=i.options,n=t.defaults.global,r=o.display,s=a(o.fontSize,n.defaultFontSize),l=i.minSize;i.isHorizontal()?(l.width=i.maxWidth,l.height=r?s+2*o.padding:0):(l.width=r?s+2*o.padding:0,l.height=i.maxHeight),i.width=l.width,i.height=l.height},afterFit:i,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var i=this,a=i.ctx,o=e.getValueOrDefault,n=i.options,r=t.defaults.global;if(n.display){var s,l,h=o(n.fontSize,r.defaultFontSize),d=o(n.fontStyle,r.defaultFontStyle),c=o(n.fontFamily,r.defaultFontFamily),u=e.fontString(h,d,c),f=0,g=i.top,p=i.left,m=i.bottom,b=i.right;a.fillStyle=o(n.fontColor,r.defaultFontColor),a.font=u,i.isHorizontal()?(s=p+(b-p)/2,l=g+(m-g)/2):(s="left"===n.position?p+h/2:b-h/2,l=g+(m-g)/2,f=Math.PI*("left"===n.position?-.5:.5)),a.save(),a.translate(s,l),a.rotate(f),a.textAlign="center",a.textBaseline="middle",a.fillText(n.text,0,0),a.restore()}}})}},{}],33:[function(t,e,i){"use strict";e.exports=function(t){function e(t,e){return e&&(i.isArray(e)?t=t.concat(e):t.push(e)),t}var i=t.helpers;t.defaults.global.tooltips={enabled:!0,custom:null,mode:"single",backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleColor:"#fff",titleAlign:"left",bodySpacing:2,bodyColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,yAlign:"center",xAlign:"center",caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",callbacks:{beforeTitle:i.noop,title:function(t,e){var i="";return t.length>0&&(t[0].xLabel?i=t[0].xLabel:e.labels.length>0&&t[0].index<e.labels.length&&(i=e.labels[t[0].index])),i},afterTitle:i.noop,beforeBody:i.noop,beforeLabel:i.noop,label:function(t,e){var i=e.datasets[t.datasetIndex].label||"";return i+": "+t.yLabel},afterLabel:i.noop,afterBody:i.noop,beforeFooter:i.noop,footer:i.noop,afterFooter:i.noop}},t.Tooltip=t.Element.extend({initialize:function(){var e=t.defaults.global,a=this._options,o=a.tooltips;i.extend(this,{_model:{xPadding:o.xPadding,yPadding:o.yPadding,xAlign:o.yAlign,yAlign:o.xAlign,bodyColor:o.bodyColor,_bodyFontFamily:i.getValueOrDefault(o.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:i.getValueOrDefault(o.bodyFontStyle,e.defaultFontStyle),_bodyAlign:o.bodyAlign,bodyFontSize:i.getValueOrDefault(o.bodyFontSize,e.defaultFontSize),bodySpacing:o.bodySpacing,titleColor:o.titleColor,_titleFontFamily:i.getValueOrDefault(o.titleFontFamily,e.defaultFontFamily),_titleFontStyle:i.getValueOrDefault(o.titleFontStyle,e.defaultFontStyle),titleFontSize:i.getValueOrDefault(o.titleFontSize,e.defaultFontSize),_titleAlign:o.titleAlign,titleSpacing:o.titleSpacing,titleMarginBottom:o.titleMarginBottom,footerColor:o.footerColor,_footerFontFamily:i.getValueOrDefault(o.footerFontFamily,e.defaultFontFamily),_footerFontStyle:i.getValueOrDefault(o.footerFontStyle,e.defaultFontStyle),footerFontSize:i.getValueOrDefault(o.footerFontSize,e.defaultFontSize),_footerAlign:o.footerAlign,footerSpacing:o.footerSpacing,footerMarginTop:o.footerMarginTop,caretSize:o.caretSize,cornerRadius:o.cornerRadius,backgroundColor:o.backgroundColor,opacity:0,legendColorBackground:o.multiKeyBackground}})},getTitle:function(){var t=this._options.tooltips.callbacks.beforeTitle.apply(this,arguments),i=this._options.tooltips.callbacks.title.apply(this,arguments),a=this._options.tooltips.callbacks.afterTitle.apply(this,arguments),o=[];return o=e(o,t),o=e(o,i),o=e(o,a)},getBeforeBody:function(){var t=this._options.tooltips.callbacks.beforeBody.apply(this,arguments);return i.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var a=[];return i.each(t,function(t){i.pushAllIfDefined(this._options.tooltips.callbacks.beforeLabel.call(this,t,e),a),i.pushAllIfDefined(this._options.tooltips.callbacks.label.call(this,t,e),a),i.pushAllIfDefined(this._options.tooltips.callbacks.afterLabel.call(this,t,e),a)},this),a},getAfterBody:function(){var t=this._options.tooltips.callbacks.afterBody.apply(this,arguments);return i.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this._options.tooltips.callbacks.beforeFooter.apply(this,arguments),i=this._options.tooltips.callbacks.footer.apply(this,arguments),a=this._options.tooltips.callbacks.afterFooter.apply(this,arguments),o=[];return o=e(o,t),o=e(o,i),o=e(o,a)},getAveragePosition:function(t){if(!t.length)return!1;var e=[],a=[];i.each(t,function(t){if(t&&t.hasValue()){var i=t.tooltipPosition();e.push(i.x),a.push(i.y)}});for(var o=0,n=0,r=0;r<e.length;r++)o+=e[r],n+=a[r];return{x:Math.round(o/e.length),y:Math.round(n/e.length)}},update:function(t){if(this._active.length){this._model.opacity=1;var e,a=this._active[0],o=[],n=[];if("single"===this._options.tooltips.mode){var r=a._yScale||a._scale;n.push({xLabel:a._xScale?a._xScale.getLabelForIndex(a._index,a._datasetIndex):"",yLabel:r?r.getLabelForIndex(a._index,a._datasetIndex):"",index:a._index,datasetIndex:a._datasetIndex}),e=this.getAveragePosition(this._active)}else i.each(this._data.datasets,function(t,e){if(this._chartInstance.isDatasetVisible(e)){var i=this._chartInstance.getDatasetMeta(e),o=i.data[a._index];if(o){var r=a._yScale||a._scale;n.push({xLabel:o._xScale?o._xScale.getLabelForIndex(o._index,o._datasetIndex):"",yLabel:r?r.getLabelForIndex(o._index,o._datasetIndex):"",index:a._index,datasetIndex:e})}}},this),i.each(this._active,function(t){t&&o.push({borderColor:t._view.borderColor,backgroundColor:t._view.backgroundColor})},null),e=this.getAveragePosition(this._active);i.extend(this._model,{title:this.getTitle(n,this._data),beforeBody:this.getBeforeBody(n,this._data),body:this.getBody(n,this._data),afterBody:this.getAfterBody(n,this._data),footer:this.getFooter(n,this._data)}),i.extend(this._model,{x:Math.round(e.x),y:Math.round(e.y),caretPadding:i.getValueOrDefault(e.padding,2),labelColors:o});var s=this.getTooltipSize(this._model);this.determineAlignment(s),i.extend(this._model,this.getBackgroundPoint(this._model,s))}else this._model.opacity=0;return t&&this._options.tooltips.custom&&this._options.tooltips.custom.call(this,this._model),this},getTooltipSize:function(t){var e=this._chart.ctx,a={height:2*t.yPadding,width:0},o=t.body.length+t.beforeBody.length+t.afterBody.length;return a.height+=t.title.length*t.titleFontSize,a.height+=(t.title.length-1)*t.titleSpacing,a.height+=t.title.length?t.titleMarginBottom:0,a.height+=o*t.bodyFontSize,a.height+=o?(o-1)*t.bodySpacing:0,a.height+=t.footer.length?t.footerMarginTop:0,a.height+=t.footer.length*t.footerFontSize,a.height+=t.footer.length?(t.footer.length-1)*t.footerSpacing:0,e.font=i.fontString(t.titleFontSize,t._titleFontStyle,t._titleFontFamily),i.each(t.title,function(t){a.width=Math.max(a.width,e.measureText(t).width)}),e.font=i.fontString(t.bodyFontSize,t._bodyFontStyle,t._bodyFontFamily),i.each(t.beforeBody.concat(t.afterBody),function(t){a.width=Math.max(a.width,e.measureText(t).width)}),i.each(t.body,function(i){a.width=Math.max(a.width,e.measureText(i).width+("single"!==this._options.tooltips.mode?t.bodyFontSize+2:0))},this),e.font=i.fontString(t.footerFontSize,t._footerFontStyle,t._footerFontFamily),i.each(t.footer,function(t){a.width=Math.max(a.width,e.measureText(t).width)}),a.width+=2*t.xPadding,a},determineAlignment:function(t){this._model.y<t.height?this._model.yAlign="top":this._model.y>this._chart.height-t.height&&(this._model.yAlign="bottom");var e,i,a,o,n,r=this,s=(this._chartInstance.chartArea.left+this._chartInstance.chartArea.right)/2,l=(this._chartInstance.chartArea.top+this._chartInstance.chartArea.bottom)/2;"center"===this._model.yAlign?(e=function(t){return s>=t},i=function(t){return t>s}):(e=function(e){return e<=t.width/2},i=function(e){return e>=r._chart.width-t.width/2}),a=function(e){return e+t.width>r._chart.width},o=function(e){return e-t.width<0},n=function(t){return l>=t?"top":"bottom"},e(this._model.x)?(this._model.xAlign="left",a(this._model.x)&&(this._model.xAlign="center",this._model.yAlign=n(this._model.y))):i(this._model.x)&&(this._model.xAlign="right",o(this._model.x)&&(this._model.xAlign="center",this._model.yAlign=n(this._model.y)))},getBackgroundPoint:function(t,e){var i={x:t.x,y:t.y};return"right"===t.xAlign?i.x-=e.width:"center"===t.xAlign&&(i.x-=e.width/2),"top"===t.yAlign?i.y+=t.caretPadding+t.caretSize:"bottom"===t.yAlign?i.y-=e.height+t.caretPadding+t.caretSize:i.y-=e.height/2,"center"===t.yAlign?"left"===t.xAlign?i.x+=t.caretPadding+t.caretSize:"right"===t.xAlign&&(i.x-=t.caretPadding+t.caretSize):"left"===t.xAlign?i.x-=t.cornerRadius+t.caretPadding:"right"===t.xAlign&&(i.x+=t.cornerRadius+t.caretPadding),i},drawCaret:function(t,e,a,o){var n,r,s,l,h,d,c=this._view,u=this._chart.ctx;"center"===c.yAlign?("left"===c.xAlign?(n=t.x,r=n-c.caretSize,s=n):(n=t.x+e.width,r=n+c.caretSize,s=n),h=t.y+e.height/2,l=h-c.caretSize,d=h+c.caretSize):("left"===c.xAlign?(n=t.x+c.cornerRadius,r=n+c.caretSize,s=r+c.caretSize):"right"===c.xAlign?(n=t.x+e.width-c.cornerRadius,r=n-c.caretSize,s=r-c.caretSize):(r=t.x+e.width/2,n=r-c.caretSize,s=r+c.caretSize),"top"===c.yAlign?(l=t.y,h=l-c.caretSize,d=l):(l=t.y+e.height,h=l+c.caretSize,d=l));var f=i.color(c.backgroundColor);u.fillStyle=f.alpha(a*f.alpha()).rgbString(),u.beginPath(),u.moveTo(n,l),u.lineTo(r,h),u.lineTo(s,d),u.closePath(),u.fill()},drawTitle:function(t,e,a,o){if(e.title.length){a.textAlign=e._titleAlign,a.textBaseline="top";var n=i.color(e.titleColor);a.fillStyle=n.alpha(o*n.alpha()).rgbString(),a.font=i.fontString(e.titleFontSize,e._titleFontStyle,e._titleFontFamily),i.each(e.title,function(i,o){a.fillText(i,t.x,t.y),t.y+=e.titleFontSize+e.titleSpacing,o+1===e.title.length&&(t.y+=e.titleMarginBottom-e.titleSpacing)})}},drawBody:function(t,e,a,o){a.textAlign=e._bodyAlign,a.textBaseline="top";var n=i.color(e.bodyColor);a.fillStyle=n.alpha(o*n.alpha()).rgbString(),a.font=i.fontString(e.bodyFontSize,e._bodyFontStyle,e._bodyFontFamily),i.each(e.beforeBody,function(i){a.fillText(i,t.x,t.y),t.y+=e.bodyFontSize+e.bodySpacing}),i.each(e.body,function(n,r){"single"!==this._options.tooltips.mode&&(a.fillStyle=i.color(e.legendColorBackground).alpha(o).rgbaString(),a.fillRect(t.x,t.y,e.bodyFontSize,e.bodyFontSize),a.strokeStyle=i.color(e.labelColors[r].borderColor).alpha(o).rgbaString(),a.strokeRect(t.x,t.y,e.bodyFontSize,e.bodyFontSize),a.fillStyle=i.color(e.labelColors[r].backgroundColor).alpha(o).rgbaString(),a.fillRect(t.x+1,t.y+1,e.bodyFontSize-2,e.bodyFontSize-2),a.fillStyle=i.color(e.bodyColor).alpha(o).rgbaString()),a.fillText(n,t.x+("single"!==this._options.tooltips.mode?e.bodyFontSize+2:0),t.y),t.y+=e.bodyFontSize+e.bodySpacing},this),i.each(e.afterBody,function(i){a.fillText(i,t.x,t.y),t.y+=e.bodyFontSize}),t.y-=e.bodySpacing},drawFooter:function(t,e,a,o){if(e.footer.length){t.y+=e.footerMarginTop,a.textAlign=e._footerAlign,a.textBaseline="top";var n=i.color(e.footerColor);a.fillStyle=n.alpha(o*n.alpha()).rgbString(),a.font=i.fontString(e.footerFontSize,e._footerFontStyle,e._footerFontFamily),i.each(e.footer,function(i){a.fillText(i,t.x,t.y),t.y+=e.footerFontSize+e.footerSpacing})}},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var a=e.caretPadding,o=this.getTooltipSize(e),n={x:e.x,y:e.y},r=Math.abs(e.opacity<.001)?0:e.opacity;if(this._options.tooltips.enabled){var s=i.color(e.backgroundColor);t.fillStyle=s.alpha(r*s.alpha()).rgbString(),i.drawRoundedRectangle(t,n.x,n.y,o.width,o.height,e.cornerRadius),t.fill(),this.drawCaret(n,o,r,a),n.x+=e.xPadding,n.y+=e.yPadding,this.drawTitle(n,e,t,r),this.drawBody(n,e,t,r),this.drawFooter(n,e,t,r)}}}})}},{}],34:[function(t,e,i){"use strict";e.exports=function(t,e){var i=t.helpers,a=t.defaults.global;a.elements.arc={backgroundColor:a.defaultColor,borderColor:"#fff",borderWidth:2},t.elements.Arc=t.Element.extend({inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hoverRadius,2):!1},inRange:function(t,e){var a=this._view;if(a){for(var o=i.getAngleFromPoint(a,{x:t,y:e}),n=o.angle,r=o.distance,s=a.startAngle,l=a.endAngle;s>l;)l+=2*Math.PI;for(;n>l;)n-=2*Math.PI;for(;s>n;)n+=2*Math.PI;var h=n>=s&&l>=n,d=r>=a.innerRadius&&r<=a.outerRadius;return h&&d}return!1},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,i=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*i,y:t.y+Math.sin(e)*i}},draw:function(){var t=this._chart.ctx,e=this._view,i=e.startAngle,a=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,i,a),t.arc(e.x,e.y,e.innerRadius,a,i,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})}},{}],35:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global;t.defaults.global.elements.line={tension:.4,backgroundColor:i.defaultColor,borderWidth:3,borderColor:i.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",fill:!0},t.elements.Line=t.Element.extend({lineToNextPoint:function(t,e,i,a,o){var n=this._chart.ctx;e._view.skip?a.call(this,t,e,i):t._view.skip?o.call(this,t,e,i):0===e._view.tension?n.lineTo(e._view.x,e._view.y):n.bezierCurveTo(t._view.controlPointNextX,t._view.controlPointNextY,e._view.controlPointPreviousX,e._view.controlPointPreviousY,e._view.x,e._view.y)},draw:function(){function t(t){r._view.skip||s._view.skip?t&&n.lineTo(a._view.scaleZero.x,a._view.scaleZero.y):n.bezierCurveTo(s._view.controlPointNextX,s._view.controlPointNextY,r._view.controlPointPreviousX,r._view.controlPointPreviousY,r._view.x,r._view.y)}var a=this,o=this._view,n=this._chart.ctx,r=this._children[0],s=this._children[this._children.length-1];n.save(),this._children.length>0&&o.fill&&(n.beginPath(),e.each(this._children,function(t,i){var a=e.previousItem(this._children,i),r=e.nextItem(this._children,i);0===i?(this._loop?n.moveTo(o.scaleZero.x,o.scaleZero.y):n.moveTo(t._view.x,o.scaleZero),t._view.skip?this._loop||n.moveTo(r._view.x,this._view.scaleZero):n.lineTo(t._view.x,t._view.y)):this.lineToNextPoint(a,t,r,function(t,e,i){this._loop?n.lineTo(this._view.scaleZero.x,this._view.scaleZero.y):(n.lineTo(t._view.x,this._view.scaleZero),n.moveTo(i._view.x,this._view.scaleZero))},function(t,e){n.lineTo(e._view.x,e._view.y)})},this),this._loop?t(!0):(n.lineTo(this._children[this._children.length-1]._view.x,o.scaleZero),n.lineTo(this._children[0]._view.x,o.scaleZero)),n.fillStyle=o.backgroundColor||i.defaultColor,n.closePath(),n.fill());var l=i.elements.line;n.lineCap=o.borderCapStyle||l.borderCapStyle,n.setLineDash&&n.setLineDash(o.borderDash||l.borderDash),n.lineDashOffset=o.borderDashOffset||l.borderDashOffset,n.lineJoin=o.borderJoinStyle||l.borderJoinStyle,n.lineWidth=o.borderWidth||l.borderWidth,n.strokeStyle=o.borderColor||i.defaultColor,n.beginPath(),e.each(this._children,function(t,i){var a=e.previousItem(this._children,i),o=e.nextItem(this._children,i);0===i?n.moveTo(t._view.x,t._view.y):this.lineToNextPoint(a,t,o,function(t,e,i){n.moveTo(i._view.x,i._view.y)},function(t,e){n.moveTo(e._view.x,e._view.y)})},this),this._loop&&this._children.length>0&&t(),n.stroke(),n.restore()}})}},{}],36:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global,a=i.defaultColor;i.elements.point={radius:3,pointStyle:"circle",backgroundColor:a,borderWidth:1,borderColor:a,hitRadius:1,hoverRadius:4,hoverBorderWidth:1},t.elements.Point=t.Element.extend({inRange:function(t,e){var i=this._view;return i?Math.pow(t-i.x,2)+Math.pow(e-i.y,2)<Math.pow(i.hitRadius+i.radius,2):!1},inLabelRange:function(t){var e=this._view;return e?Math.pow(t-e.x,2)<Math.pow(e.radius+e.hitRadius,2):!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y,padding:t.radius+t.borderWidth}},draw:function(){var t,o,n,r,s,l,h=this._view,d=this._chart.ctx,c=h.pointStyle,u=h.radius,f=h.x,g=h.y;if(!h.skip){if("object"==typeof c&&(t=c.toString(),"[object HTMLImageElement]"===t||"[object HTMLCanvasElement]"===t))return void d.drawImage(c,f-c.width/2,g-c.height/2);if(!(isNaN(u)||0>=u)){switch(d.strokeStyle=h.borderColor||a,d.lineWidth=e.getValueOrDefault(h.borderWidth,i.elements.point.borderWidth),d.fillStyle=h.backgroundColor||a,c){default:d.beginPath(),d.arc(f,g,u,0,2*Math.PI),d.closePath(),d.fill();break;case"triangle":d.beginPath(),o=3*u/Math.sqrt(3),s=o*Math.sqrt(3)/2,d.moveTo(f-o/2,g+s/3),d.lineTo(f+o/2,g+s/3),d.lineTo(f,g-2*s/3),d.closePath(),d.fill();break;case"rect":l=1/Math.SQRT2*u,d.fillRect(f-l,g-l,2*l,2*l),d.strokeRect(f-l,g-l,2*l,2*l);break;case"rectRot":d.translate(f,g),d.rotate(Math.PI/4),l=1/Math.SQRT2*u,d.fillRect(-l,-l,2*l,2*l),d.strokeRect(-l,-l,2*l,2*l),d.setTransform(1,0,0,1,0,0);break;case"cross":d.beginPath(),d.moveTo(f,g+u),d.lineTo(f,g-u),d.moveTo(f-u,g),d.lineTo(f+u,g),d.closePath();break;case"crossRot":d.beginPath(),n=Math.cos(Math.PI/4)*u,r=Math.sin(Math.PI/4)*u,d.moveTo(f-n,g-r),d.lineTo(f+n,g+r),d.moveTo(f-n,g+r),d.lineTo(f+n,g-r),d.closePath();break;case"star":d.beginPath(),d.moveTo(f,g+u),d.lineTo(f,g-u),d.moveTo(f-u,g),d.lineTo(f+u,g),n=Math.cos(Math.PI/4)*u,r=Math.sin(Math.PI/4)*u,d.moveTo(f-n,g-r),d.lineTo(f+n,g+r),d.moveTo(f-n,g+r),d.lineTo(f+n,g-r),d.closePath();break;case"line":d.beginPath(),d.moveTo(f-u,g),d.lineTo(f+u,g),d.closePath();break;case"dash":d.beginPath(),d.moveTo(f,g),d.lineTo(f+u,g),d.closePath()}d.stroke()}}}})}},{}],37:[function(t,e,i){"use strict";e.exports=function(t){var e=(t.helpers,t.defaults.global);e.elements.rectangle={backgroundColor:e.defaultColor,borderWidth:0,borderColor:e.defaultColor,borderSkipped:"bottom"},t.elements.Rectangle=t.Element.extend({draw:function(){function t(t){return l[(d+t)%4]}var e=this._chart.ctx,i=this._view,a=i.width/2,o=i.x-a,n=i.x+a,r=i.base-(i.base-i.y),s=i.borderWidth/2;i.borderWidth&&(o+=s,n-=s,r+=s),e.beginPath(),e.fillStyle=i.backgroundColor,e.strokeStyle=i.borderColor,e.lineWidth=i.borderWidth;var l=[[o,i.base],[o,r],[n,r],[n,i.base]],h=["bottom","left","top","right"],d=h.indexOf(i.borderSkipped,0);-1===d&&(d=0),e.moveTo.apply(e,t(0));for(var c=1;4>c;c++)e.lineTo.apply(e,t(c));e.fill(),i.borderWidth&&e.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var i=this._view;return i?i.y<i.base?t>=i.x-i.width/2&&t<=i.x+i.width/2&&e>=i.y&&e<=i.base:t>=i.x-i.width/2&&t<=i.x+i.width/2&&e>=i.base&&e<=i.y:!1},inLabelRange:function(t){var e=this._view;return e?t>=e.x-e.width/2&&t<=e.x+e.width/2:!1},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})}},{}],38:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"bottom"},a=t.Scale.extend({determineDataLimits:function(){this.minIndex=0,this.maxIndex=this.chart.data.labels.length-1;var t;void 0!==this.options.ticks.min&&(t=e.indexOf(this.chart.data.labels,this.options.ticks.min),this.minIndex=-1!==t?t:this.minIndex),void 0!==this.options.ticks.max&&(t=e.indexOf(this.chart.data.labels,this.options.ticks.max),this.maxIndex=-1!==t?t:this.maxIndex),this.min=this.chart.data.labels[this.minIndex],this.max=this.chart.data.labels[this.maxIndex]},buildTicks:function(t){this.ticks=0===this.minIndex&&this.maxIndex===this.chart.data.labels.length-1?this.chart.data.labels:this.chart.data.labels.slice(this.minIndex,this.maxIndex+1)},getLabelForIndex:function(t,e){return this.ticks[t]},getPixelForValue:function(t,e,i,a){var o=Math.max(this.maxIndex+1-this.minIndex-(this.options.gridLines.offsetGridLines?0:1),1);if(this.isHorizontal()){var n=this.width-(this.paddingLeft+this.paddingRight),r=n/o,s=r*(e-this.minIndex)+this.paddingLeft;return this.options.gridLines.offsetGridLines&&a&&(s+=r/2),this.left+Math.round(s)}var l=this.height-(this.paddingTop+this.paddingBottom),h=l/o,d=h*(e-this.minIndex)+this.paddingTop;return this.options.gridLines.offsetGridLines&&a&&(d+=h/2),this.top+Math.round(d)},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null,e)},getValueForPixel:function(t){var e,i=Math.max(this.ticks.length-(this.options.gridLines.offsetGridLines?0:1),1),a=this.isHorizontal(),o=a?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),n=o/i;return this.options.gridLines.offsetGridLines&&(t-=n/2),t-=a?this.paddingLeft:this.paddingTop,e=0>=t?0:Math.round(t/n)}});t.scaleService.registerScaleType("category",a,i)}},{}],39:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"left",ticks:{callback:function(t,i,a){var o=a.length>3?a[2]-a[1]:a[1]-a[0];Math.abs(o)>1&&t!==Math.floor(t)&&(o=t-Math.floor(t));var n=e.log10(Math.abs(o)),r="";if(0!==t){var s=-1*Math.floor(n);s=Math.max(Math.min(s,20),0),r=t.toFixed(s)}else r="0";return r}}},a=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===i.id:t.yAxisID===i.id}var i=this,a=i.options,o=a.ticks,n=i.chart,r=n.data,s=r.datasets,l=i.isHorizontal();if(i.min=null,i.max=null,a.stacked){var h={},d=!1,c=!1;e.each(s,function(o,r){var s=n.getDatasetMeta(r);void 0===h[s.type]&&(h[s.type]={positiveValues:[],negativeValues:[]});var l=h[s.type].positiveValues,u=h[s.type].negativeValues;n.isDatasetVisible(r)&&t(s)&&e.each(o.data,function(t,e){var o=+i.getRightValue(t);isNaN(o)||s.data[e].hidden||(l[e]=l[e]||0,u[e]=u[e]||0,a.relativePoints?l[e]=100:0>o?(c=!0,u[e]+=o):(d=!0,l[e]+=o))})}),e.each(h,function(t){var a=t.positiveValues.concat(t.negativeValues),o=e.min(a),n=e.max(a);i.min=null===i.min?o:Math.min(i.min,o),i.max=null===i.max?n:Math.max(i.max,n)})}else e.each(s,function(a,o){var r=n.getDatasetMeta(o);n.isDatasetVisible(o)&&t(r)&&e.each(a.data,function(t,e){var a=+i.getRightValue(t);isNaN(a)||r.data[e].hidden||(null===i.min?i.min=a:a<i.min&&(i.min=a),null===i.max?i.max=a:a>i.max&&(i.max=a))})});if(o.beginAtZero){var u=e.sign(i.min),f=e.sign(i.max);0>u&&0>f?i.max=0:u>0&&f>0&&(i.min=0)}void 0!==o.min?i.min=o.min:void 0!==o.suggestedMin&&(i.min=Math.min(i.min,o.suggestedMin)),void 0!==o.max?i.max=o.max:void 0!==o.suggestedMax&&(i.max=Math.max(i.max,o.suggestedMax)),i.min===i.max&&(i.max++,o.beginAtZero||i.min--)},buildTicks:function(){var i,a=this,o=a.options,n=o.ticks,r=e.getValueOrDefault,s=a.isHorizontal(),l=a.ticks=[];if(s)i=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(a.width/50));else{var h=r(n.fontSize,t.defaults.global.defaultFontSize);i=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(a.height/(2*h)))}i=Math.max(2,i);var d,c=n.fixedStepSize&&n.fixedStepSize>0||n.stepSize&&n.stepSize>0;if(c)d=r(n.fixedStepSize,n.stepSize);else{var u=e.niceNum(a.max-a.min,!1);d=e.niceNum(u/(i-1),!0)}var f=Math.floor(a.min/d)*d,g=Math.ceil(a.max/d)*d,p=(g-f)/d;p=e.almostEquals(p,Math.round(p),d/1e3)?Math.round(p):Math.ceil(p),l.push(void 0!==n.min?n.min:f);for(var m=1;p>m;++m)l.push(f+m*d);l.push(void 0!==n.max?n.max:g),
+s||l.reverse(),a.max=e.max(l),a.min=e.min(l),n.reverse?(l.reverse(),a.start=a.max,a.end=a.min):(a.start=a.min,a.end=a.max)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)},getPixelForValue:function(t,e,i,a){var o,n,r=this,s=r.paddingLeft,l=r.paddingBottom,h=r.start,d=+r.getRightValue(t),c=r.end-h;return r.isHorizontal()?(n=r.width-(s+r.paddingRight),o=r.left+n/c*(d-h),Math.round(o+s)):(n=r.height-(r.paddingTop+l),o=r.bottom-l-n/c*(d-h),Math.round(o))},getValueForPixel:function(t){var e=this,i=e.isHorizontal(),a=e.paddingLeft,o=e.paddingBottom,n=i?e.width-(a+e.paddingRight):e.height-(e.paddingTop+o),r=(i?t-e.left-a:e.bottom-o-t)/n;return e.start+(e.end-e.start)*r},getPixelForTick:function(t,e){return this.getPixelForValue(this.ticksAsNumbers[t],null,null,e)}});t.scaleService.registerScaleType("linear",a,i)}},{}],40:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i={position:"left",ticks:{callback:function(t,i,a){var o=t/Math.pow(10,Math.floor(e.log10(t)));return 1===o||2===o||5===o||0===i||i===a.length-1?t.toExponential():""}}},a=t.Scale.extend({determineDataLimits:function(){function t(t){return h?t.xAxisID===i.id:t.yAxisID===i.id}var i=this,a=i.options,o=a.ticks,n=i.chart,r=n.data,s=r.datasets,l=e.getValueOrDefault,h=i.isHorizontal();if(i.min=null,i.max=null,a.stacked){var d={};e.each(s,function(o,r){var s=n.getDatasetMeta(r);n.isDatasetVisible(r)&&t(s)&&(void 0===d[s.type]&&(d[s.type]=[]),e.each(o.data,function(t,e){var o=d[s.type],n=+i.getRightValue(t);isNaN(n)||s.data[e].hidden||(o[e]=o[e]||0,a.relativePoints?o[e]=100:o[e]+=n)}))}),e.each(d,function(t){var a=e.min(t),o=e.max(t);i.min=null===i.min?a:Math.min(i.min,a),i.max=null===i.max?o:Math.max(i.max,o)})}else e.each(s,function(a,o){var r=n.getDatasetMeta(o);n.isDatasetVisible(o)&&t(r)&&e.each(a.data,function(t,e){var a=+i.getRightValue(t);isNaN(a)||r.data[e].hidden||(null===i.min?i.min=a:a<i.min&&(i.min=a),null===i.max?i.max=a:a>i.max&&(i.max=a))})});i.min=l(o.min,i.min),i.max=l(o.max,i.max),i.min===i.max&&(0!==i.min&&null!==i.min?(i.min=Math.pow(10,Math.floor(e.log10(i.min))-1),i.max=Math.pow(10,Math.floor(e.log10(i.max))+1)):(i.min=1,i.max=10))},buildTicks:function(){for(var t=this,i=t.options,a=i.ticks,o=e.getValueOrDefault,n=t.ticks=[],r=o(a.min,Math.pow(10,Math.floor(e.log10(t.min))));r<t.max;){n.push(r);var s=Math.floor(e.log10(r)),l=Math.floor(r/Math.pow(10,s))+1;10===l&&(l=1,++s),r=l*Math.pow(10,s)}var h=o(a.max,r);n.push(h),t.isHorizontal()||n.reverse(),t.max=e.max(n),t.min=e.min(n),a.reverse?(n.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){this.tickValues=this.ticks.slice(),t.Scale.prototype.convertTicksToLabels.call(this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickValues[t],null,null,e)},getPixelForValue:function(t,i,a,o){var n,r,s=this,l=s.start,h=+s.getRightValue(t),d=e.log10(s.end)-e.log10(l),c=s.paddingTop,u=s.paddingBottom,f=s.paddingLeft;return s.isHorizontal()?0===h?r=s.left+f:(n=s.width-(f+s.paddingRight),r=s.left+n/d*(e.log10(h)-e.log10(l)),r+=f):0===h?r=s.top+c:(n=s.height-(c+u),r=s.bottom-u-n/d*(e.log10(h)-e.log10(l))),r},getValueForPixel:function(t){var i,a,o=this,n=e.log10(o.end)-e.log10(o.start);return o.isHorizontal()?(a=o.width-(o.paddingLeft+o.paddingRight),i=o.start*Math.pow(10,(t-o.left-o.paddingLeft)*n/a)):(a=o.height-(o.paddingTop+o.paddingBottom),i=Math.pow(10,(o.bottom-o.paddingBottom-t)*n/a)/o.start),i}});t.scaleService.registerScaleType("logarithmic",a,i)}},{}],41:[function(t,e,i){"use strict";e.exports=function(t){var e=t.helpers,i=t.defaults.global,a={display:!0,animate:!0,lineArc:!1,position:"chartArea",angleLines:{display:!0,color:"rgba(0, 0, 0, 0.1)",lineWidth:1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2},pointLabels:{fontSize:10,callback:function(t){return t}}},o=t.Scale.extend({getValueCount:function(){return this.chart.data.labels.length},setDimensions:function(){var t=this.options;this.width=this.maxWidth,this.height=this.maxHeight,this.xCenter=Math.round(this.width/2),this.yCenter=Math.round(this.height/2);var a=e.min([this.height,this.width]),o=e.getValueOrDefault(t.ticks.fontSize,i.defaultFontSize);this.drawingArea=t.display?a/2-(o/2+t.ticks.backdropPaddingY):a/2},determineDataLimits:function(){if(this.min=null,this.max=null,e.each(this.chart.data.datasets,function(t,i){if(this.chart.isDatasetVisible(i)){var a=this.chart.getDatasetMeta(i);e.each(t.data,function(t,e){var i=+this.getRightValue(t);isNaN(i)||a.data[e].hidden||(null===this.min?this.min=i:i<this.min&&(this.min=i),null===this.max?this.max=i:i>this.max&&(this.max=i))},this)}},this),this.options.ticks.beginAtZero){var t=e.sign(this.min),i=e.sign(this.max);0>t&&0>i?this.max=0:t>0&&i>0&&(this.min=0)}void 0!==this.options.ticks.min?this.min=this.options.ticks.min:void 0!==this.options.ticks.suggestedMin&&(this.min=Math.min(this.min,this.options.ticks.suggestedMin)),void 0!==this.options.ticks.max?this.max=this.options.ticks.max:void 0!==this.options.ticks.suggestedMax&&(this.max=Math.max(this.max,this.options.ticks.suggestedMax)),this.min===this.max&&(this.min--,this.max++)},buildTicks:function(){this.ticks=[];var t=e.getValueOrDefault(this.options.ticks.fontSize,i.defaultFontSize),a=Math.min(this.options.ticks.maxTicksLimit?this.options.ticks.maxTicksLimit:11,Math.ceil(this.drawingArea/(1.5*t)));a=Math.max(2,a);var o=e.niceNum(this.max-this.min,!1),n=e.niceNum(o/(a-1),!0),r=Math.floor(this.min/n)*n,s=Math.ceil(this.max/n)*n,l=Math.ceil((s-r)/n);this.ticks.push(void 0!==this.options.ticks.min?this.options.ticks.min:r);for(var h=1;l>h;++h)this.ticks.push(r+h*n);this.ticks.push(void 0!==this.options.ticks.max?this.options.ticks.max:s),this.max=e.max(this.ticks),this.min=e.min(this.ticks),this.options.ticks.reverse?(this.ticks.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),this.zeroLineIndex=this.ticks.indexOf(0)},convertTicksToLabels:function(){t.Scale.prototype.convertTicksToLabels.call(this),this.pointLabels=this.chart.data.labels.map(this.options.pointLabels.callback,this)},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t,a,o,n,r,s,l,h,d,c,u,f,g=this.options.pointLabels,p=e.getValueOrDefault(g.fontSize,i.defaultFontSize),m=e.getValueOrDefault(g.fontStyle,i.defaultFontStyle),b=e.getValueOrDefault(g.fontFamily,i.defaultFontFamily),v=e.fontString(p,m,b),x=e.min([this.height/2-p-5,this.width/2]),y=this.width,k=0;for(this.ctx.font=v,a=0;a<this.getValueCount();a++)t=this.getPointPosition(a,x),o=this.ctx.measureText(this.pointLabels[a]?this.pointLabels[a]:"").width+5,0===a||a===this.getValueCount()/2?(n=o/2,t.x+n>y&&(y=t.x+n,r=a),t.x-n<k&&(k=t.x-n,l=a)):a<this.getValueCount()/2?t.x+o>y&&(y=t.x+o,r=a):a>this.getValueCount()/2&&t.x-o<k&&(k=t.x-o,l=a);d=k,c=Math.ceil(y-this.width),s=this.getIndexAngle(r),h=this.getIndexAngle(l),u=c/Math.sin(s+Math.PI/2),f=d/Math.sin(h+Math.PI/2),u=e.isNumber(u)?u:0,f=e.isNumber(f)?f:0,this.drawingArea=Math.round(x-(f+u)/2),this.setCenterPoint(f,u)},setCenterPoint:function(t,e){var i=this.width-e-this.drawingArea,a=t+this.drawingArea;this.xCenter=Math.round((a+i)/2+this.left),this.yCenter=Math.round(this.height/2+this.top)},getIndexAngle:function(t){var e=2*Math.PI/this.getValueCount();return t*e-Math.PI/2},getDistanceFromCenterForValue:function(t){if(null===t)return 0;var e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e},getPointPosition:function(t,e){var i=this.getIndexAngle(t);return{x:Math.round(Math.cos(i)*e)+this.xCenter,y:Math.round(Math.sin(i)*e)+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(){var t=this,e=t.min,i=t.max;return t.getPointPositionForValue(0,t.beginAtZero?0:0>e&&0>i?i:e>0&&i>0?e:0)},draw:function(){if(this.options.display){var t=this.ctx;if(e.each(this.ticks,function(a,o){if(o>0||this.options.reverse){var n=this.getDistanceFromCenterForValue(this.ticks[o]),r=this.yCenter-n;if(this.options.gridLines.display)if(t.strokeStyle=this.options.gridLines.color,t.lineWidth=this.options.gridLines.lineWidth,this.options.lineArc)t.beginPath(),t.arc(this.xCenter,this.yCenter,n,0,2*Math.PI),t.closePath(),t.stroke();else{t.beginPath();for(var s=0;s<this.getValueCount();s++){var l=this.getPointPosition(s,this.getDistanceFromCenterForValue(this.ticks[o]));0===s?t.moveTo(l.x,l.y):t.lineTo(l.x,l.y)}t.closePath(),t.stroke()}if(this.options.ticks.display){var h=e.getValueOrDefault(this.options.ticks.fontColor,i.defaultFontColor),d=e.getValueOrDefault(this.options.ticks.fontSize,i.defaultFontSize),c=e.getValueOrDefault(this.options.ticks.fontStyle,i.defaultFontStyle),u=e.getValueOrDefault(this.options.ticks.fontFamily,i.defaultFontFamily),f=e.fontString(d,c,u);if(t.font=f,this.options.ticks.showLabelBackdrop){var g=t.measureText(a).width;t.fillStyle=this.options.ticks.backdropColor,t.fillRect(this.xCenter-g/2-this.options.ticks.backdropPaddingX,r-d/2-this.options.ticks.backdropPaddingY,g+2*this.options.ticks.backdropPaddingX,d+2*this.options.ticks.backdropPaddingY)}t.textAlign="center",t.textBaseline="middle",t.fillStyle=h,t.fillText(a,this.xCenter,r)}}},this),!this.options.lineArc){t.lineWidth=this.options.angleLines.lineWidth,t.strokeStyle=this.options.angleLines.color;for(var a=this.getValueCount()-1;a>=0;a--){if(this.options.angleLines.display){var o=this.getPointPosition(a,this.getDistanceFromCenterForValue(this.options.reverse?this.min:this.max));t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(o.x,o.y),t.stroke(),t.closePath()}var n=this.getPointPosition(a,this.getDistanceFromCenterForValue(this.options.reverse?this.min:this.max)+5),r=e.getValueOrDefault(this.options.pointLabels.fontColor,i.defaultFontColor),s=e.getValueOrDefault(this.options.pointLabels.fontSize,i.defaultFontSize),l=e.getValueOrDefault(this.options.pointLabels.fontStyle,i.defaultFontStyle),h=e.getValueOrDefault(this.options.pointLabels.fontFamily,i.defaultFontFamily),d=e.fontString(s,l,h);t.font=d,t.fillStyle=r;var c=this.pointLabels.length,u=this.pointLabels.length/2,f=u/2,g=f>a||a>c-f,p=a===f||a===c-f;0===a?t.textAlign="center":a===u?t.textAlign="center":u>a?t.textAlign="left":t.textAlign="right",p?t.textBaseline="middle":g?t.textBaseline="bottom":t.textBaseline="top",t.fillText(this.pointLabels[a]?this.pointLabels[a]:"",n.x,n.y)}}}}});t.scaleService.registerScaleType("radialLinear",o,a)}},{}],42:[function(t,e,i){"use strict";var a=t("moment");a="function"==typeof a?a:window.moment,e.exports=function(t){var e=t.helpers,i={units:[{name:"millisecond",steps:[1,2,5,10,20,50,100,250,500]},{name:"second",steps:[1,2,5,10,30]},{name:"minute",steps:[1,2,5,10,30]},{name:"hour",steps:[1,2,3,6,12]},{name:"day",steps:[1,2,5]},{name:"week",maxStep:4},{name:"month",maxStep:3},{name:"quarter",maxStep:4},{name:"year",maxStep:!1}]},o={position:"bottom",time:{parser:!1,format:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,displayFormats:{millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm:ss a",hour:"MMM D, hA",day:"ll",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"}},ticks:{autoSkip:!1}},n=t.Scale.extend({initialize:function(){if(!a)throw new Error("Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com");t.Scale.prototype.initialize.call(this)},getLabelMoment:function(t,e){return this.labelMoments[t][e]},getMomentStartOf:function(t){return"week"===this.options.time.unit&&this.options.time.isoWeekday!==!1?t.clone().startOf("isoWeek").isoWeekday(this.options.time.isoWeekday):t.clone().startOf(this.tickUnit)},determineDataLimits:function(){this.labelMoments=[];var t=[];this.chart.data.labels&&this.chart.data.labels.length>0?(e.each(this.chart.data.labels,function(e,i){var a=this.parseTime(e);a.isValid()&&(this.options.time.round&&a.startOf(this.options.time.round),t.push(a))},this),this.firstTick=a.min.call(this,t),this.lastTick=a.max.call(this,t)):(this.firstTick=null,this.lastTick=null),e.each(this.chart.data.datasets,function(i,o){var n=[],r=this.chart.isDatasetVisible(o);"object"==typeof i.data[0]&&null!==i.data[0]?e.each(i.data,function(t,e){var i=this.parseTime(this.getRightValue(t));i.isValid()&&(this.options.time.round&&i.startOf(this.options.time.round),n.push(i),r&&(this.firstTick=null!==this.firstTick?a.min(this.firstTick,i):i,this.lastTick=null!==this.lastTick?a.max(this.lastTick,i):i))},this):n=t,this.labelMoments.push(n)},this),this.options.time.min&&(this.firstTick=this.parseTime(this.options.time.min)),this.options.time.max&&(this.lastTick=this.parseTime(this.options.time.max)),this.firstTick=(this.firstTick||a()).clone(),this.lastTick=(this.lastTick||a()).clone()},buildTicks:function(a){this.ctx.save();var o=e.getValueOrDefault(this.options.ticks.fontSize,t.defaults.global.defaultFontSize),n=e.getValueOrDefault(this.options.ticks.fontStyle,t.defaults.global.defaultFontStyle),r=e.getValueOrDefault(this.options.ticks.fontFamily,t.defaults.global.defaultFontFamily),s=e.fontString(o,n,r);if(this.ctx.font=s,this.ticks=[],this.unitScale=1,this.scaleSizeInUnits=0,this.options.time.unit)this.tickUnit=this.options.time.unit||"day",this.displayFormat=this.options.time.displayFormats[this.tickUnit],this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0),this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,1);else{var l=this.isHorizontal()?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),h=this.tickFormatFunction(this.firstTick,0,[]),d=this.ctx.measureText(h).width,c=Math.cos(e.toRadians(this.options.ticks.maxRotation)),u=Math.sin(e.toRadians(this.options.ticks.maxRotation));d=d*c+o*u;var f=l/d;this.tickUnit="millisecond",this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0),this.displayFormat=this.options.time.displayFormats[this.tickUnit];for(var g=0,p=i.units[g];g<i.units.length;){if(this.unitScale=1,e.isArray(p.steps)&&Math.ceil(this.scaleSizeInUnits/f)<e.max(p.steps)){for(var m=0;m<p.steps.length;++m)if(p.steps[m]>=Math.ceil(this.scaleSizeInUnits/f)){this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,p.steps[m]);break}break}if(p.maxStep===!1||Math.ceil(this.scaleSizeInUnits/f)<p.maxStep){this.unitScale=e.getValueOrDefault(this.options.time.unitStepSize,Math.ceil(this.scaleSizeInUnits/f));break}++g,p=i.units[g],this.tickUnit=p.name;var b=this.firstTick.diff(this.getMomentStartOf(this.firstTick),this.tickUnit,!0),v=this.getMomentStartOf(this.lastTick.clone().add(1,this.tickUnit)).diff(this.lastTick,this.tickUnit,!0);this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0)+b+v,this.displayFormat=this.options.time.displayFormats[p.name]}}var x;if(this.options.time.min?x=this.getMomentStartOf(this.firstTick):(this.firstTick=this.getMomentStartOf(this.firstTick),x=this.firstTick),!this.options.time.max){var y=this.getMomentStartOf(this.lastTick);0!==y.diff(this.lastTick,this.tickUnit,!0)&&(this.lastTick=this.getMomentStartOf(this.lastTick.add(1,this.tickUnit)))}this.smallestLabelSeparation=this.width,e.each(this.chart.data.datasets,function(t,e){for(var i=1;i<this.labelMoments[e].length;i++)this.smallestLabelSeparation=Math.min(this.smallestLabelSeparation,this.labelMoments[e][i].diff(this.labelMoments[e][i-1],this.tickUnit,!0))},this),this.options.time.displayFormat&&(this.displayFormat=this.options.time.displayFormat),this.ticks.push(this.firstTick.clone());for(var k=1;k<=this.scaleSizeInUnits;++k){var S=x.clone().add(k,this.tickUnit);if(this.options.time.max&&S.diff(this.lastTick,this.tickUnit,!0)>=0)break;k%this.unitScale===0&&this.ticks.push(S)}var C=this.ticks[this.ticks.length-1].diff(this.lastTick,this.tickUnit);(0!==C||0===this.scaleSizeInUnits)&&(this.options.time.max?(this.ticks.push(this.lastTick.clone()),this.scaleSizeInUnits=this.lastTick.diff(this.ticks[0],this.tickUnit,!0)):(this.ticks.push(this.lastTick.clone()),this.scaleSizeInUnits=this.lastTick.diff(this.firstTick,this.tickUnit,!0))),this.ctx.restore()},getLabelForIndex:function(t,e){var i=this.chart.data.labels&&t<this.chart.data.labels.length?this.chart.data.labels[t]:"";return"object"==typeof this.chart.data.datasets[e].data[0]&&(i=this.getRightValue(this.chart.data.datasets[e].data[t])),this.options.time.tooltipFormat&&(i=this.parseTime(i).format(this.options.time.tooltipFormat)),i},tickFormatFunction:function(t,i,a){var o=t.format(this.displayFormat),n=this.options.ticks,r=e.getValueOrDefault(n.callback,n.userCallback);return r?r(o,i,a):o},convertTicksToLabels:function(){this.tickMoments=this.ticks,this.ticks=this.ticks.map(this.tickFormatFunction,this)},getPixelForValue:function(t,e,i,a){var o=t&&t.isValid&&t.isValid()?t:this.getLabelMoment(i,e);if(o){var n=o.diff(this.firstTick,this.tickUnit,!0),r=n/this.scaleSizeInUnits;if(this.isHorizontal()){var s=this.width-(this.paddingLeft+this.paddingRight),l=(s/Math.max(this.ticks.length-1,1),s*r+this.paddingLeft);return this.left+Math.round(l)}var h=this.height-(this.paddingTop+this.paddingBottom),d=(h/Math.max(this.ticks.length-1,1),h*r+this.paddingTop);return this.top+Math.round(d)}},getPixelForTick:function(t,e){return this.getPixelForValue(this.tickMoments[t],null,null,e)},getValueForPixel:function(t){var e=this.isHorizontal()?this.width-(this.paddingLeft+this.paddingRight):this.height-(this.paddingTop+this.paddingBottom),i=(t-(this.isHorizontal()?this.left+this.paddingLeft:this.top+this.paddingTop))/e;return i*=this.scaleSizeInUnits,this.firstTick.clone().add(a.duration(i,this.tickUnit).asSeconds(),"seconds")},parseTime:function(t){return"string"==typeof this.options.time.parser?a(t,this.options.time.parser):"function"==typeof this.options.time.parser?this.options.time.parser(t):"function"==typeof t.getMonth||"number"==typeof t?a(t):t.isValid&&t.isValid()?t:"string"!=typeof this.options.time.format&&this.options.time.format.call?(console.warn("options.time.format is deprecated and replaced by options.time.parser. See http://nnnick.github.io/Chart.js/docs-v2/#scales-time-scale"),this.options.time.format(t)):a(t,this.options.time.format)}});t.scaleService.registerScaleType("time",n,o)}},{moment:1}]},{},[7]);
\ No newline at end of file