Commits

Chris Leonello  committed a6626c2

Fixed issue #50, added option to turn off sorting.
Fixed issue #31. Implemented a better autoscaling algorithm and added an autoscale option which is on by default. Didn't address dates.

  • Participants
  • Parent commits 0f68eab

Comments (0)

Files changed (2)

File src/jqplot.core.js

         // prop: max
         // maximum value of the axis (in data units, not pixels).
         this.max=null;
+        // prop: autoscale
+        // Autoscale the axis min and max values to provide sensible tick spacing.
+        // Overrides the pad, padMin and padMax values.  Set to false
+        // to use the pad, padMin and padMax options.  If both min and max
+        // are specified, will not autoscale.
+        this.autoscale = true;
         // prop: pad
         // Padding to extend the range above and below the data bounds.
         // The data range is multiplied by this factor to determine minimum and maximum axis bounds.
+        // A value of 0 will be interpreted to mean no padding, and pad will be set to 1.0.
         this.pad = 1.2;
         // prop: padMax
         // Padding to extend the range above data bounds.
         // The top of the data range is multiplied by this factor to determine maximum axis bounds.
+        // A value of 0 will be interpreted to mean no padding, and padMax will be set to 1.0.
         this.padMax = null;
         // prop: padMin
         // Padding to extend the range below data bounds.
         // The bottom of the data range is multiplied by this factor to determine minimum axis bounds.
+        // A value of 0 will be interpreted to mean no padding, and padMin will be set to 1.0.
         this.padMin = null;
         // prop: ticks
         // 1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis.
         if (this.padMin == null) {
             this.padMin = (this.pad-1)/2 + 1;
         }
+        if (this.min != null || this.max != null) {
+            this.autoscale = false;
+        }
         this.renderer.init.call(this, this.rendererOptions);
         
     };
         // are more series than colors, colors will be reused starting at the
         // beginning.  For pie charts, this specifies the colors of the slices.
         this.seriesColors = [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc"];
+        // prop: sortData
+        // false to not sort the data passed in by the user.
+        // Many bar, stakced and other graphs as well as many plugins depend on
+        // having sorted data.
+        this.sortData = true;
         var seriesColorsIndex = 0;
         // prop textColor
         // css spec for the css color attribute.  Default for the entire plot.
                 this.axes[name].init();
             }
             
-            sortData(this.series);
-            
+            if (this.sortData) {
+                sortData(this.series);
+            }
             this.grid.init();
             this.grid._axes = this.axes;
             
             for (var i=0; i<series.length; i++) {
                 d = series[i].data;
                 if (series[i]._stackAxis == 'x') {
-                    // console.log('STACK AXIS: %s', series[i]._stackAxis);
                     d.sort(function(a,b){
                         var ret = a[1] - b[1];
                         if (ret) {
                     });
                 }
                 else {
-                    // console.log('STACK AXIS: %s', series[i]._stackAxis);
                     d.sort(function(a,b){
                         var ret = a[0] - b[0];
                         if (ret) {
             this.options = $.extend(true, {}, this.defaults, options);
             this.stackSeries = this.options.stackSeries;
             this._gridPadding = this.options.gridPadding;
+            this.sortData = (this.options.sortData != null) ? this.options.sortData : this.sortData;
             for (var n in this.axes) {
                 var axis = this.axes[n];
                 $.extend(true, axis, this.options.axesDefaults, this.options.axes[n]);

File src/jqplot.linearAxisRenderer.js

             }
             
             // if min, max and number of ticks specified, user can't specify interval.
-            if (this.min != null && this.max != null && this.numberTicks != null) {
+            if (!this.autoscale && this.min != null && this.max != null && this.numberTicks != null) {
                 this.tickInterval = null;
             }
             
 
             var range = max - min;
             var rmin, rmax;
-        
-            rmin = (this.min != null) ? this.min : min - range*(this.padMin - 1);
-            rmax = (this.max != null) ? this.max : max + range*(this.padMax - 1);
-            this.min = rmin;
-            this.max = rmax;
-            range = this.max - this.min;
+            var temp;
+            
+            // autoscale.  Can't autoscale if min or max is supplied.
+            // Will use numberTicks and tickInterval if supplied.
+            if (this.autoscale && this.min == null && this.max == null) {
+                var rrange, ti, margin;
     
-            if (this.numberTicks == null){
-                // if tickInterval is specified by user, we will ignore computed maximum.
-                // max will be equal or greater to fit even # of ticks.
-                if (this.tickInterval != null) {
-                    this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval)+1;
-                    this.max = this.min + this.tickInterval*(this.numberTicks-1);
+                if (this.numberTicks == null){
+                    if (dim > 100) {
+                        this.numberTicks = parseInt(3+(dim-100)/75, 10);
+                    }
+                    else {
+                        this.numberTicks = 2;
+                    }
                 }
-                else if (dim > 100) {
-                    this.numberTicks = parseInt(3+(dim-100)/75, 10);
+                
+                if (this.tickInterval == null) {
+                    // get a tick interval
+                    ti = range/(this.numberTicks - 1);
+                
+                    if (ti < 1) {
+                        temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10)));
+                    }
+                    else {
+                        temp = 1;
+                    }
+                    this.tickInterval = Math.ceil(ti*temp*this.pad)/temp;
                 }
-                else {
-                    this.numberTicks = 2;
+                
+                // try to compute a nicer, more even tick interval
+                // temp = Math.pow(10, Math.floor(Math.log(ti)/Math.LN10));
+                // this.tickInterval = Math.ceil(ti/temp) * temp;
+                rrange = this.tickInterval * (this.numberTicks - 1);
+                margin = (rrange - range)/2;
+                
+                if (this.min == null) {
+                    this.min = Math.floor(temp*(min-margin))/temp;
+                }
+                if (this.max == null) {
+                    this.max = this.min + rrange;
+                }
+                    
+                console.log('min: %s, max: %s, newmin: %s, newmax: %s, interval: %s, newinterval: %s, margin: %s, number: %s', min, max, this.min, this.max, ti, this.tickInterval, margin, this.numberTicks);
+            }
+            
+            else {
+                rmin = (this.min != null) ? this.min : min - range*(this.padMin - 1);
+                rmax = (this.max != null) ? this.max : max + range*(this.padMax - 1);
+                this.min = rmin;
+                this.max = rmax;
+                range = this.max - this.min;
+    
+                if (this.numberTicks == null){
+                    // if tickInterval is specified by user, we will ignore computed maximum.
+                    // max will be equal or greater to fit even # of ticks.
+                    if (this.tickInterval != null) {
+                        this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval)+1;
+                        this.max = this.min + this.tickInterval*(this.numberTicks-1);
+                    }
+                    else if (dim > 100) {
+                        this.numberTicks = parseInt(3+(dim-100)/75, 10);
+                    }
+                    else {
+                        this.numberTicks = 2;
+                    }
+                }
+            
+                if (this.tickInterval == null) {
+                	this.tickInterval = range / (this.numberTicks-1);
                 }
             }
-            
-            if (this.tickInterval == null) {
-            	this.tickInterval = range / (this.numberTicks-1);
-            }
+
             for (var i=0; i<this.numberTicks; i++){
                 tt = this.min + i * this.tickInterval;
                 var t = new this.tickRenderer(this.tickOptions);