diff options
Diffstat (limited to 'libgpl/timepicker')
-rw-r--r-- | libgpl/timepicker/jquery.timepicker.css | 72 | ||||
-rw-r--r-- | libgpl/timepicker/jquery.timepicker.js | 1149 | ||||
-rw-r--r-- | libgpl/timepicker/jquery.timepicker.min.js | 7 |
3 files changed, 1228 insertions, 0 deletions
diff --git a/libgpl/timepicker/jquery.timepicker.css b/libgpl/timepicker/jquery.timepicker.css new file mode 100644 index 0000000..cd75f13 --- /dev/null +++ b/libgpl/timepicker/jquery.timepicker.css @@ -0,0 +1,72 @@ +.ui-timepicker-wrapper { + overflow-y: auto; + height: 150px; + width: 6.5em; + background: #fff; + border: 1px solid #ddd; + -webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2); + -moz-box-shadow:0 5px 10px rgba(0,0,0,0.2); + box-shadow:0 5px 10px rgba(0,0,0,0.2); + outline: none; + z-index: 10001; + margin: 0; +} + +.ui-timepicker-wrapper.ui-timepicker-with-duration { + width: 13em; +} + +.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-30, +.ui-timepicker-wrapper.ui-timepicker-with-duration.ui-timepicker-step-60 { + width: 11em; +} + +.ui-timepicker-list { + margin: 0; + padding: 0; + list-style: none; +} + +.ui-timepicker-duration { + margin-left: 5px; color: #888; +} + +.ui-timepicker-list:hover .ui-timepicker-duration { + color: #888; +} + +.ui-timepicker-list li { + padding: 3px 0 3px 5px; + cursor: pointer; + white-space: nowrap; + color: #000; + list-style: none; + margin: 0; +} + +.ui-timepicker-list:hover .ui-timepicker-selected { + background: #fff; color: #000; +} + +li.ui-timepicker-selected, +.ui-timepicker-list li:hover, +.ui-timepicker-list .ui-timepicker-selected:hover { + background: #1980EC; color: #fff; +} + +li.ui-timepicker-selected .ui-timepicker-duration, +.ui-timepicker-list li:hover .ui-timepicker-duration { + color: #ccc; +} + +.ui-timepicker-list li.ui-timepicker-disabled, +.ui-timepicker-list li.ui-timepicker-disabled:hover, +.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { + color: #888; + cursor: default; +} + +.ui-timepicker-list li.ui-timepicker-disabled:hover, +.ui-timepicker-list li.ui-timepicker-selected.ui-timepicker-disabled { + background: #f2f2f2; +} diff --git a/libgpl/timepicker/jquery.timepicker.js b/libgpl/timepicker/jquery.timepicker.js new file mode 100644 index 0000000..462d8fe --- /dev/null +++ b/libgpl/timepicker/jquery.timepicker.js @@ -0,0 +1,1149 @@ +/************************ +jquery-timepicker v1.4.10 +http://jonthornton.github.com/jquery-timepicker/ + +requires jQuery 1.7+ +************************/ + + +(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 _baseDate = _generateBaseDate(); + 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'); + self.on('click.timepicker focus.timepicker', methods.show); + self.on('change.timepicker', _formatValue); + self.on('keydown.timepicker', _keydownhandler); + self.on('keyup.timepicker', _keyuphandler); + + _formatValue.call(self.get(0)); + } + }); + }, + + show: function(e) + { + var self = $(this); + var settings = self.data('timepicker-settings'); + + if (e) { + if (!settings.showOnFocus) { + return true; + } + + 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; + } + + // make sure other pickers are hidden + methods.hide(); + + // position the dropdown relative to the input + list.show(); + var listOffset = {}; + + if (settings.orientation == 'rtl') { + // 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); + } + + if ((self.offset().top + self.outerHeight(true) + list.outerHeight()) > $(window).height() + $(window).scrollTop()) { + // position the dropdown on top + listOffset.top = self.offset().top - list.outerHeight() + parseInt(list.css('marginTop').replace('px', ''), 10); + } else { + // put it under the input + 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) { + if (_getTimeValue(self)) { + selected = _findRow(self, list, _time2int(_getTimeValue(self))); + } 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); + } + + // attach close handlers + $(document).on('touchstart.ui-timepicker mousedown.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) + { + 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' && typeof value != 'undefined') { + settings[key] = value; + + } else if (typeof key == 'string') { + return settings[key]; + } + + 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; + } + + if (!relative_date) { + relative_date = new Date(); + } + var offset = _time2int(time_string); + + // construct a Date with today's 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; + }, + + setTime: function(value) + { + var self = this; + var settings = self.data('timepicker-settings'); + + if (settings.forceRoundTime) { + var prettyTime = _roundAndFormatTime(value, settings) + } else { + var prettyTime = _int2time(_time2int(value), settings.timeFormat); + } + + _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 = _time2int(new Date()); + } else if (settings.scrollDefault) { + settings.scrollDefault = _time2int(settings.scrollDefault); + } else if (settings.minTime) { + settings.scrollDefault = settings.minTime; + } + + if (settings.scrollDefault) { + settings.scrollDefault = _roundTime(settings.scrollDefault, settings); + } + + if ($.type(settings.timeFormat) === "string" && settings.timeFormat.match(/[gh]/)) { + settings._twelveHourTime = true; + } + + 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 = $('<select />', { 'class': 'ui-timepicker-select' }); + var wrapped_list = list; + } else { + list = $('<ul />', { 'class': 'ui-timepicker-list' }); + + var wrapped_list = $('<div />', { 'class': 'ui-timepicker-wrapper', 'tabindex': -1 }); + wrapped_list.css({'display':'none', 'position': 'absolute' }).append(list); + } + + if (settings.noneOption) { + if (settings.noneOption === true) { + settings.noneOption = (settings.useSelect) ? 'Time...' : 'None'; + } + + if ($.isArray(settings.noneOption)) { + for (var i in settings.noneOption) { + if (parseInt(i, 10) == i){ + var noneElement = _generateNoneElement(settings.noneOption[i], settings.useSelect); + list.append(noneElement); + } + } + } else { + var noneElement = _generateNoneElement(settings.noneOption, settings.useSelect); + list.append(noneElement); + } + } + + if (settings.className) { + wrapped_list.addClass(settings.className); + } + + if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) { + wrapped_list.addClass('ui-timepicker-with-duration'); + wrapped_list.addClass('ui-timepicker-step-'+settings.step); + } + + var durStart = settings.minTime; + if (typeof settings.durationTime === 'function') { + durStart = _time2int(settings.durationTime()); + } else if (settings.durationTime !== null) { + durStart = settings.durationTime; + } + var start = (settings.minTime !== null) ? settings.minTime : 0; + var end = (settings.maxTime !== null) ? settings.maxTime : (start + _ONE_DAY - 1); + + if (end <= start) { + // make sure the end time is greater than start time, otherwise there will be no list to show + end += _ONE_DAY; + } + + if (end === _ONE_DAY-1 && $.type(settings.timeFormat) === "string" && settings.timeFormat.indexOf('H') !== -1) { + // show a 24:00 option when using military time + end = _ONE_DAY; + } + + var dr = settings.disableTimeRanges; + var drCur = 0; + var drLen = dr.length; + + for (var i=start; i <= end; i += settings.step*60) { + var timeInt = i; + var timeString = _int2time(timeInt, settings.timeFormat); + + if (settings.useSelect) { + var row = $('<option />', { 'value': timeString }); + row.text(timeString); + } else { + var row = $('<li />'); + row.data('time', (timeInt <= 86400 ? timeInt : timeInt % 86400)); + row.text(timeString); + } + + if ((settings.minTime !== null || settings.durationTime !== null) && settings.showDuration) { + var durationString = _int2duration(i - durStart, settings.step); + if (settings.useSelect) { + row.text(row.text()+' ('+durationString+')'); + } else { + var duration = $('<span />', { 'class': 'ui-timepicker-duration' }); + duration.text(' ('+durationString+')'); + row.append(duration); + } + } + + if (drCur < drLen) { + if (timeInt >= dr[drCur][1]) { + drCur += 1; + } + + if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) { + if (settings.useSelect) { + row.prop('disabled', true); + } else { + row.addClass('ui-timepicker-disabled'); + } + } + } + + list.append(row); + } + + wrapped_list.data('timepicker-input', self); + self.data('timepicker-list', wrapped_list); + + if (settings.useSelect) { + if (self.val()) { + list.val(_roundAndFormatTime(self.val(), settings)); + } + + list.on('focus', function(){ + $(this).data('timepicker-input').trigger('showTimepicker'); + }); + list.on('blur', function(){ + $(this).data('timepicker-input').trigger('hideTimepicker'); + }); + list.on('change', function(){ + _setTimeValue(self, $(this).val(), 'select'); + }); + + _setTimeValue(self, list.val()); + self.hide().after(list); + } else { + var appendTo = settings.appendTo; + if (typeof appendTo === 'string') { + appendTo = $(appendTo); + } else if (typeof appendTo === 'function') { + appendTo = appendTo(self); + } + appendTo.append(wrapped_list); + _setSelected(self, list); + + list.on('mousedown', 'li', function(e) { + + // hack: temporarily disable the focus handler + // to deal with the fact that IE fires 'focus' + // events asynchronously + self.off('focus.timepicker'); + self.on('focus.timepicker-ie-hack', function(){ + self.off('focus.timepicker-ie-hack'); + self.on('focus.timepicker', methods.show); + }); + + if (!_hideKeyboard(self)) { + self[0].focus(); + } + + // make sure only the clicked row is selected + list.find('li').removeClass('ui-timepicker-selected'); + $(this).addClass('ui-timepicker-selected'); + + if (_selectValue(self)) { + self.trigger('hideTimepicker'); + wrapped_list.hide(); + } + }); + } + } + + function _generateNoneElement(optionValue, useSelect) + { + var label, className, value; + + if (typeof optionValue == 'object') { + label = optionValue.label; + className = optionValue.className; + value = optionValue.value; + } else if (typeof optionValue == 'string') { + label = optionValue; + } else { + $.error('Invalid noneOption value'); + } + + if (useSelect) { + return $('<option />', { + 'value': value, + 'class': className, + 'text': label + }); + } else { + return $('<li />', { + 'class': className, + 'text': label + }).data('time', value); + } + } + + function _roundTime(seconds, settings) + { + if (!$.isNumeric(seconds)) { + seconds = _time2int(seconds); + } + + if (seconds === null) { + return null; + } else { + var offset = seconds % (settings.step*60); // step is in minutes + + if (offset >= settings.step*30) { + // if offset is larger than a half step, round up + seconds += (settings.step*60) - offset; + } else { + // round down + seconds -= offset; + } + + return seconds; + } + } + + function _roundAndFormatTime(seconds, settings) + { + seconds = _roundTime(seconds, settings); + if (seconds !== null) { + return _int2time(seconds, settings.timeFormat); + } + } + + function _generateBaseDate() + { + return new Date(1970, 1, 1, 0, 0, 0); + } + + // event handler to decide whether to close timepicker + function _closeHandler(e) + { + var target = $(e.target); + var input = target.closest('.ui-timepicker-input'); + if (input.length === 0 && target.closest('.ui-timepicker-wrapper').length === 0) { + methods.hide(); + $(document).unbind('.ui-timepicker'); + } + } + + function _hideKeyboard(self) + { + var settings = self.data('timepicker-settings'); + return ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && settings.disableTouchKeyboard); + } + + function _findRow(self, list, value) + { + if (!value && value !== 0) { + return false; + } + + var settings = self.data('timepicker-settings'); + var out = false; + var halfStep = settings.step*30; + + // loop through the menu items + list.find('li').each(function(i, obj) { + var jObj = $(obj); + if (typeof jObj.data('time') != 'number') { + return; + } + + var offset = jObj.data('time') - value; + + // check if the value is less than half a step from each row + if (Math.abs(offset) < halfStep || offset == halfStep) { + out = jObj; + return false; + } + }); + + return out; + } + + function _setSelected(self, list) + { + list.find('li').removeClass('ui-timepicker-selected'); + + var timeValue = _time2int(_getTimeValue(self), self.data('timepicker-settings')); + if (timeValue === null) { + return; + } + + var selected = _findRow(self, list, timeValue); + if (selected) { + + var topDelta = selected.offset().top - list.offset().top; + + if (topDelta + selected.outerHeight() > list.outerHeight() || topDelta < 0) { + list.scrollTop(list.scrollTop() + selected.position().top - selected.outerHeight()); + } + + selected.addClass('ui-timepicker-selected'); + } + } + + + function _formatValue(e) + { + if (this.value === '') { + return; + } + + var self = $(this); + var list = self.data('timepicker-list'); + + if (self.is(':focus') && (!e || e.type != 'change')) { + return; + } + + var seconds = _time2int(this.value); + + if (seconds === null) { + self.trigger('timeFormatError'); + return; + } + + var settings = self.data('timepicker-settings'); + var rangeError = false; + // check that the time in within bounds + if (settings.minTime !== null && seconds < settings.minTime) { + rangeError = true; + } else if (settings.maxTime !== null && seconds > settings.maxTime) { + rangeError = true; + } + + // check that time isn't within disabled time ranges + $.each(settings.disableTimeRanges, function(){ + if (seconds >= this[0] && seconds < this[1]) { + rangeError = true; + return false; + } + }); + + if (settings.forceRoundTime) { + var offset = seconds % (settings.step*60); // step is in minutes + + if (offset >= settings.step*30) { + // if offset is larger than a half step, round up + seconds += (settings.step*60) - offset; + } else { + // round down + seconds -= offset; + } + } + + var prettyTime = _int2time(seconds, settings.timeFormat); + + if (rangeError) { + if (_setTimeValue(self, prettyTime, 'error')) { + self.trigger('timeRangeError'); + } + } else { + _setTimeValue(self, prettyTime); + } + } + + function _getTimeValue(self) + { + if (self.is('input')) { + return self.val(); + } else { + // use the element's data attributes to store values + return self.data('ui-timepicker-value'); + } + } + + function _setTimeValue(self, value, source) + { + if (self.is('input')) { + self.val(value); + + var settings = self.data('timepicker-settings'); + if (settings.useSelect) { + self.data('timepicker-list').val(_roundAndFormatTime(value, settings)); + } + } + + if (self.data('ui-timepicker-value') != value) { + self.data('ui-timepicker-value', value); + if (source == 'select') { + self.trigger('selectTime').trigger('changeTime').trigger('change'); + } else if (source != 'error') { + self.trigger('changeTime'); + } + + return true; + } else { + self.trigger('selectTime'); + return false; + } + } + + /* + * Keyboard navigation via arrow keys + */ + function _keydownhandler(e) + { + var self = $(this); + var list = self.data('timepicker-list'); + + if (!list || !_isVisible(list)) { + if (e.keyCode == 40) { + // show the list! + methods.show.call(self.get(0)); + list = self.data('timepicker-list'); + if (!_hideKeyboard(self)) { + self.focus(); + } + } else { + return true; + } + } + + switch (e.keyCode) { + + case 13: // return + if (_selectValue(self)) { + methods.hide.apply(this); + } + + e.preventDefault(); + return false; + + case 38: // up + var selected = list.find('.ui-timepicker-selected'); + + if (!selected.length) { + list.find('li').each(function(i, obj) { + if ($(obj).position().top > 0) { + selected = $(obj); + return false; + } + }); + selected.addClass('ui-timepicker-selected'); + + } else if (!selected.is(':first-child')) { + selected.removeClass('ui-timepicker-selected'); + selected.prev().addClass('ui-timepicker-selected'); + + if (selected.prev().position().top < selected.outerHeight()) { + list.scrollTop(list.scrollTop() - selected.outerHeight()); + } + } + + return false; + + case 40: // down + selected = list.find('.ui-timepicker-selected'); + + if (selected.length === 0) { + list.find('li').each(function(i, obj) { + if ($(obj).position().top > 0) { + selected = $(obj); + return false; + } + }); + + selected.addClass('ui-timepicker-selected'); + } else if (!selected.is(':last-child')) { + selected.removeClass('ui-timepicker-selected'); + selected.next().addClass('ui-timepicker-selected'); + + if (selected.next().position().top + 2*selected.outerHeight() > list.outerHeight()) { + list.scrollTop(list.scrollTop() + selected.outerHeight()); + } + } + + return false; + + case 27: // escape + list.find('li').removeClass('ui-timepicker-selected'); + methods.hide(); + break; + + case 9: //tab + methods.hide(); + break; + + default: + return true; + } + } + + /* + * Time typeahead + */ + function _keyuphandler(e) + { + var self = $(this); + var list = self.data('timepicker-list'); + + if (!list || !_isVisible(list)) { + return true; + } + + if (!self.data('timepicker-settings').typeaheadHighlight) { + list.find('li').removeClass('ui-timepicker-selected'); + return true; + } + + switch (e.keyCode) { + + case 96: // numpad numerals + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + case 103: + case 104: + case 105: + case 48: // numerals + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 65: // a + case 77: // m + case 80: // p + case 186: // colon + case 8: // backspace + case 46: // delete + _setSelected(self, list); + break; + + default: + // list.find('li').removeClass('ui-timepicker-selected'); + return; + } + } + + function _selectValue(self) + { + var settings = self.data('timepicker-settings'); + var list = self.data('timepicker-list'); + var timeValue = null; + + var cursor = list.find('.ui-timepicker-selected'); + + if (cursor.hasClass('ui-timepicker-disabled')) { + return false; + } + + if (cursor.length) { + // selected value found + timeValue = cursor.data('time'); + } + + if (timeValue !== null) { + if (typeof timeValue == 'string') { + self.val(timeValue); + } else { + var timeString = _int2time(timeValue, settings.timeFormat); + _setTimeValue(self, timeString, 'select'); + } + } + + //self.trigger('change').trigger('selectTime'); + return true; + } + + function _int2duration(seconds, step) + { + seconds = Math.abs(seconds); + var minutes = Math.round(seconds/60), + duration = [], + hours, mins; + + if (minutes < 60) { + // Only show (x mins) under 1 hour + duration = [minutes, _lang.mins]; + } else { + hours = Math.floor(minutes/60); + mins = minutes%60; + + // Show decimal notation (eg: 1.5 hrs) for 30 minute steps + if (step == 30 && mins == 30) { + hours += _lang.decimal + 5; + } + + duration.push(hours); + duration.push(hours == 1 ? _lang.hr : _lang.hrs); + + // Show remainder minutes notation (eg: 1 hr 15 mins) for non-30 minute steps + // and only if there are remainder minutes to show + if (step != 30 && mins) { + duration.push(mins); + duration.push(_lang.mins); + } + } + + return duration.join(' '); + } + + function _int2time(seconds, format) + { + if (seconds === null) { + return; + } + + var time = new Date(_baseDate.valueOf() + (seconds*1000)); + + if (isNaN(time.getTime())) { + return; + } + + if ($.type(format) === "function") { + return format(time); + } + + var output = ''; + var hour, code; + for (var i=0; i<format.length; i++) { + + code = format.charAt(i); + switch (code) { + + case 'a': + output += (time.getHours() > 11) ? _lang.pm : _lang.am; + break; + + case 'A': + output += (time.getHours() > 11) ? _lang.pm.toUpperCase() : _lang.am.toUpperCase(); + break; + + case 'g': + hour = time.getHours() % 12; + output += (hour === 0) ? '12' : hour; + break; + + case 'G': + output += time.getHours(); + break; + + case 'h': + hour = time.getHours() % 12; + + if (hour !== 0 && hour < 10) { + hour = '0'+hour; + } + + output += (hour === 0) ? '12' : hour; + break; + + case 'H': + hour = time.getHours(); + if (seconds === _ONE_DAY) hour = 24; + output += (hour > 9) ? hour : '0'+hour; + break; + + case 'i': + var minutes = time.getMinutes(); + output += (minutes > 9) ? minutes : '0'+minutes; + break; + + case 's': + seconds = time.getSeconds(); + output += (seconds > 9) ? seconds : '0'+seconds; + break; + + case '\\': + // escape character; add the next character and skip ahead + i++; + output += format.charAt(i); + break; + + default: + output += code; + } + } + + return output; + } + + function _time2int(timeString, settings) + { + if (timeString === '') return null; + if (!timeString || timeString+0 == timeString) return timeString; + + if (typeof(timeString) == 'object') { + return timeString.getHours()*3600 + timeString.getMinutes()*60 + timeString.getSeconds(); + } + + timeString = timeString.toLowerCase(); + + // if the last character is an "a" or "p", add the "m" + if (timeString.slice(-1) == 'a' || timeString.slice(-1) == 'p') { + timeString += 'm'; + } + + // try to parse time input + var pattern = new RegExp('^([0-2]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?\\s*('+_lang.am+'|'+_lang.pm+')?$'); + var time = timeString.match(pattern); + if (!time) { + return null; + } + + var hour = parseInt(time[1]*1, 10); + var ampm = time[4]; + var hours = hour; + + if (hour <= 12 && ampm) { + if (hour == 12) { + hours = (time[4] == _lang.pm) ? 12 : 0; + } else { + hours = (hour + (time[4] == _lang.pm ? 12 : 0)); + } + } + + var minutes = ( time[2]*1 || 0 ); + var seconds = ( time[3]*1 || 0 ); + var timeInt = hours*3600 + minutes*60 + seconds; + + // if no am/pm provided, intelligently guess based on the scrollDefault + if (!ampm && settings && settings._twelveHourTime && settings.scrollDefault) { + var delta = timeInt - settings.scrollDefault; + if (delta < 0 && delta >= _ONE_DAY / -2) { + timeInt = (timeInt + (_ONE_DAY / 2)) % _ONE_DAY; + } + } + + return timeInt + } + + function _pad2(n) { + return ("0" + n).slice(-2); + } + + // Plugin entry + $.fn.timepicker = function(method) + { + if (!this.length) return this; + if (methods[method]) { + // check if this element is a timepicker + if (!this.hasClass('ui-timepicker-input')) { + return this; + } + return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } + else if(typeof method === "object" || !method) { return methods.init.apply(this, arguments); } + else { $.error("Method "+ method + " does not exist on jQuery.timepicker"); } + }; + // Global defaults + $.fn.timepicker.defaults = { + className: null, + minTime: null, + maxTime: null, + durationTime: null, + step: 30, + showDuration: false, + showOnFocus: true, + timeFormat: 'g:ia', + scrollDefault: null, + selectOnBlur: false, + disableTouchKeyboard: false, + forceRoundTime: false, + appendTo: 'body', + orientation: 'ltr', + disableTimeRanges: [], + closeOnWindowScroll: false, + typeaheadHighlight: true, + noneOption: false + }; +})); diff --git a/libgpl/timepicker/jquery.timepicker.min.js b/libgpl/timepicker/jquery.timepicker.min.js new file mode 100644 index 0000000..04daf60 --- /dev/null +++ b/libgpl/timepicker/jquery.timepicker.min.js @@ -0,0 +1,7 @@ +/*! + * jquery-timepicker v1.4.10 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation. + * Copyright (c) 2014 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/ + * License: + */ + +!function(a){"object"==typeof exports&&exports&&"object"==typeof module&&module&&module.exports===exports?a(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function b(a){var b=a[0];return b.offsetWidth>0&&b.offsetHeight>0}function c(b){if(b.minTime&&(b.minTime=u(b.minTime)),b.maxTime&&(b.maxTime=u(b.maxTime)),b.durationTime&&"function"!=typeof b.durationTime&&(b.durationTime=u(b.durationTime)),"now"==b.scrollDefault?b.scrollDefault=u(new Date):b.scrollDefault?b.scrollDefault=u(b.scrollDefault):b.minTime&&(b.scrollDefault=b.minTime),b.scrollDefault&&(b.scrollDefault=f(b.scrollDefault,b)),"string"===a.type(b.timeFormat)&&b.timeFormat.match(/[gh]/)&&(b._twelveHourTime=!0),b.disableTimeRanges.length>0){for(var c in b.disableTimeRanges)b.disableTimeRanges[c]=[u(b.disableTimeRanges[c][0]),u(b.disableTimeRanges[c][1])];b.disableTimeRanges=b.disableTimeRanges.sort(function(a,b){return a[0]-b[0]});for(var c=b.disableTimeRanges.length-1;c>0;c--)b.disableTimeRanges[c][0]<=b.disableTimeRanges[c-1][1]&&(b.disableTimeRanges[c-1]=[Math.min(b.disableTimeRanges[c][0],b.disableTimeRanges[c-1][0]),Math.max(b.disableTimeRanges[c][1],b.disableTimeRanges[c-1][1])],b.disableTimeRanges.splice(c,1))}return b}function d(b){var c=b.data("timepicker-settings"),d=b.data("timepicker-list");if(d&&d.length&&(d.remove(),b.data("timepicker-list",!1)),c.useSelect){d=a("<select />",{"class":"ui-timepicker-select"});var f=d}else{d=a("<ul />",{"class":"ui-timepicker-list"});var f=a("<div />",{"class":"ui-timepicker-wrapper",tabindex:-1});f.css({display:"none",position:"absolute"}).append(d)}if(c.noneOption)if(c.noneOption===!0&&(c.noneOption=c.useSelect?"Time...":"None"),a.isArray(c.noneOption)){for(var h in c.noneOption)if(parseInt(h,10)==h){var i=e(c.noneOption[h],c.useSelect);d.append(i)}}else{var i=e(c.noneOption,c.useSelect);d.append(i)}c.className&&f.addClass(c.className),null===c.minTime&&null===c.durationTime||!c.showDuration||(f.addClass("ui-timepicker-with-duration"),f.addClass("ui-timepicker-step-"+c.step));var k=c.minTime;"function"==typeof c.durationTime?k=u(c.durationTime()):null!==c.durationTime&&(k=c.durationTime);var m=null!==c.minTime?c.minTime:0,n=null!==c.maxTime?c.maxTime:m+w-1;m>=n&&(n+=w),n===w-1&&"string"===a.type(c.timeFormat)&&-1!==c.timeFormat.indexOf("H")&&(n=w);for(var p=c.disableTimeRanges,q=0,v=p.length,h=m;n>=h;h+=60*c.step){var x=h,z=t(x,c.timeFormat);if(c.useSelect){var A=a("<option />",{value:z});A.text(z)}else{var A=a("<li />");A.data("time",86400>=x?x:x%86400),A.text(z)}if((null!==c.minTime||null!==c.durationTime)&&c.showDuration){var B=s(h-k,c.step);if(c.useSelect)A.text(A.text()+" ("+B+")");else{var C=a("<span />",{"class":"ui-timepicker-duration"});C.text(" ("+B+")"),A.append(C)}}v>q&&(x>=p[q][1]&&(q+=1),p[q]&&x>=p[q][0]&&x<p[q][1]&&(c.useSelect?A.prop("disabled",!0):A.addClass("ui-timepicker-disabled"))),d.append(A)}if(f.data("timepicker-input",b),b.data("timepicker-list",f),c.useSelect)b.val()&&d.val(g(b.val(),c)),d.on("focus",function(){a(this).data("timepicker-input").trigger("showTimepicker")}),d.on("blur",function(){a(this).data("timepicker-input").trigger("hideTimepicker")}),d.on("change",function(){o(b,a(this).val(),"select")}),o(b,d.val()),b.hide().after(d);else{var D=c.appendTo;"string"==typeof D?D=a(D):"function"==typeof D&&(D=D(b)),D.append(f),l(b,d),d.on("mousedown","li",function(){b.off("focus.timepicker"),b.on("focus.timepicker-ie-hack",function(){b.off("focus.timepicker-ie-hack"),b.on("focus.timepicker",y.show)}),j(b)||b[0].focus(),d.find("li").removeClass("ui-timepicker-selected"),a(this).addClass("ui-timepicker-selected"),r(b)&&(b.trigger("hideTimepicker"),f.hide())})}}function e(b,c){var d,e,f;return"object"==typeof b?(d=b.label,e=b.className,f=b.value):"string"==typeof b?d=b:a.error("Invalid noneOption value"),c?a("<option />",{value:f,"class":e,text:d}):a("<li />",{"class":e,text:d}).data("time",f)}function f(b,c){if(a.isNumeric(b)||(b=u(b)),null===b)return null;var d=b%(60*c.step);return d>=30*c.step?b+=60*c.step-d:b-=d,b}function g(a,b){return a=f(a,b),null!==a?t(a,b.timeFormat):void 0}function h(){return new Date(1970,1,1,0,0,0)}function i(b){var c=a(b.target),d=c.closest(".ui-timepicker-input");0===d.length&&0===c.closest(".ui-timepicker-wrapper").length&&(y.hide(),a(document).unbind(".ui-timepicker"))}function j(a){var b=a.data("timepicker-settings");return(window.navigator.msMaxTouchPoints||"ontouchstart"in document)&&b.disableTouchKeyboard}function k(b,c,d){if(!d&&0!==d)return!1;var e=b.data("timepicker-settings"),f=!1,g=30*e.step;return c.find("li").each(function(b,c){var e=a(c);if("number"==typeof e.data("time")){var h=e.data("time")-d;return Math.abs(h)<g||h==g?(f=e,!1):void 0}}),f}function l(a,b){b.find("li").removeClass("ui-timepicker-selected");var c=u(n(a),a.data("timepicker-settings"));if(null!==c){var d=k(a,b,c);if(d){var e=d.offset().top-b.offset().top;(e+d.outerHeight()>b.outerHeight()||0>e)&&b.scrollTop(b.scrollTop()+d.position().top-d.outerHeight()),d.addClass("ui-timepicker-selected")}}}function m(b){if(""!==this.value){var c=a(this);if(c.data("timepicker-list"),!c.is(":focus")||b&&"change"==b.type){var d=u(this.value);if(null===d)return c.trigger("timeFormatError"),void 0;var e=c.data("timepicker-settings"),f=!1;if(null!==e.minTime&&d<e.minTime?f=!0:null!==e.maxTime&&d>e.maxTime&&(f=!0),a.each(e.disableTimeRanges,function(){return d>=this[0]&&d<this[1]?(f=!0,!1):void 0}),e.forceRoundTime){var g=d%(60*e.step);g>=30*e.step?d+=60*e.step-g:d-=g}var h=t(d,e.timeFormat);f?o(c,h,"error")&&c.trigger("timeRangeError"):o(c,h)}}}function n(a){return a.is("input")?a.val():a.data("ui-timepicker-value")}function o(a,b,c){if(a.is("input")){a.val(b);var d=a.data("timepicker-settings");d.useSelect&&a.data("timepicker-list").val(g(b,d))}return a.data("ui-timepicker-value")!=b?(a.data("ui-timepicker-value",b),"select"==c?a.trigger("selectTime").trigger("changeTime").trigger("change"):"error"!=c&&a.trigger("changeTime"),!0):(a.trigger("selectTime"),!1)}function p(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e)){if(40!=c.keyCode)return!0;y.show.call(d.get(0)),e=d.data("timepicker-list"),j(d)||d.focus()}switch(c.keyCode){case 13:return r(d)&&y.hide.apply(this),c.preventDefault(),!1;case 38:var f=e.find(".ui-timepicker-selected");return f.length?f.is(":first-child")||(f.removeClass("ui-timepicker-selected"),f.prev().addClass("ui-timepicker-selected"),f.prev().position().top<f.outerHeight()&&e.scrollTop(e.scrollTop()-f.outerHeight())):(e.find("li").each(function(b,c){return a(c).position().top>0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")),!1;case 40:return f=e.find(".ui-timepicker-selected"),0===f.length?(e.find("li").each(function(b,c){return a(c).position().top>0?(f=a(c),!1):void 0}),f.addClass("ui-timepicker-selected")):f.is(":last-child")||(f.removeClass("ui-timepicker-selected"),f.next().addClass("ui-timepicker-selected"),f.next().position().top+2*f.outerHeight()>e.outerHeight()&&e.scrollTop(e.scrollTop()+f.outerHeight())),!1;case 27:e.find("li").removeClass("ui-timepicker-selected"),y.hide();break;case 9:y.hide();break;default:return!0}}function q(c){var d=a(this),e=d.data("timepicker-list");if(!e||!b(e))return!0;if(!d.data("timepicker-settings").typeaheadHighlight)return e.find("li").removeClass("ui-timepicker-selected"),!0;switch(c.keyCode){case 96:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:case 65:case 77:case 80:case 186:case 8:case 46:l(d,e);break;default:return}}function r(a){var b=a.data("timepicker-settings"),c=a.data("timepicker-list"),d=null,e=c.find(".ui-timepicker-selected");if(e.hasClass("ui-timepicker-disabled"))return!1;if(e.length&&(d=e.data("time")),null!==d)if("string"==typeof d)a.val(d);else{var f=t(d,b.timeFormat);o(a,f,"select")}return!0}function s(a,b){a=Math.abs(a);var c,d,e=Math.round(a/60),f=[];return 60>e?f=[e,x.mins]:(c=Math.floor(e/60),d=e%60,30==b&&30==d&&(c+=x.decimal+5),f.push(c),f.push(1==c?x.hr:x.hrs),30!=b&&d&&(f.push(d),f.push(x.mins))),f.join(" ")}function t(b,c){if(null!==b){var d=new Date(v.valueOf()+1e3*b);if(!isNaN(d.getTime())){if("function"===a.type(c))return c(d);for(var e,f,g="",h=0;h<c.length;h++)switch(f=c.charAt(h)){case"a":g+=d.getHours()>11?x.pm:x.am;break;case"A":g+=d.getHours()>11?x.pm.toUpperCase():x.am.toUpperCase();break;case"g":e=d.getHours()%12,g+=0===e?"12":e;break;case"G":g+=d.getHours();break;case"h":e=d.getHours()%12,0!==e&&10>e&&(e="0"+e),g+=0===e?"12":e;break;case"H":e=d.getHours(),b===w&&(e=24),g+=e>9?e:"0"+e;break;case"i":var i=d.getMinutes();g+=i>9?i:"0"+i;break;case"s":b=d.getSeconds(),g+=b>9?b:"0"+b;break;case"\\":h++,g+=c.charAt(h);break;default:g+=f}return g}}}function u(a,b){if(""===a)return null;if(!a||a+0==a)return a;if("object"==typeof a)return 3600*a.getHours()+60*a.getMinutes()+a.getSeconds();a=a.toLowerCase(),("a"==a.slice(-1)||"p"==a.slice(-1))&&(a+="m");var c=new RegExp("^([0-2]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?\\s*("+x.am+"|"+x.pm+")?$"),d=a.match(c);if(!d)return null;var e=parseInt(1*d[1],10),f=d[4],g=e;12>=e&&f&&(g=12==e?d[4]==x.pm?12:0:e+(d[4]==x.pm?12:0));var h=1*d[2]||0,i=1*d[3]||0,j=3600*g+60*h+i;if(!f&&b&&b._twelveHourTime&&b.scrollDefault){var k=j-b.scrollDefault;0>k&&k>=w/-2&&(j=(j+w/2)%w)}return j}var v=h(),w=86400,x={am:"am",pm:"pm",AM:"AM",PM:"PM",decimal:".",mins:"mins",hr:"hr",hrs:"hrs"},y={init:function(b){return this.each(function(){var e=a(this),f=[];for(var g in a.fn.timepicker.defaults)e.data(g)&&(f[g]=e.data(g));var h=a.extend({},a.fn.timepicker.defaults,f,b);h.lang&&(x=a.extend(x,h.lang)),h=c(h),e.data("timepicker-settings",h),e.addClass("ui-timepicker-input"),h.useSelect?d(e):(e.prop("autocomplete","off"),e.on("click.timepicker focus.timepicker",y.show),e.on("change.timepicker",m),e.on("keydown.timepicker",p),e.on("keyup.timepicker",q),m.call(e.get(0)))})},show:function(c){var e=a(this),f=e.data("timepicker-settings");if(c){if(!f.showOnFocus)return!0;c.preventDefault()}if(f.useSelect)return e.data("timepicker-list").focus(),void 0;j(e)&&e.blur();var g=e.data("timepicker-list");if(!e.prop("readonly")&&(g&&0!==g.length&&"function"!=typeof f.durationTime||(d(e),g=e.data("timepicker-list")),!b(g))){y.hide(),g.show();var h={};h.left="rtl"==f.orientation?e.offset().left+e.outerWidth()-g.outerWidth()+parseInt(g.css("marginLeft").replace("px",""),10):e.offset().left+parseInt(g.css("marginLeft").replace("px",""),10),h.top=e.offset().top+e.outerHeight(!0)+g.outerHeight()>a(window).height()+a(window).scrollTop()?e.offset().top-g.outerHeight()+parseInt(g.css("marginTop").replace("px",""),10):e.offset().top+e.outerHeight()+parseInt(g.css("marginTop").replace("px",""),10),g.offset(h);var l=g.find(".ui-timepicker-selected");if(l.length||(n(e)?l=k(e,g,u(n(e))):f.scrollDefault&&(l=k(e,g,f.scrollDefault))),l&&l.length){var m=g.scrollTop()+l.position().top-l.outerHeight();g.scrollTop(m)}else g.scrollTop(0);return a(document).on("touchstart.ui-timepicker mousedown.ui-timepicker",i),f.closeOnWindowScroll&&a(document).on("scroll.ui-timepicker",i),e.trigger("showTimepicker"),this}},hide:function(){var c=a(this),d=c.data("timepicker-settings");return d&&d.useSelect&&c.blur(),a(".ui-timepicker-wrapper").each(function(){var c=a(this);if(b(c)){var d=c.data("timepicker-input"),e=d.data("timepicker-settings");e&&e.selectOnBlur&&r(d),c.hide(),d.trigger("hideTimepicker")}}),this},option:function(b,e){return this.each(function(){var f=a(this),g=f.data("timepicker-settings"),h=f.data("timepicker-list");if("object"==typeof b)g=a.extend(g,b);else if("string"==typeof b&&"undefined"!=typeof e)g[b]=e;else if("string"==typeof b)return g[b];g=c(g),f.data("timepicker-settings",g),h&&(h.remove(),f.data("timepicker-list",!1)),g.useSelect&&d(f)})},getSecondsFromMidnight:function(){return u(n(this))},getTime:function(a){var b=this,c=n(b);if(!c)return null;a||(a=new Date);var d=u(c),e=new Date(a);return e.setHours(d/3600),e.setMinutes(d%3600/60),e.setSeconds(d%60),e.setMilliseconds(0),e},setTime:function(a){var b=this,c=b.data("timepicker-settings");if(c.forceRoundTime)var d=g(a,c);else var d=t(u(a),c.timeFormat);return o(b,d),b.data("timepicker-list")&&l(b,b.data("timepicker-list")),this},remove:function(){var a=this;if(a.hasClass("ui-timepicker-input")){var b=a.data("timepicker-settings");return a.removeAttr("autocomplete","off"),a.removeClass("ui-timepicker-input"),a.removeData("timepicker-settings"),a.off(".timepicker"),a.data("timepicker-list")&&a.data("timepicker-list").remove(),b.useSelect&&a.show(),a.removeData("timepicker-list"),this}}};a.fn.timepicker=function(b){return this.length?y[b]?this.hasClass("ui-timepicker-input")?y[b].apply(this,Array.prototype.slice.call(arguments,1)):this:"object"!=typeof b&&b?(a.error("Method "+b+" does not exist on jQuery.timepicker"),void 0):y.init.apply(this,arguments):this},a.fn.timepicker.defaults={className:null,minTime:null,maxTime:null,durationTime:null,step:30,showDuration:!1,showOnFocus:!0,timeFormat:"g:ia",scrollDefault:null,selectOnBlur:!1,disableTouchKeyboard:!1,forceRoundTime:!1,appendTo:"body",orientation:"ltr",disableTimeRanges:[],closeOnWindowScroll:!1,typeaheadHighlight:!0,noneOption:!1}});
\ No newline at end of file |