From: Evert Timberg Date: Wed, 20 May 2015 13:03:22 +0000 (-0400) Subject: Merge remote-tracking branch 'upstream/v2.0-dev' into feature/v2.0dev-xy X-Git-Tag: v2.0-alpha~8^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12e2ace03904ac07a8929f34884892b74d14c2fa;p=thirdparty%2FChart.js.git Merge remote-tracking branch 'upstream/v2.0-dev' into feature/v2.0dev-xy Conflicts: src/Chart.Core.js Fixed the sample files & chart type initialize methods so that this.data does not get set to undefined. --- 12e2ace03904ac07a8929f34884892b74d14c2fa diff --cc samples/bar.html index eea5b659b,8b0f1e942..b0f82cf1b --- a/samples/bar.html +++ b/samples/bar.html @@@ -30,26 -30,38 +30,41 @@@ label: 'Dataset 2', backgroundColor: "rgba(151,187,205,0.5)", data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] + }, { + label: 'Dataset 3', + backgroundColor: "rgba(151,187,205,0.5)", + data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] + }, { + label: 'Dataset 4', + backgroundColor: "rgba(151,187,205,0.5)", + data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] + }, { + label: 'Dataset 3', + backgroundColor: "rgba(151,187,205,0.5)", + data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()] }] - } + }; window.onload = function() { var ctx = document.getElementById("canvas").getContext("2d"); -- window.myBar = new Chart(ctx).Bar(barChartData, { -- responsive: true, -- hoverMode: 'label', -- scaleBeginAtZero: false, - hoverAnimationDuration: 400 - hoverAnimationDuration: 400, - stacked: true, ++ window.myBar = new Chart(ctx).Bar({ ++ data: barChartData, ++ options: { ++ responsive: true, ++ hoverMode: 'label', ++ scaleBeginAtZero: false, ++ hoverAnimationDuration: 400, ++ stacked: true, ++ } }); - } + }; $('#randomizeData').click(function() { - barChartData.datasets[0].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)'; - barChartData.datasets[0].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]; - - barChartData.datasets[1].backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)'; - barChartData.datasets[1].data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]; + $.each(barChartData.datasets, function(i, dataset) { + dataset.backgroundColor = 'rgba(' + randomColorFactor() + ',' + randomColorFactor() + ',' + randomColorFactor() + ',.7)'; + dataset.data = [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]; + }); window.myBar.update(); }); diff --cc samples/doughnut.color.html index 5457fd094,5457fd094..f61c25db3 --- a/samples/doughnut.color.html +++ b/samples/doughnut.color.html @@@ -48,7 -48,7 +48,12 @@@ window.onload = function(){ var ctx = document.getElementById("chart-area").getContext("2d"); -- window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, {responsive : true}); ++ window.myDoughnut = new Chart(ctx).Doughnut({ ++ data: doughnutData, ++ options: { ++ responsive : true ++ } ++ }); }; diff --cc samples/doughnut.html index 19c6a6d0c,19c6a6d0c..4a5860e30 --- a/samples/doughnut.html +++ b/samples/doughnut.html @@@ -58,8 -58,8 +58,11 @@@ window.onload = function() { var ctx = document.getElementById("chart-area").getContext("2d"); -- window.myDoughnut = new Chart(ctx).Doughnut(doughnutData, { -- responsive: true ++ window.myDoughnut = new Chart(ctx).Doughnut({ ++ data: doughnutData, ++ options: { ++ responsive: true ++ } }); }; diff --cc samples/line-customTooltips.html index 4dc46e1ab,4dc46e1ab..a9ee1b85c --- a/samples/line-customTooltips.html +++ b/samples/line-customTooltips.html @@@ -112,10 -112,10 +112,13 @@@ window.onload = function() { var ctx1 = document.getElementById("chart1").getContext("2d"); -- window.myLine = new Chart(ctx1).Line(lineChartData, { -- showScale: false, -- pointDot : true, -- responsive: true ++ window.myLine = new Chart(ctx1).Line({ ++ data: lineChartData, ++ options: { ++ showScale: false, ++ pointDot : true, ++ responsive: true ++ } }); var ctx2 = document.getElementById("chart2").getContext("2d"); diff --cc samples/line.html index b6c2ae8e7,eac9b32fe..970c66c12 --- a/samples/line.html +++ b/samples/line.html @@@ -45,9 -45,10 +45,13 @@@ window.onload = function() { var ctx = document.getElementById("canvas").getContext("2d"); -- window.myLine = new Chart(ctx).Line(lineChartData, { -- responsive: true, - hoverMode: 'label' - hoverMode: 'label', - stacked: true ++ window.myLine = new Chart(ctx).Line({ ++ data: lineChartData, ++ options: { ++ responsive: true, ++ hoverMode: 'label', ++ stacked: true ++ } }); }; diff --cc samples/pie-customTooltips.html index 732317de4,732317de4..37075ecbb --- a/samples/pie-customTooltips.html +++ b/samples/pie-customTooltips.html @@@ -145,10 -145,10 +145,14 @@@ window.onload = function() { var ctx1 = document.getElementById("chart-area1").getContext("2d"); -- window.myPie = new Chart(ctx1).Pie(pieData); ++ window.myPie = new Chart(ctx1).Pie({ ++ data: pieData ++ }); var ctx2 = document.getElementById("chart-area2").getContext("2d"); -- window.myPie = new Chart(ctx2).Pie(pieData); ++ window.myPie = new Chart(ctx2).Pie({ ++ data: pieData ++ }); }; diff --cc samples/pie.html index ca5aecde0,ca5aecde0..0bd0b38a6 --- a/samples/pie.html +++ b/samples/pie.html @@@ -52,7 -52,7 +52,9 @@@ window.onload = function(){ var ctx = document.getElementById("chart-area").getContext("2d"); -- window.myPie = new Chart(ctx).Pie(pieData); ++ window.myPie = new Chart(ctx).Pie({ ++ data: pieData ++ }); }; $('#randomizeData').click(function(){ diff --cc samples/polar-area.html index 0828c1020,0828c1020..51682e65b --- a/samples/polar-area.html +++ b/samples/polar-area.html @@@ -53,8 -53,8 +53,11 @@@ window.onload = function(){ var ctx = document.getElementById("chart-area").getContext("2d"); -- window.myPolarArea = new Chart(ctx).PolarArea(polarData, { -- responsive:true ++ window.myPolarArea = new Chart(ctx).PolarArea({ ++ data: polarData, ++ options: { ++ responsive:true ++ } }); }; diff --cc samples/radar.html index d26079784,d26079784..0885f61ab --- a/samples/radar.html +++ b/samples/radar.html @@@ -44,8 -44,8 +44,11 @@@ }; window.onload = function(){ -- window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar(radarChartData, { -- responsive: true ++ window.myRadar = new Chart(document.getElementById("canvas").getContext("2d")).Radar({ ++ data: radarChartData, ++ options: { ++ responsive: true ++ } }); } diff --cc samples/scatter-multi-axis.html index 30473a1ad,000000000..a7ca3f96e mode 100644,000000..100644 --- a/samples/scatter-multi-axis.html +++ b/samples/scatter-multi-axis.html @@@ -1,222 -1,0 +1,225 @@@ + + + + + Scatter Chart Multi Axis + + + + + +
+
+ +
+
+ + + + + diff --cc samples/scatter.html index 84cfb2a0e,000000000..b27743762 mode 100644,000000..100644 --- a/samples/scatter.html +++ b/samples/scatter.html @@@ -1,152 -1,0 +1,155 @@@ + + + + + Scatter Chart + + + + + +
+
+ +
+
+ + + + + diff --cc src/Chart.Bar.js index 8eb436a4d,ee9c7921e..e181be4fc --- a/src/Chart.Bar.js +++ b/src/Chart.Bar.js @@@ -43,13 -46,15 +46,11 @@@ Chart.Type.extend({ name: "Bar", defaults: defaultConfig, -- initialize: function(data) { -- -- // Save data as a source for updating of values & methods -- this.data = data; -- ++ initialize: function() { var options = this.options; + var _this = this; + // Custom Scale Methods and Options this.ScaleClass = Chart.Scale.extend({ offsetGridLines: true, diff --cc src/Chart.Core.js index f86f0ac0d,9d23a5801..0121b11a1 --- a/src/Chart.Core.js +++ b/src/Chart.Core.js @@@ -1162,9 -1091,9 +1166,9 @@@ Chart.types[chartName] = ChartType; //Register this new chart type in the Chart prototype - Chart.prototype[chartName] = function(data, options) { - var config = helpers.configMerge(Chart.defaults.global, Chart.defaults[chartName], options || {}); - return new ChartType(data, config, this); + Chart.prototype[chartName] = function(config) { - helpers.extend(config.options, merge(Chart.defaults.global, Chart.defaults[chartName], config.options || {})); ++ config.options = helpers.configMerge(Chart.defaults.global, Chart.defaults[chartName], config.options || {}); + return new ChartType(config, this); }; } else { warn("Name not provided for this chart, so it hasn't been registered"); diff --cc src/Chart.Doughnut.js index 1fc05581c,1fc05581c..c35306501 --- a/src/Chart.Doughnut.js +++ b/src/Chart.Doughnut.js @@@ -43,11 -43,11 +43,7 @@@ defaults: defaultConfig, //Initialize is fired when the chart is initialized - Data is passed in as a parameter //Config is automatically merged by the core of Chart.js, and is available at this.options -- initialize: function(data) { -- -- // Save data as a source for updating of values & methods -- this.data = data; -- ++ initialize: function() { // Slice Type and defaults this.Slice = Chart.Arc.extend({ _chart: this.chart, diff --cc src/Chart.PolarArea.js index c220a6f4b,c220a6f4b..4bfec4f46 --- a/src/Chart.PolarArea.js +++ b/src/Chart.PolarArea.js @@@ -58,10 -58,10 +58,7 @@@ defaults : defaultConfig, //Initialize is fired when the chart is initialized - Data is passed in as a parameter //Config is automatically merged by the core of Chart.js, and is available at this.options -- initialize: function(data){ -- // Save data as a source for updating of values & methods -- this.data = data; -- ++ initialize: function(){ this.segments = []; //Declare segment class as a chart instance specific class, so it can share props for this instance this.SegmentArc = Chart.Arc.extend({ @@@ -93,14 -93,14 +90,14 @@@ yCenter: this.chart.height/2, ctx : this.chart.ctx, templateString: this.options.scaleLabel, -- valuesCount: data.length ++ valuesCount: this.data.length }); -- this.updateScaleRange(data); ++ this.updateScaleRange(this.data); this.scale.update(); -- helpers.each(data,function(segment,index){ ++ helpers.each(this.data,function(segment,index){ this.addData(segment,index,true); },this); diff --cc src/Chart.Radar.js index b033c8bb2,b033c8bb2..ddf12388f --- a/src/Chart.Radar.js +++ b/src/Chart.Radar.js @@@ -66,10 -66,10 +66,7 @@@ }, -- initialize: function(data){ -- // Save data as a source for updating of values & methods -- this.data = data; -- ++ initialize: function(){ this.PointClass = Chart.Point.extend({ strokeWidth : this.options.pointDotStrokeWidth, radius : this.options.pointDotRadius, @@@ -80,7 -80,7 +77,7 @@@ this.datasets = []; -- this.buildScale(data); ++ this.buildScale(this.data); //Set up tooltip events on the chart if (this.options.showTooltips){ @@@ -100,7 -100,7 +97,7 @@@ } //Iterate through each of the datasets, and build this into a property of the chart -- helpers.each(data.datasets,function(dataset){ ++ helpers.each(this.data.datasets,function(dataset){ var datasetObject = { label: dataset.label || null, @@@ -121,7 -121,7 +118,7 @@@ } datasetObject.points.push(new this.PointClass({ value : dataPoint, -- label : data.labels[index], ++ label : this.data.labels[index], datasetLabel: dataset.label, x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, diff --cc src/Chart.Scatter.js index 1de1b06b9,000000000..d7318ad9c mode 100644,000000..100644 --- a/src/Chart.Scatter.js +++ b/src/Chart.Scatter.js @@@ -1,507 -1,0 +1,504 @@@ +(function() { + "use strict"; + + var root = this, + Chart = root.Chart, + helpers = Chart.helpers; + + var defaultConfig = { + hoverMode: 'single', + scales: { + xAxes: [{ + scaleType: "linear", // scatter should not use a dataset axis + show: true, + position: "bottom", + horizontal: true, + id: "x-axis-1", // need an ID so datasets can reference the scale + + // grid line settings + gridLines: { + show: true, + color: "rgba(0, 0, 0, 0.05)", + lineWidth: 1, + drawOnChartArea: true, + drawTicks: true, + zeroLineWidth: 1, + zeroLineColor: "rgba(0,0,0,0.25)", + }, + + // scale numbers + beginAtZero: false, + integersOnly: false, + override: null, + + // label settings + labels: { + show: true, + template: "<%=value%>", + fontSize: 12, + fontStyle: "normal", + fontColor: "#666", + fontFamily: "Helvetica Neue", + }, + }], + yAxes: [{ + scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance + show: true, + position: "left", + horizontal: false, + id: "y-axis-1", + + // grid line settings + gridLines: { + show: true, + color: "rgba(0, 0, 0, 0.05)", + lineWidth: 1, + drawOnChartArea: true, + drawTicks: true, // draw ticks extending towards the label + zeroLineWidth: 1, + zeroLineColor: "rgba(0,0,0,0.25)", + }, + + // scale numbers + beginAtZero: false, + integersOnly: false, + override: null, + + // label settings + labels: { + show: true, + template: "<%=value%>", + fontSize: 12, + fontStyle: "normal", + fontColor: "#666", + fontFamily: "Helvetica Neue", + } + }], + }, + + //Number - Tension of the bezier curve between points + tension: 0.4, + + //Number - Radius of each point dot in pixels + pointRadius: 4, + + //Number - Pixel width of point dot border + pointBorderWidth: 1, + + //Number - amount extra to add to the radius to cater for hit detection outside the drawn point + pointHoverRadius: 20, + + //Number - Pixel width of dataset border + borderWidth: 2, + + //String - A legend template + legendTemplate: "", + + tooltipTemplate: "(<%= dataX %>, <%= dataY %>)", + multiTooltipTemplate: "<%if (datasetLabel){%><%=datasetLabel%>: <%}%>(<%= dataX %>, <%= dataY %>)", + + }; + + + Chart.Type.extend({ + name: "Scatter", + defaults: defaultConfig, - initialize: function(data) { - // Save data as a source for updating of values & methods - this.data = data; - ++ initialize: function() { + //Custom Point Defaults + this.PointClass = Chart.Point.extend({ + _chart: this.chart, + offsetGridLines: this.options.offsetGridLines, + borderWidth: this.options.pointBorderWidth, + radius: this.options.pointRadius, + hoverRadius: this.options.pointHoverRadius, + }); + + // Events + helpers.bindEvents(this, this.options.tooltipEvents, this.onHover); + + // Build Scale + this.buildScale(); + Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height); + + //Create a new line and its points for each dataset and piece of data + helpers.each(this.data.datasets, function(dataset, datasetIndex) { + dataset.metaDataset = new Chart.Line(); + dataset.metaData = []; + helpers.each(dataset.data, function(dataPoint, index) { + dataset.metaData.push(new this.PointClass()); + }, this); + + // Make sure each dataset is bound to an x and a y axis + if (!dataset.xAxisID) { + dataset.xAxisID = this.options.scales.xAxes[0].id; + } + + if (!dataset.yAxisID) { + dataset.yAxisID = this.options.scales.yAxes[0].id; + } + }, this); + + // Set defaults for lines + this.eachDataset(function(dataset, datasetIndex) { + dataset = helpers.merge(this.options, dataset); + helpers.extend(dataset.metaDataset, { + _points: dataset.metaData, + _datasetIndex: datasetIndex, + _chart: this.chart, + }); + // Copy to view model + dataset.metaDataset.save(); + }, this); + + // Set defaults for points + this.eachElement(function(point, index, dataset, datasetIndex) { + var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID]; + + helpers.extend(point, { + x: xScale.getPixelForValue(index), + y: this.chartArea.bottom, + _datasetIndex: datasetIndex, + _index: index, + _chart: this.chart + }); + + // Default bezier control points + helpers.extend(point, { + controlPointPreviousX: this.previousPoint(dataset, index).x, + controlPointPreviousY: this.nextPoint(dataset, index).y, + controlPointNextX: this.previousPoint(dataset, index).x, + controlPointNextY: this.nextPoint(dataset, index).y, + }); + // Copy to view model + point.save(); + }, this); + + // Create tooltip instance exclusively for this chart with some defaults. + this.tooltip = new Chart.Tooltip({ + _chart: this.chart, + _data: this.data, + _options: this.options, + }, this); + + this.update(); + }, + nextPoint: function(collection, index) { + return collection[index - 1] || collection[index]; + }, + previousPoint: function(collection, index) { + return collection[index + 1] || collection[index]; + }, + onHover: function(e) { + // If exiting chart + if (e.type == 'mouseout') { + return this; + } + + this.lastActive = this.lastActive || []; + + // Find Active Elements + this.active = function() { + switch (this.options.hoverMode) { + case 'single': + return this.getElementAtEvent(e); + case 'label': + return this.getElementsAtEvent(e); + case 'dataset': + return this.getDatasetAtEvent(e); + default: + return e; + } + }.call(this); + + // On Hover hook + if (this.options.onHover) { + this.options.onHover.call(this, this.active); + } + + // Remove styling for last active (even if it may still be active) + if (this.lastActive.length) { + switch (this.options.hoverMode) { + case 'single': + this.lastActive[0].backgroundColor = this.data.datasets[this.lastActive[0]._datasetIndex].pointBackgroundColor; + this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderColor; + this.lastActive[0].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth; + break; + case 'label': + for (var i = 0; i < this.lastActive.length; i++) { + this.lastActive[i].backgroundColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBackgroundColor; + this.lastActive[i].borderColor = this.data.datasets[this.lastActive[i]._datasetIndex].pointBorderColor; + this.lastActive[i].borderWidth = this.data.datasets[this.lastActive[0]._datasetIndex].pointBorderWidth; + } + break; + case 'dataset': + break; + default: + // Don't change anything + } + } + + // Built in hover styling + if (this.active.length && this.options.hoverMode) { + switch (this.options.hoverMode) { + case 'single': + this.active[0].backgroundColor = this.data.datasets[this.active[0]._datasetIndex].hoverBackgroundColor || helpers.color(this.active[0].backgroundColor).saturate(0.5).darken(0.35).rgbString(); + this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).saturate(0.5).darken(0.35).rgbString(); + this.active[0].borderWidth = this.data.datasets[this.active[0]._datasetIndex].borderWidth + 10; + break; + case 'label': + for (var i = 0; i < this.active.length; i++) { + this.active[i].backgroundColor = this.data.datasets[this.active[i]._datasetIndex].hoverBackgroundColor || helpers.color(this.active[i].backgroundColor).saturate(0.5).darken(0.35).rgbString(); + this.active[i].borderColor = this.data.datasets[this.active[i]._datasetIndex].hoverBorderColor || helpers.color(this.active[i].borderColor).saturate(0.5).darken(0.35).rgbString(); + this.active[i].borderWidth = this.data.datasets[this.active[i]._datasetIndex].borderWidth + 2; + } + break; + case 'dataset': + break; + default: + // Don't change anything + } + } + + // Built in Tooltips + if (this.options.showTooltips) { + + // The usual updates + this.tooltip.initialize(); + + // Active + if (this.active.length) { + helpers.extend(this.tooltip, { + opacity: 1, + _active: this.active, + }); + + this.tooltip.update(); + } else { + // Inactive + helpers.extend(this.tooltip, { + opacity: 0, + }); + } + } + + // Hover animations + this.tooltip.pivot(); + + if (!this.animating) { + var changed; + + helpers.each(this.active, function(element, index) { + if (element !== this.lastActive[index]) { + changed = true; + } + }, this); + + // If entering, leaving, or changing elements, animate the change via pivot + if ((!this.lastActive.length && this.active.length) || + (this.lastActive.length && !this.active.length) || + (this.lastActive.length && this.active.length && changed)) { + + this.stop(); + this.render(this.options.hoverAnimationDuration); + } + } + + // Remember Last Active + this.lastActive = this.active; + return this; + + }, + update: function() { + Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height); + + // Update the lines + this.eachDataset(function(dataset, datasetIndex) { + helpers.extend(dataset.metaDataset, { + backgroundColor: dataset.backgroundColor || this.options.backgroundColor, + borderWidth: dataset.borderWidth || this.options.borderWidth, + borderColor: dataset.borderColor || this.options.borderColor, + tension: dataset.tension || this.options.tension, + scaleTop: this.chartArea.top, + scaleBottom: this.chartArea.bottom, + _points: dataset.metaData, + _datasetIndex: datasetIndex, + }); + dataset.metaDataset.pivot(); + }); + + // Update the points + this.eachElement(function(point, index, dataset, datasetIndex) { + var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID]; + var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID]; + + helpers.extend(point, { + x: xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x), + y: yScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].y), + dataX: this.data.datasets[datasetIndex].data[index].x, + dataY: this.data.datasets[datasetIndex].data[index].y, + label: '', // so that the multitooltip looks ok + value: this.data.datasets[datasetIndex].data[index].y, // for legacy reasons + datasetLabel: this.data.datasets[datasetIndex].label, + // Appearance + hoverBackgroundColor: this.data.datasets[datasetIndex].pointHoverBackgroundColor || this.options.pointHoverBackgroundColor, + hoverBorderColor: this.data.datasets[datasetIndex].pointHoverBorderColor || this.options.pointHoverBorderColor, + hoverRadius: this.data.datasets[datasetIndex].pointHoverRadius || this.options.pointHoverRadius, + radius: this.data.datasets[datasetIndex].pointRadius || this.options.pointRadius, + borderWidth: this.data.datasets[datasetIndex].pointBorderWidth || this.options.pointBorderWidth, + borderColor: this.data.datasets[datasetIndex].pointBorderColor || this.options.pointBorderColor, + backgroundColor: this.data.datasets[datasetIndex].pointBackgroundColor || this.options.pointBackgroundColor, + tension: this.data.datasets[datasetIndex].metaDataset.tension, + _datasetIndex: datasetIndex, + _index: index, + }); + }, this); + + // Update control points for the bezier curve + this.eachElement(function(point, index, dataset, datasetIndex) { + var controlPoints = helpers.splineCurve( + this.previousPoint(dataset, index), + point, + this.nextPoint(dataset, index), + point.tension + ); + + point.controlPointPreviousX = controlPoints.previous.x; + point.controlPointNextX = controlPoints.next.x; + + // Prevent the bezier going outside of the bounds of the graph + + // Cap puter bezier handles to the upper/lower scale bounds + if (controlPoints.next.y > this.chartArea.bottom) { + point.controlPointNextY = this.chartArea.bottom; + } else if (controlPoints.next.y < this.chartArea.top) { + point.controlPointNextY = this.chartArea.top; + } else { + point.controlPointNextY = controlPoints.next.y; + } + + // Cap inner bezier handles to the upper/lower scale bounds + if (controlPoints.previous.y > this.chartArea.bottom) { + point.controlPointPreviousY = this.chartArea.bottom; + } else if (controlPoints.previous.y < this.chartArea.top) { + point.controlPointPreviousY = this.chartArea.top; + } else { + point.controlPointPreviousY = controlPoints.previous.y; + } + // Now pivot the point for animation + point.pivot(); + }, this); + + this.render(); + }, + buildScale: function() { + var self = this; + + var calculateXRange = function() { + this.min = null; + this.max = null; + + helpers.each(self.data.datasets, function(dataset) { + // Only set the scale range for datasets that actually use this axis + if (dataset.xAxisID === this.id) { + helpers.each(dataset.data, function(value) { + if (this.min === null) { + this.min = value.x; + } else if (value.x < this.min) { + this.min = value.x; + } + + if (this.max === null) { + this.max = value.x; + } else if (value.x > this.max) { + this.max = value.x; + } + }, this); + } + }, this); + }; + + var calculateYRange = function() { + this.min = null; + this.max = null; + + helpers.each(self.data.datasets, function(dataset) { + if (dataset.yAxisID === this.id) { + helpers.each(dataset.data, function(value) { + if (this.min === null) { + this.min = value.y; + } else if (value.y < this.min) { + this.min = value.y; + } + + if (this.max === null) { + this.max = value.y; + } else if (value.y > this.max) { + this.max = value.y; + } + }, this); + } + }, this); + }; + + // Map of scale ID to scale object so we can lookup later + this.scales = {}; + + helpers.each(this.options.scales.xAxes, function(xAxisOptions) { + var ScaleClass = Chart.scales.getScaleConstructor(xAxisOptions.scaleType); + var scale = new ScaleClass({ + ctx: this.chart.ctx, + options: xAxisOptions, + calculateRange: calculateXRange, + id: xAxisOptions.id, + }); + + this.scales[scale.id] = scale; + }, this); + + helpers.each(this.options.scales.yAxes, function(yAxisOptions) { + var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType); + var scale = new ScaleClass({ + ctx: this.chart.ctx, + options: yAxisOptions, + calculateRange: calculateYRange, + id: yAxisOptions.id, + }); + + this.scales[scale.id] = scale; + }, this); + }, + redraw: function() { + + }, + draw: function(ease) { + + var easingDecimal = ease || 1; + this.clear(); + + // Draw all the scales + helpers.each(this.scales, function(scale) { + scale.draw(this.chartArea); + }, this); + + this.eachDataset(function(dataset, datasetIndex) { + // Transition Point Locations + helpers.each(dataset.metaData, function(point, index) { + point.transition(easingDecimal); + }, this); + + // Transition and Draw the line + dataset.metaDataset.transition(easingDecimal).draw(); + + // Draw the points + helpers.each(dataset.metaData, function(point) { + point.draw(); + }); + }, this); + + // Finally draw the tooltip + this.tooltip.transition(easingDecimal).draw(); + } + }); + + +}).call(this);