Subversion-Projekte lars-tiefland.cienc

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
9 lars 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