diff --git a/gulpfile.js b/gulpfile.js index 27b85ef18..68bed24db 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -29,7 +29,6 @@ gulp.task('build', function() { './src/controllers/**', './src/scales/**', './src/elements/**', - './src/charts/chart.rectangularbase.js', // need this before the other chart types './src/charts/**', './src/**', './node_modules/color/dist/color.min.js' diff --git a/src/charts/chart.line.js b/src/charts/chart.line.js index f1d71eb50..469cf0c87 100644 --- a/src/charts/chart.line.js +++ b/src/charts/chart.line.js @@ -21,7 +21,7 @@ }; - Chart.types.RectangularBase.extend({ + Chart.Type.extend({ name: "Line", defaults: defaultConfig, initialize: function() { diff --git a/src/charts/chart.rectangularbase.js b/src/charts/chart.rectangularbase.js deleted file mode 100644 index 76d03f5e3..000000000 --- a/src/charts/chart.rectangularbase.js +++ /dev/null @@ -1,168 +0,0 @@ -(function() { - "use strict"; - - var root = this, - Chart = root.Chart, - helpers = Chart.helpers; - - var defaultConfig = { - - }; - - // Rectangular base class that derives into line & bar charts - Chart.Type.extend({ - name: "RectangularBase", - defaults: defaultConfig, - update: function(animationDuration) { - this.canvasController.update(); - this.render(animationDuration); - }, - draw: helpers.noop, - events: function(e) { - - this.lastActive = this.lastActive || []; - - // Find Active Elements - if (e.type == 'mouseout') { - this.active = []; - } else { - this.active = function() { - switch (this.options.hover.mode) { - 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.hover.onHover) { - this.options.hover.onHover.call(this, this.active); - } - - if (e.type == 'mouseup' || e.type == 'click') { - if (this.options.onClick) { - this.options.onClick.call(this, e, this.active); - } - } - - var dataset; - var index; - // Remove styling for last active (even if it may still be active) - if (this.lastActive.length) { - switch (this.options.hover.mode) { - case 'single': - dataset = this.data.datasets[this.lastActive[0]._datasetIndex]; - index = this.lastActive[0]._index; - - this.lastActive[0]._model.radius = this.lastActive[0].custom && this.lastActive[0].custom.radius ? this.lastActive[0].custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, this.options.elements.point.radius); - this.lastActive[0]._model.backgroundColor = this.lastActive[0].custom && this.lastActive[0].custom.backgroundColor ? this.lastActive[0].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor); - this.lastActive[0]._model.borderColor = this.lastActive[0].custom && this.lastActive[0].custom.borderColor ? this.lastActive[0].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor); - this.lastActive[0]._model.borderWidth = this.lastActive[0].custom && this.lastActive[0].custom.borderWidth ? this.lastActive[0].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth); - break; - case 'label': - for (var i = 0; i < this.lastActive.length; i++) { - dataset = this.data.datasets[this.lastActive[i]._datasetIndex]; - index = this.lastActive[i]._index; - - this.lastActive[i]._model.radius = this.lastActive[i].custom && this.lastActive[i].custom.radius ? this.lastActive[i].custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, this.options.elements.point.radius); - this.lastActive[i]._model.backgroundColor = this.lastActive[i].custom && this.lastActive[i].custom.backgroundColor ? this.lastActive[i].custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, this.options.elements.point.backgroundColor); - this.lastActive[i]._model.borderColor = this.lastActive[i].custom && this.lastActive[i].custom.borderColor ? this.lastActive[i].custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, this.options.elements.point.borderColor); - this.lastActive[i]._model.borderWidth = this.lastActive[i].custom && this.lastActive[i].custom.borderWidth ? this.lastActive[i].custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.options.elements.point.borderWidth); - } - break; - case 'dataset': - break; - default: - // Don't change anything - } - } - - // Built in hover styling - if (this.active.length && this.options.hover.mode) { - switch (this.options.hover.mode) { - case 'single': - dataset = this.data.datasets[this.active[0]._datasetIndex]; - index = this.active[0]._index; - - this.active[0]._model.radius = this.active[0].custom && this.active[0].custom.radius ? this.active[0].custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.options.elements.point.hoverRadius); - this.active[0]._model.backgroundColor = this.active[0].custom && this.active[0].custom.hoverBackgroundColor ? this.active[0].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[0]._model.backgroundColor).saturate(0.5).darken(0.1).rgbString()); - this.active[0]._model.borderColor = this.active[0].custom && this.active[0].custom.hoverBorderColor ? this.active[0].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[0]._model.borderColor).saturate(0.5).darken(0.1).rgbString()); - this.active[0]._model.borderWidth = this.active[0].custom && this.active[0].custom.hoverBorderWidth ? this.active[0].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[0]._model.borderWidth); - break; - case 'label': - for (var i = 0; i < this.active.length; i++) { - dataset = this.data.datasets[this.active[i]._datasetIndex]; - index = this.active[i]._index; - - this.active[i]._model.radius = this.active[i].custom && this.active[i].custom.radius ? this.active[i].custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.options.elements.point.hoverRadius); - this.active[i]._model.backgroundColor = this.active[i].custom && this.active[i].custom.hoverBackgroundColor ? this.active[i].custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(this.active[i]._model.backgroundColor).saturate(0.5).darken(0.1).rgbString()); - this.active[i]._model.borderColor = this.active[i].custom && this.active[i].custom.hoverBorderColor ? this.active[i].custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(this.active[i]._model.borderColor).saturate(0.5).darken(0.1).rgbString()); - this.active[i]._model.borderWidth = this.active[i].custom && this.active[i].custom.hoverBorderWidth ? this.active[i].custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, this.active[i]._model.borderWidth); - } - break; - case 'dataset': - break; - default: - // Don't change anything - } - } - - - // Built in Tooltips - if (this.options.tooltips.enabled) { - - // The usual updates - this.tooltip.initialize(); - - // Active - if (this.active.length) { - this.tooltip._model.opacity = 1; - - helpers.extend(this.tooltip, { - _active: this.active, - }); - - this.tooltip.update(); - } else { - // Inactive - this.tooltip._model.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.hover.animationDuration); - } - } - - // Remember Last Active - this.lastActive = this.active; - return this; - }, - }); - - -}).call(this); diff --git a/src/controllers/controller.canvas.rectangular.js b/src/controllers/controller.canvas.rectangular.js index b57cfabe7..22caa778c 100644 --- a/src/controllers/controller.canvas.rectangular.js +++ b/src/controllers/controller.canvas.rectangular.js @@ -6,7 +6,7 @@ helpers = Chart.helpers; Chart.RectangularCanvasController = function(chart, elementController) { - this.chart = chart; + this.chartInstance = chart; this.elementController = elementController; }; @@ -15,59 +15,181 @@ this.buildScales(); // Need to fit scales before we reset elements. - Chart.scaleService.fitScalesForChart(this.chart, this.chart.chart.width, this.chart.chart.height); + Chart.scaleService.fitScalesForChart(this.chartInstance, this.chartInstance.chart.width, this.chartInstance.chart.height); this.elementController.resetElements(); this.initToolTip(); - this.chart.update(); + this.chartInstance.update(); }; Chart.RectangularCanvasController.prototype.bindEvents = function() { - helpers.bindEvents(this.chart, this.chart.options.events, this.chart.events); + helpers.bindEvents(this.chartInstance, this.chartInstance.options.events, function(evt) { + // this will be the chart instance + this.canvasController.eventHandler(evt); + }); + }; + + Chart.RectangularCanvasController.prototype.eventHandler = function(e) { + this.lastActive = this.lastActive || []; + + // Find Active Elements + if (e.type == 'mouseout') { + this.active = []; + } else { + this.active = function() { + switch (this.chartInstance.options.hover.mode) { + case 'single': + return this.elementController.getElementAtEvent(e); + case 'label': + return this.elementController.getElementsAtEvent(e); + case 'dataset': + return this.elementController.getDatasetAtEvent(e); + default: + return e; + } + }.call(this); + } + + // On Hover hook + if (this.chartInstance.options.hover.onHover) { + this.chartInstance.options.hover.onHover.call(this.chartInstance, this.active); + } + + if (e.type == 'mouseup' || e.type == 'click') { + if (this.chartInstance.options.onClick) { + this.chartInstance.options.onClick.call(this, e, this.active); + } + } + + var dataset; + var index; + // Remove styling for last active (even if it may still be active) + if (this.lastActive.length) { + switch (this.chartInstance.options.hover.mode) { + case 'single': + this.elementController.updatePointElementAppearance(this.lastActive[0], this.lastActive[0]._datasetIndex, this.lastActive[0]._index); + break; + case 'label': + for (var i = 0; i < this.lastActive.length; i++) { + this.elementController.updatePointElementAppearance(this.lastActive[i], this.lastActive[i]._datasetIndex, this.lastActive[i]._index); + } + break; + case 'dataset': + break; + default: + // Don't change anything + } + } + + // Built in hover styling + if (this.active.length && this.chartInstance.options.hover.mode) { + switch (this.chartInstance.options.hover.mode) { + case 'single': + this.elementController.setPointHoverStyle(this.active[0]); + break; + case 'label': + for (var i = 0; i < this.active.length; i++) { + this.elementController.setPointHoverStyle(this.active[i]); + } + break; + case 'dataset': + break; + default: + // Don't change anything + } + } + + + // Built in Tooltips + if (this.chartInstance.options.tooltips.enabled) { + + // The usual updates + this.chartInstance.tooltip.initialize(); + + // Active + if (this.active.length) { + this.chartInstance.tooltip._model.opacity = 1; + + helpers.extend(this.chartInstance.tooltip, { + _active: this.active, + }); + + this.chartInstance.tooltip.update(); + } else { + // Inactive + this.chartInstance.tooltip._model.opacity = 0; + } + } + + // Hover animations + this.chartInstance.tooltip.pivot(); + + if (!this.chartInstance.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.chartInstance.stop(); + this.chartInstance.render(this.chartInstance.options.hover.animationDuration); + } + } + + // Remember Last Active + this.lastActive = this.active; + return this; }; Chart.RectangularCanvasController.prototype.initToolTip = function() { - this.chart.tooltip = new Chart.Tooltip({ - _chart: this.chart.chart, - _data: this.chart.data, - _options: this.chart.options, + this.chartInstance.tooltip = new Chart.Tooltip({ + _chart: this.chartInstance.chart, + _data: this.chartInstance.data, + _options: this.chartInstance.options, }, this); }; Chart.RectangularCanvasController.prototype.buildScales = function() { // Map of scale ID to scale object so we can lookup later - this.chart.scales = {}; + this.chartInstance.scales = {}; // Build the x axes - helpers.each(this.chart.options.scales.xAxes, function(xAxisOptions) { + helpers.each(this.chartInstance.options.scales.xAxes, function(xAxisOptions) { var ScaleClass = Chart.scaleService.getScaleConstructor(xAxisOptions.type); var scale = new ScaleClass({ - ctx: this.chart.chart.ctx, + ctx: this.chartInstance.chart.ctx, options: xAxisOptions, - data: this.chart.data, + data: this.chartInstance.data, id: xAxisOptions.id, }); - this.chart.scales[scale.id] = scale; + this.chartInstance.scales[scale.id] = scale; }, this); // Build the y axes - helpers.each(this.chart.options.scales.yAxes, function(yAxisOptions) { + helpers.each(this.chartInstance.options.scales.yAxes, function(yAxisOptions) { var ScaleClass = Chart.scaleService.getScaleConstructor(yAxisOptions.type); var scale = new ScaleClass({ - ctx: this.chart.chart.ctx, + ctx: this.chartInstance.chart.ctx, options: yAxisOptions, - data: this.chart.data, + data: this.chartInstance.data, id: yAxisOptions.id, }); - this.chart.scales[scale.id] = scale; + this.chartInstance.scales[scale.id] = scale; }, this); }; Chart.RectangularCanvasController.prototype.update = function() { - Chart.scaleService.fitScalesForChart(this.chart, this.chart.chart.width, this.chart.chart.height); + Chart.scaleService.fitScalesForChart(this.chartInstance, this.chartInstance.chart.width, this.chartInstance.chart.height); this.elementController.updateElements(); }; }).call(this); diff --git a/src/controllers/controller.elements.rectangular.js b/src/controllers/controller.elements.rectangular.js index 96b5bc181..a23949b9d 100644 --- a/src/controllers/controller.elements.rectangular.js +++ b/src/controllers/controller.elements.rectangular.js @@ -6,11 +6,11 @@ helpers = Chart.helpers; Chart.RectangularElementController = function(chart) { - this.chart = chart; + this.chartInstance = chart; }; Chart.RectangularElementController.prototype.getScaleForId = function getScaleForId(scaleID) { - return this.chart.scales[scaleID]; + return this.chartInstance.scales[scaleID]; }; // 2 helper functions to get points in collections @@ -22,13 +22,13 @@ }; Chart.RectangularElementController.prototype.eachLine = function eachLine(callback) { - helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { + helpers.each(this.chartInstance.data.datasets, function(dataset, datasetIndex) { callback.call(this, dataset, datasetIndex) }, this); }; Chart.RectangularElementController.prototype.eachPoint = function eachPoint(callback) { - helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) { + helpers.each(this.chartInstance.data.datasets, function(dataset, datasetIndex) { helpers.each(dataset.metaData, callback, this, dataset.metaData, datasetIndex); }, this); }; @@ -36,7 +36,7 @@ Chart.RectangularElementController.prototype.addLine = function addLine(dataset, datasetIndex) { if (dataset) { dataset.metaDataset = new Chart.Line({ - _chart: this.chart.chart, + _chart: this.chartInstance.chart, _datasetIndex: datasetIndex, _points: dataset.metaData, }); @@ -45,13 +45,13 @@ Chart.RectangularElementController.prototype.addPoint = function addPoint(dataset, datasetIndex, index) { if (dataset) { - dataset.metaData = dataset.metaData || new Array(this.chart.data.datasets[datasetIndex].data.length); + dataset.metaData = dataset.metaData || new Array(this.chartInstance.data.datasets[datasetIndex].data.length); if (index < dataset.metaData.length) { dataset.metaData[index] = new Chart.Point({ _datasetIndex: datasetIndex, _index: index, - _chart: this.chart.chart, + _chart: this.chartInstance.chart, _model: { x: 0, y: 0, @@ -68,8 +68,8 @@ Chart.RectangularElementController.prototype.resetPoints = function() { this.eachPoint(function(point, index, dataset, datasetIndex) { - var xScale = this.getScaleForId(this.chart.data.datasets[datasetIndex].xAxisID); - var yScale = this.getScaleForId(this.chart.data.datasets[datasetIndex].yAxisID); + var xScale = this.getScaleForId(this.chartInstance.data.datasets[datasetIndex].xAxisID); + var yScale = this.getScaleForId(this.chartInstance.data.datasets[datasetIndex].yAxisID); var yScalePoint; @@ -84,7 +84,7 @@ helpers.extend(point, { // Utility - _chart: this.chart.chart, //WTF + _chart: this.chartInstance.chart, //WTF _xScale: xScale, _yScale: yScale, _datasetIndex: datasetIndex, @@ -92,7 +92,7 @@ // Desired view properties _model: { - x: xScale.getPointPixelForValue(this.chart.data.datasets[datasetIndex].data[index], index, datasetIndex), + x: xScale.getPointPixelForValue(this.chartInstance.data.datasets[datasetIndex].data[index], index, datasetIndex), y: yScalePoint, }, }); @@ -133,13 +133,13 @@ // Model _model: { // Appearance - tension: dataset.metaDataset.custom && dataset.metaDataset.custom.tension ? dataset.metaDataset.custom.tension : (dataset.tension || this.chart.options.elements.line.tension), - backgroundColor: dataset.metaDataset.custom && dataset.metaDataset.custom.backgroundColor ? dataset.metaDataset.custom.backgroundColor : (dataset.backgroundColor || this.chart.options.elements.line.backgroundColor), - borderWidth: dataset.metaDataset.custom && dataset.metaDataset.custom.borderWidth ? dataset.metaDataset.custom.borderWidth : (dataset.borderWidth || this.chart.options.elements.line.borderWidth), - borderColor: dataset.metaDataset.custom && dataset.metaDataset.custom.borderColor ? dataset.metaDataset.custom.borderColor : (dataset.borderColor || this.chart.options.elements.line.borderColor), - fill: dataset.metaDataset.custom && dataset.metaDataset.custom.fill ? dataset.metaDataset.custom.fill : (dataset.fill !== undefined ? dataset.fill : this.chart.options.elements.line.fill), - skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.chart.options.elements.line.skipNull, - drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.chart.options.elements.line.drawNull, + tension: dataset.metaDataset.custom && dataset.metaDataset.custom.tension ? dataset.metaDataset.custom.tension : (dataset.tension || this.chartInstance.options.elements.line.tension), + backgroundColor: dataset.metaDataset.custom && dataset.metaDataset.custom.backgroundColor ? dataset.metaDataset.custom.backgroundColor : (dataset.backgroundColor || this.chartInstance.options.elements.line.backgroundColor), + borderWidth: dataset.metaDataset.custom && dataset.metaDataset.custom.borderWidth ? dataset.metaDataset.custom.borderWidth : (dataset.borderWidth || this.chartInstance.options.elements.line.borderWidth), + borderColor: dataset.metaDataset.custom && dataset.metaDataset.custom.borderColor ? dataset.metaDataset.custom.borderColor : (dataset.borderColor || this.chartInstance.options.elements.line.borderColor), + fill: dataset.metaDataset.custom && dataset.metaDataset.custom.fill ? dataset.metaDataset.custom.fill : (dataset.fill !== undefined ? dataset.fill : this.chartInstance.options.elements.line.fill), + skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.chartInstance.options.elements.line.skipNull, + drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.chartInstance.options.elements.line.drawNull, // Scale scaleTop: yScale.top, scaleBottom: yScale.bottom, @@ -153,12 +153,12 @@ Chart.RectangularElementController.prototype.updatePoints = function() { this.eachPoint(function(point, index, dataset, datasetIndex) { - var xScale = this.getScaleForId(this.chart.data.datasets[datasetIndex].xAxisID); - var yScale = this.getScaleForId(this.chart.data.datasets[datasetIndex].yAxisID); + var xScale = this.getScaleForId(this.chartInstance.data.datasets[datasetIndex].xAxisID); + var yScale = this.getScaleForId(this.chartInstance.data.datasets[datasetIndex].yAxisID); helpers.extend(point, { // Utility - _chart: this.chart.chart, + _chart: this.chartInstance.chart, _xScale: xScale, _yScale: yScale, _datasetIndex: datasetIndex, @@ -166,8 +166,8 @@ // Desired view properties _model: { - x: xScale.getPointPixelForValue(this.chart.data.datasets[datasetIndex].data[index], index, datasetIndex), - y: yScale.getPointPixelForValue(this.chart.data.datasets[datasetIndex].data[index], index, datasetIndex), + x: xScale.getPointPixelForValue(this.chartInstance.data.datasets[datasetIndex].data[index], index, datasetIndex), + y: yScale.getPointPixelForValue(this.chartInstance.data.datasets[datasetIndex].data[index], index, datasetIndex), }, }); @@ -180,18 +180,28 @@ Chart.RectangularElementController.prototype.updatePointElementAppearance = function(point, datasetIndex, index) { helpers.extend(point._model, { // Appearance - tension: point.custom && point.custom.tension ? point.custom.tension : this.chart.options.elements.line.tension, - radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.chart.data.datasets[datasetIndex].radius, index, this.chart.options.elements.point.radius), - backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.chart.data.datasets[datasetIndex].pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor), - borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.chart.data.datasets[datasetIndex].pointBorderColor, index, this.chart.options.elements.point.borderColor), - borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.chart.data.datasets[datasetIndex].pointBorderWidth, index, this.chart.options.elements.point.borderWidth), - skip: this.chart.data.datasets[datasetIndex].data[index] === null, + tension: point.custom && point.custom.tension ? point.custom.tension : this.chartInstance.options.elements.line.tension, + radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.chartInstance.data.datasets[datasetIndex].radius, index, this.chartInstance.options.elements.point.radius), + backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.chartInstance.data.datasets[datasetIndex].pointBackgroundColor, index, this.chartInstance.options.elements.point.backgroundColor), + borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.chartInstance.data.datasets[datasetIndex].pointBorderColor, index, this.chartInstance.options.elements.point.borderColor), + borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.chartInstance.data.datasets[datasetIndex].pointBorderWidth, index, this.chartInstance.options.elements.point.borderWidth), + skip: this.chartInstance.data.datasets[datasetIndex].data[index] === null, // Tooltip - hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.chart.data.datasets[datasetIndex].hitRadius, index, this.chart.options.elements.point.hitRadius), + hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.chartInstance.data.datasets[datasetIndex].hitRadius, index, this.chartInstance.options.elements.point.hitRadius), }); }; + Chart.RectangularElementController.prototype.setPointHoverStyle = function(point) { + var dataset = this.chartInstance.data.datasets[point._datasetIndex]; + var index = point._index; + + point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chartInstance.options.elements.point.hoverRadius); + point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString()); + point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString()); + point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, point._model.borderWidth); + }; + Chart.RectangularElementController.prototype.updateBezierControlPoints = function updateBezierControlPoints() { // Update control points for the bezier curve this.eachPoint(function(point, index, dataset, datasetIndex) { @@ -208,19 +218,19 @@ // 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.chart.chartArea.bottom) { - point._model.controlPointNextY = this.chart.chartArea.bottom; - } else if (controlPoints.next.y < this.chart.chartArea.top) { - point._model.controlPointNextY = this.chart.chartArea.top; + if (controlPoints.next.y > this.chartInstance.chartArea.bottom) { + point._model.controlPointNextY = this.chartInstance.chartArea.bottom; + } else if (controlPoints.next.y < this.chartInstance.chartArea.top) { + point._model.controlPointNextY = this.chartInstance.chartArea.top; } else { point._model.controlPointNextY = controlPoints.next.y; } // Cap inner bezier handles to the upper/lower scale bounds - if (controlPoints.previous.y > this.chart.chartArea.bottom) { - point._model.controlPointPreviousY = this.chart.chartArea.bottom; - } else if (controlPoints.previous.y < this.chart.chartArea.top) { - point._model.controlPointPreviousY = this.chart.chartArea.top; + if (controlPoints.previous.y > this.chartInstance.chartArea.bottom) { + point._model.controlPointPreviousY = this.chartInstance.chartArea.bottom; + } else if (controlPoints.previous.y < this.chartInstance.chartArea.top) { + point._model.controlPointPreviousY = this.chartInstance.chartArea.top; } else { point._model.controlPointPreviousY = controlPoints.previous.y; } @@ -230,4 +240,41 @@ }, this); }; + Chart.RectangularElementController.prototype.getElementsAtEvent = function(e) { + var elementsArray = [], + eventPosition = helpers.getRelativePosition(e), + datasetIterator = function(dataset) { + elementsArray.push(dataset.metaData[elementIndex]); + }, + elementIndex; + + for (var datasetIndex = 0; datasetIndex < this.chartInstance.data.datasets.length; datasetIndex++) { + for (elementIndex = 0; elementIndex < this.chartInstance.data.datasets[datasetIndex].metaData.length; elementIndex++) { + if (this.chartInstance.data.datasets[datasetIndex].metaData[elementIndex].inGroupRange(eventPosition.x, eventPosition.y)) { + helpers.each(this.chartInstance.data.datasets, datasetIterator); + } + } + } + + return elementsArray.length ? elementsArray : []; + }; + + // Get the single element that was clicked on + // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was drawn + Chart.RectangularElementController.prototype.getElementAtEvent = function(e) { + var element = []; + var eventPosition = helpers.getRelativePosition(e); + + for (var datasetIndex = 0; datasetIndex < this.chartInstance.data.datasets.length; ++datasetIndex) { + for (var elementIndex = 0; elementIndex < this.chartInstance.data.datasets[datasetIndex].metaData.length; ++elementIndex) { + if (this.chartInstance.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x, eventPosition.y)) { + element.push(this.chartInstance.data.datasets[datasetIndex].metaData[elementIndex]); + return element; + } + } + } + + return []; + }; + }).call(this); diff --git a/src/core/core.js b/src/core/core.js index 6328edd82..e3f8ddcda 100755 --- a/src/core/core.js +++ b/src/core/core.js @@ -990,7 +990,10 @@ return this; }, - redraw: noop, + update: function(animationDuration) { + this.canvasController.update(); + this.render(animationDuration); + }, render: function(duration) { if (this.options.animation.duration !== 0 || duration) {