merged cont.
[opensuse:yast-rest-service.git] / webyast / public / javascripts / plugin / jqplot.dateAxisRenderer.js
1 /**
2  * Copyright (c) 2009 Chris Leonello
3  * jqPlot is currently available for use in all personal or commercial projects 
4  * under both the MIT and GPL version 2.0 licenses. This means that you can 
5  * choose the license that best suits your project and use it accordingly. 
6  *
7  * The author would appreciate an email letting him know of any substantial
8  * use of jqPlot.  You can reach the author at: chris dot leonello at gmail 
9  * dot com or see http://www.jqplot.com/info.php .  This is, of course, 
10  * not required.
11  *
12  * If you are feeling kind and generous, consider supporting the project by
13  * making a donation at: http://www.jqplot.com/donate.php .
14  *
15  * Thanks for using jqPlot!
16  * 
17  */
18 (function($) {  
19     /**
20      * Class: $.jqplot.DateAxisRenderer
21      * A plugin for a jqPlot to render an axis as a series of date values.
22      * This renderer has no options beyond those supplied by the <Axis> class.
23      * It supplies it's own tick formatter, so the tickOptions.formatter option
24      * should not be overridden.
25      * 
26      * Thanks to Ken Synder for his enhanced Date instance methods which are
27      * included with this code <http://kendsnyder.com/sandbox/date/>.
28      * 
29      * To use this renderer, include the plugin in your source
30      * > <script type="text/javascript" language="javascript" src="plugins/jqplot.dateAxisRenderer.js"></script>
31      * 
32      * and supply the appropriate options to your plot
33      * 
34      * > {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}}
35      * 
36      * Dates can be passed into the axis in almost any recognizable value and 
37      * will be parsed.  They will be rendered on the axis in the format
38      * specified by tickOptions.formatString.  e.g. tickOptions.formatString = '%Y-%m-%d'.
39      * 
40      * Accecptable format codes 
41      * are:
42      * 
43      * > Code    Result                  Description
44      * >             == Years ==
45      * > %Y      2008                Four-digit year
46      * > %y      08                  Two-digit year
47      * >             == Months ==
48      * > %m      09                  Two-digit month
49      * > %#m     9                   One or two-digit month
50      * > %B      September           Full month name
51      * > %b      Sep                 Abbreviated month name
52      * >             == Days ==
53      * > %d      05                  Two-digit day of month
54      * > %#d     5                   One or two-digit day of month
55      * > %e      5                   One or two-digit day of month
56      * > %A      Sunday              Full name of the day of the week
57      * > %a      Sun                 Abbreviated name of the day of the week
58      * > %w      0                   Number of the day of the week (0 = Sunday, 6 = Saturday)
59      * > %o      th                  The ordinal suffix string following the day of the month
60      * >             == Hours ==
61      * > %H      23                  Hours in 24-hour format (two digits)
62      * > %#H     3                   Hours in 24-hour integer format (one or two digits)
63      * > %I      11                  Hours in 12-hour format (two digits)
64      * > %#I     3                   Hours in 12-hour integer format (one or two digits)
65      * > %p      PM                  AM or PM
66      * >             == Minutes ==
67      * > %M      09                  Minutes (two digits)
68      * > %#M     9                   Minutes (one or two digits)
69      * >             == Seconds ==
70      * > %S      02                  Seconds (two digits)
71      * > %#S     2                   Seconds (one or two digits)
72      * > %s      1206567625723       Unix timestamp (Seconds past 1970-01-01 00:00:00)
73      * >             == Milliseconds ==
74      * > %N      008                 Milliseconds (three digits)
75      * > %#N     8                   Milliseconds (one to three digits)
76      * >             == Timezone ==
77      * > %O      360                 difference in minutes between local time and GMT
78      * > %Z      Mountain Standard Time  Name of timezone as reported by browser
79      * > %G      -06:00              Hours and minutes between GMT
80      * >             == Shortcuts ==
81      * > %F      2008-03-26          %Y-%m-%d
82      * > %T      05:06:30            %H:%M:%S
83      * > %X      05:06:30            %H:%M:%S
84      * > %x      03/26/08            %m/%d/%y
85      * > %D      03/26/08            %m/%d/%y
86      * > %#c     Wed Mar 26 15:31:00 2008  %a %b %e %H:%M:%S %Y
87      * > %v      3-Sep-2008          %e-%b-%Y
88      * > %R      15:31               %H:%M
89      * > %r      3:31:00 PM          %I:%M:%S %p
90      * >             == Characters ==
91      * > %n      \n                  Newline
92      * > %t      \t                  Tab
93      * > %%      %                   Percent Symbol 
94      */
95     $.jqplot.DateAxisRenderer = function() {
96         $.jqplot.LinearAxisRenderer.call(this);
97     };
98     
99     $.jqplot.DateAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer();
100     $.jqplot.DateAxisRenderer.prototype.constructor = $.jqplot.DateAxisRenderer;
101     
102     $.jqplot.DateTickFormatter = function(format, val) {
103         if (!format) {
104             format = '%Y/%m/%d';
105         }
106         return Date.create(val).strftime(format);
107     };
108     
109     $.jqplot.DateAxisRenderer.prototype.init = function(options){
110         // prop: tickRenderer
111         // A class of a rendering engine for creating the ticks labels displayed on the plot, 
112         // See <$.jqplot.AxisTickRenderer>.
113         // this.tickRenderer = $.jqplot.AxisTickRenderer;
114         // this.labelRenderer = $.jqplot.AxisLabelRenderer;
115         this.tickOptions.formatter = $.jqplot.DateTickFormatter;
116         this.daTickInterval = null;
117         this._daTickInterval = null;
118         $.extend(true, this, options);
119         var db = this._dataBounds;
120         // Go through all the series attached to this axis and find
121         // the min/max bounds for this axis.
122         for (var i=0; i<this._series.length; i++) {
123             var s = this._series[i];
124             var d = s.data;
125             var pd = s._plotData;
126             var sd = s._stackData;
127             
128             for (var j=0; j<d.length; j++) { 
129                 if (this.name == 'xaxis' || this.name == 'x2axis') {
130                     d[j][0] = Date.create(d[j][0]).getTime();
131                     pd[j][0] = Date.create(d[j][0]).getTime();
132                     sd[j][0] = Date.create(d[j][0]).getTime();
133                     if (d[j][0] < db.min || db.min == null) {
134                         db.min = d[j][0];
135                     }
136                     if (d[j][0] > db.max || db.max == null) {
137                         db.max = d[j][0];
138                     }
139                 }              
140                 else {
141                     d[j][1] = Date.create(d[j][1]).getTime();
142                     pd[j][1] = Date.create(d[j][1]).getTime();
143                     sd[j][1] = Date.create(d[j][1]).getTime();
144                     if (d[j][1] < db.min || db.min == null) {
145                         db.min = d[j][1];
146                     }
147                     if (d[j][1] > db.max || db.max == null) {
148                         db.max = d[j][1];
149                     }
150                 }              
151             }
152         }
153     };
154     
155     // called with scope of an axis
156     $.jqplot.DateAxisRenderer.prototype.reset = function() {
157         this.min = this._min;
158         this.max = this._max;
159         this.tickInterval = this._tickInterval;
160         this.numberTicks = this._numberTicks;
161         this.daTickInterval = this._daTickInterval;
162         // this._ticks = this.__ticks;
163     };
164     
165     $.jqplot.DateAxisRenderer.prototype.createTicks = function() {
166         // we're are operating on an axis here
167         var ticks = this._ticks;
168         var userTicks = this.ticks;
169         var name = this.name;
170         // databounds were set on axis initialization.
171         var db = this._dataBounds;
172         var dim, interval;
173         var min, max;
174         var pos1, pos2;
175         var tt, i;
176         
177         // if we already have ticks, use them.
178         // ticks must be in order of increasing value.
179         
180         if (userTicks.length) {
181             // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed
182             for (i=0; i<userTicks.length; i++){
183                 var ut = userTicks[i];
184                 var t = new this.tickRenderer(this.tickOptions);
185                 if (ut.constructor == Array) {
186                     t.value = Date.create(ut[0]).getTime();
187                     t.label = ut[1];
188                     if (!this.showTicks) {
189                         t.showLabel = false;
190                         t.showMark = false;
191                     }
192                     else if (!this.showTickMarks) {
193                         t.showMark = false;
194                     }
195                     t.setTick(t.value, this.name);
196                     this._ticks.push(t);
197                 }
198                 
199                 else {
200                     t.value = Date.create(ut).getTime();
201                     if (!this.showTicks) {
202                         t.showLabel = false;
203                         t.showMark = false;
204                     }
205                     else if (!this.showTickMarks) {
206                         t.showMark = false;
207                     }
208                     t.setTick(t.value, this.name);
209                     this._ticks.push(t);
210                 }
211             }
212             this.numberTicks = userTicks.length;
213             this.min = this._ticks[0].value;
214             this.max = this._ticks[this.numberTicks-1].value;
215             this.daTickInterval = [(this.max - this.min) / (this.numberTicks - 1)/1000, 'seconds'];
216         }
217         
218         // we don't have any ticks yet, let's make some!
219         else {
220             if (name == 'xaxis' || name == 'x2axis') {
221                 dim = this._plotDimensions.width;
222             }
223             else {
224                 dim = this._plotDimensions.height;
225             }
226             
227             // if min, max and number of ticks specified, user can't specify interval.
228             if (this.min != null && this.max != null && this.numberTicks != null) {
229                 this.tickInterval = null;
230             }
231             
232             // if user specified a tick interval, convert to usable.
233             if (this.tickInterval != null)
234             {
235                 // if interval is a number or can be converted to one, use it.
236                 // Assume it is in SECONDS!!!
237                 if (Number(this.tickInterval)) {
238                     this.daTickInterval = [Number(this.tickInterval), 'seconds'];
239                 }
240                 // else, parse out something we can build from.
241                 else if (typeof this.tickInterval == "string") {
242                     var parts = this.tickInterval.split(' ');
243                     if (parts.length == 1) {
244                         this.daTickInterval = [1, parts[0]];
245                     }
246                     else if (parts.length == 2) {
247                         this.daTickInterval = [parts[0], parts[1]];
248                     }
249                 }
250             }
251         
252             min = ((this.min != null) ? Date.create(this.min).getTime() : db.min);
253             max = ((this.max != null) ? Date.create(this.max).getTime() : db.max);
254             
255             // if min and max are same, space them out a bit
256             if (min == max) {
257                 var adj = 24*60*60*500;  // 1/2 day
258                 min -= adj;
259                 max += adj;
260             }
261
262             var range = max - min;
263             var rmin, rmax;
264         
265             rmin = (this.min != null) ? Date.create(this.min).getTime() : min - range/2*(this.padMin - 1);
266             rmax = (this.max != null) ? Date.create(this.max).getTime() : max + range/2*(this.padMax - 1);
267             this.min = rmin;
268             this.max = rmax;
269             range = this.max - this.min;
270     
271             if (this.numberTicks == null){
272                 // if tickInterval is specified by user, we will ignore computed maximum.
273                 // max will be equal or greater to fit even # of ticks.
274                 if (this.daTickInterval != null) {
275                     var nc = Date.create(this.max).diff(this.min, this.daTickInterval[1], true);
276                     this.numberTicks = Math.ceil(nc/this.daTickInterval[0]) +1;
277                     // this.max = Date.create(this.min).add(this.numberTicks-1, this.daTickInterval[1]).getTime();
278                     this.max = Date.create(this.min).add((this.numberTicks-1) * this.daTickInterval[0], this.daTickInterval[1]).getTime();
279                 }
280                 else if (dim > 200) {
281                     this.numberTicks = parseInt(3+(dim-200)/100, 10);
282                 }
283                 else {
284                     this.numberTicks = 2;
285                 }
286             }
287     
288             if (this.daTickInterval == null) {
289                 this.daTickInterval = [range / (this.numberTicks-1)/1000, 'seconds'];
290             }
291             for (var i=0; i<this.numberTicks; i++){
292                 var min = Date.create(this.min);
293                 tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime();
294                 var t = new this.tickRenderer(this.tickOptions);
295                 // var t = new $.jqplot.AxisTickRenderer(this.tickOptions);
296                 if (!this.showTicks) {
297                     t.showLabel = false;
298                     t.showMark = false;
299                 }
300                 else if (!this.showTickMarks) {
301                     t.showMark = false;
302                 }
303                 t.setTick(tt, this.name);
304                 this._ticks.push(t);
305             }
306         }
307         if (this._daTickInterval == null) {
308             this._daTickInterval = this.daTickInterval;    
309         }
310     };
311    
312 })(jQuery);
313