/*! * jquery-timepicker v1.11.1 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation. * Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/ * License: MIT */ (function (factory) { if (typeof exports === "object" && exports && typeof module === "object" && module && module.exports === exports) { // Browserify. Attach to jQuery module. factory(require("jquery")); } else if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['jquery'], factory); } else { // Browser globals factory(jQuery); } }(function ($) { var _ONE_DAY = 86400; var _lang = { am: 'am', pm: 'pm', AM: 'AM', PM: 'PM', decimal: '.', mins: 'mins', hr: 'hr', hrs: 'hrs' }; var methods = { init: function(options) { return this.each(function() { var self = $(this); // pick up settings from data attributes var attributeOptions = []; for (var key in $.fn.timepicker.defaults) { if (self.data(key)) { attributeOptions[key] = self.data(key); } } var settings = $.extend({}, $.fn.timepicker.defaults, attributeOptions, options); if (settings.lang) { _lang = $.extend(_lang, settings.lang); } settings = _parseSettings(settings); self.data('timepicker-settings', settings); self.addClass('ui-timepicker-input'); if (settings.useSelect) { _render(self); } else { self.prop('autocomplete', 'off'); if (settings.showOn) { for (var i in settings.showOn) { self.on(settings.showOn[i]+'.timepicker', methods.show); } } self.on('change.timepicker', _formatValue); self.on('keydown.timepicker', _keydownhandler); self.on('keyup.timepicker', _keyuphandler); if (settings.disableTextInput) { self.on('keydown.timepicker', _disableTextInputHandler); } _formatValue.call(self.get(0)); } }); }, show: function(e) { var self = $(this); var settings = self.data('timepicker-settings'); if (e) { e.preventDefault(); } if (settings.useSelect) { self.data('timepicker-list').focus(); return; } if (_hideKeyboard(self)) { // block the keyboard on mobile devices self.blur(); } var list = self.data('timepicker-list'); // check if input is readonly if (self.prop('readonly')) { return; } // check if list needs to be rendered if (!list || list.length === 0 || typeof settings.durationTime === 'function') { _render(self); list = self.data('timepicker-list'); } if (_isVisible(list)) { return; } self.data('ui-timepicker-value', self.val()); _setSelected(self, list); // make sure other pickers are hidden methods.hide(); // position the dropdown relative to the input list.show(); var listOffset = {}; if (settings.orientation.match(/r/)) { // right-align the dropdown listOffset.left = self.offset().left + self.outerWidth() - list.outerWidth() + parseInt(list.css('marginLeft').replace('px', ''), 10); } else { // left-align the dropdown listOffset.left = self.offset().left + parseInt(list.css('marginLeft').replace('px', ''), 10); } var verticalOrientation; if (settings.orientation.match(/t/)) { verticalOrientation = 't'; } else if (settings.orientation.match(/b/)) { verticalOrientation = 'b'; } else if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) { verticalOrientation = 't'; } else { verticalOrientation = 'b'; } if (verticalOrientation == 't') { // position the dropdown on top list.addClass('ui-timepicker-positioned-top'); listOffset.top = self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10); } else { // put it under the input list.removeClass('ui-timepicker-positioned-top'); listOffset.top = self.offset().top + self.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10); } list.offset(listOffset); // position scrolling var selected = list.find('.ui-timepicker-selected'); if (!selected.length) { var timeInt = _time2int(_getTimeValue(self)); if (timeInt !== null) { selected = _findRow(self, list, timeInt); } else if (settings.scrollDefault) { selected = _findRow(self, list, settings.scrollDefault()); } } if (selected && selected.length) { var topOffset = list.scrollTop() + selected.position().top - selected.outerHeight(); list.scrollTop(topOffset); } else { list.scrollTop(0); } // prevent scroll propagation if(settings.stopScrollPropagation) { $(document).on('wheel.ui-timepicker', '.ui-timepicker-wrapper', function(e){ e.preventDefault(); var currentScroll = $(this).scrollTop(); $(this).scrollTop(currentScroll + e.originalEvent.deltaY); }); } // attach close handlers $(document).on('touchstart.ui-timepicker mousedown.ui-timepicker', _closeHandler); $(window).on('resize.ui-timepicker', _closeHandler); if (settings.closeOnWindowScroll) { $(document).on('scroll.ui-timepicker', _closeHandler); } self.trigger('showTimepicker'); return this; }, hide: function(e) { var self = $(this); var settings = self.data('timepicker-settings'); if (settings && settings.useSelect) { self.blur(); } $('.ui-timepicker-wrapper').each(function() { var list = $(this); if (!_isVisible(list)) { return; } var self = list.data('timepicker-input'); var settings = self.data('timepicker-settings'); if (settings && settings.selectOnBlur) { _selectValue(self); } list.hide(); self.trigger('hideTimepicker'); }); return this; }, option: function(key, value) { if (typeof key == 'string' && typeof value == 'undefined') { return $(this).data('timepicker-settings')[key]; } return this.each(function(){ var self = $(this); var settings = self.data('timepicker-settings'); var list = self.data('timepicker-list'); if (typeof key == 'object') { settings = $.extend(settings, key); } else if (typeof key == 'string') { settings[key] = value; } settings = _parseSettings(settings); self.data('timepicker-settings', settings); if (list) { list.remove(); self.data('timepicker-list', false); } if (settings.useSelect) { _render(self); } }); }, getSecondsFromMidnight: function() { return _time2int(_getTimeValue(this)); }, getTime: function(relative_date) { var self = this; var time_string = _getTimeValue(self); if (!time_string) { return null; } var offset = _time2int(time_string); if (offset === null) { return null; } if (!relative_date) { relative_date = new Date(); } // construct a Date from relative date, and offset's time var time = new Date(relative_date); time.setHours(offset / 3600); time.setMinutes(offset % 3600 / 60); time.setSeconds(offset % 60); time.setMilliseconds(0); return time; }, isVisible: function() { var self = this; var list = self.data('timepicker-list'); return !!(list && _isVisible(list)); }, setTime: function(value) { var self = this; var settings = self.data('timepicker-settings'); if (settings.forceRoundTime) { var prettyTime = _roundAndFormatTime(_time2int(value), settings) } else { var prettyTime = _int2time(_time2int(value), settings); } if (value && prettyTime === null && settings.noneOption) { prettyTime = value; } _setTimeValue(self, prettyTime); if (self.data('timepicker-list')) { _setSelected(self, self.data('timepicker-list')); } return this; }, remove: function() { var self = this; // check if this element is a timepicker if (!self.hasClass('ui-timepicker-input')) { return; } var settings = self.data('timepicker-settings'); self.removeAttr('autocomplete', 'off'); self.removeClass('ui-timepicker-input'); self.removeData('timepicker-settings'); self.off('.timepicker'); // timepicker-list won't be present unless the user has interacted with this timepicker if (self.data('timepicker-list')) { self.data('timepicker-list').remove(); } if (settings.useSelect) { self.show(); } self.removeData('timepicker-list'); return this; } }; // private methods function _isVisible(elem) { var el = elem[0]; return el.offsetWidth > 0 && el.offsetHeight > 0; } function _parseSettings(settings) { if (settings.minTime) { settings.minTime = _time2int(settings.minTime); } if (settings.maxTime) { settings.maxTime = _time2int(settings.maxTime); } if (settings.durationTime && typeof settings.durationTime !== 'function') { settings.durationTime = _time2int(settings.durationTime); } if (settings.scrollDefault == 'now') { settings.scrollDefault = function() { return settings.roundingFunction(_time2int(new Date()), settings); } } else if (settings.scrollDefault && typeof settings.scrollDefault != 'function') { var val = settings.scrollDefault; settings.scrollDefault = function() { return settings.roundingFunction(_time2int(val), settings); } } else if (settings.minTime) { settings.scrollDefault = function() { return settings.roundingFunction(settings.minTime, settings); } } if ($.type(settings.timeFormat) === "string" && settings.timeFormat.match(/[gh]/)) { settings._twelveHourTime = true; } if (settings.showOnFocus === false && settings.showOn.indexOf('focus') != -1) { settings.showOn.splice(settings.showOn.indexOf('focus'), 1); } if (settings.disableTimeRanges.length > 0) { // convert string times to integers for (var i in settings.disableTimeRanges) { settings.disableTimeRanges[i] = [ _time2int(settings.disableTimeRanges[i][0]), _time2int(settings.disableTimeRanges[i][1]) ]; } // sort by starting time settings.disableTimeRanges = settings.disableTimeRanges.sort(function(a, b){ return a[0] - b[0]; }); // merge any overlapping ranges for (var i = settings.disableTimeRanges.length-1; i > 0; i--) { if (settings.disableTimeRanges[i][0] <= settings.disableTimeRanges[i-1][1]) { settings.disableTimeRanges[i-1] = [ Math.min(settings.disableTimeRanges[i][0], settings.disableTimeRanges[i-1][0]), Math.max(settings.disableTimeRanges[i][1], settings.disableTimeRanges[i-1][1]) ]; settings.disableTimeRanges.splice(i, 1); } } } return settings; } function _render(self) { var settings = self.data('timepicker-settings'); var list = self.data('timepicker-list'); if (list && list.length) { list.remove(); self.data('timepicker-list', false); } if (settings.useSelect) { list = $('