mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
More core file separation, and no duplicate copyrights
This commit is contained in:
parent
81c66c8d85
commit
3f9afb1f31
@ -25,6 +25,9 @@ gulp.task('build', function() {
|
||||
|
||||
var srcFiles = [
|
||||
'./src/core/core.js',
|
||||
'./src/core/core.helpers.js',
|
||||
'./src/core/core.chart.js',
|
||||
'./src/core/core.element.js',
|
||||
'./src/core/**',
|
||||
'./src/controllers/**',
|
||||
'./src/scales/**',
|
||||
|
||||
@ -1,14 +1,3 @@
|
||||
/*!
|
||||
* Chart.js
|
||||
* http://chartjs.org/
|
||||
* Version: {{ version }}
|
||||
*
|
||||
* Copyright 2015 Nick Downie
|
||||
* Released under the MIT license
|
||||
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
209
src/core/core.chart.js
Normal file
209
src/core/core.chart.js
Normal file
@ -0,0 +1,209 @@
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
//Declare root variable - window in the browser, global on the server
|
||||
var root = this,
|
||||
previous = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
|
||||
//Create a dictionary of chart types, to allow for extension of existing types
|
||||
Chart.types = {};
|
||||
|
||||
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
|
||||
//Destroy method on the chart will remove the instance of the chart from this reference.
|
||||
Chart.instances = {};
|
||||
|
||||
Chart.Type = function(config, instance) {
|
||||
this.data = config.data;
|
||||
this.options = config.options;
|
||||
this.chart = instance;
|
||||
this.id = helpers.uid();
|
||||
//Add the chart instance to the global namespace
|
||||
Chart.instances[this.id] = this;
|
||||
|
||||
// Initialize is always called when a chart type is created
|
||||
// By default it is a no op, but it should be extended
|
||||
if (this.options.responsive) {
|
||||
this.resize();
|
||||
}
|
||||
this.initialize.call(this);
|
||||
};
|
||||
|
||||
//Core methods that'll be a part of every chart type
|
||||
helpers.extend(Chart.Type.prototype, {
|
||||
initialize: function() {
|
||||
return this;
|
||||
},
|
||||
clear: function() {
|
||||
helpers.clear(this.chart);
|
||||
return this;
|
||||
},
|
||||
stop: function() {
|
||||
// Stops any current animation loop occuring
|
||||
Chart.animationService.cancelAnimation(this);
|
||||
return this;
|
||||
},
|
||||
resize: function() {
|
||||
this.stop();
|
||||
var canvas = this.chart.canvas,
|
||||
newWidth = helpers.getMaximumWidth(this.chart.canvas),
|
||||
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
|
||||
|
||||
canvas.width = this.chart.width = newWidth;
|
||||
canvas.height = this.chart.height = newHeight;
|
||||
|
||||
helpers.retinaScale(this.chart);
|
||||
|
||||
return this;
|
||||
},
|
||||
update: function(animationDuration) {
|
||||
this.canvasController.update();
|
||||
this.render(animationDuration);
|
||||
},
|
||||
render: function(duration) {
|
||||
|
||||
if (this.options.animation.duration !== 0 || duration) {
|
||||
var animation = new Chart.Animation();
|
||||
animation.numSteps = (duration || this.options.animation.duration) / 16.66; //60 fps
|
||||
animation.easing = this.options.animation.easing;
|
||||
|
||||
// render function
|
||||
animation.render = function(chartInstance, animationObject) {
|
||||
var easingFunction = helpers.easingEffects[animationObject.easing];
|
||||
var stepDecimal = animationObject.currentStep / animationObject.numSteps;
|
||||
var easeDecimal = easingFunction(stepDecimal);
|
||||
|
||||
chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
|
||||
};
|
||||
|
||||
// user events
|
||||
animation.onAnimationProgress = this.options.onAnimationProgress;
|
||||
animation.onAnimationComplete = this.options.onAnimationComplete;
|
||||
|
||||
Chart.animationService.addAnimation(this, animation, duration);
|
||||
} else {
|
||||
this.draw();
|
||||
this.options.onAnimationComplete.call(this);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
eachElement: function(callback) {
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(dataset.metaData, callback, this, dataset.metaData, datasetIndex);
|
||||
}, this);
|
||||
},
|
||||
eachValue: function(callback) {
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(dataset.data, callback, this, datasetIndex);
|
||||
}, this);
|
||||
},
|
||||
eachDataset: function(callback) {
|
||||
helpers.each(this.data.datasets, callback, this);
|
||||
},
|
||||
getElementsAtEvent: function(e) {
|
||||
var elementsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e),
|
||||
datasetIterator = function(dataset) {
|
||||
elementsArray.push(dataset.metaData[elementIndex]);
|
||||
},
|
||||
elementIndex;
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
|
||||
for (elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; elementIndex++) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inGroupRange(eventPosition.x, eventPosition.y)) {
|
||||
helpers.each(this.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
|
||||
getElementAtEvent: function(e) {
|
||||
var element = [];
|
||||
var eventPosition = helpers.getRelativePosition(e);
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; ++datasetIndex) {
|
||||
for (var elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; ++elementIndex) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x, eventPosition.y)) {
|
||||
element.push(this.data.datasets[datasetIndex].metaData[elementIndex]);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
generateLegend: function() {
|
||||
return template(this.options.legendTemplate, this);
|
||||
},
|
||||
destroy: function() {
|
||||
this.clear();
|
||||
unbindEvents(this, this.events);
|
||||
var canvas = this.chart.canvas;
|
||||
|
||||
// Reset canvas height/width attributes starts a fresh with the canvas context
|
||||
canvas.width = this.chart.width;
|
||||
canvas.height = this.chart.height;
|
||||
|
||||
// < IE9 doesn't support removeProperty
|
||||
if (canvas.style.removeProperty) {
|
||||
canvas.style.removeProperty('width');
|
||||
canvas.style.removeProperty('height');
|
||||
} else {
|
||||
canvas.style.removeAttribute('width');
|
||||
canvas.style.removeAttribute('height');
|
||||
}
|
||||
|
||||
delete Chart.instances[this.id];
|
||||
},
|
||||
toBase64Image: function() {
|
||||
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.Type.extend = function(extensions) {
|
||||
|
||||
var parent = this;
|
||||
|
||||
var ChartType = function() {
|
||||
return parent.apply(this, arguments);
|
||||
};
|
||||
|
||||
//Copy the prototype object of the this class
|
||||
ChartType.prototype = helpers.clone(parent.prototype);
|
||||
|
||||
//Now overwrite some of the properties in the base class with the new extensions
|
||||
helpers.extend(ChartType.prototype, extensions);
|
||||
ChartType.extend = Chart.Type.extend;
|
||||
|
||||
if (extensions.name || parent.prototype.name) {
|
||||
|
||||
var chartName = extensions.name || parent.prototype.name;
|
||||
//Assign any potential default values of the new chart type
|
||||
|
||||
//If none are defined, we'll use a clone of the chart type this is being extended from.
|
||||
//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
|
||||
//doesn't define some defaults of their own.
|
||||
|
||||
var baseDefaults = (Chart.defaults[parent.prototype.name]) ? helpers.clone(Chart.defaults[parent.prototype.name]) : {};
|
||||
|
||||
Chart.defaults[chartName] = helpers.configMerge(baseDefaults, extensions.defaults);
|
||||
|
||||
Chart.types[chartName] = ChartType;
|
||||
|
||||
//Register this new chart type in the Chart prototype
|
||||
Chart.prototype[chartName] = function(config) {
|
||||
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");
|
||||
}
|
||||
return parent;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
91
src/core/core.element.js
Normal file
91
src/core/core.element.js
Normal file
@ -0,0 +1,91 @@
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
//Declare root variable - window in the browser, global on the server
|
||||
var root = this,
|
||||
previous = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
|
||||
Chart.Element = function(configuration) {
|
||||
helpers.extend(this, configuration);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
helpers.extend(Chart.Element.prototype, {
|
||||
initialize: function() {},
|
||||
pivot: function() {
|
||||
if (!this._view) {
|
||||
this._view = helpers.clone(this._model);
|
||||
}
|
||||
this._start = helpers.clone(this._view);
|
||||
return this;
|
||||
},
|
||||
transition: function(ease) {
|
||||
if (!this._view) {
|
||||
this._view = helpers.clone(this._model);
|
||||
}
|
||||
if (!this._start) {
|
||||
this.pivot();
|
||||
}
|
||||
|
||||
helpers.each(this._model, function(value, key) {
|
||||
|
||||
if (key[0] === '_' || !this._model.hasOwnProperty(key)) {
|
||||
// Only non-underscored properties
|
||||
}
|
||||
|
||||
// Init if doesn't exist
|
||||
else if (!this._view[key]) {
|
||||
if (typeof value === 'number') {
|
||||
this._view[key] = value * ease;
|
||||
} else {
|
||||
this._view[key] = value || null;
|
||||
}
|
||||
}
|
||||
|
||||
// No unnecessary computations
|
||||
else if (this._model[key] === this._view[key]) {
|
||||
// It's the same! Woohoo!
|
||||
}
|
||||
|
||||
// Color transitions if possible
|
||||
else if (typeof value === 'string') {
|
||||
try {
|
||||
var color = helpers.color(this._start[key]).mix(helpers.color(this._model[key]), ease);
|
||||
this._view[key] = color.rgbString();
|
||||
} catch (err) {
|
||||
this._view[key] = value;
|
||||
}
|
||||
}
|
||||
// Number transitions
|
||||
else if (typeof value === 'number') {
|
||||
var startVal = this._start[key] !== undefined ? this._start[key] : 0;
|
||||
this._view[key] = ((this._model[key] - startVal) * ease) + startVal;
|
||||
}
|
||||
// Everything else
|
||||
else {
|
||||
this._view[key] = value;
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
if (ease === 1) {
|
||||
delete this._start;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
return {
|
||||
x: this._model.x,
|
||||
y: this._model.y
|
||||
};
|
||||
},
|
||||
hasValue: function() {
|
||||
return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.Element.extend = helpers.inherits;
|
||||
|
||||
}).call(this);
|
||||
395
src/core/core.js → src/core/core.helpers.js
Executable file → Normal file
395
src/core/core.js → src/core/core.helpers.js
Executable file → Normal file
@ -1,14 +1,3 @@
|
||||
/*!
|
||||
* Chart.js
|
||||
* http://chartjs.org/
|
||||
* Version: {{ version }}
|
||||
*
|
||||
* Copyright 2015 Nick Downie
|
||||
* Released under the MIT license
|
||||
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
@ -17,73 +6,6 @@
|
||||
var root = this,
|
||||
previous = root.Chart;
|
||||
|
||||
//Occupy the global variable of Chart, and create a simple base class
|
||||
var Chart = function(context) {
|
||||
var chart = this;
|
||||
|
||||
// Support a jQuery'd canvas element
|
||||
if (context.length && context[0].getContext) {
|
||||
context = context[0];
|
||||
}
|
||||
|
||||
// Support a canvas domnode
|
||||
if (context.getContext) {
|
||||
context = context.getContext("2d");
|
||||
}
|
||||
|
||||
this.canvas = context.canvas;
|
||||
|
||||
this.ctx = context;
|
||||
|
||||
//Variables global to the chart
|
||||
var computeDimension = function(element, dimension) {
|
||||
if (element['offset' + dimension]) {
|
||||
return element['offset' + dimension];
|
||||
} else {
|
||||
return document.defaultView.getComputedStyle(element).getPropertyValue(dimension);
|
||||
}
|
||||
};
|
||||
|
||||
var width = this.width = computeDimension(context.canvas, 'Width') || context.canvas.width;
|
||||
var height = this.height = computeDimension(context.canvas, 'Height') || context.canvas.height;
|
||||
|
||||
// Firefox requires this to work correctly
|
||||
context.canvas.width = width;
|
||||
context.canvas.height = height;
|
||||
|
||||
width = this.width = context.canvas.width;
|
||||
height = this.height = context.canvas.height;
|
||||
this.aspectRatio = this.width / this.height;
|
||||
//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
|
||||
helpers.retinaScale(this);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
var defaultColor = 'rgba(0,0,0,0.1)';
|
||||
|
||||
//Globally expose the defaults to allow for user updating/changing
|
||||
Chart.defaults = {
|
||||
global: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
|
||||
hover: {
|
||||
onHover: null,
|
||||
mode: 'single',
|
||||
animationDuration: 400,
|
||||
},
|
||||
onClick: null,
|
||||
defaultColor: defaultColor,
|
||||
|
||||
// Element defaults defined in element extensions
|
||||
elements: {}
|
||||
},
|
||||
};
|
||||
|
||||
//Create a dictionary of chart types, to allow for extension of existing types
|
||||
Chart.types = {};
|
||||
|
||||
//Global Chart helpers object for utility methods and classes
|
||||
var helpers = Chart.helpers = {};
|
||||
|
||||
@ -148,7 +70,7 @@
|
||||
} else if (key === 'scale') {
|
||||
// Used in polar area & radar charts since there is only one scale
|
||||
base[key] = helpers.configMerge(base.hasOwnProperty(key) ? base[key] : {}, Chart.scaleService.getScaleDefaults(value.type), value);
|
||||
}else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
|
||||
} else if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
|
||||
// In this case we have an array of objects replacing another array. Rather than doing a strict replace,
|
||||
// merge. This allows easy scale option merging
|
||||
var baseArray = base[key];
|
||||
@ -285,9 +207,7 @@
|
||||
|
||||
ChartElement.extend = inherits;
|
||||
|
||||
if (extensions) {
|
||||
extend(ChartElement.prototype, extensions);
|
||||
}
|
||||
if (extensions) extend(ChartElement.prototype, extensions);
|
||||
|
||||
ChartElement.__super__ = parent.prototype;
|
||||
|
||||
@ -943,315 +863,4 @@
|
||||
return Array.isArray(obj);
|
||||
};
|
||||
|
||||
//Store a reference to each instance - allowing us to globally resize chart instances on window resize.
|
||||
//Destroy method on the chart will remove the instance of the chart from this reference.
|
||||
Chart.instances = {};
|
||||
|
||||
Chart.Type = function(config, instance) {
|
||||
this.data = config.data;
|
||||
this.options = config.options;
|
||||
this.chart = instance;
|
||||
this.id = uid();
|
||||
//Add the chart instance to the global namespace
|
||||
Chart.instances[this.id] = this;
|
||||
|
||||
// Initialize is always called when a chart type is created
|
||||
// By default it is a no op, but it should be extended
|
||||
if (this.options.responsive) {
|
||||
this.resize();
|
||||
}
|
||||
this.initialize.call(this);
|
||||
};
|
||||
|
||||
//Core methods that'll be a part of every chart type
|
||||
extend(Chart.Type.prototype, {
|
||||
initialize: function() {
|
||||
return this;
|
||||
},
|
||||
clear: function() {
|
||||
clear(this.chart);
|
||||
return this;
|
||||
},
|
||||
stop: function() {
|
||||
// Stops any current animation loop occuring
|
||||
Chart.animationService.cancelAnimation(this);
|
||||
return this;
|
||||
},
|
||||
resize: function() {
|
||||
this.stop();
|
||||
var canvas = this.chart.canvas,
|
||||
newWidth = getMaximumWidth(this.chart.canvas),
|
||||
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas);
|
||||
|
||||
canvas.width = this.chart.width = newWidth;
|
||||
canvas.height = this.chart.height = newHeight;
|
||||
|
||||
retinaScale(this.chart);
|
||||
|
||||
return this;
|
||||
},
|
||||
update: function(animationDuration) {
|
||||
this.canvasController.update();
|
||||
this.render(animationDuration);
|
||||
},
|
||||
render: function(duration) {
|
||||
|
||||
if (this.options.animation.duration !== 0 || duration) {
|
||||
var animation = new Chart.Animation();
|
||||
animation.numSteps = (duration || this.options.animation.duration) / 16.66; //60 fps
|
||||
animation.easing = this.options.animation.easing;
|
||||
|
||||
// render function
|
||||
animation.render = function(chartInstance, animationObject) {
|
||||
var easingFunction = helpers.easingEffects[animationObject.easing];
|
||||
var stepDecimal = animationObject.currentStep / animationObject.numSteps;
|
||||
var easeDecimal = easingFunction(stepDecimal);
|
||||
|
||||
chartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);
|
||||
};
|
||||
|
||||
// user events
|
||||
animation.onAnimationProgress = this.options.onAnimationProgress;
|
||||
animation.onAnimationComplete = this.options.onAnimationComplete;
|
||||
|
||||
Chart.animationService.addAnimation(this, animation, duration);
|
||||
} else {
|
||||
this.draw();
|
||||
this.options.onAnimationComplete.call(this);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
eachElement: function(callback) {
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(dataset.metaData, callback, this, dataset.metaData, datasetIndex);
|
||||
}, this);
|
||||
},
|
||||
eachValue: function(callback) {
|
||||
helpers.each(this.data.datasets, function(dataset, datasetIndex) {
|
||||
helpers.each(dataset.data, callback, this, datasetIndex);
|
||||
}, this);
|
||||
},
|
||||
eachDataset: function(callback) {
|
||||
helpers.each(this.data.datasets, callback, this);
|
||||
},
|
||||
getElementsAtEvent: function(e) {
|
||||
var elementsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e),
|
||||
datasetIterator = function(dataset) {
|
||||
elementsArray.push(dataset.metaData[elementIndex]);
|
||||
},
|
||||
elementIndex;
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
|
||||
for (elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; elementIndex++) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inGroupRange(eventPosition.x, eventPosition.y)) {
|
||||
helpers.each(this.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
|
||||
getElementAtEvent: function(e) {
|
||||
var element = [];
|
||||
var eventPosition = helpers.getRelativePosition(e);
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; ++datasetIndex) {
|
||||
for (var elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; ++elementIndex) {
|
||||
if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x, eventPosition.y)) {
|
||||
element.push(this.data.datasets[datasetIndex].metaData[elementIndex]);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
generateLegend: function() {
|
||||
return template(this.options.legendTemplate, this);
|
||||
},
|
||||
destroy: function() {
|
||||
this.clear();
|
||||
unbindEvents(this, this.events);
|
||||
var canvas = this.chart.canvas;
|
||||
|
||||
// Reset canvas height/width attributes starts a fresh with the canvas context
|
||||
canvas.width = this.chart.width;
|
||||
canvas.height = this.chart.height;
|
||||
|
||||
// < IE9 doesn't support removeProperty
|
||||
if (canvas.style.removeProperty) {
|
||||
canvas.style.removeProperty('width');
|
||||
canvas.style.removeProperty('height');
|
||||
} else {
|
||||
canvas.style.removeAttribute('width');
|
||||
canvas.style.removeAttribute('height');
|
||||
}
|
||||
|
||||
delete Chart.instances[this.id];
|
||||
},
|
||||
toBase64Image: function() {
|
||||
return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.Type.extend = function(extensions) {
|
||||
|
||||
var parent = this;
|
||||
|
||||
var ChartType = function() {
|
||||
return parent.apply(this, arguments);
|
||||
};
|
||||
|
||||
//Copy the prototype object of the this class
|
||||
ChartType.prototype = 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) {
|
||||
|
||||
var chartName = extensions.name || parent.prototype.name;
|
||||
//Assign any potential default values of the new chart type
|
||||
|
||||
//If none are defined, we'll use a clone of the chart type this is being extended from.
|
||||
//I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart
|
||||
//doesn't define some defaults of their own.
|
||||
|
||||
var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
|
||||
|
||||
Chart.defaults[chartName] = helpers.configMerge(baseDefaults, extensions.defaults);
|
||||
|
||||
Chart.types[chartName] = ChartType;
|
||||
|
||||
//Register this new chart type in the Chart prototype
|
||||
Chart.prototype[chartName] = function(config) {
|
||||
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");
|
||||
}
|
||||
return parent;
|
||||
};
|
||||
|
||||
Chart.Element = function(configuration) {
|
||||
extend(this, configuration);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
extend(Chart.Element.prototype, {
|
||||
initialize: function() {},
|
||||
pivot: function() {
|
||||
if (!this._view) {
|
||||
this._view = clone(this._model);
|
||||
}
|
||||
this._start = clone(this._view);
|
||||
return this;
|
||||
},
|
||||
transition: function(ease) {
|
||||
if (!this._view) {
|
||||
this._view = clone(this._model);
|
||||
}
|
||||
if (!this._start) {
|
||||
this.pivot();
|
||||
}
|
||||
|
||||
each(this._model, function(value, key) {
|
||||
|
||||
if (key[0] === '_' || !this._model.hasOwnProperty(key)) {
|
||||
// Only non-underscored properties
|
||||
}
|
||||
|
||||
// Init if doesn't exist
|
||||
else if (!this._view[key]) {
|
||||
if (typeof value === 'number') {
|
||||
this._view[key] = value * ease;
|
||||
} else {
|
||||
this._view[key] = value || null;
|
||||
}
|
||||
}
|
||||
|
||||
// No unnecessary computations
|
||||
else if (this._model[key] === this._view[key]) {
|
||||
// It's the same! Woohoo!
|
||||
}
|
||||
|
||||
// Color transitions if possible
|
||||
else if (typeof value === 'string') {
|
||||
try {
|
||||
var color = helpers.color(this._start[key]).mix(helpers.color(this._model[key]), ease);
|
||||
this._view[key] = color.rgbString();
|
||||
} catch (err) {
|
||||
this._view[key] = value;
|
||||
}
|
||||
}
|
||||
// Number transitions
|
||||
else if (typeof value === 'number') {
|
||||
var startVal = this._start[key] !== undefined ? this._start[key] : 0;
|
||||
this._view[key] = ((this._model[key] - startVal) * ease) + startVal;
|
||||
}
|
||||
// Everything else
|
||||
else {
|
||||
this._view[key] = value;
|
||||
}
|
||||
|
||||
}, this);
|
||||
|
||||
if (ease === 1) {
|
||||
delete this._start;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
return {
|
||||
x: this._model.x,
|
||||
y: this._model.y
|
||||
};
|
||||
},
|
||||
hasValue: function() {
|
||||
return isNumber(this._model.x) && isNumber(this._model.y);
|
||||
}
|
||||
});
|
||||
|
||||
Chart.Element.extend = inherits;
|
||||
|
||||
|
||||
// Attach global event to resize each chart instance when the browser resizes
|
||||
helpers.addEvent(window, "resize", (function() {
|
||||
// Basic debounce of resize function so it doesn't hurt performance when resizing browser.
|
||||
var timeout;
|
||||
return function() {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() {
|
||||
each(Chart.instances, function(instance) {
|
||||
// If the responsive flag is set in the chart instance config
|
||||
// Cascade the resize event down to the chart.
|
||||
if (instance.options.responsive) {
|
||||
instance.resize();
|
||||
instance.update();
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
};
|
||||
})());
|
||||
|
||||
|
||||
if (amd) {
|
||||
define(function() {
|
||||
return Chart;
|
||||
});
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = Chart;
|
||||
}
|
||||
|
||||
root.Chart = Chart;
|
||||
|
||||
Chart.noConflict = function() {
|
||||
root.Chart = previous;
|
||||
return Chart;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
30
src/core/core.responsive.js
Normal file
30
src/core/core.responsive.js
Normal file
@ -0,0 +1,30 @@
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
//Declare root variable - window in the browser, global on the server
|
||||
var root = this,
|
||||
previous = root.Chart,
|
||||
helpers = Chart.helpers;
|
||||
|
||||
|
||||
// Attach global event to resize each chart instance when the browser resizes
|
||||
helpers.addEvent(window, "resize", (function() {
|
||||
// Basic debounce of resize function so it doesn't hurt performance when resizing browser.
|
||||
var timeout;
|
||||
return function() {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(function() {
|
||||
each(Chart.instances, function(instance) {
|
||||
// If the responsive flag is set in the chart instance config
|
||||
// Cascade the resize event down to the chart.
|
||||
if (instance.options.responsive) {
|
||||
instance.resize();
|
||||
instance.update();
|
||||
}
|
||||
});
|
||||
}, 50);
|
||||
};
|
||||
})());
|
||||
|
||||
}).call(this);
|
||||
@ -1,14 +1,3 @@
|
||||
/*!
|
||||
* Chart.js
|
||||
* http://chartjs.org/
|
||||
* Version: {{ version }}
|
||||
*
|
||||
* Copyright 2015 Nick Downie
|
||||
* Released under the MIT license
|
||||
* https://github.com/nnnick/Chart.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
|
||||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user