PageSourceSearch

https://www.ppcseagles.org/pro/js/jquery.timepicker.js

js ppcseagles.org collected 2026-10-02 08:47:48 UTC 23,367 bytes, 996 lines download raw bytes

1/************************
2jquery-timepicker v1.3.2
3http://jonthornton.github.com/jquery-timepicker/
4
5requires jQuery 1.7+
6************************/
7
8
9(function (factory) {
10	if (typeof define === 'function' && define.amd) {
11		// AMD. Register as an anonymous module.
12		define(['jquery'], factory);
13	} else {
14		// Browser globals
15		factory(jQuery);
16	}
17}(function ($) {
18	var _baseDate = _generateBaseDate();
19	var _ONE_DAY = 86400;
20	var _defaults =	{
21		className: null,
22		minTime: null,
23		maxTime: null,
24		durationTime: null,
25		step: 30,
26		showDuration: false,
27		timeFormat: 'g:ia',
28		scrollDefaultNow: false,
29		scrollDefaultTime: false,
30		selectOnBlur: false,
31		disableTouchKeyboard: false,
32		forceRoundTime: false,
33		appendTo: 'body',
34		disableTimeRanges: [],
35		closeOnWindowScroll: false,
36		typeaheadHighlight: true,
37		noneOption: false
38	};
39	var _lang = {
40		decimal: '.',
41		mins: 'mins',
42		hr: 'hr',
43		hrs: 'hrs'
44	};
45
46	var methods =
47	{
48		init: function(options)
49		{
50			return this.each(function()
51			{
52				var self = $(this);
53
54				// pick up settings from data attributes
55				var attributeOptions = [];
56				for (key in _defaults) {
57					if (self.data(key))  {
58						attributeOptions[key] = self.data(key);
59					}
60				}
61
62				var settings = $.extend({}, _defaults, attributeOptions, options);
63
64				if (settings.lang) {
65					_lang = $.extend(_lang, settings.lang);
66				}
67
68				settings = _parseSettings(settings);
69				self.data('timepicker-settings', settings);
70				self.addClass('ui-timepicker-input');
71
72				if (settings.useSelect) {
73					_render(self);
74				} else {
75					self.prop('autocomplete', 'off');
76					self.on('click.timepicker focus.timepicker', methods.show);
77					self.on('change.timepicker', _formatValue);
78					self.on('keydown.timepicker', _keydownhandler);
79					self.on('keyup.timepicker', _keyuphandler);
80
81					_formatValue.call(self.get(0));
82				}
83			});
84		},
85
86		show: function(e)
87		{
88			if (e) {
89				e.preventDefault();
90			}
91
92			var self = $(this);
93			var settings = self.data('timepicker-settings');
94
95			if (settings.useSelect) {
96				self.data('timepicker-list').focus();
97				return;
98			}
99
100			if (_hideKeyboard(self)) {
101				// block the keyboard on mobile devices
102				self.blur();
103			}
104
105			var list = self.data('timepicker-list');
106
107			// check if input is readonly
108			if (self.prop('readonly')) {
109				return;
110			}
111
112			// check if list needs to be rendered
113			if (!list || list.length === 0 || typeof settings.durationTime === 'function') {
114				_render(self);
115				list = self.data('timepicker-list');
116			}
117
118			if (list.is(':visible')) {
119				return;
120			}
121
122			// make sure other pickers are hidden
123			methods.hide();
124
125			list.show();
126
127			if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) {
128				// position the dropdown on top
129				list.offset({
130					'left': self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10),
131					'top': self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10)
132				});
133			} else {
134				// put it under the input
135				list.offset({
136					'left':self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10),
137					'top': self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10)
138				});
139			}
140
141			// position scrolling
142			var selected = list.find('.ui-timepicker-selected');
143
144			if (!selected.length) {
145				if (_getTimeValue(self)) {
146					selected = _findRow(self, list, _time2int(_getTimeValue(self)));
147				} else if (settings.scrollDefaultNow) {
148					selected = _findRow(self, list, _time2int(new Date()));
149				} else if (settings.scrollDefaultTime !== false) {
150					selected = _findRow(self, list, _time2int(settings.scrollDefaultTime));
151				}
152			}
153
154			if (selected && selected.length) {
155				var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight();
156				list.scrollTop(topOffset);
157			} else {
158				list.scrollTop(0);
159			}
160
161			// attach close handlers
162			$(document).on('touchstart.ui-timepicker mousedown.ui-timepicker', _closeHandler);
163			if (settings.closeOnWindowScroll) {
164				$(document).on('scroll.ui-timepicker', _closeHandler);
165			}
166
167			self.trigger('showTimepicker');
168
169			return this;
170		},
171
172		hide: function(e)
173		{
174			var self = $(this);
175			var settings = self.data('timepicker-settings');
176
177			if (settings && settings.useSelect) {
178				self.blur();
179			}
180
181			$('.ui-timepicker-wrapper:visible').each(function() {
182				var list = $(this);
183				var self = list.data('timepicker-input');
184				var settings = self.data('timepicker-settings');
185
186				if (settings && settings.selectOnBlur) {
187					_selectValue(self);
188				}
189
190				list.hide();
191				self.trigger('hideTimepicker');
192			});
193
194			return this;
195		},
196
197		option: function(key, value)
198		{
199			var self = this;
200			var settings = self.data('timepicker-settings');
201			var list = self.data('timepicker-list');
202
203			if (typeof key == 'object') {
204				settings = $.extend(settings, key);
205
206			} else if (typeof key == 'string' && typeof value != 'undefined') {
207				settings[key] = value;
208
209			} else if (typeof key == 'string') {
210				return settings[key];
211			}
212
213			settings = _parseSettings(settings);
214
215			self.data('timepicker-settings', settings);
216
217			if (list) {
218				list.remove();
219				self.data('timepicker-list', false);
220			}
221
222			if (settings.useSelect) {
223				_render(self);
224			}
225
226			return this;
227		},
228
229		getSecondsFromMidnight: function()
230		{
231			return _time2int(_getTimeValue(this));
232		},
233
234		getTime: function(relative_date)
235		{
236			var self = this;
237
238			var time_string = _getTimeValue(self);
239			if (!time_string) {
240				return null;
241			}
242
243			if (!relative_date) {
244				relative_date = new Date();
245			}
246
247			relative_date.setHours(0, 0, 0, 0);
248			return new Date(relative_date.valueOf() + (_time2int(time_string)*1000));
249		},
250
251		setTime: function(value)
252		{
253			var self = this;
254			var prettyTime = _int2time(_time2int(value), self.data('timepicker-settings').timeFormat);
255
256			_setTimeValue(self, prettyTime);
257			if (self.data('timepicker-list')) {
258				_setSelected(self, self.data('timepicker-list'));
259			}
260
261			return this;
262		},
263
264		remove: function()
265		{
266			var self = this;
267
268			// check if this element is a timepicker
269			if (!self.hasClass('ui-timepicker-input')) {
270				return;
271			}
272
273			self.removeAttr('autocomplete', 'off');
274			self.removeClass('ui-timepicker-input');
275			self.removeData('timepicker-settings');
276			self.off('.timepicker');
277
278			// timepicker-list won't be present unless the user has interacted with this timepicker
279			if (self.data('timepicker-list')) {
280				self.data('timepicker-list').remove();
281			}
282
283			self.removeData('timepicker-list');
284
285			return this;
286		}
287	};
288
289	// private methods
290
291	function _parseSettings(settings)
292	{
293		if (settings.minTime) {
294			settings.minTime = _time2int(settings.minTime);
295		}
296
297		if (settings.maxTime) {
298			settings.maxTime = _time2int(settings.maxTime);
299		}
300
301		if (settings.durationTime && typeof settings.durationTime !== 'function') {
302			settings.durationTime = _time2int(settings.durationTime);
303		}
304
305		if (settings.disableTimeRanges.length > 0) {
306			// convert string times to integers
307			for (var i in settings.disableTimeRanges) {
308				settings.disableTimeRanges[i] = [
309					_time2int(settings.disableTimeRanges[i][0]),
310					_time2int(settings.disableTimeRanges[i][1])
311				];
312			}
313
314			// sort by starting time
315			settings.disableTimeRanges = settings.disableTimeRanges.sort(function(a, b){
316				return a[0] - b[0];
317			});
318
319			// merge any overlapping ranges
320			for (var i = settings.disableTimeRanges.length-1; i > 0; i--) {
321				if (settings.disableTimeRanges[i][0] <= settings.disableTimeRanges[i-1][1]) {
322					settings.disableTimeRanges[i-1] = [
323						Math.min(settings.disableTimeRanges[i][0], settings.disableTimeRanges[i-1][0]),
324						Math.max(settings.disableTimeRanges[i][1], settings.disableTimeRanges[i-1][1])
325					];
326					settings.disableTimeRanges.splice(i, 1);
327				}
328			}
329		}
330
331		return settings;
332	}
333
334	function _render(self)
335	{
336		var settings = self.data('timepicker-settings');
337		var list = self.data('timepicker-list');
338
339		if (list && list.length) {
340			list.remove();
341			self.data('timepicker-list', false);
342		}
343
344		if (settings.useSelect) {
345			list = $('<select />', { 'class': 'ui-timepicker-select' });
346			var wrapped_list = list;
347		} else {
348			list = $('<ul />', { 'class': 'ui-timepicker-list' });
349
350			var wrapped_list = $('<div />', { 'class': 'ui-timepicker-wrapper', 'tabindex': -1 });
351			wrapped_list.css({'display':'none', 'position': 'absolute' }).append(list);
352		}
353
354		if (settings.noneOption) {
355			var defaultLabel = (settings.useSelect) ? 'Time...' : 'None';
356			var label = (typeof settings.noneOption == 'string') ? settings.noneOption : defaultLabel;
357			if (settings.useSelect) {
358				list.append($('<option value="">'+label+'</option>'));
359			} else {
360				list.append($('<li>'+label+'</li>'));
361			}
362		}
363
364		if (settings.className) {
365			wrapped_list.addClass(settings.className);
366		}
367
368		if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
369			wrapped_list.addClass('ui-timepicker-with-duration');
370		}
371
372		var durStart = settings.minTime;
373		if (typeof settings.durationTime === 'function') {
374			durStart = _time2int(settings.durationTime());
375		} else if (settings.durationTime !== null) {
376			durStart = settings.durationTime;
377		}
378		var start = (settings.minTime !== null) ? settings.minTime : 0;
379		var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1);
380
381		if (end <= start) {
382			// make sure the end time is greater than start time, otherwise there will be no list to show
383			end += _ONE_DAY;
384		}
385
386		if (end === _ONE_DAY-1 && settings.timeFormat.indexOf('H') !== -1) {
387			// show a 24:00 option when using military time
388			end = _ONE_DAY;
389		}
390
391		var dr = settings.disableTimeRanges;
392		var drCur = 0;
393		var drLen = dr.length;
394
395		for (var i=start; i <= end; i += settings.step*60) {
396			var timeInt = i;
397			var timeString = _int2time(timeInt, settings.timeFormat);
398
399			if (settings.useSelect) {
400				var row = $('<option />', { 'value': timeString });
401				row.text(timeString);
402			} else {
403				var row = $('<li />');
404				row.data('time', (timeInt <= 86400 ? timeInt : timeInt % 86400));
405				row.text(timeString);
406			}
407
408			if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) {
409				var durationString = _int2duration(i - durStart);
410				if (settings.useSelect) {
411					row.text(row.text()+' ('+durationString+')');
412				} else {
413					var duration = $('<span />', { 'class': 'ui-timepicker-duration' });
414					duration.text(' ('+durationString+')');
415					row.append(duration);
416				}
417			}
418
419			if (drCur < drLen) {
420				if (timeInt >= dr[drCur][1]) {
421					drCur += 1;
422				}
423
424				if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
425					if (settings.useSelect) {
426						row.prop('disabled', true);
427					} else {
428						row.addClass('ui-timepicker-disabled');
429					}
430				}
431			}
432
433			list.append(row);
434		}
435
436		wrapped_list.data('timepicker-input', self);
437		self.data('timepicker-list', wrapped_list);
438
439		if (settings.useSelect) {
440			list.val(_roundTime(self.val(), settings));
441			list.on('focus', function(){
442				$(this).data('timepicker-input').trigger('showTimepicker');
443			});
444			list.on('blur', function(){
445				$(this).data('timepicker-input').trigger('hideTimepicker');
446			});
447			list.on('change', function(){
448				_setTimeValue(self, $(this).val(), 'select');
449			});
450
451			self.hide().after(list);
452		} else {
453			var appendTo = settings.appendTo;
454			if (typeof appendTo === 'string') {
455				appendTo = $(appendTo);
456			} else if (typeof appendTo === 'function') {
457				appendTo = appendTo(self);
458			}
459			appendTo.append(wrapped_list);
460			_setSelected(self, list);
461
462			list.on('click', 'li', function(e) {
463
464				// hack: temporarily disable the focus handler
465				// to deal with the fact that IE fires 'focus'
466				// events asynchronously
467				self.off('focus.timepicker');
468				self.on('focus.timepicker-ie-hack', function(){
469					self.off('focus.timepicker-ie-hack');
470					self.on('focus.timepicker', methods.show);
471				});
472
473				if (!_hideKeyboard(self)) {
474					self[0].focus();
475				}
476
477				// make sure only the clicked row is selected
478				list.find('li').removeClass('ui-timepicker-selected');
479				$(this).addClass('ui-timepicker-selected');
480
481				if (_selectValue(self)) {
482					self.trigger('hideTimepicker');
483					wrapped_list.hide();
484				}
485			});
486		}
487	}
488
489	function _roundTime(time, settings)
490	{
491		if (!$.isNumeric(time)) {
492			time = _time2int(time);
493		}
494
495		if (time === null) {
496			return null;
497		} else {
498			var step = settings.step*60;
499			// round to the nearest step
500			return _int2time(Math.round(time / step) * step, settings.timeFormat);
501		}
502	}
503
504	function _generateBaseDate()
505	{
506		return new Date(1970, 1, 1, 0, 0, 0);
507	}
508
509	// event handler to decide whether to close timepicker
510	function _closeHandler(e)
511	{
512		var target = $(e.target);
513		var input = target.closest('.ui-timepicker-input');
514		if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) {
515			methods.hide();
516			$(document).unbind('.ui-timepicker');
517		}
518	}
519
520	function _hideKeyboard(self)
521	{
522		var settings = self.data('timepicker-settings');
523		return ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && settings.disableTouchKeyboard);
524	}
525
526	function _findRow(self, list, value)
527	{
528		if (!value && value !== 0) {
529			return false;
530		}
531
532		var settings = self.data('timepicker-settings');
533		var out = false;
534		var halfStep = settings.step*30;
535
536		// loop through the menu items
537		list.find('li').each(function(i, obj) {
538			var jObj = $(obj);
539
540			var offset = jObj.data('time') - value;
541
542			// check if the value is less than half a step from each row
543			if (Math.abs(offset) < halfStep || offset == halfStep) {
544				out = jObj;
545				return false;
546			}
547		});
548
549		return out;
550	}
551
552	function _setSelected(self, list)
553	{
554		list.find('li').removeClass('ui-timepicker-selected');
555
556		var timeValue = _time2int(_getTimeValue(self));
557		if (timeValue === null) {
558			return;
559		}
560
561		var selected = _findRow(self, list, timeValue);
562		if (selected) {
563
564			var topDelta = selected.offset().top - list.offset().top;
565
566			if (topDelta + selected.outerHeight() > list.outerHeight() || topDelta < 0) {
567				list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight());
568			}
569
570			selected.addClass('ui-timepicker-selected');
571		}
572	}
573
574
575	function _formatValue()
576	{
577		if (this.value === '') {
578			return;
579		}
580
581		var self = $(this);
582		var list = self.data('timepicker-list');
583
584		if (list && list.is(':visible')) {
585			return;
586		}
587
588		var seconds = _time2int(this.value);
589
590		if (seconds === null) {
591			self.trigger('timeFormatError');
592			return;
593		}
594
595		var settings = self.data('timepicker-settings');
596		var rangeError = false;
597		// check that the time in within bounds
598		if (settings.minTime !== null && seconds < settings.minTime) {
599			rangeError = true;
600		} else if (settings.maxTime !== null && seconds > settings.maxTime) {
601			rangeError = true;
602		}
603
604		// check that time isn't within disabled time ranges
605		$.each(settings.disableTimeRanges, function(){
606			if (seconds >= this[0] && seconds < this[1]) {
607				rangeError = true;
608				return false;
609			}
610		});
611
612		if (settings.forceRoundTime) {
613			var offset = seconds % (settings.step*60); // step is in minutes
614
615			if (offset >= settings.step*30) {
616				// if offset is larger than a half step, round up
617				seconds += (settings.step*60) - offset;
618			} else {
619				// round down
620				seconds -= offset;
621			}
622		}
623
624		var prettyTime = _int2time(seconds, settings.timeFormat);
625
626		if (rangeError) {
627			if (_setTimeValue(self, prettyTime, 'error')) {
628				self.trigger('timeRangeError');
629			}
630		} else {
631			_setTimeValue(self, prettyTime);
632		}
633	}
634
635	function _getTimeValue(self)
636	{
637		if (self.is('input')) {
638			return self.val();
639		} else {
640			// use the element's data attributes to store values
641			return self.data('ui-timepicker-value');
642		}
643	}
644
645	function _setTimeValue(self, value, source)
646	{
647		if (self.is('input')) {
648			self.val(value);
649
650			var settings = self.data('timepicker-settings');
651			if (settings.useSelect) {
652				self.data('timepicker-list').val(_roundTime(value, settings));
653			}
654		}
655
656		if (self.data('ui-timepicker-value') != value) {
657			self.data('ui-timepicker-value', value);
658			if (source == 'select') {
659				self.trigger('selectTime').trigger('changeTime').trigger('change');
660			} else if (source != 'error') {
661				self.trigger('changeTime');
662			}
663
664			return true;
665		} else {
666			self.trigger('selectTime');
667			return false;
668		}
669	}
670
671	/*
672	*  Keyboard navigation via arrow keys
673	*/
674	function _keydownhandler(e)
675	{
676		var self = $(this);
677		var list = self.data('timepicker-list');
678
679		if (!list || !list.is(':visible')) {
680			if (e.keyCode == 40) {
681				if (!_hideKeyboard(self)) {
682					self.focus();
683				}
684			} else {
685				return true;
686			}
687		}
688
689		switch (e.keyCode) {
690
691			case 13: // return
692				if (_selectValue(self)) {
693					methods.hide.apply(this);
694				}
695
696				e.preventDefault();
697				return false;
698
699			case 38: // up
700				var selected = list.find('.ui-timepicker-selected');
701
702				if (!selected.length) {
703					list.find('li').each(function(i, obj) {
704						if ($(obj).position().top > 0) {
705							selected = $(obj);
706							return false;
707						}
708					});
709					selected.addClass('ui-timepicker-selected');
710
711				} else if (!selected.is(':first-child')) {
712					selected.removeClass('ui-timepicker-selected');
713					selected.prev().addClass('ui-timepicker-selected');
714
715					if (selected.prev().position().top < selected.outerHeight()) {
716						list.scrollTop(list.scrollTop() - selected.outerHeight());
717					}
718				}
719
720				return false;
721
722			case 40: // down
723				selected = list.find('.ui-timepicker-selected');
724
725				if (selected.length === 0) {
726					list.find('li').each(function(i, obj) {
727						if ($(obj).position().top > 0) {
728							selected = $(obj);
729							return false;
730						}
731					});
732
733					selected.addClass('ui-timepicker-selected');
734				} else if (!selected.is(':last-child')) {
735					selected.removeClass('ui-timepicker-selected');
736					selected.next().addClass('ui-timepicker-selected');
737
738					if (selected.next().position().top + 2*selected.outerHeight() > list.outerHeight()) {
739						list.scrollTop(list.scrollTop() + selected.outerHeight());
740					}
741				}
742
743				return false;
744
745			case 27: // escape
746				list.find('li').removeClass('ui-timepicker-selected');
747				methods.hide();
748				break;
749
750			case 9: //tab
751				methods.hide();
752				break;
753
754			default:
755				return true;
756		}
757	}
758
759	/*
760	*	Time typeahead
761	*/
762	function _keyuphandler(e)
763	{
764		var self = $(this);
765		var list = self.data('timepicker-list');
766
767		if (!list || !list.is(':visible')) {
768			return true;
769		}
770
771		if (!self.data('timepicker-settings').typeaheadHighlight) {
772			list.find('li').removeClass('ui-timepicker-selected');
773			return true;
774		}
775
776		switch (e.keyCode) {
777
778			case 96: // numpad numerals
779			case 97:
780			case 98:
781			case 99:
782			case 100:
783			case 101:
784			case 102:
785			case 103:
786			case 104:
787			case 105:
788			case 48: // numerals
789			case 49:
790			case 50:
791			case 51:
792			case 52:
793			case 53:
794			case 54:
795			case 55:
796			case 56:
797			case 57:
798			case 65: // a
799			case 77: // m
800			case 80: // p
801			case 186: // colon
802			case 8: // backspace
803			case 46: // delete
804				_setSelected(self, list);
805				break;
806
807			default:
808				// list.find('li').removeClass('ui-timepicker-selected');
809				return;
810		}
811	}
812
813	function _selectValue(self)
814	{
815		var settings = self.data('timepicker-settings');
816		var list = self.data('timepicker-list');
817		var timeValue = null;
818
819		var cursor = list.find('.ui-timepicker-selected');
820
821		if (cursor.hasClass('ui-timepicker-disabled')) {
822			return false;
823		}
824
825		if (cursor.length) {
826			// selected value found
827			timeValue = cursor.data('time');
828
829		} else if (_getTimeValue(self)) {
830
831			// no selected value; fall back on input value
832			timeValue = _time2int(_getTimeValue(self));
833
834			_setSelected(self, list);
835		}
836
837		if (timeValue !== null) {
838			var timeString = _int2time(timeValue, settings.timeFormat);
839			_setTimeValue(self, timeString, 'select');
840		}
841
842		//self.trigger('change').trigger('selectTime');
843		return true;
844	}
845
846	function _int2duration(seconds)
847	{
848		var minutes = Math.round(seconds/60);
849		var duration;
850
851		if (Math.abs(minutes) < 60) {
852			duration = [minutes, _lang.mins];
853		} else if (minutes == 60) {
854			duration = ['1', _lang.hr];
855		} else {
856			var hours = (minutes/60).toFixed(1);
857			if (_lang.decimal != '.') hours = hours.replace('.', _lang.decimal);
858			duration = [hours, _lang.hrs];
859		}
860
861		return duration.join(' ');
862	}
863
864	function _int2time(seconds, format)
865	{
866		if (seconds === null) {
867			return;
868		}
869
870		var time = new Date(_baseDate.valueOf() + (seconds*1000));
871
872		if (isNaN(time.getTime())) {
873			return;
874		}
875
876		var output = '';
877		var hour, code;
878
879		for (var i=0; i<format.length; i++) {
880
881			code = format.charAt(i);
882			switch (code) {
883
884				case 'a':
885					output += (time.getHours() > 11) ? 'pm' : 'am';
886					break;
887
888				case 'A':
889					output += (time.getHours() > 11) ? 'PM' : 'AM';
890					break;
891
892				case 'g':
893					hour = time.getHours() % 12;
894					output += (hour === 0) ? '12' : hour;
895					break;
896
897				case 'G':
898					output += time.getHours();
899					break;
900
901				case 'h':
902					hour = time.getHours() % 12;
903
904					if (hour !== 0 && hour < 10) {
905						hour = '0'+hour;
906					}
907
908					output += (hour === 0) ? '12' : hour;
909					break;
910
911				case 'H':
912					hour = time.getHours();
913					if (seconds === _ONE_DAY) hour = 24;
914					output += (hour > 9) ? hour : '0'+hour;
915					break;
916
917				case 'i':
918					var minutes = time.getMinutes();
919					output += (minutes > 9) ? minutes : '0'+minutes;
920					break;
921
922				case 's':
923					seconds = time.getSeconds();
924					output += (seconds > 9) ? seconds : '0'+seconds;
925					break;
926
927				default:
928					output += code;
929			}
930		}
931
932		return output;
933	}
934
935	function _time2int(timeString)
936	{
937		if (timeString === '') return null;
938		if (!timeString || timeString+0 == timeString) return timeString;
939
940		if (typeof(timeString) == 'object') {
941			timeString = timeString.getHours()+':'+_pad2(timeString.getMinutes())+':'+_pad2(timeString.getSeconds());
942		}
943
944		timeString = timeString.toLowerCase();
945
946		var d = new Date(0);
947		var time;
948
949		// try to parse time input
950		if (timeString.indexOf(":") === -1) {
951			// no colon present
952			time = timeString.match(/^([0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/);
953
954			if (!time) {
955				time = timeString.match(/^([0-2][0-9]):?([0-5][0-9])?:?([0-5][0-9])?\s*([pa]?)m?$/);
956			}
957		} else {
958			time = timeString.match(/^(\d{1,2})(?::([0-5][0-9]))?(?::([0-5][0-9]))?\s*([pa]?)m?$/);
959		}
960
961		if (!time) {
962			return null;
963		}
964
965		var hour = parseInt(time[1]*1, 10);
966		var hours;
967
968		if (time[4]) {
969			if (hour == 12) {
970				hours = (time[4] == 'p') ? 12 : 0;
971			} else {
972				hours = (hour + (time[4] == 'p' ? 12 : 0));
973			}
974
975		} else {
976			hours = hour;
977		}
978
979		var minutes = ( time[2]*1 || 0 );
980		var seconds = ( time[3]*1 || 0 );
981		return hours*3600 + minutes*60 + seconds;
982	}
983
984	function _pad2(n) {
985		return ("0" + n).slice(-2);
986	}
987
988	// Plugin entry
989	$.fn.timepicker = function(method)
990	{
991		if (!this.length) return this;
992		if(methods[method]) { return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); }
993		else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); }
994		else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); }
995	};
996}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.