PageSourceSearch

https://www.hafnerfinancial.com/modules/contrib/jquery_timepicker/…/jt.timepicker/jquery.timepicker.js?v=1.x

js hafnerfinancial.com collected 2026-09-29 00:15:48 UTC 36,061 bytes, 1,383 lines download raw bytes

1/*!
2 * jquery-timepicker v1.11.13 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
3 * Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
4 * License: MIT
5 */
6
7(function(factory) {
8  if (
9    typeof exports === "object" &&
10    exports &&
11    typeof module === "object" &&
12    module &&
13    module.exports === exports
14  ) {
15    // Browserify. Attach to jQuery module.
16    factory(require("jquery"));
17  } else if (typeof define === "function" && define.amd) {
18    // AMD. Register as an anonymous module.
19    define(["jquery"], factory);
20  } else {
21    // Browser globals
22    factory(jQuery);
23  }
24})(function($) {
25  var _ONE_DAY = 86400;
26  var _lang = {
27    am: "am",
28    pm: "pm",
29    AM: "AM",
30    PM: "PM",
31    decimal: ".",
32    mins: "mins",
33    hr: "hr",
34    hrs: "hrs"
35  };
36
37  var _DEFAULTS = {
38    appendTo: "body",
39    className: null,
40    closeOnWindowScroll: false,
41    disableTextInput: false,
42    disableTimeRanges: [],
43    disableTouchKeyboard: false,
44    durationTime: null,
45    forceRoundTime: false,
46    maxTime: null,
47    minTime: null,
48    noneOption: false,
49    orientation: "l",
50    roundingFunction: function(seconds, settings) {
51      if (seconds === null) {
52        return null;
53      } else if (typeof settings.step !== "number") {
54        // TODO: nearest fit irregular steps
55        return seconds;
56      } else {
57        var offset = seconds % (settings.step * 60); // step is in minutes
58
59        var start = settings.minTime || 0;
60
61        // adjust offset by start mod step so that the offset is aligned not to 00:00 but to the start
62        offset -= start % (settings.step * 60);
63
64        if (offset >= settings.step * 30) {
65          // if offset is larger than a half step, round up
66          seconds += settings.step * 60 - offset;
67        } else {
68          // round down
69          seconds -= offset;
70        }
71
72        return _moduloSeconds(seconds, settings);
73      }
74    },
75    scrollDefault: null,
76    selectOnBlur: false,
77    show2400: false,
78    showDuration: false,
79    showOn: ["click", "focus"],
80    showOnFocus: true,
81    step: 30,
82    stopScrollPropagation: false,
83    timeFormat: "g:ia",
84    typeaheadHighlight: true,
85    useSelect: false,
86    wrapHours: true
87  };
88
89  var methods = {
90    init: function(options) {
91      return this.each(function() {
92        var self = $(this);
93
94        // pick up settings from data attributes
95        var attributeOptions = [];
96        for (var key in _DEFAULTS) {
97          if (self.data(key)) {
98            attributeOptions[key] = self.data(key);
99          }
100        }
101
102        var settings = $.extend({}, _DEFAULTS, options, attributeOptions);
103
104        if (settings.lang) {
105          _lang = $.extend(_lang, settings.lang);
106        }
107
108        settings = _parseSettings(settings);
109        self.data("timepicker-settings", settings);
110        self.addClass("ui-timepicker-input");
111
112        if (settings.useSelect) {
113          _render(self);
114        } else {
115          self.prop("autocomplete", "off");
116          if (settings.showOn) {
117            for (var i in settings.showOn) {
118              self.on(settings.showOn[i] + ".timepicker", methods.show);
119            }
120          }
121          self.on("change.timepicker", _formatValue);
122          self.on("keydown.timepicker", _keydownhandler);
123          self.on("keyup.timepicker", _keyuphandler);
124          if (settings.disableTextInput) {
125            self.on("keydown.timepicker", _disableTextInputHandler);
126          }
127          self.on("cut.timepicker", _keyuphandler);
128          self.on("paste.timepicker", _keyuphandler);
129
130          _formatValue.call(self.get(0), null, "initial");
131        }
132      });
133    },
134
135    show: function(e) {
136      var self = $(this);
137      var settings = self.data("timepicker-settings");
138
139      if (e) {
140        e.preventDefault();
141      }
142
143      if (settings.useSelect) {
144        self.data("timepicker-list").focus();
145        return;
146      }
147
148      if (_hideKeyboard(self)) {
149        // block the keyboard on mobile devices
150        self.blur();
151      }
152
153      var list = self.data("timepicker-list");
154
155      // check if input is readonly
156      if (self.prop("readonly")) {
157        return;
158      }
159
160      // check if list needs to be rendered
161      if (
162        !list ||
163        list.length === 0 ||
164        typeof settings.durationTime === "function"
165      ) {
166        _render(self);
167        list = self.data("timepicker-list");
168      }
169
170      if (_isVisible(list)) {
171        return;
172      }
173
174      self.data("ui-timepicker-value", self.val());
175      _setSelected(self, list);
176
177      // make sure other pickers are hidden
178      methods.hide();
179
180      // position the dropdown relative to the input
181      list.show();
182      var listOffset = {};
183
184      if (settings.orientation.match(/r/)) {
185        // right-align the dropdown
186        listOffset.left =
187          self.offset().left +
188          self.outerWidth() -
189          list.outerWidth() +
190          parseInt(list.css("marginLeft").replace("px", ""), 10);
191      } else {
192        // left-align the dropdown
193        listOffset.left =
194          self.offset().left +
195          parseInt(list.css("marginLeft").replace("px", ""), 10);
196      }
197
198      var verticalOrientation;
199      if (settings.orientation.match(/t/)) {
200        verticalOrientation = "t";
201      } else if (settings.orientation.match(/b/)) {
202        verticalOrientation = "b";
203      } else if (
204        self.offset().top + self.outerHeight(true) + list.outerHeight() >
205        $(window).height() + $(window).scrollTop()
206      ) {
207        verticalOrientation = "t";
208      } else {
209        verticalOrientation = "b";
210      }
211
212      if (verticalOrientation == "t") {
213        // position the dropdown on top
214        list.addClass("ui-timepicker-positioned-top");
215        listOffset.top =
216          self.offset().top -
217          list.outerHeight() +
218          parseInt(list.css("marginTop").replace("px", ""), 10);
219      } else {
220        // put it under the input
221        list.removeClass("ui-timepicker-positioned-top");
222        listOffset.top =
223          self.offset().top +
224          self.outerHeight() +
225          parseInt(list.css("marginTop").replace("px", ""), 10);
226      }
227
228      list.offset(listOffset);
229
230      // position scrolling
231      var selected = list.find(".ui-timepicker-selected");
232
233      if (!selected.length) {
234        var timeInt = _time2int(_getTimeValue(self));
235        if (timeInt !== null) {
236          selected = _findRow(self, list, timeInt);
237        } else if (settings.scrollDefault) {
238          selected = _findRow(self, list, settings.scrollDefault());
239        }
240      }
241
242      // if not found or disabled, intelligently find first selectable element
243      if (!selected.length || selected.hasClass("ui-timepicker-disabled")) {
244        selected = list.find("li:not(.ui-timepicker-disabled):first");
245      }
246
247      if (selected && selected.length) {
248        var topOffset =
249          list.scrollTop() + selected.position().top - selected.outerHeight();
250        list.scrollTop(topOffset);
251      } else {
252        list.scrollTop(0);
253      }
254
255      // prevent scroll propagation
256      if (settings.stopScrollPropagation) {
257        $(
258          document
259        ).on("wheel.ui-timepicker", ".ui-timepicker-wrapper", function(e) {
260          e.preventDefault();
261          var currentScroll = $(this).scrollTop();
262          $(this).scrollTop(currentScroll + e.originalEvent.deltaY);
263        });
264      }
265
266      // attach close handlers
267      $(document).on(
268        "touchstart.ui-timepicker mousedown.ui-timepicker",
269        _closeHandler
270      );
271      $(window).on("resize.ui-timepicker", _closeHandler);
272      if (settings.closeOnWindowScroll) {
273        $(document).on("scroll.ui-timepicker", _closeHandler);
274      }
275
276      self.trigger("showTimepicker");
277
278      return this;
279    },
280
281    hide: function(e) {
282      var self = $(this);
283      var settings = self.data("timepicker-settings");
284
285      if (settings && settings.useSelect) {
286        self.blur();
287      }
288
289      $(".ui-timepicker-wrapper").each(function() {
290        var list = $(this);
291        if (!_isVisible(list)) {
292          return;
293        }
294
295        var self = list.data("timepicker-input");
296        var settings = self.data("timepicker-settings");
297
298        if (settings && settings.selectOnBlur) {
299          _selectValue(self);
300        }
301
302        list.hide();
303        self.trigger("hideTimepicker");
304      });
305
306      return this;
307    },
308
309    option: function(key, value) {
310      if (typeof key == "string" && typeof value == "undefined") {
311        return $(this).data("timepicker-settings")[key];
312      }
313
314      return this.each(function() {
315        var self = $(this);
316        var settings = self.data("timepicker-settings");
317        var list = self.data("timepicker-list");
318
319        if (typeof key == "object") {
320          settings = $.extend(settings, key);
321        } else if (typeof key == "string") {
322          settings[key] = value;
323        }
324
325        settings = _parseSettings(settings);
326
327        self.data("timepicker-settings", settings);
328
329        _formatValue.call(self.get(0), { type: "change" }, "initial");
330
331        if (list) {
332          list.remove();
333          self.data("timepicker-list", false);
334        }
335
336        if (settings.useSelect) {
337          _render(self);
338        }
339      });
340    },
341
342    getSecondsFromMidnight: function() {
343      return _time2int(_getTimeValue(this));
344    },
345
346    getTime: function(relative_date) {
347      var self = this;
348
349      var time_string = _getTimeValue(self);
350      if (!time_string) {
351        return null;
352      }
353
354      var offset = _time2int(time_string);
355      if (offset === null) {
356        return null;
357      }
358
359      if (!relative_date) {
360        relative_date = new Date();
361      }
362
363      // construct a Date from relative date, and offset's time
364      var time = new Date(relative_date);
365      time.setHours(offset / 3600);
366      time.setMinutes((offset % 3600) / 60);
367      time.setSeconds(offset % 60);
368      time.setMilliseconds(0);
369
370      return time;
371    },
372
373    isVisible: function() {
374      var self = this;
375      var list = self.data("timepicker-list");
376      return !!(list && _isVisible(list));
377    },
378
379    setTime: function(value) {
380      var self = this;
381      var settings = self.data("timepicker-settings");
382
383      if (settings.forceRoundTime) {
384        var prettyTime = _roundAndFormatTime(_time2int(value), settings);
385      } else {
386        var prettyTime = _int2time(_time2int(value), settings);
387      }
388
389      if (value && prettyTime === null && settings.noneOption) {
390        prettyTime = value;
391      }
392
393      _setTimeValue(self, prettyTime, "initial");
394      _formatValue.call(self.get(0), { type: "change" }, "initial");
395
396      if (self.data("timepicker-list")) {
397        _setSelected(self, self.data("timepicker-list"));
398      }
399
400      return this;
401    },
402
403    remove: function() {
404      var self = this;
405
406      // check if this element is a timepicker
407      if (!self.hasClass("ui-timepicker-input")) {
408        return;
409      }
410
411      var settings = self.data("timepicker-settings");
412      self.removeAttr("autocomplete", "off");
413      self.removeClass("ui-timepicker-input");
414      self.removeData("timepicker-settings");
415      self.off(".timepicker");
416
417      // timepicker-list won't be present unless the user has interacted with this timepicker
418      if (self.data("timepicker-list")) {
419        self.data("timepicker-list").remove();
420      }
421
422      if (settings.useSelect) {
423        self.show();
424      }
425
426      self.removeData("timepicker-list");
427
428      return this;
429    }
430  };
431
432  // private methods
433
434  function _isVisible(elem) {
435    var el = elem[0];
436    return el.offsetWidth > 0 && el.offsetHeight > 0;
437  }
438
439  function _parseSettings(settings) {
440    if (settings.minTime) {
441      settings.minTime = _time2int(settings.minTime);
442    }
443
444    if (settings.maxTime) {
445      settings.maxTime = _time2int(settings.maxTime);
446    }
447
448    if (settings.durationTime && typeof settings.durationTime !== "function") {
449      settings.durationTime = _time2int(settings.durationTime);
450    }
451
452    if (settings.scrollDefault == "now") {
453      settings.scrollDefault = function() {
454        return settings.roundingFunction(_time2int(new Date()), settings);
455      };
456    } else if (
457      settings.scrollDefault &&
458      typeof settings.scrollDefault != "function"
459    ) {
460      var val = settings.scrollDefault;
461      settings.scrollDefault = function() {
462        return settings.roundingFunction(_time2int(val), settings);
463      };
464    } else if (settings.minTime) {
465      settings.scrollDefault = function() {
466        return settings.roundingFunction(settings.minTime, settings);
467      };
468    }
469
470    if (
471      $.type(settings.timeFormat) === "string" &&
472      settings.timeFormat.match(/[gh]/)
473    ) {
474      settings._twelveHourTime = true;
475    }
476
477    if (
478      settings.showOnFocus === false &&
479      settings.showOn.indexOf("focus") != -1
480    ) {
481      settings.showOn.splice(settings.showOn.indexOf("focus"), 1);
482    }
483
484    if (settings.disableTimeRanges.length > 0) {
485      // convert string times to integers
486      for (var i in settings.disableTimeRanges) {
487        settings.disableTimeRanges[i] = [
488          _time2int(settings.disableTimeRanges[i][0]),
489          _time2int(settings.disableTimeRanges[i][1])
490        ];
491      }
492
493      // sort by starting time
494      settings.disableTimeRanges = settings.disableTimeRanges.sort(function(
495        a,
496        b
497      ) {
498        return a[0] - b[0];
499      });
500
501      // merge any overlapping ranges
502      for (var i = settings.disableTimeRanges.length - 1; i > 0; i--) {
503        if (
504          settings.disableTimeRanges[i][0] <=
505          settings.disableTimeRanges[i - 1][1]
506        ) {
507          settings.disableTimeRanges[i - 1] = [
508            Math.min(
509              settings.disableTimeRanges[i][0],
510              settings.disableTimeRanges[i - 1][0]
511            ),
512            Math.max(
513              settings.disableTimeRanges[i][1],
514              settings.disableTimeRanges[i - 1][1]
515            )
516          ];
517          settings.disableTimeRanges.splice(i, 1);
518        }
519      }
520    }
521
522    return settings;
523  }
524
525  function _render(self) {
526    var settings = self.data("timepicker-settings");
527    var list = self.data("timepicker-list");
528
529    if (list && list.length) {
530      list.remove();
531      self.data("timepicker-list", false);
532    }
533
534    if (settings.useSelect) {
535      list = $("<select />", { class: "ui-timepicker-select" });
536      var wrapped_list = list;
537    } else {
538      list = $("<ul />", { class: "ui-timepicker-list" });
539
540      var wrapped_list = $("<div />", {
541        class: "ui-timepicker-wrapper",
542        tabindex: -1
543      });
544      wrapped_list.css({ display: "none", position: "absolute" }).append(list);
545    }
546
547    if (settings.noneOption) {
548      if (settings.noneOption === true) {
549        settings.noneOption = settings.useSelect ? "Time..." : "None";
550      }
551
552      if ($.isArray(settings.noneOption)) {
553        for (var i in settings.noneOption) {
554          if (parseInt(i, 10) == i) {
555            var noneElement = _generateNoneElement(
556              settings.noneOption[i],
557              settings.useSelect
558            );
559            list.append(noneElement);
560          }
561        }
562      } else {
563        var noneElement = _generateNoneElement(
564          settings.noneOption,
565          settings.useSelect
566        );
567        list.append(noneElement);
568      }
569    }
570
571    if (settings.className) {
572      wrapped_list.addClass(settings.className);
573    }
574
575    if (
576      (settings.minTime !== null || settings.durationTime !== null) &&
577      settings.showDuration
578    ) {
579      var stepval =
580        typeof settings.step == "function" ? "function" : settings.step;
581      wrapped_list.addClass("ui-timepicker-with-duration");
582      wrapped_list.addClass("ui-timepicker-step-" + settings.step);
583    }
584
585    var durStart = settings.minTime;
586    if (typeof settings.durationTime === "function") {
587      durStart = _time2int(settings.durationTime());
588    } else if (settings.durationTime !== null) {
589      durStart = settings.durationTime;
590    }
591    var start = settings.minTime !== null ? settings.minTime : 0;
592    var end =
593      settings.maxTime !== null ? settings.maxTime : start + _ONE_DAY - 1;
594
595    if (end < start) {
596      // make sure the end time is greater than start time, otherwise there will be no list to show
597      end += _ONE_DAY;
598    }
599
600    if (
601      end === _ONE_DAY - 1 &&
602      $.type(settings.timeFormat) === "string" &&
603      settings.show2400
604    ) {
605      // show a 24:00 option when using military time
606      end = _ONE_DAY;
607    }
608
609    var dr = settings.disableTimeRanges;
610    var drCur = 0;
611    var drLen = dr.length;
612
613    var stepFunc = settings.step;
614    if (typeof stepFunc != "function") {
615      stepFunc = function() {
616        return settings.step;
617      };
618    }
619
620    for (var i = start, j = 0; i <= end; j++, i += stepFunc(j) * 60) {
621      var timeInt = i;
622      var timeString = _int2time(timeInt, settings);
623
624      if (settings.useSelect) {
625        var row = $("<option />
625", { value: timeString });
626        row.text(timeString);
627      } else {
628        var row = $("<li />");
629        row.addClass(
630          timeInt % _ONE_DAY < _ONE_DAY / 2
631            ? "ui-timepicker-am"
632            : "ui-timepicker-pm"
633        );
634        row.data("time", _moduloSeconds(timeInt, settings));
635        row.text(timeString);
636      }
637
638      if (
639        (settings.minTime !== null || settings.durationTime !== null) &&
640        settings.showDuration
641      ) {
642        var durationString = _int2duration(i - durStart, settings.step);
643        if (settings.useSelect) {
644          row.text(row.text() + " (" + durationString + ")");
645        } else {
646          var duration = $("<span />", { class: "ui-timepicker-duration" });
647          duration.text(" (" + durationString + ")");
648          row.append(duration);
649        }
650      }
651
652      if (drCur < drLen) {
653        if (timeInt >= dr[drCur][1]) {
654          drCur += 1;
655        }
656
657        if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
658          if (settings.useSelect) {
659            row.prop("disabled", true);
660          } else {
661            row.addClass("ui-timepicker-disabled");
662          }
663        }
664      }
665
666      list.append(row);
667    }
668
669    wrapped_list.data("timepicker-input", self);
670    self.data("timepicker-list", wrapped_list);
671
672    if (settings.useSelect) {
673      if (self.val()) {
674        list.val(_roundAndFormatTime(_time2int(self.val()), settings));
675      }
676
677      list.on("focus", function() {
678        $(this)
679          .data("timepicker-input")
680          .trigger("showTimepicker");
681      });
682      list.on("blur", function() {
683        $(this)
684          .data("timepicker-input")
685          .trigger("hideTimepicker");
686      });
687      list.on("change", function() {
688        _setTimeValue(self, $(this).val(), "select");
689      });
690
691      _setTimeValue(self, list.val(), "initial");
692      self.hide().after(list);
693    } else {
694      var appendTo = settings.appendTo;
695      if (typeof appendTo === "string") {
696        appendTo = $(appendTo);
697      } else if (typeof appendTo === "function") {
698        appendTo = appendTo(self);
699      }
700      appendTo.append(wrapped_list);
701      _setSelected(self, list);
702
703      list.on("mousedown click", "li", function(e) {
704        // hack: temporarily disable the focus handler
705        // to deal with the fact that IE fires 'focus'
706        // events asynchronously
707        self.off("focus.timepicker");
708        self.on("focus.timepicker-ie-hack", function() {
709          self.off("focus.timepicker-ie-hack");
710          self.on("focus.timepicker", methods.show);
711        });
712
713        if (!_hideKeyboard(self)) {
714          self[0].focus();
715        }
716
717        // make sure only the clicked row is selected
718        list.find("li").removeClass("ui-timepicker-selected");
719        $(this).addClass("ui-timepicker-selected");
720
721        if (_selectValue(self)) {
722          self.trigger("hideTimepicker");
723
724          list.on("mouseup.timepicker click.timepicker", "li", function(e) {
725            list.off("mouseup.timepicker click.timepicker");
726            wrapped_list.hide();
727          });
728        }
729      });
730    }
731  }
732
733  function _generateNoneElement(optionValue, useSelect) {
734    var label, className, value;
735
736    if (typeof optionValue == "object") {
737      label = optionValue.label;
738      className = optionValue.className;
739      value = optionValue.value;
740    } else if (typeof optionValue == "string") {
741      label = optionValue;
742      value = '';
743    } else {
744      $.error("Invalid noneOption value");
745    }
746
747    if (useSelect) {
748      return $("<option />", {
749        value: value,
750        class: className,
751        text: label
752      });
753    } else {
754      return $("<li />", {
755        class: className,
756        text: label
757      }).data("time", String(value));
758    }
759  }
760
761  function _roundAndFormatTime(seconds, settings) {
762    seconds = settings.roundingFunction(seconds, settings);
763    if (seconds !== null) {
764      return _int2time(seconds, settings);
765    }
766  }
767
768  // event handler to decide whether to close timepicker
769  function _closeHandler(e) {
770    if (e.target == window) {
771      // mobile Chrome fires focus events against window for some reason
772      return;
773    }
774
775    var target = $(e.target);
776
777    if (
778      target.closest(".ui-timepicker-input").length ||
779      target.closest(".ui-timepicker-wrapper").length
780    ) {
781      // active timepicker was focused. ignore
782      return;
783    }
784
785    methods.hide();
786    $(document).unbind(".ui-timepicker");
787    $(window).unbind(".ui-timepicker");
788  }
789
790  function _hideKeyboard(self) {
791    var settings = self.data("timepicker-settings");
792    return (
793      (window.navigator.msMaxTouchPoints || "ontouchstart" in document) &&
794      settings.disableTouchKeyboard
795    );
796  }
797
798  function _findRow(self, list, value) {
799    if (!value && value !== 0) {
800      return false;
801    }
802
803    var settings = self.data("timepicker-settings");
804    var out = false;
805    var value = settings.roundingFunction(value, settings);
806
807    // loop through the menu items
808    list.find("li").each(function(i, obj) {
809      var jObj = $(obj);
810      if (typeof jObj.data("time") != "number") {
811        return;
812      }
813
814      if (jObj.data("time") == value) {
815        out = jObj;
816        return false;
817      }
818    });
819
820    return out;
821  }
822
823  function _setSelected(self, list) {
824    list.find("li").removeClass("ui-timepicker-selected");
825
826    var settings = self.data("timepicker-settings");
827    var timeValue = _time2int(_getTimeValue(self), settings);
828    if (timeValue === null) {
829      return;
830    }
831
832    var selected = _findRow(self, list, timeValue);
833    if (selected) {
834      var topDelta = selected.offset().top - list.offset().top;
835
836      if (
837        topDelta + selected.outerHeight() > list.outerHeight() ||
838        topDelta < 0
839      ) {
840        list.scrollTop(
841          list.scrollTop() + selected.position().top - selected.outerHeight()
842        );
843      }
844
845      if (settings.forceRoundTime || selected.data("time") === timeValue) {
846        selected.addClass("ui-timepicker-selected");
847      }
848    }
849  }
850
851  function _formatValue(e, origin) {
852    if (origin == "timepicker") {
853      return;
854    }
855
856    var self = $(this);
857
858    if (this.value === "") {
859      _setTimeValue(self, null, origin);
860      return;
861    }
862
863    if (self.is(":focus") && (!e || e.type != "change")) {
864      return;
865    }
866
867    var settings = self.data("timepicker-settings");
868    var seconds = _time2int(this.value, settings);
869
870    if (seconds === null) {
871      self.trigger("timeFormatError");
872      return;
873    }
874
875    var rangeError = false;
876    // check that the time in within bounds
877    if (
878      settings.minTime !== null &&
879      settings.maxTime !== null &&
880      (seconds < settings.minTime || seconds > settings.maxTime)
881    ) {
882      rangeError = true;
883    }
884
885    // check that time isn't within disabled time ranges
886    $.each(settings.disableTimeRanges, function() {
887      if (seconds >= this[0] && seconds < this[1]) {
888        rangeError = true;
889        return false;
890      }
891    });
892
893    if (settings.forceRoundTime) {
894      var roundSeconds = settings.roundingFunction(seconds, settings);
895      if (roundSeconds != seconds) {
896        seconds = roundSeconds;
897        origin = null;
898      }
899    }
900
901    var prettyTime = _int2time(seconds, settings);
902
903    if (rangeError) {
904      if (
905        _setTimeValue(self, prettyTime, "error") ||
906        (e && e.type == "change")
907      ) {
908        self.trigger("timeRangeError");
909      }
910    } else {
911      _setTimeValue(self, prettyTime, origin);
912    }
913  }
914
915  function _getTimeValue(self) {
916    if (self.is("input")) {
917      return self.val();
918    } else {
919      // use the element's data attributes to store values
920      return self.data("ui-timepicker-value");
921    }
922  }
923
924  function _setTimeValue(self, value, source) {
925    if (self.is("input")) {
926      self.val(value);
927
928      var settings = self.data("timepicker-settings");
929      if (settings.useSelect && source != "select") {
930        self
931          .data("timepicker-list")
932          .val(_roundAndFormatTime(_time2int(value), settings));
933      }
934    }
935
936    if (self.data("ui-timepicker-value") != value) {
937      self.data("ui-timepicker-value", value);
938      if (source == "select") {
939        self
940          .trigger("selectTime")
941          .trigger("changeTime")
942          .trigger("change", "timepicker");
943      } else if (["error", "initial"].indexOf(source) == -1) {
944        self.trigger("changeTime");
945      }
946
947      return true;
948    } else {
949      if (["error", "initial"].indexOf(source) == -1) {
950        self.trigger("selectTime");
951      }
952      return false;
953    }
954  }
955
956  /*
957	*  Filter freeform input
958	*/
959  function _disableTextInputHandler(e) {
960    switch (e.keyCode) {
961      case 13: // return
962      case 9: //tab
963        return;
964
965      default:
966        e.preventDefault();
967    }
968  }
969
970  /*
971	*  Keyboard navigation via arrow keys
972	*/
973  function _keydownhandler(e) {
974    var self = $(this);
975    var list = self.data("timepicker-list");
976
977    if (!list || !_isVisible(list)) {
978      if (e.keyCode == 40) {
979        // show the list!
980        methods.show.call(self.get(0));
981        list = self.data("timepicker-list");
982        if (!_hideKeyboard(self)) {
983          self.focus();
984        }
985      } else {
986        return true;
987      }
988    }
989
990    switch (e.keyCode) {
991      case 13: // return
992        if (_selectValue(self)) {
993          _formatValue.call(self.get(0), { type: "change" });
994          methods.hide.apply(this);
995        }
996
997        e.preventDefault();
998        return false;
999
1000      case 38: // up
1001        var selected = list.find(".ui-timepicker-selected");
1002
1003        if (!selected.length) {
1004          list.find("li").each(function(i, obj) {
1005            if ($(obj).position().top > 0) {
1006              selected = $(obj);
1007              return false;
1008            }
1009          });
1010          selected.addClass("ui-timepicker-selected");
1011        } else if (!selected.is(":first-child")) {
1012          selected.removeClass("ui-timepicker-selected");
1013          selected.prev().addClass("ui-timepicker-selected");
1014
1015          if (selected.prev().position().top < selected.outerHeight()) {
1016            list.scrollTop(list.scrollTop() - selected.outerHeight());
1017          }
1018        }
1019
1020        return false;
1021
1022      case 40: // down
1023        selected = list.find(".ui-timepicker-selected");
1024
1025        if (selected.length === 0) {
1026          list.find("li").each(function(i, obj) {
1027            if ($(obj).position().top > 0) {
1028              selected = $(obj);
1029              return false;
1030            }
1031          });
1032
1033          selected.addClass("ui-timepicker-selected");
1034        } else if (!selected.is(":last-child")) {
1035          selected.removeClass("ui-timepicker-selected");
1036          selected.next().addClass("ui-timepicker-selected");
1037
1038          if (
1039            selected.next().position().top + 2 * selected.outerHeight() >
1040            list.outerHeight()
1041          ) {
1042            list.scrollTop(list.scrollTop() + selected.outerHeight());
1043          }
1044        }
1045
1046        return false;
1047
1048      case 27: // escape
1049        list.find("li").removeClass("ui-timepicker-selected");
1050        methods.hide();
1051        break;
1052
1053      case 9: //tab
1054        methods.hide();
1055        break;
1056
1057      default:
1058        return true;
1059    }
1060  }
1061
1062  /*
1063	*	Time typeahead
1064	*/
1065  function _keyuphandler(e) {
1066    var self = $(this);
1067    var list = self.data("timepicker-list");
1068    var settings = self.data("timepicker-settings");
1069
1070    if (!list || !_isVisible(list) || settings.disableTextInput) {
1071      return true;
1072    }
1073
1074    if (e.type === "paste" || e.type === "cut") {
1075      setTimeout(function() {
1076        if (settings.typeaheadHighlight) {
1077          _setSelected(self, list);
1078        } else {
1079          list.hide();
1080        }
1081      }, 0);
1082      return;
1083    }
1084
1085    switch (e.keyCode) {
1086      case 96: // numpad numerals
1087      case 97:
1088      case 98:
1089      case 99:
1090      case 100:
1091      case 101:
1092      case 102:
1093      case 103:
1094      case 104:
1095      case 105:
1096      case 48: // numerals
1097      case 49:
1098      case 50:
1099      case 51:
1100      case 52:
1101      case 53:
1102      case 54:
1103      case 55:
1104      case 56:
1105      case 57:
1106      case 65: // a
1107      case 77: // m
1108      case 80: // p
1109      case 186: // colon
1110      case 8: // backspace
1111      case 46: // delete
1112        if (settings.typeaheadHighlight) {
1113          _setSelected(self, list);
1114        } else {
1115          list.hide();
1116        }
1117        break;
1118    }
1119  }
1120
1121  function _selectValue(self) {
1122    var settings = self.data("timepicker-settings");
1123    var list = self.data("timepicker-list");
1124    var timeValue = null;
1125
1126    var cursor = list.find(".ui-timepicker-selected");
1127
1128    if (cursor.hasClass("ui-timepicker-disabled")) {
1129      return false;
1130    }
1131
1132    if (cursor.length) {
1133      // selected value found
1134      timeValue = cursor.data("time");
1135    }
1136
1137    if (timeValue !== null) {
1138      if (typeof timeValue != "string") {
1139        timeValue = _int2time(timeValue, settings);
1140      }
1141
1142      _setTimeValue(self, timeValue, "select");
1143    }
1144
1145    return true;
1146  }
1147
1148  function _int2duration(seconds, step) {
1149    seconds = Math.abs(seconds);
1150    var minutes = Math.round(seconds / 60),
1151      duration = [],
1152      hours,
1153      mins;
1154
1155    if (minutes < 60) {
1156      // Only show (x mins) under 1 hour
1157      duration = [minutes, _lang.mins];
1158    } else {
1159      hours = Math.floor(minutes / 60);
1160      mins = minutes % 60;
1161
1162      // Show decimal notation (eg: 1.5 hrs) for 30 minute steps
1163      if (step == 30 && mins == 30) {
1164        hours += _lang.decimal + 5;
1165      }
1166
1167      duration.push(hours);
1168      duration.push(hours == 1 ? _lang.hr : _lang.hrs);
1169
1170      // Show remainder minutes notation (eg: 1 hr 15 mins) for non-30 minute steps
1171      // and only if there are remainder minutes to show
1172      if (step != 30 && mins) {
1173        duration.push(mins);
1174        duration.push(_lang.mins);
1175      }
1176    }
1177
1178    return duration.join(" ");
1179  }
1180
1181  function _int2time(timeInt, settings) {
1182    if (typeof timeInt != "number") {
1183      return null;
1184    }
1185
1186    var seconds = parseInt(timeInt % 60),
1187      minutes = parseInt((timeInt / 60) % 60),
1188      hours = parseInt((timeInt / (60 * 60)) % 24);
1189
1190    var time = new Date(1970, 0, 2, hours, minutes, seconds, 0);
1191
1192    if (isNaN(time.getTime())) {
1193      return null;
1194    }
1195
1196    if ($.type(settings.timeFormat) === "function") {
1197      return settings.timeFormat(time);
1198    }
1199
1200    var output = "";
1201    var hour, code;
1202    for (var i = 0; i < settings.timeFormat.length; i++) {
1203      code = settings.timeFormat.charAt(i);
1204      switch (code) {
1205        case "a":
1206          output += time.getHours() > 11 ? _lang.pm : _lang.am;
1207          break;
1208
1209        case "A":
1210          output += time.getHours() > 11 ? _lang.PM : _lang.AM;
1211          break;
1212
1213        case "g":
1214          hour = time.getHours() % 12;
1215          output += hour === 0 ? "12" : hour;
1216          break;
1217
1218        case "G":
1219          hour = time.getHours();
1220          if (timeInt === _ONE_DAY) hour = settings.show2400 ? 24 : 0;
1221          output += hour;
1222          break;
1223
1224        case "h":
1225          hour = time.getHours() % 12;
1226
1227          if (hour !== 0 && hour < 10) {
1228            hour = "0" + hour;
1229          }
1230
1231          output += hour === 0 ? "12" : hour;
1232          break;
1233
1234        case "H":
1235          hour = time.getHours();
1236          if (timeInt === _ONE_DAY) hour = settings.show2400 ? 24 : 0;
1237          output += hour > 9 ? hour : "0" + hour;
1238          break;
1239
1240        case "i":
1241          var minutes = time.getMinutes();
1242          output += minutes > 9 ? minutes : "0" + minutes;
1243          break;
1244
1245        case "s":
1246          seconds = time.getSeconds();
1247          output += seconds > 9 ? seconds : "0" + seconds;
1248          break;
1249
1250        case "\\":
1251          // escape character; add the next character and skip ahead
1252          i++;
1253          output += settings.timeFormat.charAt(i);
1254          break;
1255
1256        default:
1257          output += code;
1258      }
1259    }
1260
1261    return output;
1262  }
1263
1264  function _time2int(timeString, settings) {
1265    if (timeString === "" || timeString === null) return null;
1266    if (typeof timeString == "object") {
1267      return (
1268        timeString.getHours() * 3600 +
1269        timeString.getMinutes() * 60 +
1270        timeString.getSeconds()
1271      );
1272    }
1273    if (typeof timeString != "string") {
1274      return timeString;
1275    }
1276
1277    timeString = timeString.toLowerCase().replace(/[\s\.]/g, "");
1278
1279    // if the last character is an "a" or "p", add the "m"
1280    if (timeString.slice(-1) == "a" || timeString.slice(-1) == "p") {
1281      timeString += "m";
1282    }
1283
1284    var ampmRegex =
1285      "(" +
1286      _lang.am.replace(".", "") +
1287      "|" +
1288      _lang.pm.replace(".", "") +
1289      "|" +
1290      _lang.AM.replace(".", "") +
1291      "|" +
1292      _lang.PM.replace(".", "") +
1293      ")?";
1294
1295    // try to parse time input
1296    var pattern = new RegExp(
1297      "^" +
1298        ampmRegex +
1299        "([0-9]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?" +
1300        ampmRegex +
1301        "$"
1302    );
1303
1304    var time = timeString.match(pattern);
1305    if (!time) {
1306      return null;
1307    }
1308
1309    var hour = parseInt(time[2] * 1, 10);
1310    var ampm = time[1] || time[5];
1311    var hours = hour;
1312    var minutes = time[3] * 1 || 0;
1313    var seconds = time[4] * 1 || 0;
1314
1315    if (hour <= 12 && ampm) {
1316      var isPm = ampm == _lang.pm || ampm == _lang.PM;
1317
1318      if (hour == 12) {
1319        hours = isPm ? 12 : 0;
1320      } else {
1321        hours = hour + (isPm ? 12 : 0);
1322      }
1323    } else if (settings) {
1324      var t = hour * 3600 + minutes * 60 + seconds;
1325      if (t >= _ONE_DAY + (settings.show2400 ? 1 : 0)) {
1326        if (settings.wrapHours === false) {
1327          return null;
1328        }
1329
1330        hours = hour % 24;
1331      }
1332    }
1333
1334    var timeInt = hours * 3600 + minutes * 60 + seconds;
1335
1336    // if no am/pm provided, intelligently guess based on the scrollDefault
1337    if (
1338      hour < 12 &&
1339      !ampm &&
1340      settings &&
1341      settings._twelveHourTime &&
1342      settings.scrollDefault
1343    ) {
1344      var delta = timeInt - settings.scrollDefault();
1345      if (delta < 0 && delta >= _ONE_DAY / -2) {
1346        timeInt = (timeInt + _ONE_DAY / 2) % _ONE_DAY;
1347      }
1348    }
1349
1350    return timeInt;
1351  }
1352
1353  function _pad2(n) {
1354    return ("0" + n).slice(-2);
1355  }
1356
1357  function _moduloSeconds(seconds, settings) {
1358    if (seconds == _ONE_DAY && settings.show2400) {
1359      return seconds;
1360    }
1361
1362    return seconds % _ONE_DAY;
1363  }
1364
1365  // Plugin entry
1366  $.fn.timepicker = function(method) {
1367    if (!this.length) return this;
1368    if (methods[method]) {
1369      // check if this element is a timepicker
1370      if (!this.hasClass("ui-timepicker-input")) {
1371        return this;
1372      }
1373      return methods[method].apply(
1374        this,
1375        Array.prototype.slice.call(arguments, 1)
1376      );
1377    } else if (typeof method === "object" || !method) {
1378      return methods.init.apply(this, arguments);
1379    } else {
1380      $.error("Method " + method + " does not exist on jQuery.timepicker");
1381    }
1382  };
1383});

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.