2 * Copyright (c) 2006 Sam Collett (http://www.texotela.co.uk)
3 * Licensed under the MIT License:
4 * http://www.opensource.org/licenses/mit-license.php
8 * A time picker for jQuery
9 * Based on original timePicker by Sam Collet (http://www.texotela.co.uk)
12 * @author Anders Fajerson (http://perifer.se)
13 * @example $("#mytime").timePicker();
14 * @example $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
19 $.fn
.timePicker = function(options
) {
20 // Build main options before element iteration
21 var settings
= $.extend({}, $.fn
.timePicker
.defaults
, options
);
23 return this.each(function() {
24 $.timePicker(this, settings
);
28 $.timePicker = function (elm
, settings
) {
30 return elm
.timePicker
|| (elm
.timePicker
= new jQuery
._timePicker(elm
, settings
));
33 $._timePicker = function(elm
, settings
) {
36 var startTime
= normaliseTime(settings
.startTime
);
37 var endTime
= normaliseTime(settings
.endTime
);
39 $(elm
).attr('autocomplete', 'OFF'); // Disable browser autocomplete
42 var time
= new Date(startTime
); // Create a new date object.
43 while(time
<= endTime
) {
44 times
[times
.length
] = formatTime(time
, settings
);
45 time
= new Date(time
.setMinutes(time
.getMinutes() + settings
.step
));
48 var $tpDiv
= $('<div class="time-picker'+ (settings
.show24Hours
? '' : ' time-picker-12hours') +'"></div>');
49 var $tpList
= $('<ul></ul>');
52 for(var i
= 0; i
< times
.length
; i
++) {
53 $tpList
.append("<li>" + times
[i
] + "</li>");
55 $tpDiv
.append($tpList
);
56 // Store element offset.
57 var elmOffset
= $(elm
).offset();
58 // Append the timPicker to the body and position it.
59 $tpDiv
.appendTo('body').css({'top':elmOffset
.top
, 'left':elmOffset
.left
}).hide();
61 $("li", $tpList
).unbind().mouseover(function() {
62 $("li.selected", $tpDiv
).removeClass("selected"); // TODO: only needs to run once.
63 $(this).addClass("selected");
64 }).mousedown(function() {
67 setTimeVal(elm
, this, $tpDiv
, settings
);
71 // Store ananymous function in variable since it's used twice.
72 var showPicker = function() {
73 var elmOffset
= $(elm
).offset();
74 $tpDiv
.css({'top':elmOffset
.top
, 'left':elmOffset
.left
}).show(); // Show picker.
75 $tpDiv
.mouseover(function() { // Have to use mouseover instead of mousedown because of Opera
77 }).mouseout(function() {
80 $("li", $tpDiv
).removeClass("selected");
82 // Try to find a time in the list that matches the entered time.
83 var time
= this.value
? timeStringToDate(this.value
, settings
) : startTime
;
84 var startMin
= startTime
.getHours() * 60 + startTime
.getMinutes();
85 var min
= (time
.getHours() * 60 + time
.getMinutes()) - startMin
;
86 var steps
= Math
.round(min
/ settings
.step
);
87 var roundTime
= normaliseTime(new Date(2001, 0, 0, 0, (steps
* settings
.step
+ (startMin
)), 0));
88 roundTime
= (startTime
< roundTime
&& roundTime
< endTime
) ? roundTime
: startTime
;
90 var $matchedTime
= $("li:contains(" + formatTime(roundTime
, settings
) + ")", $tpDiv
);
92 if ($matchedTime
.length
) {
93 $matchedTime
.addClass("selected");
94 // Scroll to matched time.
95 $tpDiv
[0].scrollTop
= $matchedTime
[0].offsetTop
;
99 $(elm
).unbind().focus(showPicker
).click(showPicker
)
100 // Hide timepicker on blur
102 if (!tpOver
&& $tpDiv
[0].parentNode
) { // Don't remove when timePicker is clicked or when already removed
108 .keypress(function(e
) {
110 case 38: // Up arrow.
111 case 63232: // Safari up arrow.
112 var $selected
= $("li.selected", $tpList
);
113 var prev
= $selected
.prev().addClass("selected")[0];
115 $selected
.removeClass("selected");
116 $tpDiv
[0].scrollTop
= prev
.offsetTop
;
120 case 40: // Down arrow.
121 case 63233: // Safari down arrow.
122 var $selected
= $("li.selected", $tpList
);
123 var next
= $selected
.length
? $selected
.next().addClass("selected")[0] : $("li:first").addClass("selected")[0];
125 $selected
.removeClass("selected");
126 $tpDiv
[0].scrollTop
= next
.offsetTop
;
131 if (!$tpDiv
.is(":hidden")) {
132 var sel
= $("li.selected", $tpList
)[0];
133 setTimeVal(elm
, sel
, $tpDiv
, settings
);
140 // Helper function to get an inputs current time as Date object.
141 // Returns a Date object.
142 this.getTime = function() {
143 return timeStringToDate(elm
.value
, settings
);
145 // Helper function to set a time input.
146 // Takes a Date object.
147 this.setTime = function(time
) {
148 elm
.value
= formatTime(normaliseTime(time
), settings
);
149 // Trigger element's change events.
156 $.fn
.timePicker
.defaults
= {
158 startTime
: new Date(0, 0, 0, 0, 0, 0),
159 endTime
: new Date(0, 0, 0, 23, 30, 0),
164 // Private functions.
166 function setTimeVal(elm
, sel
, $tpDiv
, settings
) {
167 // Update input field
168 elm
.value
= $(sel
).text();
169 // Trigger element's change events.
171 // Keep focus for all but IE (which doesn't like it)
172 if (!$.browser
.msie
) {
179 function formatTime(time
, settings
) {
180 var h
= time
.getHours();
181 var hours
= settings
.show24Hours
? h
: (((h
+ 11) % 12) + 1);
182 var minutes
= time
.getMinutes();
183 return formatNumber(hours
) + settings
.separator
+ formatNumber(minutes
) + (settings
.show24Hours
? '' : ((h
< 12) ? ' AM' : ' PM'));
186 function formatNumber(value
) {
187 return (value
< 10 ? '0' : '') + value
;
190 function timeStringToDate(input
, settings
) {
192 var array
= input
.split(settings
.separator
);
193 var hours
= parseFloat(array
[0]);
194 var minutes
= parseFloat(array
[1]);
195 var time
= new Date(0, 0, 0, hours
, minutes
, 0);
196 return normaliseTime(time
);
201 /* Normalise time object to a common date. */
202 function normaliseTime(time
) {
203 time
.setFullYear(2001);