chart 0.1.4.9 → 0.1.5.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75c52b55338f3bd15897e409fb7c0e0eebecba65
4
- data.tar.gz: 8d37358086aa7c81d45b06b916ccab72c0fb6b4c
3
+ metadata.gz: d4225c1955f40f8dcf778eee2ef9e95073e7c122
4
+ data.tar.gz: ce6c3583f0a3de0632ca29ad26a79ebc62f78416
5
5
  SHA512:
6
- metadata.gz: 0a5a091be068aabd681debb72a8fe3301e3783ed5cbfb226d6b3f983b9e70142f38f2cab9eea677824cf774589a2285888b27701ebd7750b9dd4d0a8d718e64a
7
- data.tar.gz: 935f5f6f7809b35257b62587b90fc510879511eb75ccccbd2bd7c161e1e23cac40cf1a73e473051ca93f4f420cfe0b15250cc918e61ebe7909b14b53e1daa795
6
+ metadata.gz: 7053a201f730e01e912314c5a29c0dbdd35b00dd569b03c8e24567321af95d51efebd7f602970190da137355f3b905abe95d88164cf04de9e087fc16bf0e1b05
7
+ data.tar.gz: 283abed337cff774cc8a77a0a846751ffc2a7b4bc27a931421de26ffb6849966ec1b31e75d17d1d9c7396aacd1649ea6902437eb3fc8850bf84a5b69d8420573
data/lib/chart/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Chart
2
- VERSION = "0.1.4.9"
2
+ VERSION = "0.1.5.0.pre"
3
3
  end
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * Chart.js
3
3
  * http://chartjs.org/
4
- * Version: 2.1.6
4
+ * Version: 2.2.1
5
5
  *
6
6
  * Copyright 2016 Nick Downie
7
7
  * Released under the MIT license
@@ -1665,32 +1665,33 @@ module.exports = {
1665
1665
  /**
1666
1666
  * @namespace Chart
1667
1667
  */
1668
- var Chart = require(26)();
1668
+ var Chart = require(27)();
1669
1669
 
1670
+ require(26)(Chart);
1671
+ require(22)(Chart);
1670
1672
  require(25)(Chart);
1671
- require(24)(Chart);
1672
1673
  require(21)(Chart);
1673
- require(22)(Chart);
1674
1674
  require(23)(Chart);
1675
- require(27)(Chart);
1676
- require(31)(Chart);
1677
- require(29)(Chart);
1678
- require(30)(Chart);
1679
- require(32)(Chart);
1675
+ require(24)(Chart);
1680
1676
  require(28)(Chart);
1677
+ require(32)(Chart);
1678
+ require(30)(Chart);
1679
+ require(31)(Chart);
1681
1680
  require(33)(Chart);
1682
-
1681
+ require(29)(Chart);
1683
1682
  require(34)(Chart);
1683
+
1684
1684
  require(35)(Chart);
1685
1685
  require(36)(Chart);
1686
1686
  require(37)(Chart);
1687
-
1688
- require(40)(Chart);
1689
1687
  require(38)(Chart);
1690
- require(39)(Chart);
1688
+
1691
1689
  require(41)(Chart);
1690
+ require(39)(Chart);
1691
+ require(40)(Chart);
1692
1692
  require(42)(Chart);
1693
1693
  require(43)(Chart);
1694
+ require(44)(Chart);
1694
1695
 
1695
1696
  // Controllers must be loaded after elements
1696
1697
  // See Chart.core.datasetController.dataElementType
@@ -1711,7 +1712,7 @@ require(14)(Chart);
1711
1712
 
1712
1713
  window.Chart = module.exports = Chart;
1713
1714
 
1714
- },{"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){
1715
+ },{"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){
1715
1716
  "use strict";
1716
1717
 
1717
1718
  module.exports = function(Chart) {
@@ -1809,11 +1810,11 @@ module.exports = function(Chart) {
1809
1810
 
1810
1811
  tooltips: {
1811
1812
  callbacks: {
1812
- title: function(tooltipItems, data) {
1813
+ title: function() {
1813
1814
  // Title doesn't make sense for scatter since we format the data as a point
1814
1815
  return '';
1815
1816
  },
1816
- label: function(tooltipItem, data) {
1817
+ label: function(tooltipItem) {
1817
1818
  return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
1818
1819
  }
1819
1820
  }
@@ -1875,7 +1876,7 @@ module.exports = function(Chart) {
1875
1876
  },
1876
1877
 
1877
1878
  // Get the number of datasets that display bars. We use this to correctly calculate the bar width
1878
- getBarCount: function getBarCount() {
1879
+ getBarCount: function() {
1879
1880
  var me = this;
1880
1881
  var barCount = 0;
1881
1882
  helpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {
@@ -1887,14 +1888,14 @@ module.exports = function(Chart) {
1887
1888
  return barCount;
1888
1889
  },
1889
1890
 
1890
- update: function update(reset) {
1891
+ update: function(reset) {
1891
1892
  var me = this;
1892
1893
  helpers.each(me.getMeta().data, function(rectangle, index) {
1893
1894
  me.updateElement(rectangle, index, reset);
1894
1895
  }, me);
1895
1896
  },
1896
1897
 
1897
- updateElement: function updateElement(rectangle, index, reset) {
1898
+ updateElement: function(rectangle, index, reset) {
1898
1899
  var me = this;
1899
1900
  var meta = me.getMeta();
1900
1901
  var xScale = me.getScaleForId(meta.xAxisID);
@@ -1941,23 +1942,14 @@ module.exports = function(Chart) {
1941
1942
  if (yScale.options.stacked) {
1942
1943
  var chart = me.chart;
1943
1944
  var datasets = chart.data.datasets;
1944
- var value = datasets[datasetIndex].data[index];
1945
+ var value = Number(datasets[datasetIndex].data[index]);
1945
1946
 
1946
- if (value < 0) {
1947
- for (var i = 0; i < datasetIndex; i++) {
1948
- var negDS = datasets[i];
1949
- var negDSMeta = chart.getDatasetMeta(i);
1950
- if (negDSMeta.bar && negDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
1951
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
1952
- }
1953
- }
1954
- } else {
1955
- for (var j = 0; j < datasetIndex; j++) {
1956
- var posDS = datasets[j];
1957
- var posDSMeta = chart.getDatasetMeta(j);
1958
- if (posDSMeta.bar && posDSMeta.yAxisID === yScale.id && chart.isDatasetVisible(j)) {
1959
- base += posDS.data[index] > 0 ? posDS.data[index] : 0;
1960
- }
1947
+ for (var i = 0; i < datasetIndex; i++) {
1948
+ var currentDs = datasets[i];
1949
+ var currentDsMeta = chart.getDatasetMeta(i);
1950
+ if (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
1951
+ var currentVal = Number(currentDs.data[index]);
1952
+ base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
1961
1953
  }
1962
1954
  }
1963
1955
 
@@ -2006,6 +1998,9 @@ module.exports = function(Chart) {
2006
1998
 
2007
1999
  calculateBarWidth: function(index) {
2008
2000
  var xScale = this.getScaleForId(this.getMeta().xAxisID);
2001
+ if (xScale.options.barThickness) {
2002
+ return xScale.options.barThickness;
2003
+ }
2009
2004
  var ruler = this.getRuler(index);
2010
2005
  return xScale.options.stacked ? ruler.categoryWidth : ruler.barWidth;
2011
2006
  },
@@ -2051,7 +2046,7 @@ module.exports = function(Chart) {
2051
2046
  var me = this;
2052
2047
  var meta = me.getMeta();
2053
2048
  var yScale = me.getScaleForId(meta.yAxisID);
2054
- var value = me.getDataset().data[index];
2049
+ var value = Number(me.getDataset().data[index]);
2055
2050
 
2056
2051
  if (yScale.options.stacked) {
2057
2052
 
@@ -2062,10 +2057,11 @@ module.exports = function(Chart) {
2062
2057
  var ds = me.chart.data.datasets[i];
2063
2058
  var dsMeta = me.chart.getDatasetMeta(i);
2064
2059
  if (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i)) {
2065
- if (ds.data[index] < 0) {
2066
- sumNeg += ds.data[index] || 0;
2060
+ var stackedVal = Number(ds.data[index]);
2061
+ if (stackedVal < 0) {
2062
+ sumNeg += stackedVal || 0;
2067
2063
  } else {
2068
- sumPos += ds.data[index] || 0;
2064
+ sumPos += stackedVal || 0;
2069
2065
  }
2070
2066
  }
2071
2067
  }
@@ -2173,7 +2169,7 @@ module.exports = function(Chart) {
2173
2169
  };
2174
2170
 
2175
2171
  Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
2176
- updateElement: function updateElement(rectangle, index, reset, numBars) {
2172
+ updateElement: function(rectangle, index, reset) {
2177
2173
  var me = this;
2178
2174
  var meta = me.getMeta();
2179
2175
  var xScale = me.getScaleForId(meta.xAxisID);
@@ -2289,24 +2285,16 @@ module.exports = function(Chart) {
2289
2285
  var base = 0;
2290
2286
 
2291
2287
  if (xScale.options.stacked) {
2288
+ var chart = me.chart;
2289
+ var datasets = chart.data.datasets;
2290
+ var value = Number(datasets[datasetIndex].data[index]);
2292
2291
 
2293
- var value = me.chart.data.datasets[datasetIndex].data[index];
2294
-
2295
- if (value < 0) {
2296
- for (var i = 0; i < datasetIndex; i++) {
2297
- var negDS = me.chart.data.datasets[i];
2298
- var negDSMeta = me.chart.getDatasetMeta(i);
2299
- if (negDSMeta.bar && negDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
2300
- base += negDS.data[index] < 0 ? negDS.data[index] : 0;
2301
- }
2302
- }
2303
- } else {
2304
- for (var j = 0; j < datasetIndex; j++) {
2305
- var posDS = me.chart.data.datasets[j];
2306
- var posDSMeta = me.chart.getDatasetMeta(j);
2307
- if (posDSMeta.bar && posDSMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(j)) {
2308
- base += posDS.data[index] > 0 ? posDS.data[index] : 0;
2309
- }
2292
+ for (var i = 0; i < datasetIndex; i++) {
2293
+ var currentDs = datasets[i];
2294
+ var currentDsMeta = chart.getDatasetMeta(i);
2295
+ if (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i)) {
2296
+ var currentVal = Number(currentDs.data[index]);
2297
+ base += value < 0 ? Math.min(currentVal, 0) : Math.max(currentVal, 0);
2310
2298
  }
2311
2299
  }
2312
2300
 
@@ -2355,6 +2343,9 @@ module.exports = function(Chart) {
2355
2343
  calculateBarHeight: function (index) {
2356
2344
  var me = this;
2357
2345
  var yScale = me.getScaleForId(me.getMeta().yAxisID);
2346
+ if (yScale.options.barThickness) {
2347
+ return yScale.options.barThickness;
2348
+ }
2358
2349
  var ruler = me.getRuler(index);
2359
2350
  return yScale.options.stacked ? ruler.categoryHeight : ruler.barHeight;
2360
2351
  },
@@ -2363,7 +2354,7 @@ module.exports = function(Chart) {
2363
2354
  var me = this;
2364
2355
  var meta = me.getMeta();
2365
2356
  var xScale = me.getScaleForId(meta.xAxisID);
2366
- var value = me.getDataset().data[index];
2357
+ var value = Number(me.getDataset().data[index]);
2367
2358
 
2368
2359
  if (xScale.options.stacked) {
2369
2360
 
@@ -2374,10 +2365,11 @@ module.exports = function(Chart) {
2374
2365
  var ds = me.chart.data.datasets[i];
2375
2366
  var dsMeta = me.chart.getDatasetMeta(i);
2376
2367
  if (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i)) {
2377
- if (ds.data[index] < 0) {
2378
- sumNeg += ds.data[index] || 0;
2368
+ var stackedVal = Number(ds.data[index]);
2369
+ if (stackedVal < 0) {
2370
+ sumNeg += stackedVal || 0;
2379
2371
  } else {
2380
- sumPos += ds.data[index] || 0;
2372
+ sumPos += stackedVal || 0;
2381
2373
  }
2382
2374
  }
2383
2375
  }
@@ -2443,7 +2435,7 @@ module.exports = function(Chart) {
2443
2435
 
2444
2436
  tooltips: {
2445
2437
  callbacks: {
2446
- title: function(tooltipItems, data) {
2438
+ title: function() {
2447
2439
  // Title doesn't make sense for scatter since we format the data as a point
2448
2440
  return '';
2449
2441
  },
@@ -2460,7 +2452,7 @@ module.exports = function(Chart) {
2460
2452
 
2461
2453
  dataElementType: Chart.elements.Point,
2462
2454
 
2463
- update: function update(reset) {
2455
+ update: function(reset) {
2464
2456
  var me = this;
2465
2457
  var meta = me.getMeta();
2466
2458
  var points = meta.data;
@@ -2492,7 +2484,7 @@ module.exports = function(Chart) {
2492
2484
 
2493
2485
  // Desired view properties
2494
2486
  _model: {
2495
- x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(data, index, dsIndex, me.chart.isCombo),
2487
+ x: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex, me.chart.isCombo),
2496
2488
  y: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex),
2497
2489
  // Appearance
2498
2490
  radius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data),
@@ -2589,7 +2581,7 @@ module.exports = function(Chart) {
2589
2581
  var meta = chart.getDatasetMeta(0);
2590
2582
  var ds = data.datasets[0];
2591
2583
  var arc = meta.data[i];
2592
- var custom = arc.custom || {};
2584
+ var custom = arc && arc.custom || {};
2593
2585
  var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
2594
2586
  var arcOpts = chart.options.elements.arc;
2595
2587
  var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
@@ -2662,7 +2654,7 @@ module.exports = function(Chart) {
2662
2654
  linkScales: helpers.noop,
2663
2655
 
2664
2656
  // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly
2665
- getRingIndex: function getRingIndex(datasetIndex) {
2657
+ getRingIndex: function(datasetIndex) {
2666
2658
  var ringIndex = 0;
2667
2659
 
2668
2660
  for (var j = 0; j < datasetIndex; ++j) {
@@ -2674,7 +2666,7 @@ module.exports = function(Chart) {
2674
2666
  return ringIndex;
2675
2667
  },
2676
2668
 
2677
- update: function update(reset) {
2669
+ update: function(reset) {
2678
2670
  var me = this;
2679
2671
  var chart = me.chart,
2680
2672
  chartArea = chart.chartArea,
@@ -2709,8 +2701,9 @@ module.exports = function(Chart) {
2709
2701
  minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
2710
2702
  offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
2711
2703
  }
2704
+ chart.borderWidth = me.getMaxBorderWidth(meta.data);
2712
2705
 
2713
- chart.outerRadius = Math.max(minSize / 2, 0);
2706
+ chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
2714
2707
  chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 1, 0);
2715
2708
  chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();
2716
2709
  chart.offsetX = offset.x * chart.outerRadius;
@@ -2732,7 +2725,6 @@ module.exports = function(Chart) {
2732
2725
  chartArea = chart.chartArea,
2733
2726
  opts = chart.options,
2734
2727
  animationOpts = opts.animation,
2735
- arcOpts = opts.elements.arc,
2736
2728
  centerX = (chartArea.left + chartArea.right) / 2,
2737
2729
  centerY = (chartArea.top + chartArea.bottom) / 2,
2738
2730
  startAngle = opts.rotation, // non reset case handled later
@@ -2741,7 +2733,6 @@ module.exports = function(Chart) {
2741
2733
  circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),
2742
2734
  innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius,
2743
2735
  outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius,
2744
- custom = arc.custom || {},
2745
2736
  valueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
2746
2737
 
2747
2738
  helpers.extend(arc, {
@@ -2797,6 +2788,10 @@ module.exports = function(Chart) {
2797
2788
  }
2798
2789
  });
2799
2790
 
2791
+ /*if (total === 0) {
2792
+ total = NaN;
2793
+ }*/
2794
+
2800
2795
  return total;
2801
2796
  },
2802
2797
 
@@ -2807,7 +2802,25 @@ module.exports = function(Chart) {
2807
2802
  } else {
2808
2803
  return 0;
2809
2804
  }
2810
- }
2805
+ },
2806
+
2807
+ //gets the max border or hover width to properly scale pie charts
2808
+ getMaxBorderWidth: function (elements) {
2809
+ var max = 0,
2810
+ index = this.index,
2811
+ length = elements.length,
2812
+ borderWidth,
2813
+ hoverWidth;
2814
+
2815
+ for (var i = 0; i < length; i++) {
2816
+ borderWidth = elements[i]._model ? elements[i]._model.borderWidth : 0;
2817
+ hoverWidth = elements[i]._chart ? elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;
2818
+
2819
+ max = borderWidth > max ? borderWidth : max;
2820
+ max = hoverWidth > max ? hoverWidth : max;
2821
+ }
2822
+ return max;
2823
+ }
2811
2824
  });
2812
2825
  };
2813
2826
 
@@ -2820,6 +2833,7 @@ module.exports = function(Chart) {
2820
2833
 
2821
2834
  Chart.defaults.line = {
2822
2835
  showLines: true,
2836
+ spanGaps: false,
2823
2837
 
2824
2838
  hover: {
2825
2839
  mode: "label"
@@ -2860,7 +2874,7 @@ module.exports = function(Chart) {
2860
2874
  }
2861
2875
  },
2862
2876
 
2863
- update: function update(reset) {
2877
+ update: function(reset) {
2864
2878
  var me = this;
2865
2879
  var meta = me.getMeta();
2866
2880
  var line = meta.dataset;
@@ -2892,7 +2906,7 @@ module.exports = function(Chart) {
2892
2906
  // The default behavior of lines is to break at null values, according
2893
2907
  // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158
2894
2908
  // This option gives linse the ability to span gaps
2895
- spanGaps: dataset.spanGaps ? dataset.spanGaps : false,
2909
+ spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps,
2896
2910
  tension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),
2897
2911
  backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),
2898
2912
  borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),
@@ -2902,6 +2916,7 @@ module.exports = function(Chart) {
2902
2916
  borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),
2903
2917
  borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),
2904
2918
  fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),
2919
+ steppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped),
2905
2920
  // Scale
2906
2921
  scaleTop: scale.top,
2907
2922
  scaleBottom: scale.bottom,
@@ -2994,8 +3009,8 @@ module.exports = function(Chart) {
2994
3009
  dataset.pointHitRadius = dataset.hitRadius;
2995
3010
  }
2996
3011
 
2997
- x = xScale.getPixelForValue(value, index, datasetIndex, me.chart.isCombo);
2998
- y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex, me.chart.isCombo);
3012
+ x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex, me.chart.isCombo);
3013
+ y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex);
2999
3014
 
3000
3015
  // Utility
3001
3016
  point._xScale = xScale;
@@ -3015,12 +3030,13 @@ module.exports = function(Chart) {
3015
3030
  borderColor: me.getPointBorderColor(point, index),
3016
3031
  borderWidth: me.getPointBorderWidth(point, index),
3017
3032
  tension: meta.dataset._model ? meta.dataset._model.tension : 0,
3033
+ steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false,
3018
3034
  // Tooltip
3019
3035
  hitRadius: custom.hitRadius || helpers.getValueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius)
3020
3036
  };
3021
3037
  },
3022
3038
 
3023
- calculatePointY: function(value, index, datasetIndex, isCombo) {
3039
+ calculatePointY: function(value, index, datasetIndex) {
3024
3040
  var me = this;
3025
3041
  var chart = me.chart;
3026
3042
  var meta = me.getMeta();
@@ -3033,19 +3049,21 @@ module.exports = function(Chart) {
3033
3049
  for (i = 0; i < datasetIndex; i++) {
3034
3050
  ds = chart.data.datasets[i];
3035
3051
  dsMeta = chart.getDatasetMeta(i);
3036
- if (dsMeta.type === 'line' && chart.isDatasetVisible(i)) {
3037
- if (ds.data[index] < 0) {
3038
- sumNeg += ds.data[index] || 0;
3052
+ if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) {
3053
+ var stackedRightValue = Number(yScale.getRightValue(ds.data[index]));
3054
+ if (stackedRightValue < 0) {
3055
+ sumNeg += stackedRightValue || 0;
3039
3056
  } else {
3040
- sumPos += ds.data[index] || 0;
3057
+ sumPos += stackedRightValue || 0;
3041
3058
  }
3042
3059
  }
3043
3060
  }
3044
3061
 
3045
- if (value < 0) {
3046
- return yScale.getPixelForValue(sumNeg + value);
3062
+ var rightValue = Number(yScale.getRightValue(value));
3063
+ if (rightValue < 0) {
3064
+ return yScale.getPixelForValue(sumNeg + rightValue);
3047
3065
  } else {
3048
- return yScale.getPixelForValue(sumPos + value);
3066
+ return yScale.getPixelForValue(sumPos + rightValue);
3049
3067
  }
3050
3068
  }
3051
3069
 
@@ -3053,11 +3071,19 @@ module.exports = function(Chart) {
3053
3071
  },
3054
3072
 
3055
3073
  updateBezierControlPoints: function() {
3056
- var meta = this.getMeta();
3057
- var area = this.chart.chartArea;
3058
- var points = meta.data || [];
3074
+ var me = this;
3075
+ var meta = me.getMeta();
3076
+ var area = me.chart.chartArea;
3077
+
3078
+ // only consider points that are drawn in case the spanGaps option is ued
3079
+ var points = (meta.data || []).filter(function(pt) { return !pt._model.skip; });
3059
3080
  var i, ilen, point, model, controlPoints;
3060
3081
 
3082
+ var needToCap = me.chart.options.elements.line.capBezierPoints;
3083
+ function capIfNecessary(pt, min, max) {
3084
+ return needToCap ? Math.max(Math.min(pt, max), min) : pt;
3085
+ }
3086
+
3061
3087
  for (i=0, ilen=points.length; i<ilen; ++i) {
3062
3088
  point = points[i];
3063
3089
  model = point._model;
@@ -3068,10 +3094,10 @@ module.exports = function(Chart) {
3068
3094
  meta.dataset._model.tension
3069
3095
  );
3070
3096
 
3071
- model.controlPointPreviousX = controlPoints.previous.x;
3072
- model.controlPointPreviousY = controlPoints.previous.y;
3073
- model.controlPointNextX = controlPoints.next.x;
3074
- model.controlPointNextY = controlPoints.next.y;
3097
+ model.controlPointPreviousX = capIfNecessary(controlPoints.previous.x, area.left, area.right);
3098
+ model.controlPointPreviousY = capIfNecessary(controlPoints.previous.y, area.top, area.bottom);
3099
+ model.controlPointNextX = capIfNecessary(controlPoints.next.x, area.left, area.right);
3100
+ model.controlPointNextY = capIfNecessary(controlPoints.next.y, area.top, area.bottom);
3075
3101
  }
3076
3102
  },
3077
3103
 
@@ -3142,7 +3168,10 @@ module.exports = function(Chart) {
3142
3168
 
3143
3169
  scale: {
3144
3170
  type: "radialLinear",
3145
- lineArc: true // so that lines are circular
3171
+ lineArc: true, // so that lines are circular
3172
+ ticks: {
3173
+ beginAtZero: true
3174
+ }
3146
3175
  },
3147
3176
 
3148
3177
  //Boolean - Whether to animate the rotation of the chart
@@ -3151,6 +3180,7 @@ module.exports = function(Chart) {
3151
3180
  animateScale: true
3152
3181
  },
3153
3182
 
3183
+ startAngle: -0.5 * Math.PI,
3154
3184
  aspectRatio: 1,
3155
3185
  legendCallback: function(chart) {
3156
3186
  var text = [];
@@ -3239,7 +3269,7 @@ module.exports = function(Chart) {
3239
3269
 
3240
3270
  linkScales: helpers.noop,
3241
3271
 
3242
- update: function update(reset) {
3272
+ update: function(reset) {
3243
3273
  var me = this;
3244
3274
  var chart = me.chart;
3245
3275
  var chartArea = chart.chartArea;
@@ -3264,19 +3294,16 @@ module.exports = function(Chart) {
3264
3294
  updateElement: function(arc, index, reset) {
3265
3295
  var me = this;
3266
3296
  var chart = me.chart;
3267
- var chartArea = chart.chartArea;
3268
3297
  var dataset = me.getDataset();
3269
3298
  var opts = chart.options;
3270
3299
  var animationOpts = opts.animation;
3271
- var arcOpts = opts.elements.arc;
3272
- var custom = arc.custom || {};
3273
3300
  var scale = chart.scale;
3274
3301
  var getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;
3275
3302
  var labels = chart.data.labels;
3276
3303
 
3277
3304
  var circumference = me.calculateCircumference(dataset.data[index]);
3278
- var centerX = (chartArea.left + chartArea.right) / 2;
3279
- var centerY = (chartArea.top + chartArea.bottom) / 2;
3305
+ var centerX = scale.xCenter;
3306
+ var centerY = scale.yCenter;
3280
3307
 
3281
3308
  // If there is NaN data before us, we need to calculate the starting angle correctly.
3282
3309
  // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data
@@ -3288,9 +3315,10 @@ module.exports = function(Chart) {
3288
3315
  }
3289
3316
  }
3290
3317
 
3291
- var negHalfPI = -0.5 * Math.PI;
3318
+ //var negHalfPI = -0.5 * Math.PI;
3319
+ var datasetStartAngle = opts.startAngle;
3292
3320
  var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
3293
- var startAngle = (negHalfPI) + (circumference * visibleCount);
3321
+ var startAngle = datasetStartAngle + (circumference * visibleCount);
3294
3322
  var endAngle = startAngle + (arc.hidden ? 0 : circumference);
3295
3323
 
3296
3324
  var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);
@@ -3307,8 +3335,8 @@ module.exports = function(Chart) {
3307
3335
  y: centerY,
3308
3336
  innerRadius: 0,
3309
3337
  outerRadius: reset ? resetRadius : distance,
3310
- startAngle: reset && animationOpts.animateRotate ? negHalfPI : startAngle,
3311
- endAngle: reset && animationOpts.animateRotate ? negHalfPI : endAngle,
3338
+ startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,
3339
+ endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,
3312
3340
  label: getValueAtIndexOrDefault(labels, index, labels[index])
3313
3341
  }
3314
3342
  });
@@ -3381,7 +3409,7 @@ module.exports = function(Chart) {
3381
3409
  this.updateBezierControlPoints();
3382
3410
  },
3383
3411
 
3384
- update: function update(reset) {
3412
+ update: function(reset) {
3385
3413
  var me = this;
3386
3414
  var meta = me.getMeta();
3387
3415
  var line = meta.dataset;
@@ -3497,7 +3525,7 @@ module.exports = function(Chart) {
3497
3525
  var easingDecimal = ease || 1;
3498
3526
 
3499
3527
  // Transition Point Locations
3500
- helpers.each(meta.data, function(point, index) {
3528
+ helpers.each(meta.data, function(point) {
3501
3529
  point.transition(easingDecimal);
3502
3530
  });
3503
3531
 
@@ -3673,6 +3701,111 @@ module.exports = function(Chart) {
3673
3701
  },{}],22:[function(require,module,exports){
3674
3702
  "use strict";
3675
3703
 
3704
+ module.exports = function(Chart) {
3705
+ // Global Chart canvas helpers object for drawing items to canvas
3706
+ var helpers = Chart.canvasHelpers = {};
3707
+
3708
+ helpers.drawPoint = function(ctx, pointStyle, radius, x, y) {
3709
+ var type, edgeLength, xOffset, yOffset, height, size;
3710
+
3711
+ if (typeof pointStyle === 'object') {
3712
+ type = pointStyle.toString();
3713
+ if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
3714
+ ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);
3715
+ return;
3716
+ }
3717
+ }
3718
+
3719
+ if (isNaN(radius) || radius <= 0) {
3720
+ return;
3721
+ }
3722
+
3723
+ switch (pointStyle) {
3724
+ // Default includes circle
3725
+ default:
3726
+ ctx.beginPath();
3727
+ ctx.arc(x, y, radius, 0, Math.PI * 2);
3728
+ ctx.closePath();
3729
+ ctx.fill();
3730
+ break;
3731
+ case 'triangle':
3732
+ ctx.beginPath();
3733
+ edgeLength = 3 * radius / Math.sqrt(3);
3734
+ height = edgeLength * Math.sqrt(3) / 2;
3735
+ ctx.moveTo(x - edgeLength / 2, y + height / 3);
3736
+ ctx.lineTo(x + edgeLength / 2, y + height / 3);
3737
+ ctx.lineTo(x, y - 2 * height / 3);
3738
+ ctx.closePath();
3739
+ ctx.fill();
3740
+ break;
3741
+ case 'rect':
3742
+ size = 1 / Math.SQRT2 * radius;
3743
+ ctx.beginPath();
3744
+ ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
3745
+ ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
3746
+ break;
3747
+ case 'rectRot':
3748
+ size = 1 / Math.SQRT2 * radius;
3749
+ ctx.beginPath();
3750
+ ctx.moveTo(x - size, y);
3751
+ ctx.lineTo(x, y + size);
3752
+ ctx.lineTo(x + size, y);
3753
+ ctx.lineTo(x, y - size);
3754
+ ctx.closePath();
3755
+ ctx.fill();
3756
+ break;
3757
+ case 'cross':
3758
+ ctx.beginPath();
3759
+ ctx.moveTo(x, y + radius);
3760
+ ctx.lineTo(x, y - radius);
3761
+ ctx.moveTo(x - radius, y);
3762
+ ctx.lineTo(x + radius, y);
3763
+ ctx.closePath();
3764
+ break;
3765
+ case 'crossRot':
3766
+ ctx.beginPath();
3767
+ xOffset = Math.cos(Math.PI / 4) * radius;
3768
+ yOffset = Math.sin(Math.PI / 4) * radius;
3769
+ ctx.moveTo(x - xOffset, y - yOffset);
3770
+ ctx.lineTo(x + xOffset, y + yOffset);
3771
+ ctx.moveTo(x - xOffset, y + yOffset);
3772
+ ctx.lineTo(x + xOffset, y - yOffset);
3773
+ ctx.closePath();
3774
+ break;
3775
+ case 'star':
3776
+ ctx.beginPath();
3777
+ ctx.moveTo(x, y + radius);
3778
+ ctx.lineTo(x, y - radius);
3779
+ ctx.moveTo(x - radius, y);
3780
+ ctx.lineTo(x + radius, y);
3781
+ xOffset = Math.cos(Math.PI / 4) * radius;
3782
+ yOffset = Math.sin(Math.PI / 4) * radius;
3783
+ ctx.moveTo(x - xOffset, y - yOffset);
3784
+ ctx.lineTo(x + xOffset, y + yOffset);
3785
+ ctx.moveTo(x - xOffset, y + yOffset);
3786
+ ctx.lineTo(x + xOffset, y - yOffset);
3787
+ ctx.closePath();
3788
+ break;
3789
+ case 'line':
3790
+ ctx.beginPath();
3791
+ ctx.moveTo(x - radius, y);
3792
+ ctx.lineTo(x + radius, y);
3793
+ ctx.closePath();
3794
+ break;
3795
+ case 'dash':
3796
+ ctx.beginPath();
3797
+ ctx.moveTo(x, y);
3798
+ ctx.lineTo(x + radius, y);
3799
+ ctx.closePath();
3800
+ break;
3801
+ }
3802
+
3803
+ ctx.stroke();
3804
+ };
3805
+ };
3806
+ },{}],23:[function(require,module,exports){
3807
+ "use strict";
3808
+
3676
3809
  module.exports = function(Chart) {
3677
3810
 
3678
3811
  var helpers = Chart.helpers;
@@ -3718,7 +3851,7 @@ module.exports = function(Chart) {
3718
3851
 
3719
3852
  helpers.extend(Chart.Controller.prototype, /** @lends Chart.Controller */ {
3720
3853
 
3721
- initialize: function initialize() {
3854
+ initialize: function() {
3722
3855
  var me = this;
3723
3856
  // Before init plugin notification
3724
3857
  Chart.plugins.notify('beforeInit', [me]);
@@ -3741,12 +3874,12 @@ module.exports = function(Chart) {
3741
3874
  return me;
3742
3875
  },
3743
3876
 
3744
- clear: function clear() {
3877
+ clear: function() {
3745
3878
  helpers.clear(this.chart);
3746
3879
  return this;
3747
3880
  },
3748
3881
 
3749
- stop: function stop() {
3882
+ stop: function() {
3750
3883
  // Stops any current animation loop occuring
3751
3884
  Chart.animationService.cancelAnimation(this);
3752
3885
  return this;
@@ -3788,7 +3921,7 @@ module.exports = function(Chart) {
3788
3921
  return me;
3789
3922
  },
3790
3923
 
3791
- ensureScalesHaveIDs: function ensureScalesHaveIDs() {
3924
+ ensureScalesHaveIDs: function() {
3792
3925
  var options = this.options;
3793
3926
  var scalesOptions = options.scales || {};
3794
3927
  var scaleOptions = options.scale;
@@ -3809,7 +3942,7 @@ module.exports = function(Chart) {
3809
3942
  /**
3810
3943
  * Builds a map of scale ID to scale object for future lookup.
3811
3944
  */
3812
- buildScales: function buildScales() {
3945
+ buildScales: function() {
3813
3946
  var me = this;
3814
3947
  var options = me.options;
3815
3948
  var scales = me.scales = {};
@@ -3827,7 +3960,7 @@ module.exports = function(Chart) {
3827
3960
  items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true });
3828
3961
  }
3829
3962
 
3830
- helpers.each(items, function(item, index) {
3963
+ helpers.each(items, function(item) {
3831
3964
  var scaleOptions = item.options;
3832
3965
  var scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);
3833
3966
  var scaleClass = Chart.scaleService.getScaleConstructor(scaleType);
@@ -3859,7 +3992,7 @@ module.exports = function(Chart) {
3859
3992
  Chart.layoutService.update(this, this.chart.width, this.chart.height);
3860
3993
  },
3861
3994
 
3862
- buildOrUpdateControllers: function buildOrUpdateControllers() {
3995
+ buildOrUpdateControllers: function() {
3863
3996
  var me = this;
3864
3997
  var types = [];
3865
3998
  var newControllers = [];
@@ -3892,7 +4025,7 @@ module.exports = function(Chart) {
3892
4025
  return newControllers;
3893
4026
  },
3894
4027
 
3895
- resetElements: function resetElements() {
4028
+ resetElements: function() {
3896
4029
  var me = this;
3897
4030
  helpers.each(me.data.datasets, function(dataset, datasetIndex) {
3898
4031
  me.getDatasetMeta(datasetIndex).controller.reset();
@@ -4048,7 +4181,7 @@ module.exports = function(Chart) {
4048
4181
  helpers.each(me.data.datasets, function(dataset, datasetIndex) {
4049
4182
  if (me.isDatasetVisible(datasetIndex)) {
4050
4183
  var meta = me.getDatasetMeta(datasetIndex);
4051
- helpers.each(meta.data, function(element, index) {
4184
+ helpers.each(meta.data, function(element) {
4052
4185
  if (element.inRange(eventPosition.x, eventPosition.y)) {
4053
4186
  elementsArray.push(element);
4054
4187
  return elementsArray;
@@ -4057,7 +4190,7 @@ module.exports = function(Chart) {
4057
4190
  }
4058
4191
  });
4059
4192
 
4060
- return elementsArray;
4193
+ return elementsArray.slice(0, 1);
4061
4194
  },
4062
4195
 
4063
4196
  getElementsAtEvent: function(e) {
@@ -4084,10 +4217,52 @@ module.exports = function(Chart) {
4084
4217
  return elementsArray;
4085
4218
  }
4086
4219
 
4220
+ helpers.each(me.data.datasets, function(dataset, datasetIndex) {
4221
+ if (me.isDatasetVisible(datasetIndex)) {
4222
+ var meta = me.getDatasetMeta(datasetIndex),
4223
+ element = meta.data[found._index];
4224
+ if(element && !element._view.skip){
4225
+ elementsArray.push(element);
4226
+ }
4227
+ }
4228
+ }, me);
4229
+
4230
+ return elementsArray;
4231
+ },
4232
+
4233
+ getElementsAtXAxis: function(e) {
4234
+ var me = this;
4235
+ var eventPosition = helpers.getRelativePosition(e, me.chart);
4236
+ var elementsArray = [];
4237
+
4238
+ var found = (function() {
4239
+ if (me.data.datasets) {
4240
+ for (var i = 0; i < me.data.datasets.length; i++) {
4241
+ var meta = me.getDatasetMeta(i);
4242
+ if (me.isDatasetVisible(i)) {
4243
+ for (var j = 0; j < meta.data.length; j++) {
4244
+ if (meta.data[j].inLabelRange(eventPosition.x, eventPosition.y)) {
4245
+ return meta.data[j];
4246
+ }
4247
+ }
4248
+ }
4249
+ }
4250
+ }
4251
+ }).call(me);
4252
+
4253
+ if (!found) {
4254
+ return elementsArray;
4255
+ }
4256
+
4087
4257
  helpers.each(me.data.datasets, function(dataset, datasetIndex) {
4088
4258
  if (me.isDatasetVisible(datasetIndex)) {
4089
4259
  var meta = me.getDatasetMeta(datasetIndex);
4090
- elementsArray.push(meta.data[found._index]);
4260
+ var index = helpers.findIndex(meta.data, function (it) {
4261
+ return found._model.x === it._model.x;
4262
+ });
4263
+ if(index !== -1 && !meta.data[index]._view.skip) {
4264
+ elementsArray.push(meta.data[index]);
4265
+ }
4091
4266
  }
4092
4267
  }, me);
4093
4268
 
@@ -4103,6 +4278,8 @@ module.exports = function(Chart) {
4103
4278
  return me.getElementsAtEvent(e);
4104
4279
  case 'dataset':
4105
4280
  return me.getDatasetAtEvent(e);
4281
+ case 'x-axis':
4282
+ return me.getElementsAtXAxis(e);
4106
4283
  default:
4107
4284
  return e;
4108
4285
  }
@@ -4159,11 +4336,11 @@ module.exports = function(Chart) {
4159
4336
  return typeof meta.hidden === 'boolean'? !meta.hidden : !this.data.datasets[datasetIndex].hidden;
4160
4337
  },
4161
4338
 
4162
- generateLegend: function generateLegend() {
4339
+ generateLegend: function() {
4163
4340
  return this.options.legendCallback(this);
4164
4341
  },
4165
4342
 
4166
- destroy: function destroy() {
4343
+ destroy: function() {
4167
4344
  var me = this;
4168
4345
  me.stop();
4169
4346
  me.clear();
@@ -4189,11 +4366,11 @@ module.exports = function(Chart) {
4189
4366
  delete Chart.instances[me.id];
4190
4367
  },
4191
4368
 
4192
- toBase64Image: function toBase64Image() {
4369
+ toBase64Image: function() {
4193
4370
  return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
4194
4371
  },
4195
4372
 
4196
- initToolTip: function initToolTip() {
4373
+ initToolTip: function() {
4197
4374
  var me = this;
4198
4375
  me.tooltip = new Chart.Tooltip({
4199
4376
  _chart: me.chart,
@@ -4203,7 +4380,7 @@ module.exports = function(Chart) {
4203
4380
  }, me);
4204
4381
  },
4205
4382
 
4206
- bindEvents: function bindEvents() {
4383
+ bindEvents: function() {
4207
4384
  var me = this;
4208
4385
  helpers.bindEvents(me, me.options.events, function(evt) {
4209
4386
  me.eventHandler(evt);
@@ -4220,6 +4397,7 @@ module.exports = function(Chart) {
4220
4397
  break;
4221
4398
  case 'label':
4222
4399
  case 'dataset':
4400
+ case 'x-axis':
4223
4401
  // elements = elements;
4224
4402
  break;
4225
4403
  default:
@@ -4313,7 +4491,7 @@ module.exports = function(Chart) {
4313
4491
  });
4314
4492
  };
4315
4493
 
4316
- },{}],23:[function(require,module,exports){
4494
+ },{}],24:[function(require,module,exports){
4317
4495
  "use strict";
4318
4496
 
4319
4497
  module.exports = function(Chart) {
@@ -4421,7 +4599,7 @@ module.exports = function(Chart) {
4421
4599
  me.updateElement(element, index, true);
4422
4600
  },
4423
4601
 
4424
- buildOrUpdateElements: function buildOrUpdateElements() {
4602
+ buildOrUpdateElements: function() {
4425
4603
  // Handle the number of data points changing
4426
4604
  var meta = this.getMeta(),
4427
4605
  md = meta.data,
@@ -4444,7 +4622,7 @@ module.exports = function(Chart) {
4444
4622
 
4445
4623
  draw: function(ease) {
4446
4624
  var easingDecimal = ease || 1;
4447
- helpers.each(this.getMeta().data, function(element, index) {
4625
+ helpers.each(this.getMeta().data, function(element) {
4448
4626
  element.transition(easingDecimal).draw();
4449
4627
  });
4450
4628
  },
@@ -4454,7 +4632,6 @@ module.exports = function(Chart) {
4454
4632
  index = element._index,
4455
4633
  custom = element.custom || {},
4456
4634
  valueOrDefault = helpers.getValueAtIndexOrDefault,
4457
- color = helpers.color,
4458
4635
  model = element._model;
4459
4636
 
4460
4637
  model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor);
@@ -4467,7 +4644,6 @@ module.exports = function(Chart) {
4467
4644
  index = element._index,
4468
4645
  custom = element.custom || {},
4469
4646
  valueOrDefault = helpers.getValueAtIndexOrDefault,
4470
- color = helpers.color,
4471
4647
  getHoverColor = helpers.getHoverColor,
4472
4648
  model = element._model;
4473
4649
 
@@ -4475,11 +4651,13 @@ module.exports = function(Chart) {
4475
4651
  model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor));
4476
4652
  model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
4477
4653
  }
4478
- });
4654
+
4655
+ });
4656
+
4479
4657
 
4480
4658
  Chart.DatasetController.extend = helpers.inherits;
4481
4659
  };
4482
- },{}],24:[function(require,module,exports){
4660
+ },{}],25:[function(require,module,exports){
4483
4661
  "use strict";
4484
4662
 
4485
4663
  module.exports = function(Chart) {
@@ -4585,7 +4763,7 @@ module.exports = function(Chart) {
4585
4763
 
4586
4764
  };
4587
4765
 
4588
- },{}],25:[function(require,module,exports){
4766
+ },{}],26:[function(require,module,exports){
4589
4767
  /*global window: false */
4590
4768
  /*global document: false */
4591
4769
  "use strict";
@@ -5534,7 +5712,7 @@ module.exports = function(Chart) {
5534
5712
  };
5535
5713
  };
5536
5714
 
5537
- },{"3":3}],26:[function(require,module,exports){
5715
+ },{"3":3}],27:[function(require,module,exports){
5538
5716
  "use strict";
5539
5717
 
5540
5718
  module.exports = function() {
@@ -5543,7 +5721,11 @@ module.exports = function() {
5543
5721
  var Chart = function(context, config) {
5544
5722
  var me = this;
5545
5723
  var helpers = Chart.helpers;
5546
- me.config = config;
5724
+ me.config = config || {
5725
+ data: {
5726
+ datasets: []
5727
+ }
5728
+ };
5547
5729
 
5548
5730
  // Support a jQuery'd canvas element
5549
5731
  if (context.length && context[0].getContext) {
@@ -5582,10 +5764,7 @@ module.exports = function() {
5582
5764
 
5583
5765
  // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
5584
5766
  helpers.retinaScale(me);
5585
-
5586
- if (config) {
5587
- me.controller = new Chart.Controller(me);
5588
- }
5767
+ me.controller = new Chart.Controller(me);
5589
5768
 
5590
5769
  // Always bind this so that if the responsive state changes we still work
5591
5770
  helpers.addResizeListener(context.canvas.parentNode, function() {
@@ -5645,7 +5824,7 @@ module.exports = function() {
5645
5824
 
5646
5825
  };
5647
5826
 
5648
- },{}],27:[function(require,module,exports){
5827
+ },{}],28:[function(require,module,exports){
5649
5828
  "use strict";
5650
5829
 
5651
5830
  module.exports = function(Chart) {
@@ -5915,8 +6094,6 @@ module.exports = function(Chart) {
5915
6094
  // Step 7 - Position the boxes
5916
6095
  var left = xPadding;
5917
6096
  var top = yPadding;
5918
- var right = 0;
5919
- var bottom = 0;
5920
6097
 
5921
6098
  helpers.each(leftBoxes.concat(topBoxes), placeBox);
5922
6099
 
@@ -5970,7 +6147,7 @@ module.exports = function(Chart) {
5970
6147
  };
5971
6148
  };
5972
6149
 
5973
- },{}],28:[function(require,module,exports){
6150
+ },{}],29:[function(require,module,exports){
5974
6151
  "use strict";
5975
6152
 
5976
6153
  module.exports = function(Chart) {
@@ -6025,6 +6202,7 @@ module.exports = function(Chart) {
6025
6202
  lineJoin: dataset.borderJoinStyle,
6026
6203
  lineWidth: dataset.borderWidth,
6027
6204
  strokeStyle: dataset.borderColor,
6205
+ pointStyle: dataset.pointStyle,
6028
6206
 
6029
6207
  // Below is extra data used for toggling the datasets
6030
6208
  datasetIndex: i
@@ -6174,7 +6352,11 @@ module.exports = function(Chart) {
6174
6352
  ctx.textBaseline = 'top';
6175
6353
 
6176
6354
  helpers.each(me.legendItems, function(legendItem, i) {
6177
- var width = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
6355
+ var boxWidth = labelOpts.usePointStyle ?
6356
+ fontSize * Math.sqrt(2) :
6357
+ labelOpts.boxWidth;
6358
+
6359
+ var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
6178
6360
  if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) {
6179
6361
  totalHeight += fontSize + (labelOpts.padding);
6180
6362
  lineWidths[lineWidths.length] = me.left;
@@ -6202,7 +6384,11 @@ module.exports = function(Chart) {
6202
6384
  var itemHeight = fontSize + vPadding;
6203
6385
 
6204
6386
  helpers.each(me.legendItems, function(legendItem, i) {
6205
- var itemWidth = labelOpts.boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
6387
+ // If usePointStyle is set, multiple boxWidth by 2 since it represents
6388
+ // the radius and not truly the width
6389
+ var boxWidth = labelOpts.usePointStyle ? 2 * labelOpts.boxWidth : labelOpts.boxWidth;
6390
+
6391
+ var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
6206
6392
 
6207
6393
  // If too tall, go to new column
6208
6394
  if (currentColHeight + itemHeight > minSize.height) {
@@ -6250,7 +6436,6 @@ module.exports = function(Chart) {
6250
6436
  var globalDefault = Chart.defaults.global,
6251
6437
  lineDefault = globalDefault.elements.line,
6252
6438
  legendWidth = me.width,
6253
- legendHeight = me.height,
6254
6439
  lineWidths = me.lineWidths;
6255
6440
 
6256
6441
  if (opts.display) {
@@ -6276,6 +6461,10 @@ module.exports = function(Chart) {
6276
6461
 
6277
6462
  // current position
6278
6463
  var drawLegendBox = function(x, y, legendItem) {
6464
+ if (isNaN(boxWidth) || boxWidth <= 0) {
6465
+ return;
6466
+ }
6467
+
6279
6468
  // Set the ctx for the box
6280
6469
  ctx.save();
6281
6470
 
@@ -6291,9 +6480,22 @@ module.exports = function(Chart) {
6291
6480
  ctx.setLineDash(itemOrDefault(legendItem.lineDash, lineDefault.borderDash));
6292
6481
  }
6293
6482
 
6294
- // Draw the box
6295
- ctx.strokeRect(x, y, boxWidth, fontSize);
6296
- ctx.fillRect(x, y, boxWidth, fontSize);
6483
+ if (opts.labels && opts.labels.usePointStyle) {
6484
+ // Recalulate x and y for drawPoint() because its expecting
6485
+ // x and y to be center of figure (instead of top left)
6486
+ var radius = fontSize * Math.SQRT2 / 2;
6487
+ var offSet = radius / Math.SQRT2;
6488
+ var centerX = x + offSet;
6489
+ var centerY = y + offSet;
6490
+
6491
+ // Draw pointStyle as legend symbol
6492
+ Chart.canvasHelpers.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY);
6493
+ }
6494
+ else {
6495
+ // Draw box as legend symbol
6496
+ ctx.strokeRect(x, y, boxWidth, fontSize);
6497
+ ctx.fillRect(x, y, boxWidth, fontSize);
6498
+ }
6297
6499
 
6298
6500
  ctx.restore();
6299
6501
  };
@@ -6321,7 +6523,7 @@ module.exports = function(Chart) {
6321
6523
  } else {
6322
6524
  cursor = {
6323
6525
  x: me.left + labelOpts.padding,
6324
- y: me.top,
6526
+ y: me.top + labelOpts.padding,
6325
6527
  line: 0
6326
6528
  };
6327
6529
  }
@@ -6329,13 +6531,15 @@ module.exports = function(Chart) {
6329
6531
  var itemHeight = fontSize + labelOpts.padding;
6330
6532
  helpers.each(me.legendItems, function(legendItem, i) {
6331
6533
  var textWidth = ctx.measureText(legendItem.text).width,
6332
- width = boxWidth + (fontSize / 2) + textWidth,
6534
+ width = labelOpts.usePointStyle ?
6535
+ fontSize + (fontSize / 2) + textWidth :
6536
+ boxWidth + (fontSize / 2) + textWidth,
6333
6537
  x = cursor.x,
6334
6538
  y = cursor.y;
6335
6539
 
6336
6540
  if (isHorizontal) {
6337
6541
  if (x + width >= legendWidth) {
6338
- y = cursor.y += fontSize + (labelOpts.padding);
6542
+ y = cursor.y += itemHeight;
6339
6543
  cursor.line++;
6340
6544
  x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2);
6341
6545
  }
@@ -6347,7 +6551,6 @@ module.exports = function(Chart) {
6347
6551
  }
6348
6552
  }
6349
6553
 
6350
-
6351
6554
  drawLegendBox(x, y, legendItem);
6352
6555
 
6353
6556
  hitboxes[i].left = x;
@@ -6411,7 +6614,7 @@ module.exports = function(Chart) {
6411
6614
  });
6412
6615
  };
6413
6616
 
6414
- },{}],29:[function(require,module,exports){
6617
+ },{}],30:[function(require,module,exports){
6415
6618
  "use strict";
6416
6619
 
6417
6620
  module.exports = function(Chart) {
@@ -6542,7 +6745,7 @@ module.exports = function(Chart) {
6542
6745
  Chart.pluginService = Chart.plugins;
6543
6746
  };
6544
6747
 
6545
- },{}],30:[function(require,module,exports){
6748
+ },{}],31:[function(require,module,exports){
6546
6749
  "use strict";
6547
6750
 
6548
6751
  module.exports = function(Chart) {
@@ -6829,9 +7032,6 @@ module.exports = function(Chart) {
6829
7032
  var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily);
6830
7033
 
6831
7034
  var scaleLabelFontSize = helpers.getValueOrDefault(scaleLabelOpts.fontSize, globalDefaults.defaultFontSize);
6832
- var scaleLabelFontStyle = helpers.getValueOrDefault(scaleLabelOpts.fontStyle, globalDefaults.defaultFontStyle);
6833
- var scaleLabelFontFamily = helpers.getValueOrDefault(scaleLabelOpts.fontFamily, globalDefaults.defaultFontFamily);
6834
- var scaleLabelFont = helpers.fontString(scaleLabelFontSize, scaleLabelFontStyle, scaleLabelFontFamily);
6835
7035
 
6836
7036
  var tickMarkLength = opts.gridLines.tickMarkLength;
6837
7037
 
@@ -6938,7 +7138,7 @@ module.exports = function(Chart) {
6938
7138
  },
6939
7139
 
6940
7140
  // 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
6941
- getRightValue: function getRightValue(rawValue) {
7141
+ getRightValue: function(rawValue) {
6942
7142
  // Null and undefined values first
6943
7143
  if (rawValue === null || typeof(rawValue) === 'undefined') {
6944
7144
  return NaN;
@@ -6952,7 +7152,7 @@ module.exports = function(Chart) {
6952
7152
  if ((rawValue instanceof Date) || (rawValue.isValid)) {
6953
7153
  return rawValue;
6954
7154
  } else {
6955
- return getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
7155
+ return this.getRightValue(this.isHorizontal() ? rawValue.x : rawValue.y);
6956
7156
  }
6957
7157
  }
6958
7158
 
@@ -7059,9 +7259,7 @@ module.exports = function(Chart) {
7059
7259
 
7060
7260
  var labelRotationRadians = helpers.toRadians(me.labelRotation);
7061
7261
  var cosRotation = Math.cos(labelRotationRadians);
7062
- var sinRotation = Math.sin(labelRotationRadians);
7063
7262
  var longestRotatedLabel = me.longestLabelWidth * cosRotation;
7064
- var rotatedLabelHeight = tickFontSize * sinRotation;
7065
7263
 
7066
7264
  // Make sure we draw text in the correct color and font
7067
7265
  context.fillStyle = tickFontColor;
@@ -7071,11 +7269,11 @@ module.exports = function(Chart) {
7071
7269
  if (isHorizontal) {
7072
7270
  skipRatio = false;
7073
7271
 
7074
- // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation
7075
- // See #2584
7076
- if (isRotated) {
7077
- longestRotatedLabel /= 2;
7078
- }
7272
+ // Only calculate the skip ratio with the half width of longestRotateLabel if we got an actual rotation
7273
+ // See #2584
7274
+ if (isRotated) {
7275
+ longestRotatedLabel /= 2;
7276
+ }
7079
7277
 
7080
7278
  if ((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length > (me.width - (me.paddingLeft + me.paddingRight))) {
7081
7279
  skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * me.ticks.length) / (me.width - (me.paddingLeft + me.paddingRight)));
@@ -7298,7 +7496,7 @@ module.exports = function(Chart) {
7298
7496
  });
7299
7497
  };
7300
7498
 
7301
- },{}],31:[function(require,module,exports){
7499
+ },{}],32:[function(require,module,exports){
7302
7500
  "use strict";
7303
7501
 
7304
7502
  module.exports = function(Chart) {
@@ -7339,7 +7537,7 @@ module.exports = function(Chart) {
7339
7537
  }
7340
7538
  };
7341
7539
  };
7342
- },{}],32:[function(require,module,exports){
7540
+ },{}],33:[function(require,module,exports){
7343
7541
  "use strict";
7344
7542
 
7345
7543
  module.exports = function(Chart) {
@@ -7453,9 +7651,7 @@ module.exports = function(Chart) {
7453
7651
 
7454
7652
  beforeFit: noop,
7455
7653
  fit: function() {
7456
-
7457
7654
  var me = this,
7458
- ctx = me.ctx,
7459
7655
  valueOrDefault = helpers.getValueOrDefault,
7460
7656
  opts = me.options,
7461
7657
  globalDefaults = Chart.defaults.global,
@@ -7547,7 +7743,7 @@ module.exports = function(Chart) {
7547
7743
  });
7548
7744
  };
7549
7745
 
7550
- },{}],33:[function(require,module,exports){
7746
+ },{}],34:[function(require,module,exports){
7551
7747
  "use strict";
7552
7748
 
7553
7749
  module.exports = function(Chart) {
@@ -7666,9 +7862,11 @@ module.exports = function(Chart) {
7666
7862
 
7667
7863
  var x = 0,
7668
7864
  y = 0;
7669
- for (i = 0, len - xPositions.length; i < len; ++i) {
7670
- x += xPositions[i];
7671
- y += yPositions[i];
7865
+ for (i = 0; i < xPositions.length; ++i) {
7866
+ if (xPositions[ i ]) {
7867
+ x += xPositions[i];
7868
+ y += yPositions[i];
7869
+ }
7672
7870
  }
7673
7871
 
7674
7872
  return {
@@ -7706,8 +7904,8 @@ module.exports = function(Chart) {
7706
7904
  // Positioning
7707
7905
  xPadding: tooltipOpts.xPadding,
7708
7906
  yPadding: tooltipOpts.yPadding,
7709
- xAlign : tooltipOpts.yAlign,
7710
- yAlign : tooltipOpts.xAlign,
7907
+ xAlign : tooltipOpts.xAlign,
7908
+ yAlign : tooltipOpts.yAlign,
7711
7909
 
7712
7910
  // Body
7713
7911
  bodyFontColor: tooltipOpts.bodyFontColor,
@@ -7878,7 +8076,7 @@ module.exports = function(Chart) {
7878
8076
 
7879
8077
  return me;
7880
8078
  },
7881
- getTooltipSize: function getTooltipSize(vm) {
8079
+ getTooltipSize: function(vm) {
7882
8080
  var ctx = this._chart.ctx;
7883
8081
 
7884
8082
  var size = {
@@ -7941,7 +8139,7 @@ module.exports = function(Chart) {
7941
8139
 
7942
8140
  return size;
7943
8141
  },
7944
- determineAlignment: function determineAlignment(size) {
8142
+ determineAlignment: function(size) {
7945
8143
  var me = this;
7946
8144
  var model = me._model;
7947
8145
  var chart = me._chart;
@@ -8003,7 +8201,7 @@ module.exports = function(Chart) {
8003
8201
  }
8004
8202
  }
8005
8203
  },
8006
- getBackgroundPoint: function getBackgroundPoint(vm, size) {
8204
+ getBackgroundPoint: function(vm, size) {
8007
8205
  // Background Position
8008
8206
  var pt = {
8009
8207
  x: vm.x,
@@ -8048,7 +8246,7 @@ module.exports = function(Chart) {
8048
8246
 
8049
8247
  return pt;
8050
8248
  },
8051
- drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {
8249
+ drawCaret: function(tooltipPoint, size, opacity) {
8052
8250
  var vm = this._view;
8053
8251
  var ctx = this._chart.ctx;
8054
8252
  var x1, x2, x3;
@@ -8112,7 +8310,7 @@ module.exports = function(Chart) {
8112
8310
  ctx.closePath();
8113
8311
  ctx.fill();
8114
8312
  },
8115
- drawTitle: function drawTitle(pt, vm, ctx, opacity) {
8313
+ drawTitle: function(pt, vm, ctx, opacity) {
8116
8314
  var title = vm.title;
8117
8315
 
8118
8316
  if (title.length) {
@@ -8137,7 +8335,7 @@ module.exports = function(Chart) {
8137
8335
  }
8138
8336
  }
8139
8337
  },
8140
- drawBody: function drawBody(pt, vm, ctx, opacity) {
8338
+ drawBody: function(pt, vm, ctx, opacity) {
8141
8339
  var bodyFontSize = vm.bodyFontSize;
8142
8340
  var bodySpacing = vm.bodySpacing;
8143
8341
  var body = vm.body;
@@ -8198,7 +8396,7 @@ module.exports = function(Chart) {
8198
8396
  helpers.each(vm.afterBody, fillLineOfText);
8199
8397
  pt.y -= bodySpacing; // Remove last body spacing
8200
8398
  },
8201
- drawFooter: function drawFooter(pt, vm, ctx, opacity) {
8399
+ drawFooter: function(pt, vm, ctx, opacity) {
8202
8400
  var footer = vm.footer;
8203
8401
 
8204
8402
  if (footer.length) {
@@ -8217,7 +8415,7 @@ module.exports = function(Chart) {
8217
8415
  });
8218
8416
  }
8219
8417
  },
8220
- draw: function draw() {
8418
+ draw: function() {
8221
8419
  var ctx = this._chart.ctx;
8222
8420
  var vm = this._view;
8223
8421
 
@@ -8242,7 +8440,7 @@ module.exports = function(Chart) {
8242
8440
  ctx.fill();
8243
8441
 
8244
8442
  // Draw Caret
8245
- this.drawCaret(pt, tooltipSize, opacity, vm.caretPadding);
8443
+ this.drawCaret(pt, tooltipSize, opacity);
8246
8444
 
8247
8445
  // Draw Title, Body, and Footer
8248
8446
  pt.x += vm.xPadding;
@@ -8261,10 +8459,10 @@ module.exports = function(Chart) {
8261
8459
  });
8262
8460
  };
8263
8461
 
8264
- },{}],34:[function(require,module,exports){
8462
+ },{}],35:[function(require,module,exports){
8265
8463
  "use strict";
8266
8464
 
8267
- module.exports = function(Chart, moment) {
8465
+ module.exports = function(Chart) {
8268
8466
 
8269
8467
  var helpers = Chart.helpers,
8270
8468
  globalOpts = Chart.defaults.global;
@@ -8356,7 +8554,7 @@ module.exports = function(Chart, moment) {
8356
8554
  });
8357
8555
  };
8358
8556
 
8359
- },{}],35:[function(require,module,exports){
8557
+ },{}],36:[function(require,module,exports){
8360
8558
  "use strict";
8361
8559
 
8362
8560
  module.exports = function(Chart) {
@@ -8373,108 +8571,110 @@ module.exports = function(Chart) {
8373
8571
  borderDash: [],
8374
8572
  borderDashOffset: 0.0,
8375
8573
  borderJoinStyle: 'miter',
8574
+ capBezierPoints: true,
8376
8575
  fill: true // do we fill in the area between the line and its base axis
8377
8576
  };
8378
8577
 
8379
8578
  Chart.elements.Line = Chart.Element.extend({
8380
- lineToNextPoint: function(previousPoint, point, nextPoint, skipHandler, previousSkipHandler) {
8381
- var me = this;
8382
- var ctx = me._chart.ctx;
8383
- var spanGaps = me._view ? me._view.spanGaps : false;
8384
-
8385
- if (point._view.skip && !spanGaps) {
8386
- skipHandler.call(me, previousPoint, point, nextPoint);
8387
- } else if (previousPoint._view.skip && !spanGaps) {
8388
- previousSkipHandler.call(me, previousPoint, point, nextPoint);
8389
- } else if (point._view.tension === 0) {
8390
- ctx.lineTo(point._view.x, point._view.y);
8391
- } else {
8392
- // Line between points
8393
- ctx.bezierCurveTo(
8394
- previousPoint._view.controlPointNextX,
8395
- previousPoint._view.controlPointNextY,
8396
- point._view.controlPointPreviousX,
8397
- point._view.controlPointPreviousY,
8398
- point._view.x,
8399
- point._view.y
8400
- );
8401
- }
8402
- },
8403
-
8404
8579
  draw: function() {
8405
8580
  var me = this;
8406
-
8407
8581
  var vm = me._view;
8582
+ var spanGaps = vm.spanGaps;
8583
+ var scaleZero = vm.scaleZero;
8584
+ var loop = me._loop;
8585
+
8408
8586
  var ctx = me._chart.ctx;
8409
- var first = me._children[0];
8410
- var last = me._children[me._children.length - 1];
8587
+ ctx.save();
8411
8588
 
8412
- function loopBackToStart(drawLineToCenter) {
8413
- if (!first._view.skip && !last._view.skip) {
8414
- // Draw a bezier line from last to first
8589
+ // Helper function to draw a line to a point
8590
+ function lineToPoint(previousPoint, point) {
8591
+ var vm = point._view;
8592
+ if (point._view.steppedLine === true) {
8593
+ ctx.lineTo(point._view.x, previousPoint._view.y);
8594
+ ctx.lineTo(point._view.x, point._view.y);
8595
+ } else if (point._view.tension === 0) {
8596
+ ctx.lineTo(vm.x, vm.y);
8597
+ } else {
8415
8598
  ctx.bezierCurveTo(
8416
- last._view.controlPointNextX,
8417
- last._view.controlPointNextY,
8418
- first._view.controlPointPreviousX,
8419
- first._view.controlPointPreviousY,
8420
- first._view.x,
8421
- first._view.y
8599
+ previousPoint._view.controlPointNextX,
8600
+ previousPoint._view.controlPointNextY,
8601
+ vm.controlPointPreviousX,
8602
+ vm.controlPointPreviousY,
8603
+ vm.x,
8604
+ vm.y
8422
8605
  );
8423
- } else if (drawLineToCenter) {
8424
- // Go to center
8425
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
8426
8606
  }
8427
8607
  }
8428
8608
 
8429
- ctx.save();
8609
+ var points = me._children.slice(); // clone array
8610
+ var lastDrawnIndex = -1;
8611
+
8612
+ // If we are looping, adding the first point again
8613
+ if (loop && points.length) {
8614
+ points.push(points[0]);
8615
+ }
8430
8616
 
8431
- // If we had points and want to fill this line, do so.
8432
- if (me._children.length > 0 && vm.fill) {
8433
- // Draw the background first (so the border is always on top)
8617
+ var index, current, previous, currentVM;
8618
+
8619
+ // Fill Line
8620
+ if (points.length && vm.fill) {
8434
8621
  ctx.beginPath();
8435
8622
 
8436
- helpers.each(me._children, function(point, index) {
8437
- var previous = helpers.previousItem(me._children, index);
8438
- var next = helpers.nextItem(me._children, index);
8623
+ for (index = 0; index < points.length; ++index) {
8624
+ current = points[index];
8625
+ previous = helpers.previousItem(points, index);
8626
+ currentVM = current._view;
8439
8627
 
8440
8628
  // First point moves to it's starting position no matter what
8441
8629
  if (index === 0) {
8442
- if (me._loop) {
8443
- ctx.moveTo(vm.scaleZero.x, vm.scaleZero.y);
8630
+ if (loop) {
8631
+ ctx.moveTo(scaleZero.x, scaleZero.y);
8444
8632
  } else {
8445
- ctx.moveTo(point._view.x, vm.scaleZero);
8633
+ ctx.moveTo(currentVM.x, scaleZero);
8446
8634
  }
8447
8635
 
8448
- if (point._view.skip) {
8449
- if (!me._loop) {
8450
- ctx.moveTo(next._view.x, me._view.scaleZero);
8451
- }
8452
- } else {
8453
- ctx.lineTo(point._view.x, point._view.y);
8636
+ if (!currentVM.skip) {
8637
+ lastDrawnIndex = index;
8638
+ ctx.lineTo(currentVM.x, currentVM.y);
8454
8639
  }
8455
8640
  } else {
8456
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
8457
- if (me._loop) {
8458
- // Go to center
8459
- ctx.lineTo(me._view.scaleZero.x, me._view.scaleZero.y);
8641
+ previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
8642
+
8643
+ if (currentVM.skip) {
8644
+ // Only do this if this is the first point that is skipped
8645
+ if (!spanGaps && lastDrawnIndex === (index - 1)) {
8646
+ if (loop) {
8647
+ ctx.lineTo(scaleZero.x, scaleZero.y);
8648
+ } else {
8649
+ ctx.lineTo(previous._view.x, scaleZero);
8650
+ }
8651
+ }
8652
+ } else {
8653
+ if (lastDrawnIndex !== (index - 1)) {
8654
+ // 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.
8655
+ // If the first data point is NaN, then there is no real gap to skip
8656
+ if (spanGaps && lastDrawnIndex !== -1) {
8657
+ // We are spanning the gap, so simple draw a line to this point
8658
+ lineToPoint(previous, current);
8659
+ } else {
8660
+ if (loop) {
8661
+ ctx.lineTo(currentVM.x, currentVM.y);
8662
+ } else {
8663
+ ctx.lineTo(currentVM.x, scaleZero);
8664
+ ctx.lineTo(currentVM.x, currentVM.y);
8665
+ }
8666
+ }
8460
8667
  } else {
8461
- ctx.lineTo(previousPoint._view.x, me._view.scaleZero);
8462
- ctx.moveTo(nextPoint._view.x, me._view.scaleZero);
8668
+ // Line to next point
8669
+ lineToPoint(previous, current);
8463
8670
  }
8464
- }, function(previousPoint, point) {
8465
- // If we skipped the last point, draw a line to ourselves so that the fill is nice
8466
- ctx.lineTo(point._view.x, point._view.y);
8467
- });
8671
+ lastDrawnIndex = index;
8672
+ }
8468
8673
  }
8469
- }, me);
8674
+ }
8470
8675
 
8471
- // For radial scales, loop back around to the first point
8472
- if (me._loop) {
8473
- loopBackToStart(true);
8474
- } else {
8475
- //Round off the line by going to the base of the chart, back to the start, then fill.
8476
- ctx.lineTo(me._children[me._children.length - 1]._view.x, vm.scaleZero);
8477
- ctx.lineTo(me._children[0]._view.x, vm.scaleZero);
8676
+ if (!loop) {
8677
+ ctx.lineTo(points[lastDrawnIndex]._view.x, scaleZero);
8478
8678
  }
8479
8679
 
8480
8680
  ctx.fillStyle = vm.backgroundColor || globalDefaults.defaultColor;
@@ -8482,8 +8682,8 @@ module.exports = function(Chart) {
8482
8682
  ctx.fill();
8483
8683
  }
8484
8684
 
8685
+ // Stroke Line Options
8485
8686
  var globalOptionLineElements = globalDefaults.elements.line;
8486
- // Now draw the line between all the points with any borders
8487
8687
  ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle;
8488
8688
 
8489
8689
  // IE 9 and 10 do not support line dash
@@ -8495,26 +8695,38 @@ module.exports = function(Chart) {
8495
8695
  ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle;
8496
8696
  ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth;
8497
8697
  ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor;
8698
+
8699
+ // Stroke Line
8498
8700
  ctx.beginPath();
8701
+ lastDrawnIndex = -1;
8499
8702
 
8500
- helpers.each(me._children, function(point, index) {
8501
- var previous = helpers.previousItem(me._children, index);
8502
- var next = helpers.nextItem(me._children, index);
8703
+ for (index = 0; index < points.length; ++index) {
8704
+ current = points[index];
8705
+ previous = helpers.previousItem(points, index);
8706
+ currentVM = current._view;
8503
8707
 
8708
+ // First point moves to it's starting position no matter what
8504
8709
  if (index === 0) {
8505
- ctx.moveTo(point._view.x, point._view.y);
8710
+ if (currentVM.skip) {
8711
+
8712
+ } else {
8713
+ ctx.moveTo(currentVM.x, currentVM.y);
8714
+ lastDrawnIndex = index;
8715
+ }
8506
8716
  } else {
8507
- me.lineToNextPoint(previous, point, next, function(previousPoint, point, nextPoint) {
8508
- ctx.moveTo(nextPoint._view.x, nextPoint._view.y);
8509
- }, function(previousPoint, point) {
8510
- // If we skipped the last point, move up to our point preventing a line from being drawn
8511
- ctx.moveTo(point._view.x, point._view.y);
8512
- });
8513
- }
8514
- }, me);
8717
+ previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex];
8515
8718
 
8516
- if (me._loop && me._children.length > 0) {
8517
- loopBackToStart();
8719
+ if (!currentVM.skip) {
8720
+ if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) {
8721
+ // There was a gap and this is the first point after the gap
8722
+ ctx.moveTo(currentVM.x, currentVM.y);
8723
+ } else {
8724
+ // Line to next point
8725
+ lineToPoint(previous, current);
8726
+ }
8727
+ lastDrawnIndex = index;
8728
+ }
8729
+ }
8518
8730
  }
8519
8731
 
8520
8732
  ctx.stroke();
@@ -8522,7 +8734,7 @@ module.exports = function(Chart) {
8522
8734
  }
8523
8735
  });
8524
8736
  };
8525
- },{}],36:[function(require,module,exports){
8737
+ },{}],37:[function(require,module,exports){
8526
8738
  "use strict";
8527
8739
 
8528
8740
  module.exports = function(Chart) {
@@ -8567,119 +8779,26 @@ module.exports = function(Chart) {
8567
8779
  var radius = vm.radius;
8568
8780
  var x = vm.x;
8569
8781
  var y = vm.y;
8570
- var type, edgeLength, xOffset, yOffset, height, size;
8571
8782
 
8572
8783
  if (vm.skip) {
8573
8784
  return;
8574
8785
  }
8575
8786
 
8576
- if (typeof pointStyle === 'object') {
8577
- type = pointStyle.toString();
8578
- if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
8579
- ctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);
8580
- return;
8581
- }
8582
- }
8583
-
8584
- if (isNaN(radius) || radius <= 0) {
8585
- return;
8586
- }
8587
-
8588
8787
  ctx.strokeStyle = vm.borderColor || defaultColor;
8589
8788
  ctx.lineWidth = helpers.getValueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);
8590
8789
  ctx.fillStyle = vm.backgroundColor || defaultColor;
8591
8790
 
8592
- switch (pointStyle) {
8593
- // Default includes circle
8594
- default:
8595
- ctx.beginPath();
8596
- ctx.arc(x, y, radius, 0, Math.PI * 2);
8597
- ctx.closePath();
8598
- ctx.fill();
8599
- break;
8600
- case 'triangle':
8601
- ctx.beginPath();
8602
- edgeLength = 3 * radius / Math.sqrt(3);
8603
- height = edgeLength * Math.sqrt(3) / 2;
8604
- ctx.moveTo(x - edgeLength / 2, y + height / 3);
8605
- ctx.lineTo(x + edgeLength / 2, y + height / 3);
8606
- ctx.lineTo(x, y - 2 * height / 3);
8607
- ctx.closePath();
8608
- ctx.fill();
8609
- break;
8610
- case 'rect':
8611
- size = 1 / Math.SQRT2 * radius;
8612
- ctx.fillRect(x - size, y - size, 2 * size, 2 * size);
8613
- ctx.strokeRect(x - size, y - size, 2 * size, 2 * size);
8614
- break;
8615
- case 'rectRot':
8616
- size = 1 / Math.SQRT2 * radius;
8617
- ctx.beginPath();
8618
- ctx.moveTo(x - size, y);
8619
- ctx.lineTo(x, y + size);
8620
- ctx.lineTo(x + size, y);
8621
- ctx.lineTo(x, y - size);
8622
- ctx.closePath();
8623
- ctx.fill();
8624
- break;
8625
- case 'cross':
8626
- ctx.beginPath();
8627
- ctx.moveTo(x, y + radius);
8628
- ctx.lineTo(x, y - radius);
8629
- ctx.moveTo(x - radius, y);
8630
- ctx.lineTo(x + radius, y);
8631
- ctx.closePath();
8632
- break;
8633
- case 'crossRot':
8634
- ctx.beginPath();
8635
- xOffset = Math.cos(Math.PI / 4) * radius;
8636
- yOffset = Math.sin(Math.PI / 4) * radius;
8637
- ctx.moveTo(x - xOffset, y - yOffset);
8638
- ctx.lineTo(x + xOffset, y + yOffset);
8639
- ctx.moveTo(x - xOffset, y + yOffset);
8640
- ctx.lineTo(x + xOffset, y - yOffset);
8641
- ctx.closePath();
8642
- break;
8643
- case 'star':
8644
- ctx.beginPath();
8645
- ctx.moveTo(x, y + radius);
8646
- ctx.lineTo(x, y - radius);
8647
- ctx.moveTo(x - radius, y);
8648
- ctx.lineTo(x + radius, y);
8649
- xOffset = Math.cos(Math.PI / 4) * radius;
8650
- yOffset = Math.sin(Math.PI / 4) * radius;
8651
- ctx.moveTo(x - xOffset, y - yOffset);
8652
- ctx.lineTo(x + xOffset, y + yOffset);
8653
- ctx.moveTo(x - xOffset, y + yOffset);
8654
- ctx.lineTo(x + xOffset, y - yOffset);
8655
- ctx.closePath();
8656
- break;
8657
- case 'line':
8658
- ctx.beginPath();
8659
- ctx.moveTo(x - radius, y);
8660
- ctx.lineTo(x + radius, y);
8661
- ctx.closePath();
8662
- break;
8663
- case 'dash':
8664
- ctx.beginPath();
8665
- ctx.moveTo(x, y);
8666
- ctx.lineTo(x + radius, y);
8667
- ctx.closePath();
8668
- break;
8669
- }
8670
-
8671
- ctx.stroke();
8791
+ Chart.canvasHelpers.drawPoint(ctx, pointStyle, radius, x, y);
8672
8792
  }
8673
8793
  });
8674
8794
  };
8675
8795
 
8676
- },{}],37:[function(require,module,exports){
8796
+ },{}],38:[function(require,module,exports){
8677
8797
  "use strict";
8678
8798
 
8679
8799
  module.exports = function(Chart) {
8680
8800
 
8681
- var helpers = Chart.helpers,
8682
- globalOpts = Chart.defaults.global;
8801
+ var globalOpts = Chart.defaults.global;
8683
8802
 
8684
8803
  globalOpts.elements.rectangle = {
8685
8804
  backgroundColor: globalOpts.defaultColor,
@@ -8768,7 +8887,7 @@ module.exports = function(Chart) {
8768
8887
  });
8769
8888
 
8770
8889
  };
8771
- },{}],38:[function(require,module,exports){
8890
+ },{}],39:[function(require,module,exports){
8772
8891
  "use strict";
8773
8892
 
8774
8893
  module.exports = function(Chart) {
@@ -8780,36 +8899,47 @@ module.exports = function(Chart) {
8780
8899
  };
8781
8900
 
8782
8901
  var DatasetScale = Chart.Scale.extend({
8902
+ /**
8903
+ * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use tose
8904
+ * else fall back to data.labels
8905
+ * @private
8906
+ */
8907
+ getLabels: function() {
8908
+ var data = this.chart.data;
8909
+ return (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels;
8910
+ },
8783
8911
  // Implement this so that
8784
8912
  determineDataLimits: function() {
8785
8913
  var me = this;
8914
+ var labels = me.getLabels();
8786
8915
  me.minIndex = 0;
8787
- me.maxIndex = me.chart.data.labels.length - 1;
8916
+ me.maxIndex = labels.length - 1;
8788
8917
  var findIndex;
8789
8918
 
8790
8919
  if (me.options.ticks.min !== undefined) {
8791
8920
  // user specified min value
8792
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.min);
8921
+ findIndex = helpers.indexOf(labels, me.options.ticks.min);
8793
8922
  me.minIndex = findIndex !== -1 ? findIndex : me.minIndex;
8794
8923
  }
8795
8924
 
8796
8925
  if (me.options.ticks.max !== undefined) {
8797
8926
  // user specified max value
8798
- findIndex = helpers.indexOf(me.chart.data.labels, me.options.ticks.max);
8927
+ findIndex = helpers.indexOf(labels, me.options.ticks.max);
8799
8928
  me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex;
8800
8929
  }
8801
8930
 
8802
- me.min = me.chart.data.labels[me.minIndex];
8803
- me.max = me.chart.data.labels[me.maxIndex];
8931
+ me.min = labels[me.minIndex];
8932
+ me.max = labels[me.maxIndex];
8804
8933
  },
8805
8934
 
8806
- buildTicks: function(index) {
8935
+ buildTicks: function() {
8807
8936
  var me = this;
8937
+ var labels = me.getLabels();
8808
8938
  // If we are viewing some subset of labels, slice the original array
8809
- 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);
8939
+ me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1);
8810
8940
  },
8811
8941
 
8812
- getLabelForIndex: function(index, datasetIndex) {
8942
+ getLabelForIndex: function(index) {
8813
8943
  return this.ticks[index];
8814
8944
  },
8815
8945
 
@@ -8819,6 +8949,12 @@ module.exports = function(Chart) {
8819
8949
  // 1 is added because we need the length but we have the indexes
8820
8950
  var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - ((me.options.gridLines.offsetGridLines) ? 0 : 1)), 1);
8821
8951
 
8952
+ if (value !== undefined) {
8953
+ var labels = me.getLabels();
8954
+ var idx = labels.indexOf(value);
8955
+ index = idx !== -1 ? idx : index;
8956
+ }
8957
+
8822
8958
  if (me.isHorizontal()) {
8823
8959
  var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
8824
8960
  var valueWidth = innerWidth / offsetAmt;
@@ -8852,6 +8988,8 @@ module.exports = function(Chart) {
8852
8988
  var innerDimension = horz ? me.width - (me.paddingLeft + me.paddingRight) : me.height - (me.paddingTop + me.paddingBottom);
8853
8989
  var valueDimension = innerDimension / offsetAmt;
8854
8990
 
8991
+ pixel -= horz ? me.left : me.top;
8992
+
8855
8993
  if (me.options.gridLines.offsetGridLines) {
8856
8994
  pixel -= (valueDimension / 2);
8857
8995
  }
@@ -8864,13 +9002,16 @@ module.exports = function(Chart) {
8864
9002
  }
8865
9003
 
8866
9004
  return value;
9005
+ },
9006
+ getBasePixel: function() {
9007
+ return this.bottom;
8867
9008
  }
8868
9009
  });
8869
9010
 
8870
9011
  Chart.scaleService.registerScaleType("category", DatasetScale, defaultConfig);
8871
9012
 
8872
9013
  };
8873
- },{}],39:[function(require,module,exports){
9014
+ },{}],40:[function(require,module,exports){
8874
9015
  "use strict";
8875
9016
 
8876
9017
  module.exports = function(Chart) {
@@ -8912,7 +9053,6 @@ module.exports = function(Chart) {
8912
9053
  determineDataLimits: function() {
8913
9054
  var me = this;
8914
9055
  var opts = me.options;
8915
- var tickOpts = opts.ticks;
8916
9056
  var chart = me.chart;
8917
9057
  var data = chart.data;
8918
9058
  var datasets = data.datasets;
@@ -9032,9 +9172,9 @@ module.exports = function(Chart) {
9032
9172
  return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
9033
9173
  },
9034
9174
  // Utils
9035
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
9175
+ getPixelForValue: function(value) {
9036
9176
  // This must be called after fit has been run so that
9037
- // this.left, this.top, this.right, and this.bottom have been defined
9177
+ // this.left, this.top, this.right, and this.bottom have been defined
9038
9178
  var me = this;
9039
9179
  var paddingLeft = me.paddingLeft;
9040
9180
  var paddingBottom = me.paddingBottom;
@@ -9064,14 +9204,14 @@ module.exports = function(Chart) {
9064
9204
  var offset = (isHorizontal ? pixel - me.left - paddingLeft : me.bottom - paddingBottom - pixel) / innerDimension;
9065
9205
  return me.start + ((me.end - me.start) * offset);
9066
9206
  },
9067
- getPixelForTick: function(index, includeOffset) {
9068
- return this.getPixelForValue(this.ticksAsNumbers[index], null, null, includeOffset);
9207
+ getPixelForTick: function(index) {
9208
+ return this.getPixelForValue(this.ticksAsNumbers[index]);
9069
9209
  }
9070
9210
  });
9071
9211
  Chart.scaleService.registerScaleType("linear", LinearScale, defaultConfig);
9072
9212
 
9073
9213
  };
9074
- },{}],40:[function(require,module,exports){
9214
+ },{}],41:[function(require,module,exports){
9075
9215
  "use strict";
9076
9216
 
9077
9217
  module.exports = function(Chart) {
@@ -9127,11 +9267,9 @@ module.exports = function(Chart) {
9127
9267
  buildTicks: function() {
9128
9268
  var me = this;
9129
9269
  var opts = me.options;
9270
+ var ticks = me.ticks = [];
9130
9271
  var tickOpts = opts.ticks;
9131
9272
  var getValueOrDefault = helpers.getValueOrDefault;
9132
- var isHorizontal = me.isHorizontal();
9133
-
9134
- var ticks = me.ticks = [];
9135
9273
 
9136
9274
  // Figure out what the max number of ticks we can support it is based on the size of
9137
9275
  // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
@@ -9199,7 +9337,7 @@ module.exports = function(Chart) {
9199
9337
  },
9200
9338
  });
9201
9339
  };
9202
- },{}],41:[function(require,module,exports){
9340
+ },{}],42:[function(require,module,exports){
9203
9341
  "use strict";
9204
9342
 
9205
9343
  module.exports = function(Chart) {
@@ -9379,10 +9517,10 @@ module.exports = function(Chart) {
9379
9517
  getLabelForIndex: function(index, datasetIndex) {
9380
9518
  return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]);
9381
9519
  },
9382
- getPixelForTick: function(index, includeOffset) {
9383
- return this.getPixelForValue(this.tickValues[index], null, null, includeOffset);
9520
+ getPixelForTick: function(index) {
9521
+ return this.getPixelForValue(this.tickValues[index]);
9384
9522
  },
9385
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
9523
+ getPixelForValue: function(value) {
9386
9524
  var me = this;
9387
9525
  var innerDimension;
9388
9526
  var pixel;
@@ -9417,10 +9555,8 @@ module.exports = function(Chart) {
9417
9555
  },
9418
9556
  getValueForPixel: function(pixel) {
9419
9557
  var me = this;
9420
- var offset;
9421
9558
  var range = helpers.log10(me.end) - helpers.log10(me.start);
9422
- var value;
9423
- var innerDimension;
9559
+ var value, innerDimension;
9424
9560
 
9425
9561
  if (me.isHorizontal()) {
9426
9562
  innerDimension = me.width - (me.paddingLeft + me.paddingRight);
@@ -9436,7 +9572,7 @@ module.exports = function(Chart) {
9436
9572
  Chart.scaleService.registerScaleType("logarithmic", LogarithmicScale, defaultConfig);
9437
9573
 
9438
9574
  };
9439
- },{}],42:[function(require,module,exports){
9575
+ },{}],43:[function(require,module,exports){
9440
9576
  "use strict";
9441
9577
 
9442
9578
  module.exports = function(Chart) {
@@ -9603,16 +9739,20 @@ module.exports = function(Chart) {
9603
9739
  xProtrusionLeft,
9604
9740
  xProtrusionRight,
9605
9741
  radiusReductionRight,
9606
- radiusReductionLeft,
9607
- maxWidthRadius;
9742
+ radiusReductionLeft;
9608
9743
  this.ctx.font = pointLabeFont;
9609
9744
 
9610
9745
  for (i = 0; i < this.getValueCount(); i++) {
9611
9746
  // 5px to space the text slightly out - similar to what we do in the draw function.
9612
9747
  pointPosition = this.getPointPosition(i, largestPossibleRadius);
9613
9748
  textWidth = this.ctx.measureText(this.pointLabels[i] ? this.pointLabels[i] : '').width + 5;
9614
- if (i === 0 || i === this.getValueCount() / 2) {
9615
- // If we're at index zero, or exactly the middle, we're at exactly the top/bottom
9749
+
9750
+ // Add quarter circle to make degree 0 mean top of circle
9751
+ var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
9752
+ var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;
9753
+
9754
+ if (angle === 0 || angle === 180) {
9755
+ // At angle 0 and 180, we're at exactly the top/bottom
9616
9756
  // of the radar chart, so text will be aligned centrally, so we'll half it and compare
9617
9757
  // w/left and right text sizes
9618
9758
  halfTextWidth = textWidth / 2;
@@ -9624,13 +9764,13 @@ module.exports = function(Chart) {
9624
9764
  furthestLeft = pointPosition.x - halfTextWidth;
9625
9765
  furthestLeftIndex = i;
9626
9766
  }
9627
- } else if (i < this.getValueCount() / 2) {
9767
+ } else if (angle < 180) {
9628
9768
  // Less than half the values means we'll left align the text
9629
9769
  if (pointPosition.x + textWidth > furthestRight) {
9630
9770
  furthestRight = pointPosition.x + textWidth;
9631
9771
  furthestRightIndex = i;
9632
9772
  }
9633
- } else if (i > this.getValueCount() / 2) {
9773
+ } else {
9634
9774
  // More than half the values means we'll right align the text
9635
9775
  if (pointPosition.x - textWidth < furthestLeft) {
9636
9776
  furthestLeft = pointPosition.x - textWidth;
@@ -9667,9 +9807,14 @@ module.exports = function(Chart) {
9667
9807
 
9668
9808
  getIndexAngle: function(index) {
9669
9809
  var angleMultiplier = (Math.PI * 2) / this.getValueCount();
9670
- // Start from the top instead of right, so remove a quarter of the circle
9810
+ var startAngle = this.chart.options && this.chart.options.startAngle ?
9811
+ this.chart.options.startAngle :
9812
+ 0;
9671
9813
 
9672
- return index * angleMultiplier - (Math.PI / 2);
9814
+ var startAngleRadians = startAngle * Math.PI * 2 / 360;
9815
+
9816
+ // Start from the top instead of right, so remove a quarter of the circle
9817
+ return index * angleMultiplier - (Math.PI / 2) + startAngleRadians;
9673
9818
  },
9674
9819
  getDistanceFromCenterForValue: function(value) {
9675
9820
  var me = this;
@@ -9813,26 +9958,24 @@ module.exports = function(Chart) {
9813
9958
  ctx.font = pointLabeFont;
9814
9959
  ctx.fillStyle = pointLabelFontColor;
9815
9960
 
9816
- var pointLabels = me.pointLabels,
9817
- labelsCount = pointLabels.length,
9818
- halfLabelsCount = pointLabels.length / 2,
9819
- quarterLabelsCount = halfLabelsCount / 2,
9820
- upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount),
9821
- exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount);
9822
- if (i === 0) {
9823
- ctx.textAlign = 'center';
9824
- } else if (i === halfLabelsCount) {
9961
+ var pointLabels = me.pointLabels;
9962
+
9963
+ // Add quarter circle to make degree 0 mean top of circle
9964
+ var angleRadians = this.getIndexAngle(i) + (Math.PI / 2);
9965
+ var angle = (angleRadians * 360 / (2 * Math.PI)) % 360;
9966
+
9967
+ if (angle === 0 || angle === 180) {
9825
9968
  ctx.textAlign = 'center';
9826
- } else if (i < halfLabelsCount) {
9969
+ } else if (angle < 180) {
9827
9970
  ctx.textAlign = 'left';
9828
9971
  } else {
9829
9972
  ctx.textAlign = 'right';
9830
9973
  }
9831
9974
 
9832
9975
  // Set the correct text baseline based on outer positioning
9833
- if (exactQuarter) {
9976
+ if (angle === 90 || angle === 270) {
9834
9977
  ctx.textBaseline = 'middle';
9835
- } else if (upperHalf) {
9978
+ } else if (angle > 270 || angle < 90) {
9836
9979
  ctx.textBaseline = 'bottom';
9837
9980
  } else {
9838
9981
  ctx.textBaseline = 'top';
@@ -9848,7 +9991,7 @@ module.exports = function(Chart) {
9848
9991
 
9849
9992
  };
9850
9993
 
9851
- },{}],43:[function(require,module,exports){
9994
+ },{}],44:[function(require,module,exports){
9852
9995
  /*global window: false */
9853
9996
  "use strict";
9854
9997
 
@@ -9927,7 +10070,11 @@ module.exports = function(Chart) {
9927
10070
  Chart.Scale.prototype.initialize.call(this);
9928
10071
  },
9929
10072
  getLabelMoment: function(datasetIndex, index) {
9930
- return this.labelMoments[datasetIndex][index];
10073
+ if (typeof this.labelMoments[datasetIndex] != 'undefined') {
10074
+ return this.labelMoments[datasetIndex][index];
10075
+ }
10076
+
10077
+ return null;
9931
10078
  },
9932
10079
  getMomentStartOf: function(tick) {
9933
10080
  var me = this;
@@ -9945,7 +10092,7 @@ module.exports = function(Chart) {
9945
10092
  // these
9946
10093
  var scaleLabelMoments = [];
9947
10094
  if (me.chart.data.labels && me.chart.data.labels.length > 0) {
9948
- helpers.each(me.chart.data.labels, function(label, index) {
10095
+ helpers.each(me.chart.data.labels, function(label) {
9949
10096
  var labelMoment = me.parseTime(label);
9950
10097
 
9951
10098
  if (labelMoment.isValid()) {
@@ -9968,7 +10115,7 @@ module.exports = function(Chart) {
9968
10115
  var datasetVisible = me.chart.isDatasetVisible(datasetIndex);
9969
10116
 
9970
10117
  if (typeof dataset.data[0] === 'object' && dataset.data[0] !== null) {
9971
- helpers.each(dataset.data, function(value, index) {
10118
+ helpers.each(dataset.data, function(value) {
9972
10119
  var labelMoment = me.parseTime(me.getRightValue(value));
9973
10120
 
9974
10121
  if (labelMoment.isValid()) {
@@ -10005,7 +10152,7 @@ module.exports = function(Chart) {
10005
10152
  me.firstTick = (me.firstTick || moment()).clone();
10006
10153
  me.lastTick = (me.lastTick || moment()).clone();
10007
10154
  },
10008
- buildTicks: function(index) {
10155
+ buildTicks: function() {
10009
10156
  var me = this;
10010
10157
 
10011
10158
  me.ctx.save();
@@ -10091,10 +10238,15 @@ module.exports = function(Chart) {
10091
10238
  // Only round the last tick if we have no hard maximum
10092
10239
  if (!me.options.time.max) {
10093
10240
  var roundedEnd = me.getMomentStartOf(me.lastTick);
10094
- if (roundedEnd.diff(me.lastTick, me.tickUnit, true) !== 0) {
10241
+ var delta = roundedEnd.diff(me.lastTick, me.tickUnit, true);
10242
+ if (delta < 0) {
10095
10243
  // Do not use end of because we need me to be in the next time unit
10096
10244
  me.lastTick = me.getMomentStartOf(me.lastTick.add(1, me.tickUnit));
10245
+ } else if (delta >= 0) {
10246
+ me.lastTick = roundedEnd;
10097
10247
  }
10248
+
10249
+ me.scaleSizeInUnits = me.lastTick.diff(me.firstTick, me.tickUnit, true);
10098
10250
  }
10099
10251
 
10100
10252
  me.smallestLabelSeparation = me.width;
@@ -10160,7 +10312,7 @@ module.exports = function(Chart) {
10160
10312
  return label;
10161
10313
  },
10162
10314
  // Function to format an individual tick mark
10163
- tickFormatFunction: function tickFormatFunction(tick, index, ticks) {
10315
+ tickFormatFunction: function(tick, index, ticks) {
10164
10316
  var formattedTick = tick.format(this.displayFormat);
10165
10317
  var tickOpts = this.options.ticks;
10166
10318
  var callback = helpers.getValueOrDefault(tickOpts.callback, tickOpts.userCallback);
@@ -10176,32 +10328,34 @@ module.exports = function(Chart) {
10176
10328
  me.tickMoments = me.ticks;
10177
10329
  me.ticks = me.ticks.map(me.tickFormatFunction, me);
10178
10330
  },
10179
- getPixelForValue: function(value, index, datasetIndex, includeOffset) {
10331
+ getPixelForValue: function(value, index, datasetIndex) {
10180
10332
  var me = this;
10333
+ if (!value || !value.isValid) {
10334
+ // not already a moment object
10335
+ value = moment(me.getRightValue(value));
10336
+ }
10181
10337
  var labelMoment = value && value.isValid && value.isValid() ? value : me.getLabelMoment(datasetIndex, index);
10182
10338
 
10183
10339
  if (labelMoment) {
10184
10340
  var offset = labelMoment.diff(me.firstTick, me.tickUnit, true);
10185
10341
 
10186
- var decimal = offset / me.scaleSizeInUnits;
10342
+ var decimal = offset !== 0 ? offset / me.scaleSizeInUnits : offset;
10187
10343
 
10188
10344
  if (me.isHorizontal()) {
10189
10345
  var innerWidth = me.width - (me.paddingLeft + me.paddingRight);
10190
- var valueWidth = innerWidth / Math.max(me.ticks.length - 1, 1);
10191
10346
  var valueOffset = (innerWidth * decimal) + me.paddingLeft;
10192
10347
 
10193
10348
  return me.left + Math.round(valueOffset);
10194
10349
  } else {
10195
10350
  var innerHeight = me.height - (me.paddingTop + me.paddingBottom);
10196
- var valueHeight = innerHeight / Math.max(me.ticks.length - 1, 1);
10197
10351
  var heightOffset = (innerHeight * decimal) + me.paddingTop;
10198
10352
 
10199
10353
  return me.top + Math.round(heightOffset);
10200
10354
  }
10201
10355
  }
10202
10356
  },
10203
- getPixelForTick: function(index, includeOffset) {
10204
- return this.getPixelForValue(this.tickMoments[index], null, null, includeOffset);
10357
+ getPixelForTick: function(index) {
10358
+ return this.getPixelForValue(this.tickMoments[index], null, null);
10205
10359
  },
10206
10360
  getValueForPixel: function(pixel) {
10207
10361
  var me = this;