]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Make `Chart.defaults/Ticks/Interaction` importable (#4512)
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Sun, 16 Jul 2017 17:38:19 +0000 (19:38 +0200)
committerGitHub <noreply@github.com>
Sun, 16 Jul 2017 17:38:19 +0000 (19:38 +0200)
Default options can now be accessed by importing `core/core.defaults`. The returned object acts as a singleton and is populated when importing classes that expose their own default values (meaning that importing only `code.defaults` results in an empty object). Also make `Chart.Ticks` and `Chart.Interaction` importable since existing defaults rely on these values.

Add the `defaults._set` method that make easier declaring new defaults by merging given values with existing ones for a specific scope (`global`, `scale`, `bar`, etc).

32 files changed:
src/chart.js
src/charts/Chart.Scatter.js
src/controllers/controller.bar.js
src/controllers/controller.bubble.js
src/controllers/controller.doughnut.js
src/controllers/controller.line.js
src/controllers/controller.polarArea.js
src/controllers/controller.radar.js
src/controllers/controller.scatter.js [new file with mode: 0644]
src/core/core.animation.js
src/core/core.controller.js
src/core/core.defaults.js [new file with mode: 0644]
src/core/core.helpers.js
src/core/core.interaction.js
src/core/core.js
src/core/core.plugin.js
src/core/core.scale.js
src/core/core.scaleService.js
src/core/core.ticks.js
src/core/core.tooltip.js
src/elements/element.arc.js
src/elements/element.line.js
src/elements/element.point.js
src/elements/element.rectangle.js
src/plugins/plugin.filler.js
src/plugins/plugin.legend.js
src/plugins/plugin.title.js
src/scales/scale.linear.js
src/scales/scale.linearbase.js
src/scales/scale.logarithmic.js
src/scales/scale.radialLinear.js
src/scales/scale.time.js

index 9580c2387b5c3de42e8d9fe4f223efd0ff6b169e..146cfbaa8d3a61d64a5ef867c32604b320e8a5bd 100644 (file)
@@ -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);
index 7b7e67d435e7bc871ce722594e688cfcd7b4ffeb..9006e57129357ab6830dc27bc318e83446cb68d6 100644 (file)
@@ -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);
        };
-
 };
index 93d285323c3be357caf8fde41103c9d5b9403b6b..97a077e66d55f9149983dcf1b630b2b55afc6c7c 100644 (file)
@@ -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
index b91b15f1277fc1a7a760144975361c1eb0df5a4d..6d410114ec20e6c683fbc0a977aa8b7b8e5850cc 100644 (file)
@@ -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({
 
index c87c59bbcb08feb9e7f97e75dec9179cbdf1ca1d..ffbf22a66cc88c4fd745f5941795c5bf77b6b2f2 100644 (file)
 '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('<ul class="' + chart.id + '-legend">');
-
-                       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('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
-                                       if (labels[i]) {
-                                               text.push(labels[i]);
-                                       }
-                                       text.push('</li>');
+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('<ul class="' + chart.id + '-legend">');
+
+               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('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
+                               if (labels[i]) {
+                                       text.push(labels[i]);
                                }
+                               text.push('</li>');
                        }
+               }
 
-                       text.push('</ul>');
-                       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('</ul>');
+               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({
 
index c31e73f23d44a8709968c8c229e55b402b1ec155..d841ada64dc1c8d0cb813bcd2788e68f5dbfba3f 100644 (file)
@@ -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);
index bf2cd6b41bf5aac9a3a09379969e7da899b184d4..c0ac2993e38f7b94d33e2b0378f01f8a9caa537e 100644 (file)
 '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('<ul class="' + chart.id + '-legend">');
-
-                       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('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
-                                       if (labels[i]) {
-                                               text.push(labels[i]);
-                                       }
-                                       text.push('</li>');
+               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('<ul class="' + chart.id + '-legend">');
+
+               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('<li><span style="background-color:' + datasets[0].backgroundColor[i] + '"></span>');
+                               if (labels[i]) {
+                                       text.push(labels[i]);
                                }
+                               text.push('</li>');
                        }
+               }
 
-                       text.push('</ul>');
-                       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('</ul>');
+               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({
 
index 24c83b4631833130ab4dadfcbac1db5cb5bfe2d3..b3bccdca97091da1e39c369b73d0aa07a4441b30 100644 (file)
@@ -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 (file)
index 0000000..b2e2cf1
--- /dev/null
@@ -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;
+
+};
index 40208916a6644260c404e6f796a5f4c6a7ba7d4f..bbd44cde18ead31672c682036c96c6e43897c6df 100644 (file)
@@ -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
index 4a86d70d2fbbb9e53ada26e1f4832e1980a5e3a3..2033c5425495be82fb2ab094880ee3145eace991 100644 (file)
@@ -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 (file)
index 0000000..29bb040
--- /dev/null
@@ -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);
+       }
+};
index 8896e232aad1d02ad8e1a83d8d922c0284571e9f..90e116d2ceed3172ab8cd399d711a761f02a65ab 100644 (file)
@@ -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);
index 6e35bd950e851ff88e4951f74b8d580800096142..793468d43fbe0ec3a4cd2cca9e45071c19db78cd 100644 (file)
 
 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;
                }
-       };
+       }
 };
index afb51c71d65fb96a35689ce2f2daceb24eb1d8ac..906b897c6990225aa9f43613818e2f2a92b4a883 100644 (file)
@@ -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('<ul class="' + chart.id + '-legend">');
-                               for (var i = 0; i < chart.data.datasets.length; i++) {
-                                       text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
-                                       if (chart.data.datasets[i].label) {
-                                               text.push(chart.data.datasets[i].label);
-                                       }
-                                       text.push('</li>');
-                               }
-                               text.push('</ul>');
-
-                               return text.join('');
-                       }
-               }
-       };
-
        Chart.Chart = Chart;
 
        return Chart;
index 92761158033d9d5780c2c5ac23fb2c49cbc6b40d..2c472ce0da42c5be13dca4bc4712b051efb15158 100644 (file)
@@ -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);
index 38d1d10ac5a86a985e9d593f7069d2eb2e1b2fb7..9626c3f0e6cb19f204072bcf50f265f0807deaae 100644 (file)
@@ -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;
index e903b701b087f0c98fa27f36077939f4ab37c910..23cabe610d26f39874cc2ac0e5a98e6cf9c1d624 100644 (file)
@@ -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) {
index a3b721164bacc284ac372dc8d19edf88de75d337..11f44142c47ff36840aef6ff4989b89df5347722 100644 (file)
 
 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<Number>} 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<Number>} 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<Number>} 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<Number>} 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<Number>} 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<Number>} 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 '';
                }
-       };
+       }
 };
index 6794320511f88b27585855d7748ed278f795bb1b..a1ded8e3b6b46e1fc9463abfe12f7431b7578b19 100644 (file)
@@ -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 {
index 8604dfaea269554e5b6f2519c6f4fef9cb875575..101302cf8aadd1700484bece30f6c4f4317835ac 100644 (file)
@@ -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) {
index 5a21fafb20b8f1c03fd2682e59c01e6b16e057b9..f2bfcf67dc9e033ed254af949cedbb1c9622bd31 100644 (file)
@@ -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() {
index c09329b1737753a760b61202640d706d988acaae..0b5d12d12864bd881224ffcf950b30f69c113a15 100644 (file)
@@ -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.
index c3b819761408b52c25f5b3132f1a2a55d3b785f3..00f017e66e47cfa03f390d72622dd2271de9d252 100644 (file)
@@ -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;
index 4f49064f084b459360e8e53a0ea3141ecfd53126..51aed7669cf9e9f93e02853e6ebb1c9cac40f6ba 100644 (file)
@@ -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;
index 3eb0f57dfcba3e21b111629fe43cd0e6ae7ed038..1a32c07985777fd5d454b388e145eda57a48554c 100644 (file)
@@ -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('<ul class="' + chart.id + '-legend">');
+               for (var i = 0; i < chart.data.datasets.length; i++) {
+                       text.push('<li><span style="background-color:' + chart.data.datasets[i].backgroundColor + '"></span>');
+                       if (chart.data.datasets[i].label) {
+                               text.push(chart.data.datasets[i].label);
+                       }
+                       text.push('</li>');
+               }
+               text.push('</ul>');
+               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);
index 42ad1b0d3dbe1284b4f493d19c554d90af417031..30f8813d92a2e5cceec397894f8aa4732a34f8bc 100644 (file)
@@ -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);
index 34223c283838d02a45e326b2dc5f2bfdba1b9534..94ebd12a5a01a819c4a0ac4ddd8f6d8198454741 100644 (file)
@@ -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)));
                        }
 
index 33bc22517bf91822c53f1a38d4bb14006422d53b..cf75b31663d9572ccefd7b6ed2ae19b78c4d3063 100644 (file)
@@ -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();
 
index a5c5fa918a28ebc05bdcf7d60b9080c14396b3c2..a6a0606ade1edba368387c406f019d92f6f9297e 100644 (file)
@@ -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
index 93036c691e53b268f7a9e29cb63e3ef2911ae58f..f1194fd82ae58f7e2955e6abd0586cabb1be67d0 100644 (file)
@@ -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: {
index fab5ccd64160c64449929f54484b8264c64a640e..41d022a7938ed6a95f7f38a8b83bc1d9883d3ef4 100644 (file)
@@ -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) {