'./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'
};
- Chart.Type.extend({
+ Chart.types.RectangularBase.extend({
name: "Line",
defaults: defaultConfig,
initialize: function() {
- var _this = this;
- this.controller = new Chart.RectangularController(this);
-
- // Events
- helpers.bindEvents(this, this.options.events, this.events);
+ this.controller = new Chart.RectangularElementController(this);
// Create a new line and its points for each dataset and piece of data
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
}
}, this);
- // Build and fit the scale. Needs to happen after the axis IDs have been set
- this.buildScale();
-
- // 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);
-
- // Need to fit scales before we reset elements.
- Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
-
- // Reset so that we animation from the baseline
- this.resetElements();
-
- // Update that shiz
- this.update();
- },
- nextPoint: function(collection, index) {
- return collection[index + 1] || collection[index];
- },
- previousPoint: function(collection, index) {
- return collection[index - 1] || collection[index];
- },
- resetElements: function() {
- this.controller.resetElements();
- },
- update: function(animationDuration) {
-
- Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
-
- // Update the lines
- this.eachDataset(function(dataset, datasetIndex) {
- var yScale = this.scales[dataset.yAxisID];
- var scaleBase;
-
- if (yScale.min < 0 && yScale.max < 0) {
- scaleBase = yScale.getPixelForValue(yScale.max);
- } else if (yScale.min > 0 && yScale.max > 0) {
- scaleBase = yScale.getPixelForValue(yScale.min);
- } else {
- scaleBase = yScale.getPixelForValue(0);
- }
-
- helpers.extend(dataset.metaDataset, {
- // Utility
- _scale: yScale,
- _datasetIndex: datasetIndex,
- // Data
- _children: dataset.metaData,
- // Model
- _model: {
- // Appearance
- tension: dataset.metaDataset.custom && dataset.metaDataset.custom.tension ? dataset.metaDataset.custom.tension : (dataset.tension || this.options.elements.line.tension),
- backgroundColor: dataset.metaDataset.custom && dataset.metaDataset.custom.backgroundColor ? dataset.metaDataset.custom.backgroundColor : (dataset.backgroundColor || this.options.elements.line.backgroundColor),
- borderWidth: dataset.metaDataset.custom && dataset.metaDataset.custom.borderWidth ? dataset.metaDataset.custom.borderWidth : (dataset.borderWidth || this.options.elements.line.borderWidth),
- borderColor: dataset.metaDataset.custom && dataset.metaDataset.custom.borderColor ? dataset.metaDataset.custom.borderColor : (dataset.borderColor || this.options.elements.line.borderColor),
- fill: dataset.metaDataset.custom && dataset.metaDataset.custom.fill ? dataset.metaDataset.custom.fill : (dataset.fill !== undefined ? dataset.fill : this.options.elements.line.fill),
- skipNull: dataset.skipNull !== undefined ? dataset.skipNull : this.options.elements.line.skipNull,
- drawNull: dataset.drawNull !== undefined ? dataset.drawNull : this.options.elements.line.drawNull,
- // Scale
- scaleTop: yScale.top,
- scaleBottom: yScale.bottom,
- scaleZero: scaleBase,
- },
- });
-
- 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, {
- // Utility
- _chart: this.chart,
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: datasetIndex,
- _index: index,
-
- // Desired view properties
- _model: {
- x: xScale.getPointPixelForValue(this.data.datasets[datasetIndex].data[index], index, datasetIndex),
- y: yScale.getPointPixelForValue(this.data.datasets[datasetIndex].data[index], index, datasetIndex),
-
- // Appearance
- tension: point.custom && point.custom.tension ? point.custom.tension : this.options.elements.line.tension,
- radius: point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].radius, index, this.options.elements.point.radius),
- backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBackgroundColor, index, this.options.elements.point.backgroundColor),
- borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderColor, index, this.options.elements.point.borderColor),
- borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].pointBorderWidth, index, this.options.elements.point.borderWidth),
- skip: this.data.datasets[datasetIndex].data[index] === null,
-
- // Tooltip
- hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.data.datasets[datasetIndex].hitRadius, index, this.options.elements.point.hitRadius),
- },
- });
- }, this);
-
-
- // Update control points for the bezier curve
- this.eachElement(function(point, index, dataset, datasetIndex) {
- var controlPoints = helpers.splineCurve(
- this.previousPoint(dataset, index)._model,
- point._model,
- this.nextPoint(dataset, index)._model,
- point._model.tension
- );
-
- point._model.controlPointPreviousX = controlPoints.previous.x;
- point._model.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._model.controlPointNextY = this.chartArea.bottom;
- } else if (controlPoints.next.y < this.chartArea.top) {
- point._model.controlPointNextY = this.chartArea.top;
- } else {
- point._model.controlPointNextY = controlPoints.next.y;
- }
-
- // Cap inner bezier handles to the upper/lower scale bounds
- if (controlPoints.previous.y > this.chartArea.bottom) {
- point._model.controlPointPreviousY = this.chartArea.bottom;
- } else if (controlPoints.previous.y < this.chartArea.top) {
- point._model.controlPointPreviousY = this.chartArea.top;
- } else {
- point._model.controlPointPreviousY = controlPoints.previous.y;
- }
-
- // Now pivot the point for animation
- point.pivot();
- }, this);
-
- this.render(animationDuration);
- },
- buildScale: function() {
- // Map of scale ID to scale object so we can lookup later
- this.scales = {};
-
- // Build the x axes
- helpers.each(this.options.scales.xAxes, function(xAxisOptions) {
- var ScaleClass = Chart.scaleService.getScaleConstructor(xAxisOptions.type);
- var scale = new ScaleClass({
- ctx: this.chart.ctx,
- options: xAxisOptions,
- data: this.data,
- id: xAxisOptions.id,
- });
-
- this.scales[scale.id] = scale;
- }, this);
-
- // Build the y axes
- helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
- var ScaleClass = Chart.scaleService.getScaleConstructor(yAxisOptions.type);
- var scale = new ScaleClass({
- ctx: this.chart.ctx,
- options: yAxisOptions,
- data: this.data,
- id: yAxisOptions.id,
- });
-
- this.scales[scale.id] = scale;
- }, this);
+ this.__super__.initialize.call(this);
},
draw: function(ease) {
// Finally draw the tooltip
this.tooltip.transition(easingDecimal).draw();
},
- 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);
--- /dev/null
+(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,
+ initialize: function() {
+ // Events
+ helpers.bindEvents(this, this.options.events, this.events);
+
+ // Build and fit the scale. Needs to happen after the axis IDs have been set
+ this.buildScales();
+
+ // 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);
+
+ // Need to fit scales before we reset elements.
+ Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
+
+ // Reset so that we animation from the baseline
+ this.resetElements();
+
+ // Update that shiz
+ this.update();
+ },
+ resetElements: function() {
+ this.controller.resetElements();
+ },
+ update: function(animationDuration) {
+
+ Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
+ this.controller.updateElements();
+ this.render(animationDuration);
+ },
+ buildScales: function() {
+ // Map of scale ID to scale object so we can lookup later
+ this.scales = {};
+
+ // Build the x axes
+ helpers.each(this.options.scales.xAxes, function(xAxisOptions) {
+ var ScaleClass = Chart.scaleService.getScaleConstructor(xAxisOptions.type);
+ var scale = new ScaleClass({
+ ctx: this.chart.ctx,
+ options: xAxisOptions,
+ data: this.data,
+ id: xAxisOptions.id,
+ });
+
+ this.scales[scale.id] = scale;
+ }, this);
+
+ // Build the y axes
+ helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
+ var ScaleClass = Chart.scaleService.getScaleConstructor(yAxisOptions.type);
+ var scale = new ScaleClass({
+ ctx: this.chart.ctx,
+ options: yAxisOptions,
+ data: this.data,
+ id: yAxisOptions.id,
+ });
+
+ this.scales[scale.id] = scale;
+ }, this);
+ },
+ 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);
--- /dev/null
+(function() {
+ "use strict";
+
+ var root = this,
+ Chart = root.Chart,
+ helpers = Chart.helpers;
+
+ Chart.RectangularElementController = function(chart) {
+ this.chart = chart;
+ };
+
+ Chart.RectangularElementController.prototype.getScaleForId = function getScaleForId(scaleID) {
+ return this.chart.scales[scaleID];
+ };
+
+ // 2 helper functions to get points in collections
+ Chart.RectangularElementController.prototype.nextPoint = function nextPoint(collection, index) {
+ return collection[index + 1] || collection[index];
+ };
+ Chart.RectangularElementController.prototype.previousPoint = function previousPoint(collection, index) {
+ return collection[index - 1] || collection[index];
+ };
+
+ Chart.RectangularElementController.prototype.eachLine = function eachLine(callback) {
+ helpers.each(this.chart.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(dataset.metaData, callback, this, dataset.metaData, datasetIndex);
+ }, this);
+ };
+
+ Chart.RectangularElementController.prototype.addLine = function addLine(dataset, datasetIndex) {
+ if (dataset) {
+ dataset.metaDataset = new Chart.Line({
+ _chart: this.chart.chart,
+ _datasetIndex: datasetIndex,
+ _points: dataset.metaData,
+ });
+ }
+ }
+
+ Chart.RectangularElementController.prototype.addPoint = function addPoint(dataset, datasetIndex, index) {
+ if (dataset) {
+ dataset.metaData = dataset.metaData || new Array(this.chart.data.datasets[datasetIndex].data.length);
+
+ if (index < dataset.metaData.length) {
+ dataset.metaData[index] = new Chart.Point({
+ _datasetIndex: datasetIndex,
+ _index: index,
+ _chart: this.chart.chart,
+ _model: {
+ x: 0,
+ y: 0,
+ },
+ })
+ }
+ }
+ };
+
+ Chart.RectangularElementController.prototype.resetElements = function resetElements() {
+ // Update the points
+ this.resetPoints();
+ };
+
+ 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 yScalePoint;
+
+ if (yScale.min < 0 && yScale.max < 0) {
+ // all less than 0. use the top
+ yScalePoint = yScale.getPixelForValue(yScale.max);
+ } else if (yScale.min > 0 && yScale.max > 0) {
+ yScalePoint = yScale.getPixelForValue(yScale.min);
+ } else {
+ yScalePoint = yScale.getPixelForValue(0);
+ }
+
+ helpers.extend(point, {
+ // Utility
+ _chart: this.chart.chart, //WTF
+ _xScale: xScale,
+ _yScale: yScale,
+ _datasetIndex: datasetIndex,
+ _index: index,
+
+ // Desired view properties
+ _model: {
+ x: xScale.getPointPixelForValue(this.chart.data.datasets[datasetIndex].data[index], index, datasetIndex),
+ y: yScalePoint,
+ },
+ });
+
+ this.updatePointElementAppearance(point, datasetIndex, index);
+ }, this);
+
+ this.updateBezierControlPoints();
+ };
+
+ Chart.RectangularElementController.prototype.updateElements = function updateElements() {
+ // Update the lines
+ this.updateLines();
+
+ // Update the points
+ this.updatePoints();
+ };
+
+ Chart.RectangularElementController.prototype.updateLines = function updateLines() {
+ this.eachLine(function(dataset, datasetIndex) {
+ var yScale = this.getScaleForId(dataset.yAxisID);
+ var scaleBase;
+
+ if (yScale.min < 0 && yScale.max < 0) {
+ scaleBase = yScale.getPixelForValue(yScale.max);
+ } else if (yScale.min > 0 && yScale.max > 0) {
+ scaleBase = yScale.getPixelForValue(yScale.min);
+ } else {
+ scaleBase = yScale.getPixelForValue(0);
+ }
+
+ helpers.extend(dataset.metaDataset, {
+ // Utility
+ _scale: yScale,
+ _datasetIndex: datasetIndex,
+ // Data
+ _children: dataset.metaData,
+ // 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,
+ // Scale
+ scaleTop: yScale.top,
+ scaleBottom: yScale.bottom,
+ scaleZero: scaleBase,
+ },
+ });
+
+ dataset.metaDataset.pivot();
+ });
+ };
+
+ 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);
+
+ helpers.extend(point, {
+ // Utility
+ _chart: this.chart.chart,
+ _xScale: xScale,
+ _yScale: yScale,
+ _datasetIndex: datasetIndex,
+ _index: index,
+
+ // 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),
+ },
+ });
+
+ this.updatePointElementAppearance(point, datasetIndex, index);
+ }, this);
+
+ this.updateBezierControlPoints();
+ };
+
+ 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,
+
+ // 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),
+ });
+ };
+
+ Chart.RectangularElementController.prototype.updateBezierControlPoints = function updateBezierControlPoints() {
+ // Update control points for the bezier curve
+ this.eachPoint(function(point, index, dataset, datasetIndex) {
+ var controlPoints = helpers.splineCurve(
+ this.previousPoint(dataset, index)._model,
+ point._model,
+ this.nextPoint(dataset, index)._model,
+ point._model.tension
+ );
+
+ point._model.controlPointPreviousX = controlPoints.previous.x;
+ point._model.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.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;
+ } 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;
+ } else {
+ point._model.controlPointPreviousY = controlPoints.previous.y;
+ }
+
+ // Now pivot the point for animation
+ point.pivot();
+ }, this);
+ };
+
+}).call(this);
+++ /dev/null
-(function() {
- "use strict";
-
- var root = this,
- Chart = root.Chart,
- helpers = Chart.helpers;
-
- Chart.RectangularController = function(chart) {
- this.chart = chart;
- };
-
- Chart.RectangularController.prototype.eachLine = function(callback) {
- helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
- callback(dataset.metaDataset, datasetIndex)
- }, this);
- };
-
- Chart.RectangularController.prototype.eachPoint = function(callback) {
- helpers.each(this.chart.data.datasets, function(dataset, datasetIndex) {
- helpers.each(dataset.metaData, callback, this, dataset.metaData, datasetIndex);
- }, this);
- };
-
- Chart.RectangularController.prototype.addLine = function addLine(dataset, datasetIndex) {
- if (dataset) {
- dataset.metaDataset = new Chart.Line({
- _chart: this.chart.chart,
- _datasetIndex: datasetIndex,
- _points: dataset.metaData,
- });
- }
- }
-
- Chart.RectangularController.prototype.addPoint = function(dataset, datasetIndex, index) {
- if (dataset) {
- dataset.metaData = dataset.metaData || new Array(this.chart.data.datasets[datasetIndex].data.length);
-
- if (index < dataset.metaData.length) {
- dataset.metaData[index] = new Chart.Point({
- _datasetIndex: datasetIndex,
- _index: index,
- _chart: this.chart.chart,
- _model: {
- x: 0,
- y: 0,
- },
- })
- }
- }
- };
-
- Chart.RectangularController.prototype.resetElements = function() {
- // Update the points
- this.eachPoint(function(point, index, dataset, datasetIndex) {
- var xScale = this.chart.scales[this.chart.data.datasets[datasetIndex].xAxisID];
- var yScale = this.chart.scales[this.chart.data.datasets[datasetIndex].yAxisID];
-
- var yScalePoint;
-
- if (yScale.min < 0 && yScale.max < 0) {
- // all less than 0. use the top
- yScalePoint = yScale.getPixelForValue(yScale.max);
- } else if (yScale.min > 0 && yScale.max > 0) {
- yScalePoint = yScale.getPixelForValue(yScale.min);
- } else {
- yScalePoint = yScale.getPixelForValue(0);
- }
-
- helpers.extend(point, {
- // Utility
- _chart: this.chart.chart, //WTF
- _xScale: xScale,
- _yScale: yScale,
- _datasetIndex: datasetIndex,
- _index: index,
-
- // Desired view properties
- _model: {
- x: xScale.getPointPixelForValue(this.chart.data.datasets[datasetIndex].data[index], index, datasetIndex),
- y: yScalePoint,
-
- // 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,
-
- // 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),
- },
- });
- }, this);
-
- // Update control points for the bezier curve
- this.eachPoint(function(point, index, dataset, datasetIndex) {
- var controlPoints = helpers.splineCurve(
- this.chart.previousPoint(dataset, index)._model,
- point._model,
- this.chart.nextPoint(dataset, index)._model,
- point._model.tension
- );
-
- point._model.controlPointPreviousX = controlPoints.previous.x;
- point._model.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.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;
- } 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;
- } else {
- point._model.controlPointPreviousY = controlPoints.previous.y;
- }
-
- // Now pivot the point for animation
- point.pivot();
- }, this);
- };
-
-}).call(this);
//Copy the prototype object of the this class
ChartType.prototype = clone(parent.prototype);
+ ChartType.prototype.__super__ = clone(parent.prototype);
+
//Now overwrite some of the properties in the base class with the new extensions
extend(ChartType.prototype, extensions);
+
ChartType.extend = Chart.Type.extend;
if (extensions.name || parent.prototype.name) {