switched to 3.9.7 defaults
[psensor-pkg-ubuntu.git] / www / jqplot.dateAxisRenderer.js
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.DateAxisRenderer
34      * A plugin for a jqPlot to render an axis as a series of date values.
35      * This renderer has no options beyond those supplied by the <Axis> class.
36      * It supplies its own tick formatter, so the tickOptions.formatter option
37      * should not be overridden.
38      * 
39      * Thanks to Ken Synder for his enhanced Date instance methods which are
40      * included with this code <http://kendsnyder.com/sandbox/date/>.
41      * 
42      * To use this renderer, include the plugin in your source
43      * > <script type="text/javascript" language="javascript" src="plugins/jqplot.dateAxisRenderer.js"></script>
44      * 
45      * and supply the appropriate options to your plot
46      * 
47      * > {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}}
48      * 
49      * Dates can be passed into the axis in almost any recognizable value and 
50      * will be parsed.  They will be rendered on the axis in the format
51      * specified by tickOptions.formatString.  e.g. tickOptions.formatString = '%Y-%m-%d'.
52      * 
53      * Accecptable format codes 
54      * are:
55      * 
56      * > Code    Result                  Description
57      * >             == Years ==
58      * > %Y      2008                Four-digit year
59      * > %y      08                  Two-digit year
60      * >             == Months ==
61      * > %m      09                  Two-digit month
62      * > %#m     9                   One or two-digit month
63      * > %B      September           Full month name
64      * > %b      Sep                 Abbreviated month name
65      * >             == Days ==
66      * > %d      05                  Two-digit day of month
67      * > %#d     5                   One or two-digit day of month
68      * > %e      5                   One or two-digit day of month
69      * > %A      Sunday              Full name of the day of the week
70      * > %a      Sun                 Abbreviated name of the day of the week
71      * > %w      0                   Number of the day of the week (0 = Sunday, 6 = Saturday)
72      * > %o      th                  The ordinal suffix string following the day of the month
73      * >             == Hours ==
74      * > %H      23                  Hours in 24-hour format (two digits)
75      * > %#H     3                   Hours in 24-hour integer format (one or two digits)
76      * > %I      11                  Hours in 12-hour format (two digits)
77      * > %#I     3                   Hours in 12-hour integer format (one or two digits)
78      * > %p      PM                  AM or PM
79      * >             == Minutes ==
80      * > %M      09                  Minutes (two digits)
81      * > %#M     9                   Minutes (one or two digits)
82      * >             == Seconds ==
83      * > %S      02                  Seconds (two digits)
84      * > %#S     2                   Seconds (one or two digits)
85      * > %s      1206567625723       Unix timestamp (Seconds past 1970-01-01 00:00:00)
86      * >             == Milliseconds ==
87      * > %N      008                 Milliseconds (three digits)
88      * > %#N     8                   Milliseconds (one to three digits)
89      * >             == Timezone ==
90      * > %O      360                 difference in minutes between local time and GMT
91      * > %Z      Mountain Standard Time  Name of timezone as reported by browser
92      * > %G      -06:00              Hours and minutes between GMT
93      * >             == Shortcuts ==
94      * > %F      2008-03-26          %Y-%m-%d
95      * > %T      05:06:30            %H:%M:%S
96      * > %X      05:06:30            %H:%M:%S
97      * > %x      03/26/08            %m/%d/%y
98      * > %D      03/26/08            %m/%d/%y
99      * > %#c     Wed Mar 26 15:31:00 2008  %a %b %e %H:%M:%S %Y
100      * > %v      3-Sep-2008          %e-%b-%Y
101      * > %R      15:31               %H:%M
102      * > %r      3:31:00 PM          %I:%M:%S %p
103      * >             == Characters ==
104      * > %n      \n                  Newline
105      * > %t      \t                  Tab
106      * > %%      %                   Percent Symbol 
107      */
108     $.jqplot.DateAxisRenderer = function() {
109         $.jqplot.LinearAxisRenderer.call(this);
110         this.date = new $.jsDate();
111     };
112
113     var second = 1000;
114     var minute = 60 * second;
115     var hour = 60 * minute;
116     var day = 24 * hour;
117     var week = 7 * day;
118
119     // these are less definitive
120     var month = 30.4368499 * day;
121     var year = 365.242199 * day;
122
123     var daysInMonths = [31,28,31,30,31,30,31,30,31,30,31,30];
124     // array of consistent nice intervals.  Longer intervals
125     // will depend on days in month, days in year, etc.
126     var niceFormatStrings = ['%M:%S.%#N', '%M:%S.%#N', '%M:%S.%#N', '%M:%S', '%M:%S', '%M:%S', '%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%a %H:%M', '%a %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%v', '%v', '%v', '%v', '%v', '%v', '%v'];
127     var niceIntervals = [0.1*second, 0.2*second, 0.5*second, second, 2*second, 5*second, 10*second, 15*second, 30*second, minute, 2*minute, 5*minute, 10*minute, 15*minute, 30*minute, hour, 2*hour, 4*hour, 6*hour, 8*hour, 12*hour, day, 2*day, 3*day, 4*day, 5*day, week, 2*week];
128
129     var niceMonthlyIntervals = [];
130
131     function bestDateInterval(min, max, titarget) {
132         // iterate through niceIntervals to find one closest to titarget
133         var badness = Number.MAX_VALUE;
134         var temp, bestTi, bestfmt;
135         for (var i=0, l=niceIntervals.length; i < l; i++) {
136             temp = Math.abs(titarget - niceIntervals[i]);
137             if (temp < badness) {
138                 badness = temp;
139                 bestTi = niceIntervals[i];
140                 bestfmt = niceFormatStrings[i];
141             }
142         }
143
144         return [bestTi, bestfmt];
145     }
146     
147     $.jqplot.DateAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
148     $.jqplot.DateAxisRenderer.prototype.constructor = $.jqplot.DateAxisRenderer;
149     
150     $.jqplot.DateTickFormatter = function(format, val) {
151         if (!format) {
152             format = '%Y/%m/%d';
153         }
154         return $.jsDate.strftime(val, format);
155     };
156     
157     $.jqplot.DateAxisRenderer.prototype.init = function(options){
158         // prop: tickRenderer
159         // A class of a rendering engine for creating the ticks labels displayed on the plot, 
160         // See <$.jqplot.AxisTickRenderer>.
161         // this.tickRenderer = $.jqplot.AxisTickRenderer;
162         // this.labelRenderer = $.jqplot.AxisLabelRenderer;
163         this.tickOptions.formatter = $.jqplot.DateTickFormatter;
164         // prop: tickInset
165         // Controls the amount to inset the first and last ticks from 
166         // the edges of the grid, in multiples of the tick interval.
167         // 0 is no inset, 0.5 is one half a tick interval, 1 is a full
168         // tick interval, etc.
169         this.tickInset = 0;
170         // prop: drawBaseline
171         // True to draw the axis baseline.
172         this.drawBaseline = true;
173         // prop: baselineWidth
174         // width of the baseline in pixels.
175         this.baselineWidth = null;
176         // prop: baselineColor
177         // CSS color spec for the baseline.
178         this.baselineColor = null;
179         this.daTickInterval = null;
180         this._daTickInterval = null;
181         
182         $.extend(true, this, options);
183         
184         var db = this._dataBounds,
185             stats, 
186             sum,
187             s,
188             d,
189             pd,
190             sd,
191             intv;
192         
193         // Go through all the series attached to this axis and find
194         // the min/max bounds for this axis.
195         for (var i=0; i<this._series.length; i++) {
196             stats = {intervals:[], frequencies:{}, sortedIntervals:[], min:null, max:null, mean:null};
197             sum = 0;
198             s = this._series[i];
199             d = s.data;
200             pd = s._plotData;
201             sd = s._stackData;
202             intv = 0;
203             
204             for (var j=0; j<d.length; j++) { 
205                 if (this.name == 'xaxis' || this.name == 'x2axis') {
206                     d[j][0] = new $.jsDate(d[j][0]).getTime();
207                     pd[j][0] = new $.jsDate(d[j][0]).getTime();
208                     sd[j][0] = new $.jsDate(d[j][0]).getTime();
209                     if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) {
210                         db.min = d[j][0];
211                     }
212                     if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) {
213                         db.max = d[j][0];
214                     }
215                     if (j>0) {
216                         intv = Math.abs(d[j][0] - d[j-1][0]);
217                         stats.intervals.push(intv);
218                         if (stats.frequencies.hasOwnProperty(intv)) {
219                             stats.frequencies[intv] += 1;
220                         }
221                         else {
222                             stats.frequencies[intv] = 1;
223                         }
224                     }
225                     sum += intv;
226                     
227                 }              
228                 else {
229                     d[j][1] = new $.jsDate(d[j][1]).getTime();
230                     pd[j][1] = new $.jsDate(d[j][1]).getTime();
231                     sd[j][1] = new $.jsDate(d[j][1]).getTime();
232                     if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) {
233                         db.min = d[j][1];
234                     }
235                     if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) {
236                         db.max = d[j][1];
237                     }
238                     if (j>0) {
239                         intv = Math.abs(d[j][1] - d[j-1][1]);
240                         stats.intervals.push(intv);
241                         if (stats.frequencies.hasOwnProperty(intv)) {
242                             stats.frequencies[intv] += 1;
243                         }
244                         else {
245                             stats.frequencies[intv] = 1;
246                         }
247                     }
248                 }
249                 sum += intv;              
250             }
251
252             if (s.renderer.bands) {
253                 if (s.renderer.bands.hiData.length) {
254                     var bd = s.renderer.bands.hiData;
255                     for (var j=0, l=bd.length; j < l; j++) {
256                         if (this.name === 'xaxis' || this.name === 'x2axis') {
257                             bd[j][0] = new $.jsDate(bd[j][0]).getTime();
258                             if ((bd[j][0] != null && bd[j][0] > db.max) || db.max == null) {
259                                 db.max = bd[j][0];
260                             }                        
261                         }              
262                         else {
263                             bd[j][1] = new $.jsDate(bd[j][1]).getTime();
264                             if ((bd[j][1] != null && bd[j][1] > db.max) || db.max == null) {
265                                 db.max = bd[j][1];
266                             }
267                         }
268                     }
269                 }
270                 if (s.renderer.bands.lowData.length) {
271                     var bd = s.renderer.bands.lowData;
272                     for (var j=0, l=bd.length; j < l; j++) {
273                         if (this.name === 'xaxis' || this.name === 'x2axis') {
274                             bd[j][0] = new $.jsDate(bd[j][0]).getTime();
275                             if ((bd[j][0] != null && bd[j][0] < db.min) || db.min == null) {
276                                 db.min = bd[j][0];
277                             }                       
278                         }              
279                         else {
280                             bd[j][1] = new $.jsDate(bd[j][1]).getTime();
281                             if ((bd[j][1] != null && bd[j][1] < db.min) || db.min == null) {
282                                 db.min = bd[j][1];
283                             }
284                         }
285                     }
286                 }
287             }
288             
289             var tempf = 0,
290                 tempn=0;
291             for (var n in stats.frequencies) {
292                 stats.sortedIntervals.push({interval:n, frequency:stats.frequencies[n]});
293             }
294             stats.sortedIntervals.sort(function(a, b){
295                 return b.frequency - a.frequency;
296             });
297             
298             stats.min = $.jqplot.arrayMin(stats.intervals);
299             stats.max = $.jqplot.arrayMax(stats.intervals);
300             stats.mean = sum/d.length;
301             this._intervalStats.push(stats);
302             stats = sum = s = d = pd = sd = null;
303         }
304         db = null;
305         
306     };
307     
308     // called with scope of an axis
309     $.jqplot.DateAxisRenderer.prototype.reset = function() {
310         this.min = this._options.min;
311         this.max = this._options.max;
312         this.tickInterval = this._options.tickInterval;
313         this.numberTicks = this._options.numberTicks;
314         this._autoFormatString = '';
315         if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) {
316             this.tickOptions.formatString = '';
317         }
318         this.daTickInterval = this._daTickInterval;
319         // this._ticks = this.__ticks;
320     };
321     
322     $.jqplot.DateAxisRenderer.prototype.createTicks = function(plot) {
323         // we're are operating on an axis here
324         var ticks = this._ticks;
325         var userTicks = this.ticks;
326         var name = this.name;
327         // databounds were set on axis initialization.
328         var db = this._dataBounds;
329         var iv = this._intervalStats;
330         var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height;
331         var interval;
332         var min, max;
333         var pos1, pos2;
334         var tt, i;
335         var threshold = 30;
336         var insetMult = 1;
337         var daTickInterval = null;
338         
339         // if user specified a tick interval, convert to usable.
340         if (this.tickInterval != null)
341         {
342             // if interval is a number or can be converted to one, use it.
343             // Assume it is in SECONDS!!!
344             if (Number(this.tickInterval)) {
345                 daTickInterval = [Number(this.tickInterval), 'seconds'];
346             }
347             // else, parse out something we can build from.
348             else if (typeof this.tickInterval == "string") {
349                 var parts = this.tickInterval.split(' ');
350                 if (parts.length == 1) {
351                     daTickInterval = [1, parts[0]];
352                 }
353                 else if (parts.length == 2) {
354                     daTickInterval = [parts[0], parts[1]];
355                 }
356             }
357         }
358
359         var tickInterval = this.tickInterval;
360         
361         // if we already have ticks, use them.
362         // ticks must be in order of increasing value.
363         
364         min = new $.jsDate((this.min != null) ? this.min : db.min).getTime();
365         max = new $.jsDate((this.max != null) ? this.max : db.max).getTime();
366
367         // see if we're zooming.  if we are, don't use the min and max we're given,
368         // but compute some nice ones.  They will be reset later.
369
370         var cursor = plot.plugins.cursor;
371
372         if (cursor && cursor._zoom && cursor._zoom.zooming) {
373             this.min = null;
374             this.max = null;
375         }
376
377         var range = max - min;
378
379         if (this.tickOptions == null || !this.tickOptions.formatString) {
380             this._overrideFormatString = true;
381         }
382         
383         if (userTicks.length) {
384             // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed
385             for (i=0; i<userTicks.length; i++){
386                 var ut = userTicks[i];
387                 var t = new this.tickRenderer(this.tickOptions);
388                 if (ut.constructor == Array) {
389                     t.value = new $.jsDate(ut[0]).getTime();
390                     t.label = ut[1];
391                     if (!this.showTicks) {
392                         t.showLabel = false;
393                         t.showMark = false;
394                     }
395                     else if (!this.showTickMarks) {
396                         t.showMark = false;
397                     }
398                     t.setTick(t.value, this.name);
399                     this._ticks.push(t);
400                 }
401                 
402                 else {
403                     t.value = new $.jsDate(ut).getTime();
404                     if (!this.showTicks) {
405                         t.showLabel = false;
406                         t.showMark = false;
407                     }
408                     else if (!this.showTickMarks) {
409                         t.showMark = false;
410                     }
411                     t.setTick(t.value, this.name);
412                     this._ticks.push(t);
413                 }
414             }
415             this.numberTicks = userTicks.length;
416             this.min = this._ticks[0].value;
417             this.max = this._ticks[this.numberTicks-1].value;
418             this.daTickInterval = [(this.max - this.min) / (this.numberTicks - 1)/1000, 'seconds'];
419         }
420
421         ////////
422         // We don't have any ticks yet, let's make some!
423         ////////
424
425         // special case when there is only one point, make three tick marks to center the point
426         else if (this.min == null && this.max == null && db.min == db.max)
427         {
428              var onePointOpts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});
429              var delta = 300000;
430              this.min = db.min - delta;
431              this.max = db.max + delta;
432              this.numberTicks = 3;
433
434              for(var i=this.min;i<=this.max;i+= delta)
435              {
436                  onePointOpts.value = i;
437
438                  var t = new this.tickRenderer(onePointOpts);
439
440                  if (this._overrideFormatString && this._autoFormatString != '') {
441                     t.formatString = this._autoFormatString;
442                  }
443
444                  t.showLabel = false;
445                  t.showMark = false;
446
447                  this._ticks.push(t);
448              }
449
450              if(this.showTicks) {
451                  this._ticks[1].showLabel = true;
452              }
453              if(this.showTickMarks) {
454                  this._ticks[1].showTickMarks = true;
455              }                   
456         }
457         // if user specified min and max are null, we set those to make best ticks.
458         else if (this.min == null && this.max == null) {
459
460             var opts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null});
461
462             // want to find a nice interval 
463             var nttarget,
464                 titarget;
465
466             // if no tickInterval or numberTicks options specified,  make a good guess.
467             if (!this.tickInterval && !this.numberTicks) {
468                 var tdim = Math.max(dim, threshold+1);
469                 // how many ticks to put on the axis?
470                 // date labels tend to be long.  If ticks not rotated,
471                 // don't use too many and have a high spacing factor.
472                 // If we are rotating ticks, use a lower factor.
473                 var spacingFactor = 115;
474                 if (this.tickRenderer === $.jqplot.CanvasAxisTickRenderer && this.tickOptions.angle) {
475                     spacingFactor = 115 - 40 * Math.abs(Math.sin(this.tickOptions.angle/180*Math.PI));
476                 }
477
478                 nttarget =  Math.ceil((tdim-threshold)/spacingFactor + 1);
479                 titarget = (max - min) / (nttarget - 1);
480             }
481
482             // If tickInterval is specified, we'll try to honor it.
483             // Not guaranteed to get this interval, but we'll get as close as
484             // we can.
485             // tickInterval will be used before numberTicks, that is if
486             // both are specified, numberTicks will be ignored.
487             else if (this.tickInterval) {
488                 titarget = new $.jsDate(0).add(daTickInterval[0], daTickInterval[1]).getTime();
489             }
490
491             // if numberTicks specified, try to honor it.
492             // Not guaranteed, but will try to get close.
493             else if (this.numberTicks) {
494                 nttarget = this.numberTicks;
495                 titarget = (max - min) / (nttarget - 1);
496             }
497
498             // If we can use an interval of 2 weeks or less, pick best one
499             if (titarget <= 19*day) {
500                 var ret = bestDateInterval(min, max, titarget);
501                 var tempti = ret[0];
502                 this._autoFormatString = ret[1];
503
504                 min = new $.jsDate(min);
505                 min = Math.floor((min.getTime() - min.getUtcOffset())/tempti) * tempti + min.getUtcOffset();
506
507                 nttarget = Math.ceil((max - min) / tempti) + 1;
508                 this.min = min;
509                 this.max = min + (nttarget - 1) * tempti;
510
511                 // if max is less than max, add an interval
512                 if (this.max < max) {
513                     this.max += tempti;
514                     nttarget += 1;
515                 }
516                 this.tickInterval = tempti;
517                 this.numberTicks = nttarget;
518
519                 for (var i=0; i<nttarget; i++) {
520                     opts.value = this.min + i * tempti;
521                     t = new this.tickRenderer(opts);
522                     
523                     if (this._overrideFormatString && this._autoFormatString != '') {
524                         t.formatString = this._autoFormatString;
525                     }
526                     if (!this.showTicks) {
527                         t.showLabel = false;
528                         t.showMark = false;
529                     }
530                     else if (!this.showTickMarks) {
531                         t.showMark = false;
532                     }
533                     this._ticks.push(t);
534                 }
535
536                 insetMult = this.tickInterval;
537             }
538
539             // should we use a monthly interval?
540             else if (titarget <= 9 * month) {
541
542                 this._autoFormatString = '%v';
543
544                 // how many months in an interval?
545                 var intv = Math.round(titarget/month);
546                 if (intv < 1) {
547                     intv = 1;
548                 }
549                 else if (intv > 6) {
550                     intv = 6;
551                 }
552
553                 // figure out the starting month and ending month.
554                 var mstart = new $.jsDate(min).setDate(1).setHours(0,0,0,0);
555
556                 // See if max ends exactly on a month
557                 var tempmend = new $.jsDate(max);
558                 var mend = new $.jsDate(max).setDate(1).setHours(0,0,0,0);
559
560                 if (tempmend.getTime() !== mend.getTime()) {
561                     mend = mend.add(1, 'month');
562                 }
563
564                 var nmonths = mend.diff(mstart, 'month');
565
566                 nttarget = Math.ceil(nmonths/intv) + 1;
567
568                 this.min = mstart.getTime();
569                 this.max = mstart.clone().add((nttarget - 1) * intv, 'month').getTime();
570                 this.numberTicks = nttarget;
571
572                 for (var i=0; i<nttarget; i++) {
573                     if (i === 0) {
574                         opts.value = mstart.getTime();
575                     }
576                     else {
577                         opts.value = mstart.add(intv, 'month').getTime();
578                     }
579                     t = new this.tickRenderer(opts);
580                     
581                     if (this._overrideFormatString && this._autoFormatString != '') {
582                         t.formatString = this._autoFormatString;
583                     }
584                     if (!this.showTicks) {
585                         t.showLabel = false;
586                         t.showMark = false;
587                     }
588                     else if (!this.showTickMarks) {
589                         t.showMark = false;
590                     }
591                     this._ticks.push(t);
592                 }
593
594                 insetMult = intv * month;
595             }
596
597             // use yearly intervals
598             else {
599
600                 this._autoFormatString = '%v';
601
602                 // how many years in an interval?
603                 var intv = Math.round(titarget/year);
604                 if (intv < 1) {
605                     intv = 1;
606                 }
607
608                 // figure out the starting and ending years.
609                 var mstart = new $.jsDate(min).setMonth(0, 1).setHours(0,0,0,0);
610                 var mend = new $.jsDate(max).add(1, 'year').setMonth(0, 1).setHours(0,0,0,0);
611
612                 var nyears = mend.diff(mstart, 'year');
613
614                 nttarget = Math.ceil(nyears/intv) + 1;
615
616                 this.min = mstart.getTime();
617                 this.max = mstart.clone().add((nttarget - 1) * intv, 'year').getTime();
618                 this.numberTicks = nttarget;
619
620                 for (var i=0; i<nttarget; i++) {
621                     if (i === 0) {
622                         opts.value = mstart.getTime();
623                     }
624                     else {
625                         opts.value = mstart.add(intv, 'year').getTime();
626                     }
627                     t = new this.tickRenderer(opts);
628                     
629                     if (this._overrideFormatString && this._autoFormatString != '') {
630                         t.formatString = this._autoFormatString;
631                     }
632                     if (!this.showTicks) {
633                         t.showLabel = false;
634                         t.showMark = false;
635                     }
636                     else if (!this.showTickMarks) {
637                         t.showMark = false;
638                     }
639                     this._ticks.push(t);
640                 }
641
642                 insetMult = intv * year;
643             }
644         }
645
646         ////////
647         // Some option(s) specified, work around that.
648         ////////
649         
650         else {      
651             if (name == 'xaxis' || name == 'x2axis') {
652                 dim = this._plotDimensions.width;
653             }
654             else {
655                 dim = this._plotDimensions.height;
656             }
657             
658             // if min, max and number of ticks specified, user can't specify interval.
659             if (this.min != null && this.max != null && this.numberTicks != null) {
660                 this.tickInterval = null;
661             }
662             
663             if (this.tickInterval != null && daTickInterval != null) {
664                 this.daTickInterval = daTickInterval;
665             }
666             
667             // if min and max are same, space them out a bit
668             if (min == max) {
669                 var adj = 24*60*60*500;  // 1/2 day
670                 min -= adj;
671                 max += adj;
672             }
673
674             range = max - min;
675             
676             var optNumTicks = 2 + parseInt(Math.max(0, dim-100)/100, 10);
677             
678             
679             var rmin, rmax;
680             
681             rmin = (this.min != null) ? new $.jsDate(this.min).getTime() : min - range/2*(this.padMin - 1);
682             rmax = (this.max != null) ? new $.jsDate(this.max).getTime() : max + range/2*(this.padMax - 1);
683             this.min = rmin;
684             this.max = rmax;
685             range = this.max - this.min;
686             
687             if (this.numberTicks == null){
688                 // if tickInterval is specified by user, we will ignore computed maximum.
689                 // max will be equal or greater to fit even # of ticks.
690                 if (this.daTickInterval != null) {
691                     var nc = new $.jsDate(this.max).diff(this.min, this.daTickInterval[1], true);
692                     this.numberTicks = Math.ceil(nc/this.daTickInterval[0]) +1;
693                     // this.max = new $.jsDate(this.min).add(this.numberTicks-1, this.daTickInterval[1]).getTime();
694                     this.max = new $.jsDate(this.min).add((this.numberTicks-1) * this.daTickInterval[0], this.daTickInterval[1]).getTime();
695                 }
696                 else if (dim > 200) {
697                     this.numberTicks = parseInt(3+(dim-200)/100, 10);
698                 }
699                 else {
700                     this.numberTicks = 2;
701                 }
702             }
703             
704             insetMult = range / (this.numberTicks-1)/1000;
705
706             if (this.daTickInterval == null) {
707                 this.daTickInterval = [insetMult, 'seconds'];
708             }
709
710
711             for (var i=0; i<this.numberTicks; i++){
712                 var min = new $.jsDate(this.min);
713                 tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime();
714                 var t = new this.tickRenderer(this.tickOptions);
715                 // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);
716                 if (!this.showTicks) {
717                     t.showLabel = false;
718                     t.showMark = false;
719                 }
720                 else if (!this.showTickMarks) {
721                     t.showMark = false;
722                 }
723                 t.setTick(tt, this.name);
724                 this._ticks.push(t);
725             }
726         }
727
728         if (this.tickInset) {
729             this.min = this.min - this.tickInset * insetMult;
730             this.max = this.max + this.tickInset * insetMult;
731         }
732
733         if (this._daTickInterval == null) {
734             this._daTickInterval = this.daTickInterval;    
735         }
736
737         ticks = null;
738     };
739    
740 })(jQuery);
741