Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HiveStatistics/sources/HeuristicLab.Services.Hive.Statistics/3.3/Scripts/jqPlot/plugins/jqplot.logAxisRenderer.js @ 11222

Last change on this file since 11222 was 11222, checked in by mroscoe, 10 years ago
File size: 21.3 KB
Line 
1/**
2 * jqPlot
3 * Pure JavaScript plotting plugin using jQuery
4 *
5 * Version: 1.0.8
6 * Revision: 1250
7 *
8 * Copyright (c) 2009-2013 Chris Leonello
9 * jqPlot is currently available for use in all personal or commercial projects
10 * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL
11 * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can
12 * choose the license that best suits your project and use it accordingly.
13 *
14 * Although not required, the author would appreciate an email letting him
15 * know of any substantial use of jqPlot.  You can reach the author at:
16 * chris at jqplot dot com or see http://www.jqplot.com/info.php .
17 *
18 * If you are feeling kind and generous, consider supporting the project by
19 * making a donation at: http://www.jqplot.com/donate.php .
20 *
21 * sprintf functions contained in jqplot.sprintf.js by Ash Searle:
22 *
23 *     version 2007.04.27
24 *     author Ash Searle
25 *     http://hexmen.com/blog/2007/03/printf-sprintf/
26 *     http://hexmen.com/js/sprintf.js
27 *     The author (Ash Searle) has placed this code in the public domain:
28 *     "This code is unrestricted: you are free to use it however you like."
29 *
30 */
31(function($) {
32    /**
33    *  class: $.jqplot.LogAxisRenderer
34    *  A plugin for a jqPlot to render a logarithmic axis.
35    *
36    *  To use this renderer, include the plugin in your source
37    *  > <script type="text/javascript" language="javascript" src="plugins/jqplot.logAxisRenderer.js"></script>
38    * 
39    *  and supply the appropriate options to your plot
40    * 
41    *  > {axes:{xaxis:{renderer:$.jqplot.LogAxisRenderer}}}
42    **/
43    $.jqplot.LogAxisRenderer = function() {
44        $.jqplot.LinearAxisRenderer.call(this);
45        // prop: axisDefaults
46        // Default properties which will be applied directly to the series.
47        //
48        // Group: Properties
49        //
50        // Properties
51        //
52        // base - the logarithmic base, commonly 2, 10 or Math.E
53        // tickDistribution - Deprecated.  "power" distribution of ticks
54        // always used.  Option has no effect.
55        this.axisDefaults = {
56            base : 10,
57            tickDistribution :'power'
58        };
59    };
60   
61    $.jqplot.LogAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
62    $.jqplot.LogAxisRenderer.prototype.constructor = $.jqplot.LogAxisRenderer;
63   
64    $.jqplot.LogAxisRenderer.prototype.init = function(options) {
65        // prop: drawBaseline
66        // True to draw the axis baseline.
67        this.drawBaseline = true;
68        // prop: minorTicks
69        // Number of ticks to add between "major" ticks.
70        // Major ticks are ticks supplied by user or auto computed.
71        // Minor ticks cannot be created by user.
72        this.minorTicks = 'auto';
73        this._scalefact = 1.0;
74
75        $.extend(true, this, options);
76
77        this._autoFormatString = '%d';
78        this._overrideFormatString = false;
79
80        for (var d in this.renderer.axisDefaults) {
81            if (this[d] == null) {
82                this[d] = this.renderer.axisDefaults[d];
83            }
84        }
85
86        this.resetDataBounds();
87    };
88   
89    $.jqplot.LogAxisRenderer.prototype.createTicks = function(plot) {
90        // we're are operating on an axis here
91        var ticks = this._ticks;
92        var userTicks = this.ticks;
93        var name = this.name;
94        var db = this._dataBounds;
95        var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;
96        var interval;
97        var min, max;
98        var pos1, pos2;
99        var tt, i;
100
101        var threshold = 30;
102        // For some reason scalefactor is screwing up ticks.
103        this._scalefact =  (Math.max(dim, threshold+1) - threshold)/300;
104
105        // if we already have ticks, use them.
106        // ticks must be in order of increasing value.
107        if (userTicks.length) {
108            // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed
109            for (i=0; i<userTicks.length; i++){
110                var ut = userTicks[i];
111                var t = new this.tickRenderer(this.tickOptions);
112                if (ut.constructor == Array) {
113                    t.value = ut[0];
114                    t.label = ut[1];
115                    if (!this.showTicks) {
116                        t.showLabel = false;
117                        t.showMark = false;
118                    }
119                    else if (!this.showTickMarks) {
120                        t.showMark = false;
121                    }
122                    t.setTick(ut[0], this.name);
123                    this._ticks.push(t);
124                }
125
126                else if ($.isPlainObject(ut)) {
127                    $.extend(true, t, ut);
128                    t.axis = this.name;
129                    this._ticks.push(t);
130                }
131               
132                else {
133                    t.value = ut;
134                    if (!this.showTicks) {
135                        t.showLabel = false;
136                        t.showMark = false;
137                    }
138                    else if (!this.showTickMarks) {
139                        t.showMark = false;
140                    }
141                    t.setTick(ut, this.name);
142                    this._ticks.push(t);
143                }
144            }
145            this.numberTicks = userTicks.length;
146            this.min = this._ticks[0].value;
147            this.max = this._ticks[this.numberTicks-1].value;
148        }
149       
150        // we don't have any ticks yet, let's make some!
151        else if (this.min == null && this.max == null) {
152            min = db.min * (2 - this.padMin);
153            max = db.max * this.padMax;
154           
155            // if min and max are same, space them out a bit
156            if (min == max) {
157                var adj = 0.05;
158                min = min*(1-adj);
159                max = max*(1+adj);
160            }
161           
162            // perform some checks
163            if (this.min != null && this.min <= 0) {
164                throw new Error("Log axis minimum must be greater than 0");
165            }
166            if (this.max != null && this.max <= 0) {
167                throw new Error("Log axis maximum must be greater than 0");
168            }
169
170            function findCeil (val) {
171                var order = Math.pow(10, Math.floor(Math.log(val)/Math.LN10));
172                return Math.ceil(val/order) * order;
173            }
174
175            function findFloor(val) {
176                var order = Math.pow(10, Math.floor(Math.log(val)/Math.LN10));
177                return Math.floor(val/order) * order;
178            }
179
180            // var range = max - min;
181            var rmin, rmax;
182
183            // for power distribution, open up range to get a nice power of axis.renderer.base.
184            // power distribution won't respect the user's min/max settings.
185            rmin = Math.pow(this.base, Math.floor(Math.log(min)/Math.log(this.base)));
186            rmax = Math.pow(this.base, Math.ceil(Math.log(max)/Math.log(this.base)));
187
188            // // if min and max are same, space them out a bit
189            // if (rmin === rmax) {
190            //     var adj = 0.05;
191            //     rmin = rmin*(1-adj);
192            //     rmax = rmax*(1+adj);
193            // }
194
195            // Handle case where a data value was zero
196            if (rmin === 0) {
197              rmin = 1;
198            }
199
200            var order = Math.round(Math.log(rmin)/Math.LN10);
201
202            if (this.tickOptions == null || !this.tickOptions.formatString) {
203                this._overrideFormatString = true;
204            }
205
206            this.min = rmin;
207            this.max = rmax;
208            var range = this.max - this.min;           
209
210            var minorTicks = (this.minorTicks === 'auto') ? 0 : this.minorTicks;
211            var numberTicks;
212            if (this.numberTicks == null){
213                if (dim > 140) {
214                    numberTicks = Math.round(Math.log(this.max/this.min)/Math.log(this.base) + 1);
215                    if (numberTicks < 2) {
216                        numberTicks = 2;
217                    }
218                    if (minorTicks === 0) {
219                        var temp = dim/(numberTicks - 1);
220                        if (temp < 100) {
221                            minorTicks = 0;
222                        }
223                        else if (temp < 190) {
224                            minorTicks = 1;
225                        }
226                        else if (temp < 250) {
227                            minorTicks = 3;
228                        }
229                        else if (temp < 600) {
230                            minorTicks = 4;
231                        }
232                        else {
233                            minorTicks = 9;
234                        }
235                    }
236                }
237                else {
238                    numberTicks = 2;
239                    if (minorTicks === 0) {
240                        minorTicks = 1;
241                    }
242                    minorTicks = 0;
243                }
244            }
245            else {
246                numberTicks = this.numberTicks;
247            }
248
249            if (order >= 0 && minorTicks !== 3) {
250                this._autoFormatString = '%d';
251            }
252            // Adjust format string for case with 3 ticks where we'll have like 1, 2.5, 5, 7.5, 10
253            else if (order <= 0 && minorTicks === 3) {
254                var temp = -(order - 1);
255                this._autoFormatString = '%.'+ Math.abs(order-1) + 'f';
256            }
257
258            // Adjust format string for values less than 1.
259            else if (order < 0) {
260                var temp = -order;
261                this._autoFormatString = '%.'+ Math.abs(order) + 'f';
262            }
263
264            else {
265                this._autoFormatString = '%d';
266            }
267
268            var to, t, val, tt1, spread, interval;
269            for (var i=0; i<numberTicks; i++){
270                tt = Math.pow(this.base, i - numberTicks + 1) * this.max;
271
272                t = new this.tickRenderer(this.tickOptions);
273           
274                if (this._overrideFormatString) {
275                    t.formatString = this._autoFormatString;
276                }
277               
278                if (!this.showTicks) {
279                    t.showLabel = false;
280                    t.showMark = false;
281                }
282                else if (!this.showTickMarks) {
283                    t.showMark = false;
284                }
285                t.setTick(tt, this.name);
286                this._ticks.push(t);
287
288                if (minorTicks && i<numberTicks-1) {
289                    tt1 = Math.pow(this.base, i - numberTicks + 2) * this.max;
290                    spread = tt1 - tt;
291                    interval = tt1 / (minorTicks+1);
292                    for (var j=minorTicks-1; j>=0; j--) {
293                        val = tt1-interval*(j+1);
294                        t = new this.tickRenderer(this.tickOptions);
295           
296                        if (this._overrideFormatString && this._autoFormatString != '') {
297                            t.formatString = this._autoFormatString;
298                        }
299                        if (!this.showTicks) {
300                            t.showLabel = false;
301                            t.showMark = false;
302                        }
303                        else if (!this.showTickMarks) {
304                            t.showMark = false;
305                        }
306                        t.setTick(val, this.name);
307                        this._ticks.push(t);
308                    }
309                }       
310            }     
311        }
312
313        // min and max are set as would be the case with zooming
314        else if (this.min != null && this.max != null) {
315            var opts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});
316            var nt, ti;
317            // don't have an interval yet, pick one that gives the most
318            // "round" ticks we can get.
319            if (this.numberTicks == null && this.tickInterval == null) {
320                // var threshold = 30;
321                var tdim = Math.max(dim, threshold+1);
322                var nttarget =  Math.ceil((tdim-threshold)/35 + 1);
323
324                var ret = $.jqplot.LinearTickGenerator.bestConstrainedInterval(this.min, this.max, nttarget);
325
326                this._autoFormatString = ret[3];
327                nt = ret[2];
328                ti = ret[4];
329
330                for (var i=0; i<nt; i++) {
331                    opts.value = this.min + i * ti;
332                    t = new this.tickRenderer(opts);
333                   
334                    if (this._overrideFormatString && this._autoFormatString != '') {
335                        t.formatString = this._autoFormatString;
336                    }
337                    if (!this.showTicks) {
338                        t.showLabel = false;
339                        t.showMark = false;
340                    }
341                    else if (!this.showTickMarks) {
342                        t.showMark = false;
343                    }
344                    this._ticks.push(t);
345                }
346            }
347
348            // for loose zoom, number ticks and interval are also set.
349            else if (this.numberTicks != null && this.tickInterval != null) {
350                nt = this.numberTicks;
351                for (var i=0; i<nt; i++) {
352                    opts.value = this.min + i * this.tickInterval;
353                    t = new this.tickRenderer(opts);
354                   
355                    if (this._overrideFormatString && this._autoFormatString != '') {
356                        t.formatString = this._autoFormatString;
357                    }
358                    if (!this.showTicks) {
359                        t.showLabel = false;
360                        t.showMark = false;
361                    }
362                    else if (!this.showTickMarks) {
363                        t.showMark = false;
364                    }
365                    this._ticks.push(t);
366                }
367            }
368        }
369    };
370   
371    $.jqplot.LogAxisRenderer.prototype.pack = function(pos, offsets) {
372        var lb = parseInt(this.base, 10);
373        var ticks = this._ticks;
374        var trans = function (v) { return Math.log(v)/Math.log(lb); };
375        var invtrans = function (v) { return Math.pow(Math.E, (Math.log(lb)*v)); };
376        var max = trans(this.max);
377        var min = trans(this.min);
378        var offmax = offsets.max;
379        var offmin = offsets.min;
380        var lshow = (this._label == null) ? false : this._label.show;
381       
382        for (var p in pos) {
383            this._elem.css(p, pos[p]);
384        }
385       
386        this._offsets = offsets;
387        // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left.
388        var pixellength = offmax - offmin;
389        var unitlength = max - min;
390       
391        // point to unit and unit to point conversions references to Plot DOM element top left corner.
392        this.p2u = function(p){
393            return invtrans((p - offmin) * unitlength / pixellength + min);
394        };
395       
396        this.u2p = function(u){
397            return (trans(u) - min) * pixellength / unitlength + offmin;
398        };
399       
400        if (this.name == 'xaxis' || this.name == 'x2axis'){
401            this.series_u2p = function(u){
402                return (trans(u) - min) * pixellength / unitlength;
403            };
404            this.series_p2u = function(p){
405                return invtrans(p * unitlength / pixellength + min);
406            };
407        }
408        // yaxis is max at top of canvas.
409        else {
410            this.series_u2p = function(u){
411                return (trans(u) - max) * pixellength / unitlength;
412            };
413            this.series_p2u = function(p){
414                return invtrans(p * unitlength / pixellength + max);
415            };
416        }
417       
418        if (this.show) {
419            if (this.name == 'xaxis' || this.name == 'x2axis') {
420                for (var i=0; i<ticks.length; i++) {
421                    var t = ticks[i];
422                    if (t.show && t.showLabel) {
423                        var shim;
424                       
425                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {
426                            switch (t.labelPosition) {
427                                case 'auto':
428                                    // position at end
429                                    if (t.angle < 0) {
430                                        shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;
431                                    }
432                                    // position at start
433                                    else {
434                                        shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;
435                                    }
436                                    break;
437                                case 'end':
438                                    shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;
439                                    break;
440                                case 'start':
441                                    shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;
442                                    break;
443                                case 'middle':
444                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;
445                                    break;
446                                default:
447                                    shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;
448                                    break;
449                            }
450                        }
451                        else {
452                            shim = -t.getWidth()/2;
453                        }
454                        // var shim = t.getWidth()/2;
455                        var val = this.u2p(t.value) + shim + 'px';
456                        t._elem.css('left', val);
457                        t.pack();
458                    }
459                }
460                if (lshow) {
461                    var w = this._label._elem.outerWidth(true);
462                    this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px');
463                    if (this.name == 'xaxis') {
464                        this._label._elem.css('bottom', '0px');
465                    }
466                    else {
467                        this._label._elem.css('top', '0px');
468                    }
469                    this._label.pack();
470                }
471            }
472            else {
473                for (var i=0; i<ticks.length; i++) {
474                    var t = ticks[i];
475                    if (t.show && t.showLabel) {                       
476                        var shim;
477                        if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) {
478                            switch (t.labelPosition) {
479                                case 'auto':
480                                    // position at end
481                                case 'end':
482                                    if (t.angle < 0) {
483                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;
484                                    }
485                                    else {
486                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;
487                                    }
488                                    break;
489                                case 'start':
490                                    if (t.angle > 0) {
491                                        shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2;
492                                    }
493                                    else {
494                                        shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2;
495                                    }
496                                    break;
497                                case 'middle':
498                                    // if (t.angle > 0) {
499                                    //     shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2;
500                                    // }
501                                    // else {
502                                    //     shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2;
503                                    // }
504                                    shim = -t.getHeight()/2;
505                                    break;
506                                default:
507                                    shim = -t.getHeight()/2;
508                                    break;
509                            }
510                        }
511                        else {
512                            shim = -t.getHeight()/2;
513                        }
514                       
515                        var val = this.u2p(t.value) + shim + 'px';
516                        t._elem.css('top', val);
517                        t.pack();
518                    }
519                }
520                if (lshow) {
521                    var h = this._label._elem.outerHeight(true);
522                    this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px');
523                    if (this.name == 'yaxis') {
524                        this._label._elem.css('left', '0px');
525                    }
526                    else {
527                        this._label._elem.css('right', '0px');
528                    }   
529                    this._label.pack();
530                }
531            }
532        }       
533    };
534})(jQuery);
Note: See TracBrowser for help on using the repository browser.