vendor/assets/javascripts/chart2.js in chart-0.1.4.9 vs vendor/assets/javascripts/chart2.js in chart-0.1.5.0.pre
- old
+ new
@@ -1,9 +1,9 @@
/*!
* Chart.js
* http://chartjs.org/
- * Version: 2.1.6
+ * Version: 2.2.1
*
* Copyright 2016 Nick Downie
* Released under the MIT license
* https://github.com/chartjs/Chart.js/blob/master/LICENSE.md
*/
@@ -1663,36 +1663,37 @@
};
},{}],7:[function(require,module,exports){
/**
* @namespace Chart
*/
-var Chart = require(26)();
+var Chart = require(27)();
+require(26)(Chart);
+require(22)(Chart);
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(24)(Chart);
require(28)(Chart);
+require(32)(Chart);
+require(30)(Chart);
+require(31)(Chart);
require(33)(Chart);
-
+require(29)(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(39)(Chart);
+require(40)(Chart);
require(42)(Chart);
require(43)(Chart);
+require(44)(Chart);
// Controllers must be loaded after elements
// See Chart.core.datasetController.dataElementType
require(15)(Chart);
require(16)(Chart);
@@ -1709,11 +1710,11 @@
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){
+},{"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,"44":44,"8":8,"9":9}],8:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
Chart.Bar = function(context, config) {
@@ -1807,15 +1808,15 @@
}]
},
tooltips: {
callbacks: {
- title: function(tooltipItems, data) {
+ title: function() {
// Title doesn't make sense for scatter since we format the data as a point
return '';
},
- label: function(tooltipItem, data) {
+ label: function(tooltipItem) {
return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
}
}
}
};
@@ -1873,11 +1874,11 @@
// 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() {
+ getBarCount: function() {
var me = this;
var barCount = 0;
helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
var meta = me.chart.getDatasetMeta(datasetIndex);
if (meta.bar && me.chart.isDatasetVisible(datasetIndex)) {
@@ -1885,18 +1886,18 @@
}
}, me);
return barCount;
},
- update: function update(reset) {
+ update: function(reset) {
var me = this;
helpers.each(me.getMeta().data, function(rectangle, index) {
me.updateElement(rectangle, index, reset);
}, me);
},
- updateElement: function updateElement(rectangle, index, reset) {
+ updateElement: function(rectangle, index, reset) {
var me = this;
var meta = me.getMeta();
var xScale = me.getScaleForId(meta.xAxisID);
var yScale = me.getScaleForId(meta.yAxisID);
var scaleBase = yScale.getBasePixel();
@@ -1939,28 +1940,19 @@
var base = 0;
if (yScale.options.stacked) {
var chart = me.chart;
var datasets = chart.data.datasets;
- var value = datasets[datasetIndex].data[index];
+ var value = Number(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;
- }
+ for (var i = 0; i < datasetIndex; i++) {
+ var currentDs = datasets[i];
+ var currentDsMeta = chart.getDatasetMeta(i);
+ if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
+ var currentVal = Number(currentDs.data[index]);
+ base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
}
- } 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);
}
@@ -2004,10 +1996,13 @@
};
},
calculateBarWidth: function(index) {
var xScale = this.getScaleForId(this.getMeta().xAxisID);
+ if (xScale.options.barThickness) {
+ return xScale.options.barThickness;
+ }
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
@@ -2049,25 +2044,26 @@
calculateBarY: function(index, datasetIndex) {
var me = this;
var meta = me.getMeta();
var yScale = me.getScaleForId(meta.yAxisID);
- var value = me.getDataset().data[index];
+ var value = Number(me.getDataset().data[index]);
if (yScale.options.stacked) {
var sumPos = 0,
sumNeg = 0;
for (var i = 0; i < datasetIndex; i++) {
var ds = me.chart.data.datasets[i];
var dsMeta = me.chart.getDatasetMeta(i);
if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
+ var stackedVal = Number(ds.data[index]);
+ if (stackedVal < 0) {
+ sumNeg += stackedVal || 0;
} else {
- sumPos += ds.data[index] || 0;
+ sumPos += stackedVal || 0;
}
}
}
if (value < 0) {
@@ -2171,11 +2167,11 @@
}
}
};
Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
- updateElement: function updateElement(rectangle, index, reset, numBars) {
+ updateElement: function(rectangle, index, reset) {
var me = this;
var meta = me.getMeta();
var xScale = me.getScaleForId(meta.xAxisID);
var yScale = me.getScaleForId(meta.yAxisID);
var scaleBase = xScale.getBasePixel();
@@ -2287,29 +2283,21 @@
var meta = me.getMeta();
var xScale = me.getScaleForId(meta.xAxisID);
var base = 0;
if (xScale.options.stacked) {
+ var chart = me.chart;
+ var datasets = chart.data.datasets;
+ var value = Number(datasets[datasetIndex].data[index]);
- 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;
- }
+ for (var i = 0; i < datasetIndex; i++) {
+ var currentDs = datasets[i];
+ var currentDsMeta = chart.getDatasetMeta(i);
+ if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i)) {
+ var currentVal = Number(currentDs.data[index]);
+ base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
}
- } 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);
}
@@ -2353,33 +2341,37 @@
},
calculateBarHeight: function (index) {
var me = this;
var yScale = me.getScaleForId(me.getMeta().yAxisID);
+ if (yScale.options.barThickness) {
+ return yScale.options.barThickness;
+ }
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];
+ var value = Number(me.getDataset().data[index]);
if (xScale.options.stacked) {
var sumPos = 0,
sumNeg = 0;
for (var i = 0; i < datasetIndex; i++) {
var ds = me.chart.data.datasets[i];
var dsMeta = me.chart.getDatasetMeta(i);
if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
- if (ds.data[index] < 0) {
- sumNeg += ds.data[index] || 0;
+ var stackedVal = Number(ds.data[index]);
+ if (stackedVal < 0) {
+ sumNeg += stackedVal || 0;
} else {
- sumPos += ds.data[index] || 0;
+ sumPos += stackedVal || 0;
}
}
}
if (value < 0) {
@@ -2441,11 +2433,11 @@
}]
},
tooltips: {
callbacks: {
- title: function(tooltipItems, data) {
+ title: function() {
// 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 || '';
@@ -2458,11 +2450,11 @@
Chart.controllers.bubble = Chart.DatasetController.extend({
dataElementType: Chart.elements.Point,
- update: function update(reset) {
+ update: function(reset) {
var me = this;
var meta = me.getMeta();
var points = meta.data;
// Update Points
@@ -2490,11 +2482,11 @@
_datasetIndex: dsIndex,
_index: index,
// Desired view properties
_model: {
- x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, dsIndex, me.chart.isCombo),
+ x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, 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
@@ -2587,11 +2579,11 @@
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 custom = arc && 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);
@@ -2660,11 +2652,11 @@
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) {
+ getRingIndex: function(datasetIndex) {
var ringIndex = 0;
for (var j = 0; j < datasetIndex; ++j) {
if (this.chart.isDatasetVisible(j)) {
++ringIndex;
@@ -2672,11 +2664,11 @@
}
return ringIndex;
},
- update: function update(reset) {
+ update: function(reset) {
var me = this;
var chart = me.chart,
chartArea = chart.chartArea,
opts = chart.options,
arcOpts = opts.elements.arc,
@@ -2707,12 +2699,13 @@
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.borderWidth = me.getMaxBorderWidth(meta.data);
- chart.outerRadius = Math.max(minSize / 2, 0);
+ chart.outerRadius = Math.max((minSize - chart.borderWidth) / 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;
@@ -2730,20 +2723,18 @@
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,
@@ -2795,21 +2786,43 @@
if (!isNaN(value) && !element.hidden) {
total += Math.abs(value);
}
});
+ /*if (total === 0) {
+ total = NaN;
+ }*/
+
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;
}
- }
+ },
+
+ //gets the max border or hover width to properly scale pie charts
+ getMaxBorderWidth: function (elements) {
+ var max = 0,
+ index = this.index,
+ length = elements.length,
+ borderWidth,
+ hoverWidth;
+
+ for (var i = 0; i < length; i++) {
+ borderWidth = elements[i]._model ? elements[i]._model.borderWidth : 0;
+ hoverWidth = elements[i]._chart ? elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;
+
+ max = borderWidth > max ? borderWidth : max;
+ max = hoverWidth > max ? hoverWidth : max;
+ }
+ return max;
+ }
});
};
},{}],18:[function(require,module,exports){
"use strict";
@@ -2818,10 +2831,11 @@
var helpers = Chart.helpers;
Chart.defaults.line = {
showLines: true,
+ spanGaps: false,
hover: {
mode: "label"
},
@@ -2858,11 +2872,11 @@
if (lineEnabled(me.getDataset(), options) && meta.dataset._model.tension !== 0) {
me.updateBezierControlPoints();
}
},
- update: function update(reset) {
+ update: function(reset) {
var me = this;
var meta = me.getMeta();
var line = meta.dataset;
var points = meta.data || [];
var options = me.chart.options;
@@ -2890,20 +2904,21 @@
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,
+ spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps,
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),
+ steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
// Scale
scaleTop: scale.top,
scaleBottom: scale.bottom,
scaleZero: scale.getBasePixel()
};
@@ -2992,12 +3007,12 @@
}
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);
+ x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, me.chart.isCombo);
+ y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
// Utility
point._xScale = xScale;
point._yScale = yScale;
point._datasetIndex = datasetIndex;
@@ -3013,16 +3028,17 @@
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,
+ steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
// Tooltip
hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
};
},
- calculatePointY: function(value, index, datasetIndex, isCombo) {
+ calculatePointY: function(value, index, datasetIndex) {
var me = this;
var chart = me.chart;
var meta = me.getMeta();
var yScale = me.getScaleForId(meta.yAxisID);
var sumPos = 0;
@@ -3031,49 +3047,59 @@
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;
+ if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
+ var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
+ if (stackedRightValue < 0) {
+ sumNeg += stackedRightValue || 0;
} else {
- sumPos += ds.data[index] || 0;
+ sumPos += stackedRightValue || 0;
}
}
}
- if (value < 0) {
- return yScale.getPixelForValue(sumNeg + value);
+ var rightValue = Number(yScale.getRightValue(value));
+ if (rightValue < 0) {
+ return yScale.getPixelForValue(sumNeg + rightValue);
} else {
- return yScale.getPixelForValue(sumPos + value);
+ return yScale.getPixelForValue(sumPos + rightValue);
}
}
return yScale.getPixelForValue(value);
},
updateBezierControlPoints: function() {
- var meta = this.getMeta();
- var area = this.chart.chartArea;
- var points = meta.data || [];
+ var me = this;
+ var meta = me.getMeta();
+ var area = me.chart.chartArea;
+
+ // only consider points that are drawn in case the spanGaps option is ued
+ var points = (meta.data || []).filter(function(pt) { return !pt._model.skip; });
var i, ilen, point, model, controlPoints;
+ var needToCap = me.chart.options.elements.line.capBezierPoints;
+ function capIfNecessary(pt, min, max) {
+ return needToCap ? Math.max(Math.min(pt, max), min) : pt;
+ }
+
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
);
- model.controlPointPreviousX = controlPoints.previous.x;
- model.controlPointPreviousY = controlPoints.previous.y;
- model.controlPointNextX = controlPoints.next.x;
- model.controlPointNextY = controlPoints.next.y;
+ model.controlPointPreviousX = capIfNecessary(controlPoints.previous.x, area.left, area.right);
+ model.controlPointPreviousY = capIfNecessary(controlPoints.previous.y, area.top, area.bottom);
+ model.controlPointNextX = capIfNecessary(controlPoints.next.x, area.left, area.right);
+ model.controlPointNextY = capIfNecessary(controlPoints.next.y, area.top, area.bottom);
}
},
draw: function(ease) {
var me = this;
@@ -3140,19 +3166,23 @@
Chart.defaults.polarArea = {
scale: {
type: "radialLinear",
- lineArc: true // so that lines are circular
+ lineArc: true, // so that lines are circular
+ ticks: {
+ beginAtZero: true
+ }
},
//Boolean - Whether to animate the rotation of the chart
animation: {
animateRotate: true,
animateScale: true
},
+ startAngle: -0.5 * Math.PI,
aspectRatio: 1,
legendCallback: function(chart) {
var text = [];
text.push('<ul class="' + chart.id + '-legend">');
@@ -3237,11 +3267,11 @@
dataElementType: Chart.elements.Arc,
linkScales: helpers.noop,
- update: function update(reset) {
+ update: function(reset) {
var me = this;
var chart = me.chart;
var chartArea = chart.chartArea;
var meta = me.getMeta();
var opts = chart.options;
@@ -3262,23 +3292,20 @@
},
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;
+ var centerX = scale.xCenter;
+ var centerY = scale.yCenter;
// 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();
@@ -3286,13 +3313,14 @@
if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {
++visibleCount;
}
}
- var negHalfPI = -0.5 * Math.PI;
+ //var negHalfPI = -0.5 * Math.PI;
+ var datasetStartAngle = opts.startAngle;
var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
- var startAngle = (negHalfPI) + (circumference * visibleCount);
+ var startAngle = datasetStartAngle + (circumference * visibleCount);
var endAngle = startAngle + (arc.hidden ? 0 : circumference);
var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
helpers.extend(arc, {
@@ -3305,12 +3333,12 @@
_model: {
x: centerX,
y: centerY,
innerRadius: 0,
outerRadius: reset ? resetRadius : distance,
- startAngle: reset && animationOpts.animateRotate ? negHalfPI : startAngle,
- endAngle: reset && animationOpts.animateRotate ? negHalfPI : endAngle,
+ startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
+ endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
label: getValueAtIndexOrDefault(labels, index, labels[index])
}
});
// Apply border and fill style
@@ -3379,11 +3407,11 @@
// Make sure bezier control points are updated
this.updateBezierControlPoints();
},
- update: function update(reset) {
+ update: function(reset) {
var me = this;
var meta = me.getMeta();
var line = meta.dataset;
var points = meta.data;
var custom = line.custom || {};
@@ -3495,11 +3523,11 @@
draw: function(ease) {
var meta = this.getMeta();
var easingDecimal = ease || 1;
// Transition Point Locations
- helpers.each(meta.data, function(point, index) {
+ helpers.each(meta.data, function(point) {
point.transition(easingDecimal);
});
// Transition and Draw the line
meta.dataset.transition(easingDecimal).draw();
@@ -3672,11 +3700,116 @@
};
},{}],22:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
+ // Global Chart canvas helpers object for drawing items to canvas
+ var helpers = Chart.canvasHelpers = {};
+ helpers.drawPoint = function(ctx, pointStyle, radius, x, y) {
+ var type, edgeLength, xOffset, yOffset, height, size;
+
+ 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;
+ }
+
+ 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.beginPath();
+ 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();
+ };
+};
+},{}],23:[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.
@@ -3716,11 +3849,11 @@
return this;
};
helpers.extend(Chart.Controller.prototype, /** @lends Chart.Controller */ {
- initialize: function initialize() {
+ initialize: function() {
var me = this;
// Before init plugin notification
Chart.plugins.notify('beforeInit', [me]);
me.bindEvents();
@@ -3739,16 +3872,16 @@
Chart.plugins.notify('afterInit', [me]);
return me;
},
- clear: function clear() {
+ clear: function() {
helpers.clear(this.chart);
return this;
},
- stop: function stop() {
+ stop: function() {
// Stops any current animation loop occuring
Chart.animationService.cancelAnimation(this);
return this;
},
@@ -3786,11 +3919,11 @@
}
return me;
},
- ensureScalesHaveIDs: function ensureScalesHaveIDs() {
+ ensureScalesHaveIDs: function() {
var options = this.options;
var scalesOptions = options.scales || {};
var scaleOptions = options.scale;
helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {
@@ -3807,11 +3940,11 @@
},
/**
* Builds a map of scale ID to scale object for future lookup.
*/
- buildScales: function buildScales() {
+ buildScales: function() {
var me = this;
var options = me.options;
var scales = me.scales = {};
var items = [];
@@ -3825,11 +3958,11 @@
if (options.scale) {
items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });
}
- helpers.each(items, function(item, index) {
+ helpers.each(items, function(item) {
var scaleOptions = item.options;
var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);
var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
if (!scaleClass) {
return;
@@ -3857,11 +3990,11 @@
updateLayout: function() {
Chart.layoutService.update(this, this.chart.width, this.chart.height);
},
- buildOrUpdateControllers: function buildOrUpdateControllers() {
+ buildOrUpdateControllers: function() {
var me = this;
var types = [];
var newControllers = [];
helpers.each(me.data.datasets, function(dataset, datasetIndex) {
@@ -3890,11 +4023,11 @@
}
return newControllers;
},
- resetElements: function resetElements() {
+ resetElements: function() {
var me = this;
helpers.each(me.data.datasets, function(dataset, datasetIndex) {
me.getDatasetMeta(datasetIndex).controller.reset();
}, me);
},
@@ -4046,20 +4179,20 @@
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) {
+ helpers.each(meta.data, function(element) {
if (element.inRange(eventPosition.x, eventPosition.y)) {
elementsArray.push(element);
return elementsArray;
}
});
}
});
- return elementsArray;
+ return elementsArray.slice(0, 1);
},
getElementsAtEvent: function(e) {
var me = this;
var eventPosition = helpers.getRelativePosition(e, me.chart);
@@ -4084,12 +4217,54 @@
return elementsArray;
}
helpers.each(me.data.datasets, function(dataset, datasetIndex) {
if (me.isDatasetVisible(datasetIndex)) {
+ var meta = me.getDatasetMeta(datasetIndex),
+ element = meta.data[found._index];
+ if(element && !element._view.skip){
+ elementsArray.push(element);
+ }
+ }
+ }, me);
+
+ return elementsArray;
+ },
+
+ getElementsAtXAxis: 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].inLabelRange(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]);
+ var index = helpers.findIndex(meta.data, function (it) {
+ return found._model.x === it._model.x;
+ });
+ if(index !== -1 && !meta.data[index]._view.skip) {
+ elementsArray.push(meta.data[index]);
+ }
}
}, me);
return elementsArray;
},
@@ -4101,10 +4276,12 @@
return me.getElementAtEvent(e);
case 'label':
return me.getElementsAtEvent(e);
case 'dataset':
return me.getDatasetAtEvent(e);
+ case 'x-axis':
+ return me.getElementsAtXAxis(e);
default:
return e;
}
},
@@ -4157,15 +4334,15 @@
// 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() {
+ generateLegend: function() {
return this.options.legendCallback(this);
},
- destroy: function destroy() {
+ destroy: function() {
var me = this;
me.stop();
me.clear();
helpers.unbindEvents(me, me.events);
helpers.removeResizeListener(me.chart.canvas.parentNode);
@@ -4187,25 +4364,25 @@
Chart.plugins.notify('destroy', [me]);
delete Chart.instances[me.id];
},
- toBase64Image: function toBase64Image() {
+ toBase64Image: function() {
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
},
- initToolTip: function initToolTip() {
+ initToolTip: function() {
var me = this;
me.tooltip = new Chart.Tooltip({
_chart: me.chart,
_chartInstance: me,
_data: me.data,
_options: me.options.tooltips
}, me);
},
- bindEvents: function bindEvents() {
+ bindEvents: function() {
var me = this;
helpers.bindEvents(me, me.options.events, function(evt) {
me.eventHandler(evt);
});
},
@@ -4218,10 +4395,11 @@
case 'single':
elements = [ elements[0] ];
break;
case 'label':
case 'dataset':
+ case 'x-axis':
// elements = elements;
break;
default:
// unsupported mode
return;
@@ -4311,11 +4489,11 @@
return me;
}
});
};
-},{}],23:[function(require,module,exports){
+},{}],24:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -4419,11 +4597,11 @@
var element = me.createMetaData(index);
me.getMeta().data.splice(index, 0, element);
me.updateElement(element, index, true);
},
- buildOrUpdateElements: function buildOrUpdateElements() {
+ buildOrUpdateElements: function() {
// Handle the number of data points changing
var meta = this.getMeta(),
md = meta.data,
numData = this.getDataset().data.length,
numMetaData = md.length;
@@ -4442,21 +4620,20 @@
update: noop,
draw: function(ease) {
var easingDecimal = ease || 1;
- helpers.each(this.getMeta().data, function(element, index) {
+ helpers.each(this.getMeta().data, function(element) {
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);
@@ -4465,23 +4642,24 @@
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){
+},{}],25:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -4583,11 +4761,11 @@
Chart.Element.extend = helpers.inherits;
};
-},{}],25:[function(require,module,exports){
+},{}],26:[function(require,module,exports){
/*global window: false */
/*global document: false */
"use strict";
var color = require(3);
@@ -5532,20 +5710,24 @@
color :
helpers.color(color).saturate(0.5).darken(0.1).rgbString();
};
};
-},{"3":3}],26:[function(require,module,exports){
+},{"3":3}],27:[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;
+ me.config = config || {
+ data: {
+ datasets: []
+ }
+ };
// Support a jQuery'd canvas element
if (context.length && context[0].getContext) {
context = context[0];
}
@@ -5580,15 +5762,12 @@
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);
+ me.controller = new Chart.Controller(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();
}
@@ -5643,11 +5822,11 @@
return Chart;
};
-},{}],27:[function(require,module,exports){
+},{}],28:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -5913,12 +6092,10 @@
}
// 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;
@@ -5968,11 +6145,11 @@
});
}
};
};
-},{}],28:[function(require,module,exports){
+},{}],29:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -6023,10 +6200,11 @@
lineDash: dataset.borderDash,
lineDashOffset: dataset.borderDashOffset,
lineJoin: dataset.borderJoinStyle,
lineWidth: dataset.borderWidth,
strokeStyle: dataset.borderColor,
+ pointStyle: dataset.pointStyle,
// Below is extra data used for toggling the datasets
datasetIndex: i
};
}, this) : [];
@@ -6172,11 +6350,15 @@
ctx.textAlign = "left";
ctx.textBaseline = 'top';
helpers.each(me.legendItems, function(legendItem, i) {
- var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+ var boxWidth = labelOpts.usePointStyle ?
+ fontSize * Math.sqrt(2) :
+ labelOpts.boxWidth;
+
+ var width = 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;
}
@@ -6200,12 +6382,16 @@
var currentColWidth = 0;
var currentColHeight = 0;
var itemHeight = fontSize + vPadding;
helpers.each(me.legendItems, function(legendItem, i) {
- var itemWidth = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+ // If usePointStyle is set, multiple boxWidth by 2 since it represents
+ // the radius and not truly the width
+ var boxWidth = labelOpts.usePointStyle ? 2 * labelOpts.boxWidth : labelOpts.boxWidth;
+ var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+
// If too tall, go to new column
if (currentColHeight + itemHeight > minSize.height) {
totalWidth += currentColWidth + labelOpts.padding;
columnWidths.push(currentColWidth); // previous column width
@@ -6248,11 +6434,10 @@
var opts = me.options;
var labelOpts = opts.labels;
var globalDefault = Chart.defaults.global,
lineDefault = globalDefault.elements.line,
legendWidth = me.width,
- legendHeight = me.height,
lineWidths = me.lineWidths;
if (opts.display) {
var ctx = me.ctx,
cursor,
@@ -6274,10 +6459,14 @@
var boxWidth = labelOpts.boxWidth,
hitboxes = me.legendHitBoxes;
// current position
var drawLegendBox = function(x, y, legendItem) {
+ if (isNaN(boxWidth) || boxWidth <= 0) {
+ return;
+ }
+
// Set the ctx for the box
ctx.save();
ctx.fillStyle = itemOrDefault(legendItem.fillStyle, globalDefault.defaultColor);
ctx.lineCap = itemOrDefault(legendItem.lineCap, lineDefault.borderCapStyle);
@@ -6289,14 +6478,27 @@
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);
+ if (opts.labels && opts.labels.usePointStyle) {
+ // Recalulate x and y for drawPoint() because its expecting
+ // x and y to be center of figure (instead of top left)
+ var radius = fontSize * Math.SQRT2 / 2;
+ var offSet = radius / Math.SQRT2;
+ var centerX = x + offSet;
+ var centerY = y + offSet;
+ // Draw pointStyle as legend symbol
+ Chart.canvasHelpers.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
+ }
+ else {
+ // Draw box as legend symbol
+ ctx.strokeRect(x, y, boxWidth, fontSize);
+ ctx.fillRect(x, y, boxWidth, fontSize);
+ }
+
ctx.restore();
};
var fillText = function(x, y, legendItem, textWidth) {
ctx.fillText(legendItem.text, boxWidth + (fontSize / 2) + x, y);
@@ -6319,25 +6521,27 @@
line: 0
};
} else {
cursor = {
x: me.left + labelOpts.padding,
- y: me.top,
+ y: me.top + labelOpts.padding,
line: 0
};
}
var itemHeight = fontSize + labelOpts.padding;
helpers.each(me.legendItems, function(legendItem, i) {
var textWidth = ctx.measureText(legendItem.text).width,
- width = boxWidth + (fontSize / 2) + textWidth,
+ width = labelOpts.usePointStyle ?
+ fontSize + (fontSize / 2) + textWidth :
+ boxWidth + (fontSize / 2) + textWidth,
x = cursor.x,
y = cursor.y;
if (isHorizontal) {
if (x + width >= legendWidth) {
- y = cursor.y += fontSize + (labelOpts.padding);
+ y = cursor.y += itemHeight;
cursor.line++;
x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
}
} else {
if (y + itemHeight > me.bottom) {
@@ -6345,11 +6549,10 @@
y = cursor.y = me.top;
cursor.line++;
}
}
-
drawLegendBox(x, y, legendItem);
hitboxes[i].left = x;
hitboxes[i].top = y;
@@ -6409,11 +6612,11 @@
}
}
});
};
-},{}],29:[function(require,module,exports){
+},{}],30:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var noop = Chart.helpers.noop;
@@ -6540,11 +6743,11 @@
* @todo remove me at version 3
*/
Chart.pluginService = Chart.plugins;
};
-},{}],30:[function(require,module,exports){
+},{}],31:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -6827,13 +7030,10 @@
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) {
@@ -6936,11 +7136,11 @@
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) {
+ getRightValue: function(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
@@ -6950,11 +7150,11 @@
// 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);
+ return this.getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
}
}
// Value is good, return it
return rawValue;
@@ -7057,27 +7257,25 @@
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;
var itemsToDraw = [];
if (isHorizontal) {
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;
- }
+ // 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)));
}
@@ -7296,11 +7494,11 @@
}
}
});
};
-},{}],31:[function(require,module,exports){
+},{}],32:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -7337,11 +7535,11 @@
Chart.layoutService.addBox(chartInstance, scale);
});
}
};
};
-},{}],32:[function(require,module,exports){
+},{}],33:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -7451,13 +7649,11 @@
//
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),
@@ -7545,11 +7741,11 @@
}
}
});
};
-},{}],33:[function(require,module,exports){
+},{}],34:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -7664,13 +7860,15 @@
}
}
var x = 0,
y = 0;
- for (i = 0, len - xPositions.length; i < len; ++i) {
- x += xPositions[i];
- y += yPositions[i];
+ for (i = 0; i < xPositions.length; ++i) {
+ if (xPositions[ i ]) {
+ x += xPositions[i];
+ y += yPositions[i];
+ }
}
return {
x: Math.round(x / xPositions.length),
y: Math.round(y / xPositions.length)
@@ -7704,12 +7902,12 @@
helpers.extend(me, {
_model: {
// Positioning
xPadding: tooltipOpts.xPadding,
yPadding: tooltipOpts.yPadding,
- xAlign : tooltipOpts.yAlign,
- yAlign : tooltipOpts.xAlign,
+ xAlign : tooltipOpts.xAlign,
+ yAlign : tooltipOpts.yAlign,
// Body
bodyFontColor: tooltipOpts.bodyFontColor,
_bodyFontFamily: getValueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily),
_bodyFontStyle: getValueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle),
@@ -7876,11 +8074,11 @@
opts.custom.call(me, model);
}
return me;
},
- getTooltipSize: function getTooltipSize(vm) {
+ getTooltipSize: function(vm) {
var ctx = this._chart.ctx;
var size = {
height: vm.yPadding * 2, // Tooltip Padding
width: 0
@@ -7939,11 +8137,11 @@
// Add padding
size.width += 2 * vm.xPadding;
return size;
},
- determineAlignment: function determineAlignment(size) {
+ determineAlignment: function(size) {
var me = this;
var model = me._model;
var chart = me._chart;
var chartArea = me._chartInstance.chartArea;
@@ -8001,11 +8199,11 @@
model.xAlign = 'center';
model.yAlign = yf(model.y);
}
}
},
- getBackgroundPoint: function getBackgroundPoint(vm, size) {
+ getBackgroundPoint: function(vm, size) {
// Background Position
var pt = {
x: vm.x,
y: vm.y
};
@@ -8046,11 +8244,11 @@
}
}
return pt;
},
- drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {
+ drawCaret: function(tooltipPoint, size, opacity) {
var vm = this._view;
var ctx = this._chart.ctx;
var x1, x2, x3;
var y1, y2, y3;
var caretSize = vm.caretSize;
@@ -8110,11 +8308,11 @@
ctx.lineTo(x2, y2);
ctx.lineTo(x3, y3);
ctx.closePath();
ctx.fill();
},
- drawTitle: function drawTitle(pt, vm, ctx, opacity) {
+ drawTitle: function(pt, vm, ctx, opacity) {
var title = vm.title;
if (title.length) {
ctx.textAlign = vm._titleAlign;
ctx.textBaseline = "top";
@@ -8135,11 +8333,11 @@
pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing
}
}
}
},
- drawBody: function drawBody(pt, vm, ctx, opacity) {
+ drawBody: function(pt, vm, ctx, opacity) {
var bodyFontSize = vm.bodyFontSize;
var bodySpacing = vm.bodySpacing;
var body = vm.body;
ctx.textAlign = vm._bodyAlign;
@@ -8196,11 +8394,11 @@
// After body lines
helpers.each(vm.afterBody, fillLineOfText);
pt.y -= bodySpacing; // Remove last body spacing
},
- drawFooter: function drawFooter(pt, vm, ctx, opacity) {
+ drawFooter: function(pt, vm, ctx, opacity) {
var footer = vm.footer;
if (footer.length) {
pt.y += vm.footerMarginTop;
@@ -8215,11 +8413,11 @@
ctx.fillText(line, pt.x, pt.y);
pt.y += vm.footerFontSize + vm.footerSpacing;
});
}
},
- draw: function draw() {
+ draw: function() {
var ctx = this._chart.ctx;
var vm = this._view;
if (vm.opacity === 0) {
return;
@@ -8240,11 +8438,11 @@
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);
+ this.drawCaret(pt, tooltipSize, opacity);
// Draw Title, Body, and Footer
pt.x += vm.xPadding;
pt.y += vm.yPadding;
@@ -8259,14 +8457,14 @@
}
}
});
};
-},{}],34:[function(require,module,exports){
+},{}],35:[function(require,module,exports){
"use strict";
-module.exports = function(Chart, moment) {
+module.exports = function(Chart) {
var helpers = Chart.helpers,
globalOpts = Chart.defaults.global;
globalOpts.elements.arc = {
@@ -8354,11 +8552,11 @@
}
}
});
};
-},{}],35:[function(require,module,exports){
+},{}],36:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -8371,121 +8569,123 @@
borderColor: globalDefaults.defaultColor,
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
+ capBezierPoints: true,
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 spanGaps = vm.spanGaps;
+ var scaleZero = vm.scaleZero;
+ var loop = me._loop;
+
var ctx = me._chart.ctx;
- var first = me._children[0];
- var last = me._children[me._children.length - 1];
+ ctx.save();
- function loopBackToStart(drawLineToCenter) {
- if (!first._view.skip && !last._view.skip) {
- // Draw a bezier line from last to first
+ // Helper function to draw a line to a point
+ function lineToPoint(previousPoint, point) {
+ var vm = point._view;
+ if (point._view.steppedLine === true) {
+ ctx.lineTo(point._view.x, previousPoint._view.y);
+ ctx.lineTo(point._view.x, point._view.y);
+ } else if (point._view.tension === 0) {
+ ctx.lineTo(vm.x, vm.y);
+ } else {
ctx.bezierCurveTo(
- last._view.controlPointNextX,
- last._view.controlPointNextY,
- first._view.controlPointPreviousX,
- first._view.controlPointPreviousY,
- first._view.x,
- first._view.y
+ previousPoint._view.controlPointNextX,
+ previousPoint._view.controlPointNextY,
+ vm.controlPointPreviousX,
+ vm.controlPointPreviousY,
+ vm.x,
+ vm.y
);
- } else if (drawLineToCenter) {
- // Go to center
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
}
}
- ctx.save();
+ var points = me._children.slice(); // clone array
+ var lastDrawnIndex = -1;
- // 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)
+ // If we are looping, adding the first point again
+ if (loop && points.length) {
+ points.push(points[0]);
+ }
+
+ var index, current, previous, currentVM;
+
+ // Fill Line
+ if (points.length && vm.fill) {
ctx.beginPath();
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
+ for (index = 0; index < points.length; ++index) {
+ current = points[index];
+ previous = helpers.previousItem(points, index);
+ currentVM = current._view;
// 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);
+ if (loop) {
+ ctx.moveTo(scaleZero.x, scaleZero.y);
} else {
- ctx.moveTo(point._view.x, vm.scaleZero);
+ ctx.moveTo(currentVM.x, 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);
+ if (!currentVM.skip) {
+ lastDrawnIndex = index;
+ ctx.lineTo(currentVM.x, currentVM.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);
+ previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
+
+ if (currentVM.skip) {
+ // Only do this if this is the first point that is skipped
+ if (!spanGaps && lastDrawnIndex === (index - 1)) {
+ if (loop) {
+ ctx.lineTo(scaleZero.x, scaleZero.y);
+ } else {
+ ctx.lineTo(previous._view.x, scaleZero);
+ }
+ }
+ } else {
+ if (lastDrawnIndex !== (index - 1)) {
+ // There was a gap and this is the first point after the gap. If we've never drawn a point, this is a special case.
+ // If the first data point is NaN, then there is no real gap to skip
+ if (spanGaps && lastDrawnIndex !== -1) {
+ // We are spanning the gap, so simple draw a line to this point
+ lineToPoint(previous, current);
+ } else {
+ if (loop) {
+ ctx.lineTo(currentVM.x, currentVM.y);
+ } else {
+ ctx.lineTo(currentVM.x, scaleZero);
+ ctx.lineTo(currentVM.x, currentVM.y);
+ }
+ }
} else {
- ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
- ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
+ // Line to next point
+ lineToPoint(previous, current);
}
- }, 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);
- });
+ lastDrawnIndex = index;
+ }
}
- }, 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);
+ if (!loop) {
+ ctx.lineTo(points[lastDrawnIndex]._view.x, scaleZero);
}
ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
ctx.closePath();
ctx.fill();
}
+ // Stroke Line Options
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);
@@ -8493,38 +8693,50 @@
ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset;
ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
+
+ // Stroke Line
ctx.beginPath();
+ lastDrawnIndex = -1;
- helpers.each(me._children, function(point, index) {
- var previous = helpers.previousItem(me._children, index);
- var next = helpers.nextItem(me._children, index);
+ for (index = 0; index < points.length; ++index) {
+ current = points[index];
+ previous = helpers.previousItem(points, index);
+ currentVM = current._view;
+ // First point moves to it's starting position no matter what
if (index === 0) {
- ctx.moveTo(point._view.x, point._view.y);
+ if (currentVM.skip) {
+
+ } else {
+ ctx.moveTo(currentVM.x, currentVM.y);
+ lastDrawnIndex = index;
+ }
} 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);
+ previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
- if (me._loop && me._children.length > 0) {
- loopBackToStart();
+ if (!currentVM.skip) {
+ if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
+ // There was a gap and this is the first point after the gap
+ ctx.moveTo(currentVM.x, currentVM.y);
+ } else {
+ // Line to next point
+ lineToPoint(previous, current);
+ }
+ lastDrawnIndex = index;
+ }
+ }
}
ctx.stroke();
ctx.restore();
}
});
};
-},{}],36:[function(require,module,exports){
+},{}],37:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers,
@@ -8565,123 +8777,30 @@
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();
+ Chart.canvasHelpers.drawPoint(ctx, pointStyle, radius, x, y);
}
});
};
-},{}],37:[function(require,module,exports){
+},{}],38:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
- var helpers = Chart.helpers,
- globalOpts = Chart.defaults.global;
+ var globalOpts = Chart.defaults.global;
globalOpts.elements.rectangle = {
backgroundColor: globalOpts.defaultColor,
borderWidth: 0,
borderColor: globalOpts.defaultColor,
@@ -8766,11 +8885,11 @@
};
}
});
};
-},{}],38:[function(require,module,exports){
+},{}],39:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -8778,49 +8897,66 @@
var defaultConfig = {
position: "bottom"
};
var DatasetScale = Chart.Scale.extend({
+ /**
+ * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use tose
+ * else fall back to data.labels
+ * @private
+ */
+ getLabels: function() {
+ var data = this.chart.data;
+ return (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels;
+ },
// Implement this so that
determineDataLimits: function() {
var me = this;
+ var labels = me.getLabels();
me.minIndex = 0;
- me.maxIndex = me.chart.data.labels.length - 1;
+ me.maxIndex = 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);
+ findIndex = helpers.indexOf(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);
+ findIndex = helpers.indexOf(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];
+ me.min = labels[me.minIndex];
+ me.max = labels[me.maxIndex];
},
- buildTicks: function(index) {
+ buildTicks: function() {
var me = this;
+ var labels = me.getLabels();
// 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);
+ me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
},
- getLabelForIndex: function(index, datasetIndex) {
+ getLabelForIndex: function(index) {
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 (value !== undefined) {
+ var labels = me.getLabels();
+ var idx = labels.indexOf(value);
+ index = idx !== -1 ? idx : index;
+ }
+
if (me.isHorizontal()) {
var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
var valueWidth = innerWidth / offsetAmt;
var widthOffset = (valueWidth * (index - me.minIndex)) + me.paddingLeft;
@@ -8850,10 +8986,12 @@
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;
+ pixel -= horz ? me.left : me.top;
+
if (me.options.gridLines.offsetGridLines) {
pixel -= (valueDimension / 2);
}
pixel -= horz ? me.paddingLeft : me.paddingTop;
@@ -8862,17 +9000,20 @@
} else {
value = Math.round(pixel / valueDimension);
}
return value;
+ },
+ getBasePixel: function() {
+ return this.bottom;
}
});
Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);
};
-},{}],39:[function(require,module,exports){
+},{}],40:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -8910,11 +9051,10 @@
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();
@@ -9030,13 +9170,13 @@
},
getLabelForIndex: function(index, datasetIndex) {
return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
},
// Utils
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
+ getPixelForValue: function(value) {
// This must be called after fit has been run so that
- // this.left, this.top, this.right, and this.bottom have been defined
+ // 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;
@@ -9062,18 +9202,18 @@
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);
+ getPixelForTick: function(index) {
+ return this.getPixelForValue(this.ticksAsNumbers[index]);
}
});
Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);
};
-},{}],40:[function(require,module,exports){
+},{}],41:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers,
@@ -9125,16 +9265,14 @@
handleDirectionalChanges: noop,
buildTicks: function() {
var me = this;
var opts = me.options;
+ var ticks = me.ticks = [];
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
@@ -9197,11 +9335,11 @@
Chart.Scale.prototype.convertTicksToLabels.call(me);
},
});
};
-},{}],41:[function(require,module,exports){
+},{}],42:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -9377,14 +9515,14 @@
},
// 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);
+ getPixelForTick: function(index) {
+ return this.getPixelForValue(this.tickValues[index]);
},
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
+ getPixelForValue: function(value) {
var me = this;
var innerDimension;
var pixel;
var start = me.start;
@@ -9415,14 +9553,12 @@
return pixel;
},
getValueForPixel: function(pixel) {
var me = this;
- var offset;
var range = helpers.log10(me.end) - helpers.log10(me.start);
- var value;
- var innerDimension;
+ var value, 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 {
@@ -9434,11 +9570,11 @@
}
});
Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);
};
-},{}],42:[function(require,module,exports){
+},{}],43:[function(require,module,exports){
"use strict";
module.exports = function(Chart) {
var helpers = Chart.helpers;
@@ -9601,20 +9737,24 @@
furthestLeftIndex,
furthestLeftAngle,
xProtrusionLeft,
xProtrusionRight,
radiusReductionRight,
- radiusReductionLeft,
- maxWidthRadius;
+ radiusReductionLeft;
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
+
+ // Add quarter circle to make degree 0 mean top of circle
+ var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
+ var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;
+
+ if (angle === 0 || angle === 180) {
+ // At angle 0 and 180, 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;
@@ -9622,17 +9762,17 @@
}
if (pointPosition.x - halfTextWidth < furthestLeft) {
furthestLeft = pointPosition.x - halfTextWidth;
furthestLeftIndex = i;
}
- } else if (i < this.getValueCount() / 2) {
+ } else if (angle < 180) {
// 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) {
+ } else {
// More than half the values means we'll right align the text
if (pointPosition.x - textWidth < furthestLeft) {
furthestLeft = pointPosition.x - textWidth;
furthestLeftIndex = i;
}
@@ -9665,13 +9805,18 @@
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
+ var startAngle = this.chart.options && this.chart.options.startAngle ?
+ this.chart.options.startAngle :
+ 0;
- return index * angleMultiplier - (Math.PI / 2);
+ var startAngleRadians = startAngle * Math.PI * 2 / 360;
+
+ // Start from the top instead of right, so remove a quarter of the circle
+ return index * angleMultiplier - (Math.PI / 2) + startAngleRadians;
},
getDistanceFromCenterForValue: function(value) {
var me = this;
if (value === null) {
@@ -9811,30 +9956,28 @@
// 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) {
+ var pointLabels = me.pointLabels;
+
+ // Add quarter circle to make degree 0 mean top of circle
+ var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
+ var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;
+
+ if (angle === 0 || angle === 180) {
ctx.textAlign = 'center';
- } else if (i === halfLabelsCount) {
- ctx.textAlign = 'center';
- } else if (i < halfLabelsCount) {
+ } else if (angle < 180) {
ctx.textAlign = 'left';
} else {
ctx.textAlign = 'right';
}
// Set the correct text baseline based on outer positioning
- if (exactQuarter) {
+ if (angle === 90 || angle === 270) {
ctx.textBaseline = 'middle';
- } else if (upperHalf) {
+ } else if (angle > 270 || angle < 90) {
ctx.textBaseline = 'bottom';
} else {
ctx.textBaseline = 'top';
}
@@ -9846,11 +9989,11 @@
});
Chart.scaleService.registerScaleType("radialLinear", LinearRadialScale, defaultConfig);
};
-},{}],43:[function(require,module,exports){
+},{}],44:[function(require,module,exports){
/*global window: false */
"use strict";
var moment = require(1);
moment = typeof(moment) === 'function' ? moment : window.moment;
@@ -9925,11 +10068,15 @@
}
Chart.Scale.prototype.initialize.call(this);
},
getLabelMoment: function(datasetIndex, index) {
- return this.labelMoments[datasetIndex][index];
+ if (typeof this.labelMoments[datasetIndex] != 'undefined') {
+ return this.labelMoments[datasetIndex][index];
+ }
+
+ return null;
},
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);
@@ -9943,11 +10090,11 @@
// 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) {
+ helpers.each(me.chart.data.labels, function(label) {
var labelMoment = me.parseTime(label);
if (labelMoment.isValid()) {
if (me.options.time.round) {
labelMoment.startOf(me.options.time.round);
@@ -9966,11 +10113,11 @@
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) {
+ helpers.each(dataset.data, function(value) {
var labelMoment = me.parseTime(me.getRightValue(value));
if (labelMoment.isValid()) {
if (me.options.time.round) {
labelMoment.startOf(me.options.time.round);
@@ -10003,11 +10150,11 @@
// We will modify these, so clone for later
me.firstTick = (me.firstTick || moment()).clone();
me.lastTick = (me.lastTick || moment()).clone();
},
- buildTicks: function(index) {
+ buildTicks: function() {
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);
@@ -10089,14 +10236,19 @@
}
// 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) {
+ var delta = roundedEnd.diff(me.lastTick, me.tickUnit, true);
+ if (delta < 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));
+ } else if (delta >= 0) {
+ me.lastTick = roundedEnd;
}
+
+ me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
}
me.smallestLabelSeparation = me.width;
helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
@@ -10158,11 +10310,11 @@
}
return label;
},
// Function to format an individual tick mark
- tickFormatFunction: function tickFormatFunction(tick, index, ticks) {
+ tickFormatFunction: function(tick, index, ticks) {
var formattedTick = tick.format(this.displayFormat);
var tickOpts = this.options.ticks;
var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);
if (callback) {
@@ -10174,35 +10326,37 @@
convertTicksToLabels: function() {
var me = this;
me.tickMoments = me.ticks;
me.ticks = me.ticks.map(me.tickFormatFunction, me);
},
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
+ getPixelForValue: function(value, index, datasetIndex) {
var me = this;
+ if (!value || !value.isValid) {
+ // not already a moment object
+ value = moment(me.getRightValue(value));
+ }
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;
+ var decimal = offset !== 0 ? offset / me.scaleSizeInUnits : offset;
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);
+ getPixelForTick: function(index) {
+ return this.getPixelForValue(this.tickMoments[index], null, null);
},
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;