]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Initial config merge. Handles special cases for objects and arrays and merges smarter...
authoretimberg <evert.timberg@gmail.com>
Mon, 18 May 2015 18:19:34 +0000 (14:19 -0400)
committeretimberg <evert.timberg@gmail.com>
Mon, 18 May 2015 18:19:34 +0000 (14:19 -0400)
samples/scatter.html
src/Chart.Core.js
src/Chart.Scatter.js

index 56c23fa72ca6d5ddb2e789390b1c91ba4389e98b..ecc259f2faf39f17711487926f49d953fc0ae7ca 100644 (file)
         var ctx = document.getElementById("canvas").getContext("2d");
         window.myScatter = new Chart(ctx).Scatter(scatterChartData, {
             responsive: true,
-            hoverMode: 'single'
+            hoverMode: 'single',
+            scales: {
+               xAxes: [{
+                       gridLines: {
+                               zeroLineColor: "rgba(0,0,0,1)"
+                       }
+               }]
+            }
         });
     };
 
index e5bfd2af3373f852fb181ea70634b2a2e685f661..f86f0ac0d6eec0590250581b5b4982acdd0bb4f1 100755 (executable)
             args.unshift({});
             return extend.apply(null, args);
         },
+        // Need a special merge function to chart configs since they are now grouped
+        configMerge = helpers.configMerge = function(base) {
+            helpers.each(Array.prototype.slice.call(arguments, 1), function(extension) {
+                helpers.each(extension, function(value, key) {
+                    if (extension.hasOwnProperty(key)) {
+                        if (base.hasOwnProperty(key) && helpers.isArray(base[key]) && helpers.isArray(value)) {
+                            // In this case we have an array of objects replacing another array. Rather than doing a strict replace,
+                            // merge. This allows easy scale option merging
+                            var baseArray = base[key];
+
+                            helpers.each(value, function(valueObj, index) {
+                                if (index < baseArray.length) {
+                                    baseArray[index] = helpers.configMerge(baseArray[index], valueObj);
+                                } else {
+                                    baseArray.push(valueObj); // nothing to merge
+                                }
+                            });
+                        }
+                        else if (base.hasOwnProperty(key) && typeof base[key] == "object" && typeof value == "object") {
+                            // If we are overwriting an object with an object, do a merge of the properties.
+                            base[key] = helpers.configMerge(base[key], value);
+                        } else {
+                            // can just overwrite the value in this case
+                            base[key] = value;
+                        }
+                    }
+                });
+            });
+            
+            return base;
+        },
         indexOf = helpers.indexOf = function(arrayToSearch, item) {
             if (Array.prototype.indexOf) {
                 return arrayToSearch.indexOf(item);
 
             var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {};
 
-            Chart.defaults[chartName] = extend(baseDefaults, extensions.defaults);
+            Chart.defaults[chartName] = helpers.configMerge(baseDefaults, extensions.defaults);
 
             Chart.types[chartName] = ChartType;
 
             //Register this new chart type in the Chart prototype
             Chart.prototype[chartName] = function(data, options) {
-                var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {});
+                var config = helpers.configMerge(Chart.defaults.global, Chart.defaults[chartName], options || {});
                 return new ChartType(data, config, this);
             };
         } else {
index 3a364e30ad766515e72c9ba9474b933d87d9914e..10aa6757ce55f6f00ce78898a7416ecd030330c9 100644 (file)
@@ -7,20 +7,72 @@
 
     var defaultConfig = {
 
-        ///Boolean - Whether grid lines are shown across the chart
-        scaleShowGridLines: true,
-
-        //String - Colour of the grid lines
-        scaleGridLineColor: "rgba(0,0,0,.05)",
-
-        //Number - Width of the grid lines
-        scaleGridLineWidth: 1,
-
-        //Boolean - Whether to show horizontal lines (except X axis)
-        scaleShowHorizontalLines: true,
-
-        //Boolean - Whether to show vertical lines (except Y axis)
-        scaleShowVerticalLines: true,
+        scales: {
+            xAxes: [{
+                scaleType: "linear", // scatter should not use a dataset axis
+                show: true,
+                position: "bottom",
+                horizontal: true,
+                id: "x-axis-1", // need an ID so datasets can reference the scale
+                
+                // grid line settings
+                gridLines: {
+                    show: true,
+                    color: "rgba(0, 0, 0, 0.05)",
+                    lineWidth: 1,
+                    drawOnChartArea: true,
+                    zeroLineWidth: 1,
+                    zeroLineColor: "rgba(0,0,0,0.25)",
+                },
+
+                // scale numbers
+                beginAtZero: false,
+                integersOnly: false,
+                override: null,
+
+                // label settings
+                labels: {
+                    show: true,
+                    template: "<%=value%>",
+                    fontSize: 12,
+                    fontStyle: "normal",
+                    fontColor: "#666",
+                    fontFamily: "Helvetica Neue",
+                },
+            }],
+            yAxes: [{
+                scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
+                show: true,
+                position: "left",
+                horizontal: false, 
+                id: "y-axis-1",
+        
+                // grid line settings
+                gridLines: {
+                    show: true,
+                    color: "rgba(0, 0, 0, 0.05)",
+                    lineWidth: 1,
+                    drawOnChartArea: true,
+                    zeroLineWidth: 1,
+                    zeroLineColor: "rgba(0,0,0,0.25)",
+                },
+
+                // scale numbers
+                beginAtZero: false,
+                integersOnly: false,
+                override: null,
+
+                // label settings
+                labels: {
+                    show: true,
+                    template: "<%=value%>",
+                    fontSize: 12,
+                    fontStyle: "normal",
+                    fontColor: "#666",
+                    fontFamily: "Helvetica Neue",
+                }
+            }],
+        },
 
         //Number - Tension of the bezier curve between points
         tension: 0.4,
@@ -40,9 +92,6 @@
         //String - A legend template
         legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].borderColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
 
-        //Boolean - Whether to horizontally center the label and point dot inside the grid
-        offsetGridLines: false
-
     };
 
 
             helpers.bindEvents(this, this.options.tooltipEvents, this.onHover);
 
             // Build Scale
-            this.buildScale(this.data.labels);
+            this.buildScale();
                        Chart.scaleService.fitScalesForChart(this, this.chart.width, this.chart.height);
 
             //Create a new line and its points for each dataset and piece of data
                 helpers.each(dataset.data, function(dataPoint, index) {
                     dataset.metaData.push(new this.PointClass());
                 }, this);
+
+                // Make sure each dataset is bound to an x and a y axis
+                if (!dataset.xAxisID) {
+                    dataset.xAxisID = this.options.scales.xAxes[0].id;
+                }
+
+                if (!dataset.yAxisID) {
+                    dataset.yAxisID = this.options.scales.yAxes[0].id;
+                }
             }, this);
 
             // Set defaults for lines
 
             // Set defaults for points
             this.eachElement(function(point, index, dataset, datasetIndex) {
+                var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
+
                 helpers.extend(point, {
-                    x: this.xScale.getPixelForValue(index),
+                    x: xScale.getPixelForValue(index),
                     y: this.chartArea.bottom,
                     _datasetIndex: datasetIndex,
                     _index: index,
 
             // Update the points
             this.eachElement(function(point, index, dataset, datasetIndex) {
+                var xScale = this.scales[this.data.datasets[datasetIndex].xAxisID];
+                var yScale = this.scales[this.data.datasets[datasetIndex].yAxisID];
+
                 helpers.extend(point, {
-                    x: this.xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x),
-                    y: this.yScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].y),
+                    x: xScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].x),
+                    y: yScale.getPixelForValue(this.data.datasets[datasetIndex].data[index].y),
                     value: this.data.datasets[datasetIndex].data[index].y,
                     label: this.data.datasets[datasetIndex].data[index].x,
                     datasetLabel: this.data.datasets[datasetIndex].label,
 
             this.render();
         },
-        buildScale: function(labels) {
+        buildScale: function() {
             var self = this;
 
-            var dataTotal = function() {
-                var values = [];
-                self.eachValue(function(value) {
-                    values.push(value);
-                });
+            var calculateXRange = function() {
+                this.min = null;
+                this.max = null;
+                
+                helpers.each(self.data.datasets, function(dataset) {
+                    // Only set the scale range for datasets that actually use this axis
+                    if (dataset.xAxisID === this.id) {
+                        helpers.each(dataset.data, function(value) {
+                            if (this.min === null) {
+                                this.min = value.x;
+                            } else if (value.x < this.min) {
+                                this.min = value.x;
+                            }
+                            
+                            if (this.max === null) {
+                                this.max = value.x;
+                            } else if (value.x > this.max) {
+                                this.max = value.x;
+                            }
+                        }, this);
+                    }
+                }, this);
+            };
 
-                return values;
+            var calculateYRange = function() {
+                this.min = null;
+                this.max = null;
+                
+                helpers.each(self.data.datasets, function(dataset) {
+                    if (dataset.yAxisID === this.id) {
+                        helpers.each(dataset.data, function(value) {
+                            if (this.min === null) {
+                                this.min = value.y;
+                            } else if (value.y < this.min) {
+                                this.min = value.y;
+                            }
+                            
+                            if (this.max === null) {
+                                this.max = value.y;
+                            } else if (value.y > this.max) {
+                                this.max = value.y;
+                            }
+                        }, this);
+                    }
+                }, this);
             };
 
-                       var XScaleClass = Chart.scales.getScaleConstructor("linear");
-                       var YScaleClass = Chart.scales.getScaleConstructor("linear");
-                       
-                       this.xScale = new XScaleClass({
-                               ctx: this.chart.ctx,
-                       });
-                       
-                       // Eventually this will be referenced from the user supplied config options.
-                       this.xScale.options = {
-                               scaleType: "dataset", // default options are 'dataset', 'linear'. 
-                               show: true,
-                               position: "bottom",
-                               horizontal: true,
-                               
-                               // grid line settings
-                               gridLines: {
-                                       show: true,
-                                       color: "rgba(0, 0, 0, 0.05)",
-                                       lineWidth: 1,
-                                       drawOnChartArea: true,
-                    zeroLineWidth: 1,
-                    zeroLineColor: "rgba(0,0,0,0.25)",
-                               },
-
-                               // scale numbers
-                               beginAtZero: false,
-                               integersOnly: false,
-                               override: null,
-
-                               // label settings
-                               labels: {
-                                       show: true,
-                                       template: "<%=value%>",
-                                       fontSize: 12,
-                                       fontStyle: "normal",
-                                       fontColor: "#666",
-                                       fontFamily: "Helvetica Neue",
-                               },
-                       };
-                       this.yScale = new YScaleClass({
-                               ctx: this.chart.ctx,
-                       });
-                       this.yScale.options = {
-                               scaleType: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
-                               show: true,
-                               position: "left",
-                               horizontal: false, 
-               
-                               // grid line settings
-                               gridLines: {
-                                       show: true,
-                                       color: "rgba(0, 0, 0, 0.05)",
-                                       lineWidth: 1,
-                                       drawOnChartArea: true,
-                    zeroLineWidth: 1,
-                    zeroLineColor: "rgba(0,0,0,0.25)",
-                               },
-
-                               // scale numbers
-                               beginAtZero: false,
-                               integersOnly: false,
-                               override: null,
-
-                               // label settings
-                               labels: {
-                                       show: true,
-                                       template: "<%=value%>",
-                                       fontSize: 12,
-                                       fontStyle: "normal",
-                                       fontColor: "#666",
-                                       fontFamily: "Helvetica Neue",
-                               },
-                       };
-                       
-                       this.xScale.calculateRange = function() {
-                               this.min = null;
-                               this.max = null;
-                               
-                               helpers.each(self.data.datasets, function(dataset) {
-                                       helpers.each(dataset.data, function(value) {
-                                               if (this.min === null) {
-                                                       this.min = value.x;
-                                               } else if (value.x < this.min) {
-                                                       this.min = value.x;
-                                               }
-                                               
-                                               if (this.max === null) {
-                                                       this.max = value.x;
-                                               } else if (value.x > this.max) {
-                                                       this.max = value.x;
-                                               }
-                                       }, this);
-                               }, this);
-                       };
-                       
-                       this.yScale.calculateRange = function() {
-                               this.min = null;
-                               this.max = null;
-                               
-                               helpers.each(self.data.datasets, function(dataset) {
-                                       helpers.each(dataset.data, function(value) {
-                                               if (this.min === null) {
-                                                       this.min = value.y;
-                                               } else if (value.y < this.min) {
-                                                       this.min = value.y;
-                                               }
-                                               
-                                               if (this.max === null) {
-                                                       this.max = value.y;
-                                               } else if (value.y > this.max) {
-                                                       this.max = value.y;
-                                               }
-                                       }, this);
-                               }, this);
-                       };
-                       
-                       // Register the axes with the scale service
-                       Chart.scaleService.registerChartScale(this, this.xScale);
-                       Chart.scaleService.registerChartScale(this, this.yScale);
+            // Map of scale ID to scale object so we can lookup later 
+            this.scales = {};
+
+            helpers.each(this.options.scales.xAxes, function(xAxisOptions) {
+                var ScaleClass = Chart.scales.getScaleConstructor(xAxisOptions.scaleType);
+                var scale = new ScaleClass({
+                    ctx: this.chart.ctx,
+                    options: xAxisOptions,
+                    calculateRange: calculateXRange,
+                    id: xAxisOptions.id,
+                });
+
+                this.scales[scale.id] = scale;
+                Chart.scaleService.registerChartScale(this, scale);
+            }, this);
+
+            helpers.each(this.options.scales.yAxes, function(yAxisOptions) {
+                var ScaleClass = Chart.scales.getScaleConstructor(yAxisOptions.scaleType);
+                var scale = new ScaleClass({
+                    ctx: this.chart.ctx,
+                    options: yAxisOptions,
+                    calculateRange: calculateYRange,
+                    id: yAxisOptions.id,
+                });
+
+                this.scales[scale.id] = scale;
+                Chart.scaleService.registerChartScale(this, scale);
+            }, this);
         },
         redraw: function() {