diff --git a/src/chart.js b/src/chart.js
index 9580c2387b5..146cfbaa8d3 100644
--- a/src/chart.js
+++ b/src/chart.js
@@ -8,7 +8,10 @@ Chart.helpers = require('./helpers/index');
// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests!
require('./core/core.helpers')(Chart);
+Chart.defaults = require('./core/core.defaults');
+Chart.Interaction = require('./core/core.interaction');
Chart.platform = require('./platforms/platform');
+Chart.Ticks = require('./core/core.ticks');
require('./core/core.element')(Chart);
require('./core/core.plugin')(Chart);
@@ -17,9 +20,7 @@ require('./core/core.controller')(Chart);
require('./core/core.datasetController')(Chart);
require('./core/core.layoutService')(Chart);
require('./core/core.scaleService')(Chart);
-require('./core/core.ticks')(Chart);
require('./core/core.scale')(Chart);
-require('./core/core.interaction')(Chart);
require('./core/core.tooltip')(Chart);
require('./elements/element.arc')(Chart);
@@ -42,6 +43,7 @@ require('./controllers/controller.doughnut')(Chart);
require('./controllers/controller.line')(Chart);
require('./controllers/controller.polarArea')(Chart);
require('./controllers/controller.radar')(Chart);
+require('./controllers/controller.scatter')(Chart);
require('./charts/Chart.Bar')(Chart);
require('./charts/Chart.Bubble')(Chart);
diff --git a/src/charts/Chart.Scatter.js b/src/charts/Chart.Scatter.js
index 7b7e67d435e..9006e571293 100644
--- a/src/charts/Chart.Scatter.js
+++ b/src/charts/Chart.Scatter.js
@@ -1,48 +1,8 @@
'use strict';
module.exports = function(Chart) {
-
- var defaultConfig = {
- hover: {
- mode: 'single'
- },
-
- scales: {
- xAxes: [{
- type: 'linear', // scatter should not use a category axis
- position: 'bottom',
- id: 'x-axis-1' // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: 'linear',
- position: 'left',
- id: 'y-axis-1'
- }]
- },
- showLines: false,
-
- tooltips: {
- callbacks: {
- title: function() {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem) {
- return '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';
- }
- }
- }
- };
-
- // Register the default config for this type
- Chart.defaults.scatter = defaultConfig;
-
- // Scatter charts use line controllers
- Chart.controllers.scatter = Chart.controllers.line;
-
Chart.Scatter = function(context, config) {
config.type = 'scatter';
return new Chart(context, config);
};
-
};
diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js
index 93d285323c3..97a077e66d5 100644
--- a/src/controllers/controller.bar.js
+++ b/src/controllers/controller.bar.js
@@ -1,32 +1,91 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
+defaults._set('bar', {
+ hover: {
+ mode: 'label'
+ },
- Chart.defaults.bar = {
- hover: {
- mode: 'label'
- },
+ scales: {
+ xAxes: [{
+ type: 'category',
- scales: {
- xAxes: [{
- type: 'category',
+ // Specific to Bar Controller
+ categoryPercentage: 0.8,
+ barPercentage: 0.9,
- // Specific to Bar Controller
- categoryPercentage: 0.8,
- barPercentage: 0.9,
+ // grid line settings
+ gridLines: {
+ offsetGridLines: true
+ }
+ }],
+
+ yAxes: [{
+ type: 'linear'
+ }]
+ }
+});
+
+defaults._set('horizontalBar', {
+ hover: {
+ mode: 'label'
+ },
+
+ scales: {
+ xAxes: [{
+ type: 'linear',
+ position: 'bottom'
+ }],
+
+ yAxes: [{
+ position: 'left',
+ type: 'category',
+
+ // Specific to Horizontal Bar Controller
+ categoryPercentage: 0.8,
+ barPercentage: 0.9,
+
+ // grid line settings
+ gridLines: {
+ offsetGridLines: true
+ }
+ }]
+ },
- // grid line settings
- gridLines: {
- offsetGridLines: true
+ elements: {
+ rectangle: {
+ borderSkipped: 'left'
+ }
+ },
+
+ tooltips: {
+ callbacks: {
+ title: function(item, data) {
+ // Pick first xLabel for now
+ var title = '';
+
+ if (item.length > 0) {
+ if (item[0].yLabel) {
+ title = item[0].yLabel;
+ } else if (data.labels.length > 0 && item[0].index < data.labels.length) {
+ title = data.labels[item[0].index];
+ }
}
- }],
- yAxes: [{
- type: 'linear'
- }]
+
+ return title;
+ },
+
+ label: function(item, data) {
+ var datasetLabel = data.datasets[item.datasetIndex].label || '';
+ return datasetLabel + ': ' + item.xLabel;
+ }
}
- };
+ }
+});
+
+module.exports = function(Chart) {
Chart.controllers.bar = Chart.DatasetController.extend({
@@ -309,62 +368,6 @@ module.exports = function(Chart) {
}
});
-
- // including horizontalBar in the bar file, instead of a file of its own
- // it extends bar (like pie extends doughnut)
- Chart.defaults.horizontalBar = {
- hover: {
- mode: 'label'
- },
-
- scales: {
- xAxes: [{
- type: 'linear',
- position: 'bottom'
- }],
- yAxes: [{
- position: 'left',
- type: 'category',
-
- // Specific to Horizontal Bar Controller
- categoryPercentage: 0.8,
- barPercentage: 0.9,
-
- // grid line settings
- gridLines: {
- offsetGridLines: true
- }
- }]
- },
- elements: {
- rectangle: {
- borderSkipped: 'left'
- }
- },
- tooltips: {
- callbacks: {
- title: function(tooltipItems, data) {
- // Pick first xLabel for now
- var title = '';
-
- if (tooltipItems.length > 0) {
- if (tooltipItems[0].yLabel) {
- title = tooltipItems[0].yLabel;
- } else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {
- title = data.labels[tooltipItems[0].index];
- }
- }
-
- return title;
- },
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- return datasetLabel + ': ' + tooltipItem.xLabel;
- }
- }
- }
- };
-
Chart.controllers.horizontalBar = Chart.controllers.bar.extend({
/**
* @private
diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js
index b91b15f1277..6d410114ec2 100644
--- a/src/controllers/controller.bubble.js
+++ b/src/controllers/controller.bubble.js
@@ -1,41 +1,43 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- Chart.defaults.bubble = {
- hover: {
- mode: 'single'
- },
-
- scales: {
- xAxes: [{
- type: 'linear', // bubble should probably use a linear scale by default
- position: 'bottom',
- id: 'x-axis-0' // need an ID so datasets can reference the scale
- }],
- yAxes: [{
- type: 'linear',
- position: 'left',
- id: 'y-axis-0'
- }]
- },
-
- tooltips: {
- callbacks: {
- title: function() {
- // Title doesn't make sense for scatter since we format the data as a point
- return '';
- },
- label: function(tooltipItem, data) {
- var datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';
- var dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
- return datasetLabel + ': (' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ', ' + dataPoint.r + ')';
- }
+defaults._set('bubble', {
+ hover: {
+ mode: 'single'
+ },
+
+ scales: {
+ xAxes: [{
+ type: 'linear', // bubble should probably use a linear scale by default
+ position: 'bottom',
+ id: 'x-axis-0' // need an ID so datasets can reference the scale
+ }],
+ yAxes: [{
+ type: 'linear',
+ position: 'left',
+ id: 'y-axis-0'
+ }]
+ },
+
+ tooltips: {
+ callbacks: {
+ title: function() {
+ // Title doesn't make sense for scatter since we format the data as a point
+ return '';
+ },
+ label: function(item, data) {
+ var datasetLabel = data.datasets[item.datasetIndex].label || '';
+ var dataPoint = data.datasets[item.datasetIndex].data[item.index];
+ return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')';
}
}
- };
+ }
+});
+
+
+module.exports = function(Chart) {
Chart.controllers.bubble = Chart.DatasetController.extend({
diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js
index c87c59bbcb0..ffbf22a66cc 100644
--- a/src/controllers/controller.doughnut.js
+++ b/src/controllers/controller.doughnut.js
@@ -1,130 +1,128 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- var defaults = Chart.defaults;
-
- defaults.doughnut = {
- animation: {
- // Boolean - Whether we animate the rotation of the Doughnut
- animateRotate: true,
- // Boolean - Whether we animate scaling the Doughnut from the centre
- animateScale: false
- },
- hover: {
- mode: 'single'
- },
- legendCallback: function(chart) {
- var text = [];
- text.push('
');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('- ');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('
');
+defaults._set('doughnut', {
+ animation: {
+ // Boolean - Whether we animate the rotation of the Doughnut
+ animateRotate: true,
+ // Boolean - Whether we animate scaling the Doughnut from the centre
+ animateScale: false
+ },
+ hover: {
+ mode: 'single'
+ },
+ legendCallback: function(chart) {
+ var text = [];
+ text.push('');
+
+ var data = chart.data;
+ var datasets = data.datasets;
+ var labels = data.labels;
+
+ if (datasets.length) {
+ for (var i = 0; i < datasets[0].data.length; ++i) {
+ text.push('- ');
+ if (labels[i]) {
+ text.push(labels[i]);
}
+ text.push('
');
}
+ }
- text.push('
');
- return text.join('');
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc && arc.custom || {};
- var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- }
- return [];
+ text.push('
');
+ return text.join('');
+ },
+ legend: {
+ labels: {
+ generateLabels: function(chart) {
+ var data = chart.data;
+ if (data.labels.length && data.datasets.length) {
+ return data.labels.map(function(label, i) {
+ var meta = chart.getDatasetMeta(0);
+ var ds = data.datasets[0];
+ var arc = meta.data[i];
+ var custom = arc && arc.custom || {};
+ var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
+ var arcOpts = chart.options.elements.arc;
+ var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
+ var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
+ var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
+
+ return {
+ text: label,
+ fillStyle: fill,
+ strokeStyle: stroke,
+ lineWidth: bw,
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
+
+ // Extra data used for toggling the correct item
+ index: i
+ };
+ });
}
- },
+ return [];
+ }
+ },
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
-
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- // toggle visibility of index if exists
- if (meta.data[index]) {
- meta.data[index].hidden = !meta.data[index].hidden;
- }
- }
+ onClick: function(e, legendItem) {
+ var index = legendItem.index;
+ var chart = this.chart;
+ var i, ilen, meta;
- chart.update();
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
+ meta = chart.getDatasetMeta(i);
+ // toggle visibility of index if exists
+ if (meta.data[index]) {
+ meta.data[index].hidden = !meta.data[index].hidden;
+ }
}
- },
- // The percentage of the chart that we cut out of the middle.
- cutoutPercentage: 50,
+ chart.update();
+ }
+ },
- // The rotation of the chart, where the first data arc begins.
- rotation: Math.PI * -0.5,
+ // The percentage of the chart that we cut out of the middle.
+ cutoutPercentage: 50,
- // The total circumference of the chart.
- circumference: Math.PI * 2.0,
+ // The rotation of the chart, where the first data arc begins.
+ rotation: Math.PI * -0.5,
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- var dataLabel = data.labels[tooltipItem.index];
- var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
-
- if (helpers.isArray(dataLabel)) {
- // show value on first line of multiline label
- // need to clone because we are changing the value
- dataLabel = dataLabel.slice();
- dataLabel[0] += value;
- } else {
- dataLabel += value;
- }
-
- return dataLabel;
+ // The total circumference of the chart.
+ circumference: Math.PI * 2.0,
+
+ // Need to override these to give a nice default
+ tooltips: {
+ callbacks: {
+ title: function() {
+ return '';
+ },
+ label: function(tooltipItem, data) {
+ var dataLabel = data.labels[tooltipItem.index];
+ var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
+
+ if (helpers.isArray(dataLabel)) {
+ // show value on first line of multiline label
+ // need to clone because we are changing the value
+ dataLabel = dataLabel.slice();
+ dataLabel[0] += value;
+ } else {
+ dataLabel += value;
}
+
+ return dataLabel;
}
}
- };
+ }
+});
- defaults.pie = helpers.clone(defaults.doughnut);
- helpers.extend(defaults.pie, {
- cutoutPercentage: 0
- });
+defaults._set('pie', helpers.clone(defaults.doughnut));
+defaults._set('pie', {
+ cutoutPercentage: 0
+});
+module.exports = function(Chart) {
Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({
diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js
index c31e73f23d4..d841ada64dc 100644
--- a/src/controllers/controller.line.js
+++ b/src/controllers/controller.line.js
@@ -1,28 +1,29 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- Chart.defaults.line = {
- showLines: true,
- spanGaps: false,
-
- hover: {
- mode: 'label'
- },
+defaults._set('line', {
+ showLines: true,
+ spanGaps: false,
+
+ hover: {
+ mode: 'label'
+ },
+
+ scales: {
+ xAxes: [{
+ type: 'category',
+ id: 'x-axis-0'
+ }],
+ yAxes: [{
+ type: 'linear',
+ id: 'y-axis-0'
+ }]
+ }
+});
- scales: {
- xAxes: [{
- type: 'category',
- id: 'x-axis-0'
- }],
- yAxes: [{
- type: 'linear',
- id: 'y-axis-0'
- }]
- }
- };
+module.exports = function(Chart) {
function lineEnabled(dataset, options) {
return helpers.valueOrDefault(dataset.showLine, options.showLines);
diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js
index bf2cd6b41bf..c0ac2993e38 100644
--- a/src/controllers/controller.polarArea.js
+++ b/src/controllers/controller.polarArea.js
@@ -1,113 +1,113 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- Chart.defaults.polarArea = {
-
- scale: {
- type: 'radialLinear',
- angleLines: {
- display: false
- },
- gridLines: {
- circular: true
- },
- pointLabels: {
- display: false
- },
- ticks: {
- beginAtZero: true
- }
+defaults._set('polarArea', {
+ scale: {
+ type: 'radialLinear',
+ angleLines: {
+ display: false
},
-
- // Boolean - Whether to animate the rotation of the chart
- animation: {
- animateRotate: true,
- animateScale: true
+ gridLines: {
+ circular: true
},
-
- startAngle: -0.5 * Math.PI,
- legendCallback: function(chart) {
- var text = [];
- text.push('');
-
- var data = chart.data;
- var datasets = data.datasets;
- var labels = data.labels;
-
- if (datasets.length) {
- for (var i = 0; i < datasets[0].data.length; ++i) {
- text.push('- ');
- if (labels[i]) {
- text.push(labels[i]);
- }
- text.push('
');
+ pointLabels: {
+ display: false
+ },
+ ticks: {
+ beginAtZero: true
+ }
+ },
+
+ // Boolean - Whether to animate the rotation of the chart
+ animation: {
+ animateRotate: true,
+ animateScale: true
+ },
+
+ startAngle: -0.5 * Math.PI,
+ legendCallback: function(chart) {
+ var text = [];
+ text.push('');
+
+ var data = chart.data;
+ var datasets = data.datasets;
+ var labels = data.labels;
+
+ if (datasets.length) {
+ for (var i = 0; i < datasets[0].data.length; ++i) {
+ text.push('- ');
+ if (labels[i]) {
+ text.push(labels[i]);
}
+ text.push('
');
}
+ }
- text.push('
');
- return text.join('');
- },
- legend: {
- labels: {
- generateLabels: function(chart) {
- var data = chart.data;
- if (data.labels.length && data.datasets.length) {
- return data.labels.map(function(label, i) {
- var meta = chart.getDatasetMeta(0);
- var ds = data.datasets[0];
- var arc = meta.data[i];
- var custom = arc.custom || {};
- var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
- var arcOpts = chart.options.elements.arc;
- var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
- var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
- var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
-
- return {
- text: label,
- fillStyle: fill,
- strokeStyle: stroke,
- lineWidth: bw,
- hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
-
- // Extra data used for toggling the correct item
- index: i
- };
- });
- }
- return [];
+ text.push('
');
+ return text.join('');
+ },
+ legend: {
+ labels: {
+ generateLabels: function(chart) {
+ var data = chart.data;
+ if (data.labels.length && data.datasets.length) {
+ return data.labels.map(function(label, i) {
+ var meta = chart.getDatasetMeta(0);
+ var ds = data.datasets[0];
+ var arc = meta.data[i];
+ var custom = arc.custom || {};
+ var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault;
+ var arcOpts = chart.options.elements.arc;
+ var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
+ var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
+ var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
+
+ return {
+ text: label,
+ fillStyle: fill,
+ strokeStyle: stroke,
+ lineWidth: bw,
+ hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
+
+ // Extra data used for toggling the correct item
+ index: i
+ };
+ });
}
- },
-
- onClick: function(e, legendItem) {
- var index = legendItem.index;
- var chart = this.chart;
- var i, ilen, meta;
+ return [];
+ }
+ },
- for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
- meta = chart.getDatasetMeta(i);
- meta.data[index].hidden = !meta.data[index].hidden;
- }
+ onClick: function(e, legendItem) {
+ var index = legendItem.index;
+ var chart = this.chart;
+ var i, ilen, meta;
- chart.update();
+ for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {
+ meta = chart.getDatasetMeta(i);
+ meta.data[index].hidden = !meta.data[index].hidden;
}
- },
- // Need to override these to give a nice default
- tooltips: {
- callbacks: {
- title: function() {
- return '';
- },
- label: function(tooltipItem, data) {
- return data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;
- }
+ chart.update();
+ }
+ },
+
+ // Need to override these to give a nice default
+ tooltips: {
+ callbacks: {
+ title: function() {
+ return '';
+ },
+ label: function(item, data) {
+ return data.labels[item.index] + ': ' + item.yLabel;
}
}
- };
+ }
+});
+
+module.exports = function(Chart) {
Chart.controllers.polarArea = Chart.DatasetController.extend({
diff --git a/src/controllers/controller.radar.js b/src/controllers/controller.radar.js
index 24c83b46318..b3bccdca970 100644
--- a/src/controllers/controller.radar.js
+++ b/src/controllers/controller.radar.js
@@ -1,19 +1,20 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- Chart.defaults.radar = {
- scale: {
- type: 'radialLinear'
- },
- elements: {
- line: {
- tension: 0 // no bezier in radar
- }
+defaults._set('radar', {
+ scale: {
+ type: 'radialLinear'
+ },
+ elements: {
+ line: {
+ tension: 0 // no bezier in radar
}
- };
+ }
+});
+
+module.exports = function(Chart) {
Chart.controllers.radar = Chart.DatasetController.extend({
diff --git a/src/controllers/controller.scatter.js b/src/controllers/controller.scatter.js
new file mode 100644
index 00000000000..b2e2cf1f7e1
--- /dev/null
+++ b/src/controllers/controller.scatter.js
@@ -0,0 +1,42 @@
+'use strict';
+
+var defaults = require('../core/core.defaults');
+
+defaults._set('scatter', {
+ hover: {
+ mode: 'single'
+ },
+
+ scales: {
+ xAxes: [{
+ id: 'x-axis-1', // need an ID so datasets can reference the scale
+ type: 'linear', // scatter should not use a category axis
+ position: 'bottom'
+ }],
+ yAxes: [{
+ id: 'y-axis-1',
+ type: 'linear',
+ position: 'left'
+ }]
+ },
+
+ showLines: false,
+
+ tooltips: {
+ callbacks: {
+ title: function() {
+ return ''; // doesn't make sense for scatter since data are formatted as a point
+ },
+ label: function(item) {
+ return '(' + item.xLabel + ', ' + item.yLabel + ')';
+ }
+ }
+ }
+});
+
+module.exports = function(Chart) {
+
+ // Scatter charts use line controllers
+ Chart.controllers.scatter = Chart.controllers.line;
+
+};
diff --git a/src/core/core.animation.js b/src/core/core.animation.js
index 40208916a66..bbd44cde18e 100644
--- a/src/core/core.animation.js
+++ b/src/core/core.animation.js
@@ -1,16 +1,19 @@
/* global window: false */
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- Chart.defaults.global.animation = {
+defaults._set('global', {
+ animation: {
duration: 1000,
easing: 'easeOutQuart',
onProgress: helpers.noop,
onComplete: helpers.noop
- };
+ }
+});
+
+module.exports = function(Chart) {
Chart.Animation = Chart.Element.extend({
chart: null, // the animation associated chart instance
diff --git a/src/core/core.controller.js b/src/core/core.controller.js
index 4a86d70d2fb..2033c542549 100644
--- a/src/core/core.controller.js
+++ b/src/core/core.controller.js
@@ -1,6 +1,8 @@
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
+var Interaction = require('./core.interaction');
var platform = require('../platforms/platform');
module.exports = function(Chart) {
@@ -29,8 +31,8 @@ module.exports = function(Chart) {
data.labels = data.labels || [];
config.options = helpers.configMerge(
- Chart.defaults.global,
- Chart.defaults[config.type],
+ defaults.global,
+ defaults[config.type],
config.options || {});
return config;
@@ -601,19 +603,19 @@ module.exports = function(Chart) {
// 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 draw
getElementAtEvent: function(e) {
- return Chart.Interaction.modes.single(this, e);
+ return Interaction.modes.single(this, e);
},
getElementsAtEvent: function(e) {
- return Chart.Interaction.modes.label(this, e, {intersect: true});
+ return Interaction.modes.label(this, e, {intersect: true});
},
getElementsAtXAxis: function(e) {
- return Chart.Interaction.modes['x-axis'](this, e, {intersect: true});
+ return Interaction.modes['x-axis'](this, e, {intersect: true});
},
getElementsAtEventForMode: function(e, mode, options) {
- var method = Chart.Interaction.modes[mode];
+ var method = Interaction.modes[mode];
if (typeof method === 'function') {
return method(this, e, options);
}
@@ -622,7 +624,7 @@ module.exports = function(Chart) {
},
getDatasetAtEvent: function(e) {
- return Chart.Interaction.modes.dataset(this, e, {intersect: true});
+ return Interaction.modes.dataset(this, e, {intersect: true});
},
getDatasetMeta: function(datasetIndex) {
diff --git a/src/core/core.defaults.js b/src/core/core.defaults.js
new file mode 100644
index 00000000000..29bb040d4f0
--- /dev/null
+++ b/src/core/core.defaults.js
@@ -0,0 +1,12 @@
+'use strict';
+
+var helpers = require('../helpers/index');
+
+module.exports = {
+ /**
+ * @private
+ */
+ _set: function(scope, values) {
+ return helpers.merge(this[scope] || (this[scope] = {}), values);
+ }
+};
diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js
index 8896e232aad..90e116d2cee 100644
--- a/src/core/core.helpers.js
+++ b/src/core/core.helpers.js
@@ -3,6 +3,7 @@
'use strict';
var color = require('chartjs-color');
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
module.exports = function(Chart) {
@@ -43,7 +44,7 @@ module.exports = function(Chart) {
merger: function(key, target, source, options) {
if (key === 'xAxes' || key === 'yAxes') {
var slen = source[key].length;
- var i, type, scale, defaults;
+ var i, type, scale;
if (!target[key]) {
target[key] = [];
@@ -52,7 +53,6 @@ module.exports = function(Chart) {
for (i = 0; i < slen; ++i) {
scale = source[key][i];
type = helpers.valueOrDefault(scale.type, key === 'xAxes'? 'category' : 'linear');
- defaults = Chart.scaleService.getScaleDefaults(type);
if (i >= target[key].length) {
target[key].push({});
@@ -61,7 +61,7 @@ module.exports = function(Chart) {
if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) {
// new/untyped scale or type changed: let's apply the new defaults
// then merge source scale to correctly overwrite the defaults.
- helpers.merge(target[key][i], [defaults, scale]);
+ helpers.merge(target[key][i], [Chart.scaleService.getScaleDefaults(type), scale]);
} else {
// scales type are the same
helpers.merge(target[key][i], scale);
@@ -612,7 +612,7 @@ module.exports = function(Chart) {
function(value) {
/* global CanvasGradient */
if (value instanceof CanvasGradient) {
- value = Chart.defaults.global.defaultColor;
+ value = defaults.global.defaultColor;
}
return color(value);
diff --git a/src/core/core.interaction.js b/src/core/core.interaction.js
index 6e35bd950e8..793468d43fb 100644
--- a/src/core/core.interaction.js
+++ b/src/core/core.interaction.js
@@ -2,316 +2,313 @@
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- /**
- * Helper function to get relative position for an event
- * @param {Event|IEvent} event - The event to get the position for
- * @param {Chart} chart - The chart
- * @returns {Point} the event position
- */
- function getRelativePosition(e, chart) {
- if (e.native) {
- return {
- x: e.x,
- y: e.y
- };
- }
-
- return helpers.getRelativePosition(e, chart);
+/**
+ * Helper function to get relative position for an event
+ * @param {Event|IEvent} event - The event to get the position for
+ * @param {Chart} chart - The chart
+ * @returns {Point} the event position
+ */
+function getRelativePosition(e, chart) {
+ if (e.native) {
+ return {
+ x: e.x,
+ y: e.y
+ };
}
- /**
- * Helper function to traverse all of the visible elements in the chart
- * @param chart {chart} the chart
- * @param handler {Function} the callback to execute for each visible item
- */
- function parseVisibleItems(chart, handler) {
- var datasets = chart.data.datasets;
- var meta, i, j, ilen, jlen;
-
- for (i = 0, ilen = datasets.length; i < ilen; ++i) {
- if (!chart.isDatasetVisible(i)) {
- continue;
- }
+ return helpers.getRelativePosition(e, chart);
+}
+
+/**
+ * Helper function to traverse all of the visible elements in the chart
+ * @param chart {chart} the chart
+ * @param handler {Function} the callback to execute for each visible item
+ */
+function parseVisibleItems(chart, handler) {
+ var datasets = chart.data.datasets;
+ var meta, i, j, ilen, jlen;
+
+ for (i = 0, ilen = datasets.length; i < ilen; ++i) {
+ if (!chart.isDatasetVisible(i)) {
+ continue;
+ }
- meta = chart.getDatasetMeta(i);
- for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
- var element = meta.data[j];
- if (!element._view.skip) {
- handler(element);
- }
+ meta = chart.getDatasetMeta(i);
+ for (j = 0, jlen = meta.data.length; j < jlen; ++j) {
+ var element = meta.data[j];
+ if (!element._view.skip) {
+ handler(element);
}
}
}
-
- /**
- * Helper function to get the items that intersect the event position
- * @param items {ChartElement[]} elements to filter
- * @param position {Point} the point to be nearest to
- * @return {ChartElement[]} the nearest items
- */
- function getIntersectItems(chart, position) {
- var elements = [];
-
- parseVisibleItems(chart, function(element) {
- if (element.inRange(position.x, position.y)) {
- elements.push(element);
- }
- });
-
- return elements;
+}
+
+/**
+ * Helper function to get the items that intersect the event position
+ * @param items {ChartElement[]} elements to filter
+ * @param position {Point} the point to be nearest to
+ * @return {ChartElement[]} the nearest items
+ */
+function getIntersectItems(chart, position) {
+ var elements = [];
+
+ parseVisibleItems(chart, function(element) {
+ if (element.inRange(position.x, position.y)) {
+ elements.push(element);
+ }
+ });
+
+ return elements;
+}
+
+/**
+ * Helper function to get the items nearest to the event position considering all visible items in teh chart
+ * @param chart {Chart} the chart to look at elements from
+ * @param position {Point} the point to be nearest to
+ * @param intersect {Boolean} if true, only consider items that intersect the position
+ * @param distanceMetric {Function} Optional function to provide the distance between
+ * @return {ChartElement[]} the nearest items
+ */
+function getNearestItems(chart, position, intersect, distanceMetric) {
+ var minDistance = Number.POSITIVE_INFINITY;
+ var nearestItems = [];
+
+ if (!distanceMetric) {
+ distanceMetric = helpers.distanceBetweenPoints;
}
- /**
- * Helper function to get the items nearest to the event position considering all visible items in teh chart
- * @param chart {Chart} the chart to look at elements from
- * @param position {Point} the point to be nearest to
- * @param intersect {Boolean} if true, only consider items that intersect the position
- * @param distanceMetric {Function} Optional function to provide the distance between
- * @return {ChartElement[]} the nearest items
- */
- function getNearestItems(chart, position, intersect, distanceMetric) {
- var minDistance = Number.POSITIVE_INFINITY;
- var nearestItems = [];
-
- if (!distanceMetric) {
- distanceMetric = helpers.distanceBetweenPoints;
+ parseVisibleItems(chart, function(element) {
+ if (intersect && !element.inRange(position.x, position.y)) {
+ return;
}
- parseVisibleItems(chart, function(element) {
- if (intersect && !element.inRange(position.x, position.y)) {
- return;
- }
+ var center = element.getCenterPoint();
+ var distance = distanceMetric(position, center);
- var center = element.getCenterPoint();
- var distance = distanceMetric(position, center);
+ if (distance < minDistance) {
+ nearestItems = [element];
+ minDistance = distance;
+ } else if (distance === minDistance) {
+ // Can have multiple items at the same distance in which case we sort by size
+ nearestItems.push(element);
+ }
+ });
- if (distance < minDistance) {
- nearestItems = [element];
- minDistance = distance;
- } else if (distance === minDistance) {
- // Can have multiple items at the same distance in which case we sort by size
- nearestItems.push(element);
- }
- });
+ return nearestItems;
+}
- return nearestItems;
+function indexMode(chart, e, options) {
+ var position = getRelativePosition(e, chart);
+ var distanceMetric = function(pt1, pt2) {
+ return Math.abs(pt1.x - pt2.x);
+ };
+ var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
+ var elements = [];
+
+ if (!items.length) {
+ return [];
}
- function indexMode(chart, e, options) {
- var position = getRelativePosition(e, chart);
- var distanceMetric = function(pt1, pt2) {
- return Math.abs(pt1.x - pt2.x);
- };
- var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
- var elements = [];
+ chart.data.datasets.forEach(function(dataset, datasetIndex) {
+ if (chart.isDatasetVisible(datasetIndex)) {
+ var meta = chart.getDatasetMeta(datasetIndex),
+ element = meta.data[items[0]._index];
- if (!items.length) {
- return [];
+ // don't count items that are skipped (null data)
+ if (element && !element._view.skip) {
+ elements.push(element);
+ }
}
-
- chart.data.datasets.forEach(function(dataset, datasetIndex) {
- if (chart.isDatasetVisible(datasetIndex)) {
- var meta = chart.getDatasetMeta(datasetIndex),
- element = meta.data[items[0]._index];
-
- // don't count items that are skipped (null data)
- if (element && !element._view.skip) {
+ });
+
+ return elements;
+}
+
+/**
+ * @interface IInteractionOptions
+ */
+/**
+ * If true, only consider items that intersect the point
+ * @name IInterfaceOptions#boolean
+ * @type Boolean
+ */
+
+/**
+ * Contains interaction related functions
+ * @namespace Chart.Interaction
+ */
+module.exports = {
+ // Helper function for different modes
+ modes: {
+ single: function(chart, e) {
+ var position = getRelativePosition(e, chart);
+ var elements = [];
+
+ parseVisibleItems(chart, function(element) {
+ if (element.inRange(position.x, position.y)) {
elements.push(element);
+ return elements;
}
+ });
+
+ return elements.slice(0, 1);
+ },
+
+ /**
+ * @function Chart.Interaction.modes.label
+ * @deprecated since version 2.4.0
+ * @todo remove at version 3
+ * @private
+ */
+ label: indexMode,
+
+ /**
+ * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
+ * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
+ * @function Chart.Interaction.modes.index
+ * @since v2.4.0
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @param options {IInteractionOptions} options to use during interaction
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ index: indexMode,
+
+ /**
+ * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
+ * If the options.intersect is false, we find the nearest item and return the items in that dataset
+ * @function Chart.Interaction.modes.dataset
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @param options {IInteractionOptions} options to use during interaction
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ dataset: function(chart, e, options) {
+ var position = getRelativePosition(e, chart);
+ var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false);
+
+ if (items.length > 0) {
+ items = chart.getDatasetMeta(items[0]._datasetIndex).data;
}
- });
- return elements;
- }
-
- /**
- * @interface IInteractionOptions
- */
- /**
- * If true, only consider items that intersect the point
- * @name IInterfaceOptions#boolean
- * @type Boolean
- */
-
- /**
- * Contains interaction related functions
- * @namespace Chart.Interaction
- */
- Chart.Interaction = {
- // Helper function for different modes
- modes: {
- single: function(chart, e) {
- var position = getRelativePosition(e, chart);
- var elements = [];
-
- parseVisibleItems(chart, function(element) {
- if (element.inRange(position.x, position.y)) {
- elements.push(element);
- return elements;
+ return items;
+ },
+
+ /**
+ * @function Chart.Interaction.modes.x-axis
+ * @deprecated since version 2.4.0. Use index mode and intersect == true
+ * @todo remove at version 3
+ * @private
+ */
+ 'x-axis': function(chart, e) {
+ return indexMode(chart, e, true);
+ },
+
+ /**
+ * Point mode returns all elements that hit test based on the event position
+ * of the event
+ * @function Chart.Interaction.modes.intersect
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ point: function(chart, e) {
+ var position = getRelativePosition(e, chart);
+ return getIntersectItems(chart, position);
+ },
+
+ /**
+ * nearest mode returns the element closest to the point
+ * @function Chart.Interaction.modes.intersect
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @param options {IInteractionOptions} options to use
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ nearest: function(chart, e, options) {
+ var position = getRelativePosition(e, chart);
+ var nearestItems = getNearestItems(chart, position, options.intersect);
+
+ // We have multiple items at the same distance from the event. Now sort by smallest
+ if (nearestItems.length > 1) {
+ nearestItems.sort(function(a, b) {
+ var sizeA = a.getArea();
+ var sizeB = b.getArea();
+ var ret = sizeA - sizeB;
+
+ if (ret === 0) {
+ // if equal sort by dataset index
+ ret = a._datasetIndex - b._datasetIndex;
}
+
+ return ret;
});
+ }
- return elements.slice(0, 1);
- },
-
- /**
- * @function Chart.Interaction.modes.label
- * @deprecated since version 2.4.0
- * @todo remove at version 3
- * @private
- */
- label: indexMode,
-
- /**
- * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something
- * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item
- * @function Chart.Interaction.modes.index
- * @since v2.4.0
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @param options {IInteractionOptions} options to use during interaction
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- index: indexMode,
-
- /**
- * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something
- * If the options.intersect is false, we find the nearest item and return the items in that dataset
- * @function Chart.Interaction.modes.dataset
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @param options {IInteractionOptions} options to use during interaction
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- dataset: function(chart, e, options) {
- var position = getRelativePosition(e, chart);
- var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false);
-
- if (items.length > 0) {
- items = chart.getDatasetMeta(items[0]._datasetIndex).data;
+ // Return only 1 item
+ return nearestItems.slice(0, 1);
+ },
+
+ /**
+ * x mode returns the elements that hit-test at the current x coordinate
+ * @function Chart.Interaction.modes.x
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @param options {IInteractionOptions} options to use
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ x: function(chart, e, options) {
+ var position = getRelativePosition(e, chart);
+ var items = [];
+ var intersectsItem = false;
+
+ parseVisibleItems(chart, function(element) {
+ if (element.inXRange(position.x)) {
+ items.push(element);
}
- return items;
- },
-
- /**
- * @function Chart.Interaction.modes.x-axis
- * @deprecated since version 2.4.0. Use index mode and intersect == true
- * @todo remove at version 3
- * @private
- */
- 'x-axis': function(chart, e) {
- return indexMode(chart, e, true);
- },
-
- /**
- * Point mode returns all elements that hit test based on the event position
- * of the event
- * @function Chart.Interaction.modes.intersect
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- point: function(chart, e) {
- var position = getRelativePosition(e, chart);
- return getIntersectItems(chart, position);
- },
-
- /**
- * nearest mode returns the element closest to the point
- * @function Chart.Interaction.modes.intersect
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @param options {IInteractionOptions} options to use
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- nearest: function(chart, e, options) {
- var position = getRelativePosition(e, chart);
- var nearestItems = getNearestItems(chart, position, options.intersect);
-
- // We have multiple items at the same distance from the event. Now sort by smallest
- if (nearestItems.length > 1) {
- nearestItems.sort(function(a, b) {
- var sizeA = a.getArea();
- var sizeB = b.getArea();
- var ret = sizeA - sizeB;
-
- if (ret === 0) {
- // if equal sort by dataset index
- ret = a._datasetIndex - b._datasetIndex;
- }
-
- return ret;
- });
+ if (element.inRange(position.x, position.y)) {
+ intersectsItem = true;
}
+ });
- // Return only 1 item
- return nearestItems.slice(0, 1);
- },
-
- /**
- * x mode returns the elements that hit-test at the current x coordinate
- * @function Chart.Interaction.modes.x
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @param options {IInteractionOptions} options to use
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- x: function(chart, e, options) {
- var position = getRelativePosition(e, chart);
- var items = [];
- var intersectsItem = false;
-
- parseVisibleItems(chart, function(element) {
- if (element.inXRange(position.x)) {
- items.push(element);
- }
-
- if (element.inRange(position.x, position.y)) {
- intersectsItem = true;
- }
- });
-
- // If we want to trigger on an intersect and we don't have any items
- // that intersect the position, return nothing
- if (options.intersect && !intersectsItem) {
- items = [];
+ // If we want to trigger on an intersect and we don't have any items
+ // that intersect the position, return nothing
+ if (options.intersect && !intersectsItem) {
+ items = [];
+ }
+ return items;
+ },
+
+ /**
+ * y mode returns the elements that hit-test at the current y coordinate
+ * @function Chart.Interaction.modes.y
+ * @param chart {chart} the chart we are returning items from
+ * @param e {Event} the event we are find things at
+ * @param options {IInteractionOptions} options to use
+ * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
+ */
+ y: function(chart, e, options) {
+ var position = getRelativePosition(e, chart);
+ var items = [];
+ var intersectsItem = false;
+
+ parseVisibleItems(chart, function(element) {
+ if (element.inYRange(position.y)) {
+ items.push(element);
}
- return items;
- },
-
- /**
- * y mode returns the elements that hit-test at the current y coordinate
- * @function Chart.Interaction.modes.y
- * @param chart {chart} the chart we are returning items from
- * @param e {Event} the event we are find things at
- * @param options {IInteractionOptions} options to use
- * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned
- */
- y: function(chart, e, options) {
- var position = getRelativePosition(e, chart);
- var items = [];
- var intersectsItem = false;
-
- parseVisibleItems(chart, function(element) {
- if (element.inYRange(position.y)) {
- items.push(element);
- }
- if (element.inRange(position.x, position.y)) {
- intersectsItem = true;
- }
- });
-
- // If we want to trigger on an intersect and we don't have any items
- // that intersect the position, return nothing
- if (options.intersect && !intersectsItem) {
- items = [];
+ if (element.inRange(position.x, position.y)) {
+ intersectsItem = true;
}
- return items;
+ });
+
+ // If we want to trigger on an intersect and we don't have any items
+ // that intersect the position, return nothing
+ if (options.intersect && !intersectsItem) {
+ items = [];
}
+ return items;
}
- };
+ }
};
diff --git a/src/core/core.js b/src/core/core.js
index afb51c71d65..906b897c699 100644
--- a/src/core/core.js
+++ b/src/core/core.js
@@ -1,5 +1,40 @@
'use strict';
+var defaults = require('./core.defaults');
+
+defaults._set('global', {
+ responsive: true,
+ responsiveAnimationDuration: 0,
+ maintainAspectRatio: true,
+ events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
+ hover: {
+ onHover: null,
+ mode: 'nearest',
+ intersect: true,
+ animationDuration: 400
+ },
+ onClick: null,
+ defaultColor: 'rgba(0,0,0,0.1)',
+ defaultFontColor: '#666',
+ defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
+ defaultFontSize: 12,
+ defaultFontStyle: 'normal',
+ showLines: true,
+
+ // Element defaults defined in element extensions
+ elements: {},
+
+ // Layout options such as padding
+ layout: {
+ padding: {
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0
+ }
+ }
+});
+
module.exports = function() {
// Occupy the global variable of Chart, and create a simple base class
@@ -8,58 +43,6 @@ module.exports = function() {
return this;
};
- // Globally expose the defaults to allow for user updating/changing
- Chart.defaults = {
- global: {
- responsive: true,
- responsiveAnimationDuration: 0,
- maintainAspectRatio: true,
- events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
- hover: {
- onHover: null,
- mode: 'nearest',
- intersect: true,
- animationDuration: 400
- },
- onClick: null,
- defaultColor: 'rgba(0,0,0,0.1)',
- defaultFontColor: '#666',
- defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
- defaultFontSize: 12,
- defaultFontStyle: 'normal',
- showLines: true,
-
- // Element defaults defined in element extensions
- elements: {},
-
- // Layout options such as padding
- layout: {
- padding: {
- top: 0,
- right: 0,
- bottom: 0,
- left: 0
- }
- },
-
- // Legend callback string
- legendCallback: function(chart) {
- var text = [];
- text.push('');
- for (var i = 0; i < chart.data.datasets.length; i++) {
- text.push('- ');
- if (chart.data.datasets[i].label) {
- text.push(chart.data.datasets[i].label);
- }
- text.push('
');
- }
- text.push('
');
-
- return text.join('');
- }
- }
- };
-
Chart.Chart = Chart;
return Chart;
diff --git a/src/core/core.plugin.js b/src/core/core.plugin.js
index 92761158033..2c472ce0da4 100644
--- a/src/core/core.plugin.js
+++ b/src/core/core.plugin.js
@@ -1,10 +1,13 @@
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
+defaults._set('global', {
+ plugins: {}
+});
- Chart.defaults.global.plugins = {};
+module.exports = function(Chart) {
/**
* The plugin service singleton
@@ -128,7 +131,6 @@ module.exports = function(Chart) {
var plugins = [];
var descriptors = [];
var config = (chart && chart.config) || {};
- var defaults = Chart.defaults.global.plugins;
var options = (config.options && config.options.plugins) || {};
this._plugins.concat(config.plugins || []).forEach(function(plugin) {
@@ -144,7 +146,7 @@ module.exports = function(Chart) {
}
if (opts === true) {
- opts = helpers.clone(defaults[id]);
+ opts = helpers.clone(defaults.global.plugins[id]);
}
plugins.push(plugin);
diff --git a/src/core/core.scale.js b/src/core/core.scale.js
index 38d1d10ac5a..9626c3f0e6c 100644
--- a/src/core/core.scale.js
+++ b/src/core/core.scale.js
@@ -1,58 +1,60 @@
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
+var Ticks = require('./core.ticks');
-module.exports = function(Chart) {
+defaults._set('scale', {
+ display: true,
+ position: 'left',
- Chart.defaults.scale = {
+ // grid line settings
+ gridLines: {
display: true,
- position: 'left',
-
- // grid line settings
- gridLines: {
- display: true,
- color: 'rgba(0, 0, 0, 0.1)',
- lineWidth: 1,
- drawBorder: true,
- drawOnChartArea: true,
- drawTicks: true,
- tickMarkLength: 10,
- zeroLineWidth: 1,
- zeroLineColor: 'rgba(0,0,0,0.25)',
- zeroLineBorderDash: [],
- zeroLineBorderDashOffset: 0.0,
- offsetGridLines: false,
- borderDash: [],
- borderDashOffset: 0.0
- },
-
- // scale label
- scaleLabel: {
- // actual label
- labelString: '',
-
- // display property
- display: false,
- },
+ color: 'rgba(0, 0, 0, 0.1)',
+ lineWidth: 1,
+ drawBorder: true,
+ drawOnChartArea: true,
+ drawTicks: true,
+ tickMarkLength: 10,
+ zeroLineWidth: 1,
+ zeroLineColor: 'rgba(0,0,0,0.25)',
+ zeroLineBorderDash: [],
+ zeroLineBorderDashOffset: 0.0,
+ offsetGridLines: false,
+ borderDash: [],
+ borderDashOffset: 0.0
+ },
+
+ // scale label
+ scaleLabel: {
+ // actual label
+ labelString: '',
+
+ // display property
+ display: false,
+ },
+
+ // label settings
+ ticks: {
+ beginAtZero: false,
+ minRotation: 0,
+ maxRotation: 50,
+ mirror: false,
+ padding: 0,
+ reverse: false,
+ display: true,
+ autoSkip: true,
+ autoSkipPadding: 0,
+ labelOffset: 0,
+ // We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
+ callback: Ticks.formatters.values,
+ minor: {},
+ major: {}
+ }
+});
- // label settings
- ticks: {
- beginAtZero: false,
- minRotation: 0,
- maxRotation: 50,
- mirror: false,
- padding: 0,
- reverse: false,
- display: true,
- autoSkip: true,
- autoSkipPadding: 0,
- labelOffset: 0,
- // We pass through arrays to be rendered as multiline labels, we convert Others to strings here.
- callback: Chart.Ticks.formatters.values,
- minor: {},
- major: {}
- }
- };
+module.exports = function(Chart) {
function computeTextSize(context, tick, font) {
return helpers.isArray(tick) ?
@@ -62,7 +64,7 @@ module.exports = function(Chart) {
function parseFontOptions(options) {
var valueOrDefault = helpers.valueOrDefault;
- var globalDefaults = Chart.defaults.global;
+ var globalDefaults = defaults.global;
var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize);
var style = valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle);
var family = valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily);
@@ -511,7 +513,7 @@ module.exports = function(Chart) {
}
var context = me.ctx;
- var globalDefaults = Chart.defaults.global;
+ var globalDefaults = defaults.global;
var optionTicks = options.ticks.minor;
var optionMajorTicks = options.ticks.major || optionTicks;
var gridLines = options.gridLines;
diff --git a/src/core/core.scaleService.js b/src/core/core.scaleService.js
index e903b701b08..23cabe610d2 100644
--- a/src/core/core.scaleService.js
+++ b/src/core/core.scaleService.js
@@ -1,5 +1,6 @@
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
module.exports = function(Chart) {
@@ -13,21 +14,21 @@ module.exports = function(Chart) {
// Scale config defaults
defaults: {},
- registerScaleType: function(type, scaleConstructor, defaults) {
+ registerScaleType: function(type, scaleConstructor, scaleDefaults) {
this.constructors[type] = scaleConstructor;
- this.defaults[type] = helpers.clone(defaults);
+ this.defaults[type] = helpers.clone(scaleDefaults);
},
getScaleConstructor: function(type) {
return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined;
},
getScaleDefaults: function(type) {
// Return the scale defaults merged with the global settings so that we always use the latest ones
- return this.defaults.hasOwnProperty(type) ? helpers.merge({}, [Chart.defaults.scale, this.defaults[type]]) : {};
+ return this.defaults.hasOwnProperty(type) ? helpers.merge({}, [defaults.scale, this.defaults[type]]) : {};
},
updateScaleDefaults: function(type, additions) {
- var defaults = this.defaults;
- if (defaults.hasOwnProperty(type)) {
- defaults[type] = helpers.extend(defaults[type], additions);
+ var me = this;
+ if (me.defaults.hasOwnProperty(type)) {
+ me.defaults[type] = helpers.extend(me.defaults[type], additions);
}
},
addScalesToLayout: function(chart) {
diff --git a/src/core/core.ticks.js b/src/core/core.ticks.js
index a3b721164ba..11f44142c47 100644
--- a/src/core/core.ticks.js
+++ b/src/core/core.ticks.js
@@ -2,209 +2,206 @@
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
+/**
+ * Namespace to hold static tick generation functions
+ * @namespace Chart.Ticks
+ */
+module.exports = {
/**
- * Namespace to hold static tick generation functions
- * @namespace Chart.Ticks
+ * Namespace to hold generators for different types of ticks
+ * @namespace Chart.Ticks.generators
*/
- Chart.Ticks = {
+ generators: {
/**
- * Namespace to hold generators for different types of ticks
- * @namespace Chart.Ticks.generators
+ * Interface for the options provided to the numeric tick generator
+ * @interface INumericTickGenerationOptions
+ */
+ /**
+ * The maximum number of ticks to display
+ * @name INumericTickGenerationOptions#maxTicks
+ * @type Number
+ */
+ /**
+ * The distance between each tick.
+ * @name INumericTickGenerationOptions#stepSize
+ * @type Number
+ * @optional
+ */
+ /**
+ * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum
+ * @name INumericTickGenerationOptions#min
+ * @type Number
+ * @optional
+ */
+ /**
+ * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum
+ * @name INumericTickGenerationOptions#max
+ * @type Number
+ * @optional
*/
- generators: {
- /**
- * Interface for the options provided to the numeric tick generator
- * @interface INumericTickGenerationOptions
- */
- /**
- * The maximum number of ticks to display
- * @name INumericTickGenerationOptions#maxTicks
- * @type Number
- */
- /**
- * The distance between each tick.
- * @name INumericTickGenerationOptions#stepSize
- * @type Number
- * @optional
- */
- /**
- * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum
- * @name INumericTickGenerationOptions#min
- * @type Number
- * @optional
- */
- /**
- * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum
- * @name INumericTickGenerationOptions#max
- * @type Number
- * @optional
- */
-
- /**
- * Generate a set of linear ticks
- * @method Chart.Ticks.generators.linear
- * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
- * @param dataRange {IRange} the range of the data
- * @returns {Array} array of tick values
- */
- linear: function(generationOptions, dataRange) {
- var ticks = [];
- // To get a "nice" value for the tick spacing, we will use the appropriately named
- // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
- // for details.
-
- var spacing;
- if (generationOptions.stepSize && generationOptions.stepSize > 0) {
- spacing = generationOptions.stepSize;
- } else {
- var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
- spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true);
- }
- var niceMin = Math.floor(dataRange.min / spacing) * spacing;
- var niceMax = Math.ceil(dataRange.max / spacing) * spacing;
-
- // If min, max and stepSize is set and they make an evenly spaced scale use it.
- if (generationOptions.min && generationOptions.max && generationOptions.stepSize) {
- // If very close to our whole number, use it.
- if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) {
- niceMin = generationOptions.min;
- niceMax = generationOptions.max;
- }
- }
- var numSpaces = (niceMax - niceMin) / spacing;
- // If very close to our rounded value, use it.
- if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
- numSpaces = Math.round(numSpaces);
- } else {
- numSpaces = Math.ceil(numSpaces);
+ /**
+ * Generate a set of linear ticks
+ * @method Chart.Ticks.generators.linear
+ * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
+ * @param dataRange {IRange} the range of the data
+ * @returns {Array} array of tick values
+ */
+ linear: function(generationOptions, dataRange) {
+ var ticks = [];
+ // To get a "nice" value for the tick spacing, we will use the appropriately named
+ // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks
+ // for details.
+
+ var spacing;
+ if (generationOptions.stepSize && generationOptions.stepSize > 0) {
+ spacing = generationOptions.stepSize;
+ } else {
+ var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false);
+ spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true);
+ }
+ var niceMin = Math.floor(dataRange.min / spacing) * spacing;
+ var niceMax = Math.ceil(dataRange.max / spacing) * spacing;
+
+ // If min, max and stepSize is set and they make an evenly spaced scale use it.
+ if (generationOptions.min && generationOptions.max && generationOptions.stepSize) {
+ // If very close to our whole number, use it.
+ if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) {
+ niceMin = generationOptions.min;
+ niceMax = generationOptions.max;
}
+ }
- // Put the values into the ticks array
- ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin);
- for (var j = 1; j < numSpaces; ++j) {
- ticks.push(niceMin + (j * spacing));
- }
- ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax);
-
- return ticks;
- },
-
- /**
- * Generate a set of logarithmic ticks
- * @method Chart.Ticks.generators.logarithmic
- * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
- * @param dataRange {IRange} the range of the data
- * @returns {Array} array of tick values
- */
- logarithmic: function(generationOptions, dataRange) {
- var ticks = [];
- var valueOrDefault = helpers.valueOrDefault;
-
- // Figure out what the max number of ticks we can support it is based on the size of
- // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
- // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
- // the graph
- var tickVal = valueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min))));
-
- var endExp = Math.floor(helpers.log10(dataRange.max));
- var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
- var exp;
- var significand;
-
- if (tickVal === 0) {
- exp = Math.floor(helpers.log10(dataRange.minNotZero));
- significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp));
-
- ticks.push(tickVal);
- tickVal = significand * Math.pow(10, exp);
- } else {
- exp = Math.floor(helpers.log10(tickVal));
- significand = Math.floor(tickVal / Math.pow(10, exp));
- }
+ var numSpaces = (niceMax - niceMin) / spacing;
+ // If very close to our rounded value, use it.
+ if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
+ numSpaces = Math.round(numSpaces);
+ } else {
+ numSpaces = Math.ceil(numSpaces);
+ }
+
+ // Put the values into the ticks array
+ ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin);
+ for (var j = 1; j < numSpaces; ++j) {
+ ticks.push(niceMin + (j * spacing));
+ }
+ ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax);
+
+ return ticks;
+ },
- do {
- ticks.push(tickVal);
+ /**
+ * Generate a set of logarithmic ticks
+ * @method Chart.Ticks.generators.logarithmic
+ * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks
+ * @param dataRange {IRange} the range of the data
+ * @returns {Array} array of tick values
+ */
+ logarithmic: function(generationOptions, dataRange) {
+ var ticks = [];
+ var valueOrDefault = helpers.valueOrDefault;
+
+ // Figure out what the max number of ticks we can support it is based on the size of
+ // the axis area. For now, we say that the minimum tick spacing in pixels must be 50
+ // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on
+ // the graph
+ var tickVal = valueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min))));
+
+ var endExp = Math.floor(helpers.log10(dataRange.max));
+ var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
+ var exp;
+ var significand;
+
+ if (tickVal === 0) {
+ exp = Math.floor(helpers.log10(dataRange.minNotZero));
+ significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp));
+
+ ticks.push(tickVal);
+ tickVal = significand * Math.pow(10, exp);
+ } else {
+ exp = Math.floor(helpers.log10(tickVal));
+ significand = Math.floor(tickVal / Math.pow(10, exp));
+ }
- ++significand;
- if (significand === 10) {
- significand = 1;
- ++exp;
- }
+ do {
+ ticks.push(tickVal);
- tickVal = significand * Math.pow(10, exp);
- } while (exp < endExp || (exp === endExp && significand < endSignificand));
+ ++significand;
+ if (significand === 10) {
+ significand = 1;
+ ++exp;
+ }
- var lastTick = valueOrDefault(generationOptions.max, tickVal);
- ticks.push(lastTick);
+ tickVal = significand * Math.pow(10, exp);
+ } while (exp < endExp || (exp === endExp && significand < endSignificand));
- return ticks;
- },
+ var lastTick = valueOrDefault(generationOptions.max, tickVal);
+ ticks.push(lastTick);
- time: helpers.time.generateTicks
+ return ticks;
},
+ time: helpers.time.generateTicks
+ },
+
+ /**
+ * Namespace to hold formatters for different types of ticks
+ * @namespace Chart.Ticks.formatters
+ */
+ formatters: {
/**
- * Namespace to hold formatters for different types of ticks
- * @namespace Chart.Ticks.formatters
+ * Formatter for value labels
+ * @method Chart.Ticks.formatters.values
+ * @param value the value to display
+ * @return {String|Array} the label to display
*/
- formatters: {
- /**
- * Formatter for value labels
- * @method Chart.Ticks.formatters.values
- * @param value the value to display
- * @return {String|Array} the label to display
- */
- values: function(value) {
- return helpers.isArray(value) ? value : '' + value;
- },
-
- /**
- * Formatter for linear numeric ticks
- * @method Chart.Ticks.formatters.linear
- * @param tickValue {Number} the value to be formatted
- * @param index {Number} the position of the tickValue parameter in the ticks array
- * @param ticks {Array} the list of ticks being converted
- * @return {String} string representation of the tickValue parameter
- */
- linear: function(tickValue, index, ticks) {
- // If we have lots of ticks, don't use the ones
- var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
-
- // If we have a number like 2.5 as the delta, figure out how many decimal places we need
- if (Math.abs(delta) > 1) {
- if (tickValue !== Math.floor(tickValue)) {
- // not an integer
- delta = tickValue - Math.floor(tickValue);
- }
+ values: function(value) {
+ return helpers.isArray(value) ? value : '' + value;
+ },
+
+ /**
+ * Formatter for linear numeric ticks
+ * @method Chart.Ticks.formatters.linear
+ * @param tickValue {Number} the value to be formatted
+ * @param index {Number} the position of the tickValue parameter in the ticks array
+ * @param ticks {Array} the list of ticks being converted
+ * @return {String} string representation of the tickValue parameter
+ */
+ linear: function(tickValue, index, ticks) {
+ // If we have lots of ticks, don't use the ones
+ var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0];
+
+ // If we have a number like 2.5 as the delta, figure out how many decimal places we need
+ if (Math.abs(delta) > 1) {
+ if (tickValue !== Math.floor(tickValue)) {
+ // not an integer
+ delta = tickValue - Math.floor(tickValue);
}
+ }
- var logDelta = helpers.log10(Math.abs(delta));
- var tickString = '';
+ var logDelta = helpers.log10(Math.abs(delta));
+ var tickString = '';
- if (tickValue !== 0) {
- var numDecimal = -1 * Math.floor(logDelta);
- numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
- tickString = tickValue.toFixed(numDecimal);
- } else {
- tickString = '0'; // never show decimal places for 0
- }
+ if (tickValue !== 0) {
+ var numDecimal = -1 * Math.floor(logDelta);
+ numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places
+ tickString = tickValue.toFixed(numDecimal);
+ } else {
+ tickString = '0'; // never show decimal places for 0
+ }
- return tickString;
- },
+ return tickString;
+ },
- logarithmic: function(tickValue, index, ticks) {
- var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue))));
+ logarithmic: function(tickValue, index, ticks) {
+ var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue))));
- if (tickValue === 0) {
- return '0';
- } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) {
- return tickValue.toExponential();
- }
- return '';
+ if (tickValue === 0) {
+ return '0';
+ } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) {
+ return tickValue.toExponential();
}
+ return '';
}
- };
+ }
};
diff --git a/src/core/core.tooltip.js b/src/core/core.tooltip.js
index 6794320511f..a1ded8e3b6b 100644
--- a/src/core/core.tooltip.js
+++ b/src/core/core.tooltip.js
@@ -1,18 +1,10 @@
'use strict';
+var defaults = require('./core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- /**
- * Helper method to merge the opacity into a color
- */
- function mergeOpacity(colorString, opacity) {
- var color = helpers.color(colorString);
- return color.alpha(opacity * color.alpha()).rgbaString();
- }
-
- Chart.defaults.global.tooltips = {
+defaults._set('global', {
+ tooltips: {
enabled: true,
custom: null,
mode: 'nearest',
@@ -100,7 +92,18 @@ module.exports = function(Chart) {
footer: helpers.noop,
afterFooter: helpers.noop
}
- };
+ }
+});
+
+module.exports = function(Chart) {
+
+ /**
+ * Helper method to merge the opacity into a color
+ */
+ function mergeOpacity(colorString, opacity) {
+ var color = helpers.color(colorString);
+ return color.alpha(opacity * color.alpha()).rgbaString();
+ }
// Helper to push or concat based on if the 2nd parameter is an array or not
function pushOrConcat(base, toPush) {
@@ -140,7 +143,7 @@ module.exports = function(Chart) {
* @param tooltipOpts {Object} the tooltip options
*/
function getBaseModel(tooltipOpts) {
- var globalDefaults = Chart.defaults.global;
+ var globalDefaults = defaults.global;
var valueOrDefault = helpers.valueOrDefault;
return {
diff --git a/src/elements/element.arc.js b/src/elements/element.arc.js
index 8604dfaea26..101302cf8aa 100644
--- a/src/elements/element.arc.js
+++ b/src/elements/element.arc.js
@@ -1,16 +1,19 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- var globalOpts = Chart.defaults.global;
+defaults._set('global', {
+ elements: {
+ arc: {
+ backgroundColor: defaults.global.defaultColor,
+ borderColor: '#fff',
+ borderWidth: 2
+ }
+ }
+});
- globalOpts.elements.arc = {
- backgroundColor: globalOpts.defaultColor,
- borderColor: '#fff',
- borderWidth: 2
- };
+module.exports = function(Chart) {
Chart.elements.Arc = Chart.Element.extend({
inLabelRange: function(mouseX) {
diff --git a/src/elements/element.line.js b/src/elements/element.line.js
index 5a21fafb20b..f2bfcf67dc9 100644
--- a/src/elements/element.line.js
+++ b/src/elements/element.line.js
@@ -1,23 +1,28 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
+var globalDefaults = defaults.global;
- var globalDefaults = Chart.defaults.global;
+defaults._set('global', {
+ elements: {
+ line: {
+ tension: 0.4,
+ backgroundColor: globalDefaults.defaultColor,
+ borderWidth: 3,
+ borderColor: globalDefaults.defaultColor,
+ borderCapStyle: 'butt',
+ borderDash: [],
+ borderDashOffset: 0.0,
+ borderJoinStyle: 'miter',
+ capBezierPoints: true,
+ fill: true, // do we fill in the area between the line and its base axis
+ }
+ }
+});
- Chart.defaults.global.elements.line = {
- tension: 0.4,
- backgroundColor: globalDefaults.defaultColor,
- borderWidth: 3,
- borderColor: globalDefaults.defaultColor,
- borderCapStyle: 'butt',
- borderDash: [],
- borderDashOffset: 0.0,
- borderJoinStyle: 'miter',
- capBezierPoints: true,
- fill: true, // do we fill in the area between the line and its base axis
- };
+module.exports = function(Chart) {
Chart.elements.Line = Chart.Element.extend({
draw: function() {
diff --git a/src/elements/element.point.js b/src/elements/element.point.js
index c09329b1737..0b5d12d1286 100644
--- a/src/elements/element.point.js
+++ b/src/elements/element.point.js
@@ -1,23 +1,27 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
+var defaultColor = defaults.global.defaultColor;
- var globalOpts = Chart.defaults.global,
- defaultColor = globalOpts.defaultColor;
+defaults._set('global', {
+ elements: {
+ point: {
+ radius: 3,
+ pointStyle: 'circle',
+ backgroundColor: defaultColor,
+ borderColor: defaultColor,
+ borderWidth: 1,
+ // Hover
+ hitRadius: 1,
+ hoverRadius: 4,
+ hoverBorderWidth: 1
+ }
+ }
+});
- globalOpts.elements.point = {
- radius: 3,
- pointStyle: 'circle',
- backgroundColor: defaultColor,
- borderWidth: 1,
- borderColor: defaultColor,
- // Hover
- hitRadius: 1,
- hoverRadius: 4,
- hoverBorderWidth: 1
- };
+module.exports = function(Chart) {
function xRange(mouseX) {
var vm = this._view;
@@ -74,7 +78,7 @@ module.exports = function(Chart) {
}
ctx.strokeStyle = vm.borderColor || defaultColor;
- ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, globalOpts.elements.point.borderWidth);
+ ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, defaults.global.elements.point.borderWidth);
ctx.fillStyle = vm.backgroundColor || defaultColor;
// Cliping for Points.
diff --git a/src/elements/element.rectangle.js b/src/elements/element.rectangle.js
index c3b81976140..00f017e66e4 100644
--- a/src/elements/element.rectangle.js
+++ b/src/elements/element.rectangle.js
@@ -1,15 +1,19 @@
'use strict';
-module.exports = function(Chart) {
-
- var globalOpts = Chart.defaults.global;
+var defaults = require('../core/core.defaults');
+
+defaults._set('global', {
+ elements: {
+ rectangle: {
+ backgroundColor: defaults.global.defaultColor,
+ borderColor: defaults.global.defaultColor,
+ borderSkipped: 'bottom',
+ borderWidth: 0
+ }
+ }
+});
- globalOpts.elements.rectangle = {
- backgroundColor: globalOpts.defaultColor,
- borderWidth: 0,
- borderColor: globalOpts.defaultColor,
- borderSkipped: 'bottom'
- };
+module.exports = function(Chart) {
function isVertical(bar) {
return bar._view.width !== undefined;
diff --git a/src/plugins/plugin.filler.js b/src/plugins/plugin.filler.js
index 4f49064f084..51aed7669cf 100644
--- a/src/plugins/plugin.filler.js
+++ b/src/plugins/plugin.filler.js
@@ -1,18 +1,24 @@
+/**
+ * Plugin based on discussion from the following Chart.js issues:
+ * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569
+ * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897
+ */
+
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
+defaults._set('global', {
+ plugins: {
+ filler: {
+ propagate: true
+ }
+ }
+});
+
module.exports = function(Chart) {
- /**
- * Plugin based on discussion from the following Chart.js issues:
- * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569
- * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897
- */
- Chart.defaults.global.plugins.filler = {
- propagate: true
- };
- var defaults = Chart.defaults;
var mappers = {
dataset: function(source) {
var index = source.fill;
diff --git a/src/plugins/plugin.legend.js b/src/plugins/plugin.legend.js
index 3eb0f57dfcb..1a32c079857 100644
--- a/src/plugins/plugin.legend.js
+++ b/src/plugins/plugin.legend.js
@@ -1,13 +1,10 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- var layout = Chart.layoutService;
- var noop = helpers.noop;
-
- Chart.defaults.global.legend = {
+defaults._set('global', {
+ legend: {
display: true,
position: 'top',
fullWidth: true,
@@ -64,7 +61,27 @@ module.exports = function(Chart) {
}, this) : [];
}
}
- };
+ },
+
+ legendCallback: function(chart) {
+ var text = [];
+ text.push('');
+ for (var i = 0; i < chart.data.datasets.length; i++) {
+ text.push('- ');
+ if (chart.data.datasets[i].label) {
+ text.push(chart.data.datasets[i].label);
+ }
+ text.push('
');
+ }
+ text.push('
');
+ return text.join('');
+ }
+});
+
+module.exports = function(Chart) {
+
+ var layout = Chart.layoutService;
+ var noop = helpers.noop;
/**
* Helper function to get the box width based on the usePointStyle option
@@ -192,7 +209,7 @@ module.exports = function(Chart) {
var ctx = me.ctx;
- var globalDefault = Chart.defaults.global,
+ var globalDefault = defaults.global,
valueOrDefault = helpers.valueOrDefault,
fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize),
fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle),
@@ -304,7 +321,7 @@ module.exports = function(Chart) {
var me = this;
var opts = me.options;
var labelOpts = opts.labels;
- var globalDefault = Chart.defaults.global,
+ var globalDefault = defaults.global,
lineDefault = globalDefault.elements.line,
legendWidth = me.width,
lineWidths = me.lineWidths;
@@ -525,7 +542,7 @@ module.exports = function(Chart) {
var legend = chart.legend;
if (legendOpts) {
- helpers.mergeIf(legendOpts, Chart.defaults.global.legend);
+ helpers.mergeIf(legendOpts, defaults.global.legend);
if (legend) {
layout.configure(chart, legend, legendOpts);
diff --git a/src/plugins/plugin.title.js b/src/plugins/plugin.title.js
index 42ad1b0d3db..30f8813d92a 100644
--- a/src/plugins/plugin.title.js
+++ b/src/plugins/plugin.title.js
@@ -1,23 +1,24 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
-module.exports = function(Chart) {
-
- var layout = Chart.layoutService;
- var noop = helpers.noop;
-
- Chart.defaults.global.title = {
+defaults._set('global', {
+ title: {
display: false,
- position: 'top',
- fullWidth: true,
- weight: 2000, // by default greater than legend (1000) to be above
fontStyle: 'bold',
+ fullWidth: true,
padding: 10,
+ position: 'top',
+ text: '',
+ weight: 2000 // by default greater than legend (1000) to be above
+ }
+});
- // actual title
- text: ''
- };
+module.exports = function(Chart) {
+
+ var layout = Chart.layoutService;
+ var noop = helpers.noop;
Chart.Title = Chart.Element.extend({
initialize: function(config) {
@@ -109,9 +110,8 @@ module.exports = function(Chart) {
var me = this,
valueOrDefault = helpers.valueOrDefault,
opts = me.options,
- globalDefaults = Chart.defaults.global,
display = opts.display,
- fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
+ fontSize = valueOrDefault(opts.fontSize, defaults.global.defaultFontSize),
minSize = me.minSize,
lineCount = helpers.isArray(opts.text) ? opts.text.length : 1,
lineHeight = valueOrDefault(opts.lineHeight, fontSize),
@@ -143,7 +143,7 @@ module.exports = function(Chart) {
ctx = me.ctx,
valueOrDefault = helpers.valueOrDefault,
opts = me.options,
- globalDefaults = Chart.defaults.global;
+ globalDefaults = defaults.global;
if (opts.display) {
var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize),
@@ -225,7 +225,7 @@ module.exports = function(Chart) {
var titleBlock = chart.titleBlock;
if (titleOpts) {
- helpers.mergeIf(titleOpts, Chart.defaults.global.title);
+ helpers.mergeIf(titleOpts, defaults.global.title);
if (titleBlock) {
layout.configure(chart, titleBlock, titleOpts);
diff --git a/src/scales/scale.linear.js b/src/scales/scale.linear.js
index 34223c28383..94ebd12a5a0 100644
--- a/src/scales/scale.linear.js
+++ b/src/scales/scale.linear.js
@@ -1,13 +1,15 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
+var Ticks = require('../core/core.ticks');
module.exports = function(Chart) {
var defaultConfig = {
position: 'left',
ticks: {
- callback: Chart.Ticks.formatters.linear
+ callback: Ticks.formatters.linear
}
};
@@ -139,7 +141,7 @@ module.exports = function(Chart) {
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50));
} else {
// The factor of 2 used to scale the font size has been experimentally determined.
- var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, Chart.defaults.global.defaultFontSize);
+ var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize);
maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize)));
}
diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js
index 33bc22517bf..cf75b31663d 100644
--- a/src/scales/scale.linearbase.js
+++ b/src/scales/scale.linearbase.js
@@ -1,6 +1,7 @@
'use strict';
var helpers = require('../helpers/index');
+var Ticks = require('../core/core.ticks');
module.exports = function(Chart) {
@@ -94,7 +95,7 @@ module.exports = function(Chart) {
max: tickOpts.max,
stepSize: helpers.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize)
};
- var ticks = me.ticks = Chart.Ticks.generators.linear(numericGeneratorOptions, me);
+ var ticks = me.ticks = Ticks.generators.linear(numericGeneratorOptions, me);
me.handleDirectionalChanges();
diff --git a/src/scales/scale.logarithmic.js b/src/scales/scale.logarithmic.js
index a5c5fa918a2..a6a0606ade1 100644
--- a/src/scales/scale.logarithmic.js
+++ b/src/scales/scale.logarithmic.js
@@ -1,6 +1,7 @@
'use strict';
var helpers = require('../helpers/index');
+var Ticks = require('../core/core.ticks');
module.exports = function(Chart) {
@@ -9,7 +10,7 @@ module.exports = function(Chart) {
// label settings
ticks: {
- callback: Chart.Ticks.formatters.logarithmic
+ callback: Ticks.formatters.logarithmic
}
};
@@ -142,7 +143,7 @@ module.exports = function(Chart) {
min: tickOpts.min,
max: tickOpts.max
};
- var ticks = me.ticks = Chart.Ticks.generators.logarithmic(generationOptions, me);
+ var ticks = me.ticks = Ticks.generators.logarithmic(generationOptions, me);
if (!me.isHorizontal()) {
// We are in a vertical orientation. The top value is the highest. So reverse the array
diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js
index 93036c691e5..f1194fd82ae 100644
--- a/src/scales/scale.radialLinear.js
+++ b/src/scales/scale.radialLinear.js
@@ -1,10 +1,12 @@
'use strict';
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
+var Ticks = require('../core/core.ticks');
module.exports = function(Chart) {
- var globalDefaults = Chart.defaults.global;
+ var globalDefaults = defaults.global;
var defaultConfig = {
display: true,
@@ -37,7 +39,7 @@ module.exports = function(Chart) {
// Number - The backdrop padding to the side of the label in pixels
backdropPaddingX: 2,
- callback: Chart.Ticks.formatters.linear
+ callback: Ticks.formatters.linear
},
pointLabels: {
diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js
index fab5ccd6416..41d022a7938 100644
--- a/src/scales/scale.time.js
+++ b/src/scales/scale.time.js
@@ -4,6 +4,7 @@
var moment = require('moment');
moment = typeof(moment) === 'function' ? moment : window.moment;
+var defaults = require('../core/core.defaults');
var helpers = require('../helpers/index');
module.exports = function(Chart) {
@@ -274,7 +275,7 @@ module.exports = function(Chart) {
var tickLabelWidth = me.ctx.measureText(label).width;
var cosRotation = Math.cos(helpers.toRadians(ticks.maxRotation));
var sinRotation = Math.sin(helpers.toRadians(ticks.maxRotation));
- var tickFontSize = helpers.valueOrDefault(ticks.fontSize, Chart.defaults.global.defaultFontSize);
+ var tickFontSize = helpers.valueOrDefault(ticks.fontSize, defaults.global.defaultFontSize);
return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation);
},
getLabelCapacity: function(exampleTime) {