Skip to content
Snippets Groups Projects
jquery-ui-timepicker-addon.js 76.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 				timeString: allParts.splice(0, timePartsLen).join(separator)
    			};
    		}
    
    		return {
    			dateString: dateTimeString,
    			timeString: ''
    		};
    	};
    
    	/*
    	* Internal function to parse datetime interval
    	* Returns: {date: Date, timeObj: Object}, where
    	*   date - parsed date without time (type Date)
    	*   timeObj = {hour: , minute: , second: , millisec: , microsec: } - parsed time. Optional
    	*/
    	var parseDateTimeInternal = function (dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
    		var date,
    			parts,
    			parsedTime;
    
    		parts = splitDateTime(dateTimeString, timeSettings);
    		date = $.datepicker._base_parseDate(dateFormat, parts.dateString, dateSettings);
    
    		if (parts.timeString === '') {
    			return {
    				date: date
    			};
    		}
    
    		parsedTime = $.datepicker.parseTime(timeFormat, parts.timeString, timeSettings);
    
    		if (!parsedTime) {
    			throw 'Wrong time format';
    		}
    
    		return {
    			date: date,
    			timeObj: parsedTime
    		};
    	};
    
    	/*
    	* Internal function to set timezone_select to the local timezone
    	*/
    	var selectLocalTimezone = function (tp_inst, date) {
    		if (tp_inst && tp_inst.timezone_select) {
    			var now = date || new Date();
    			tp_inst.timezone_select.val(-now.getTimezoneOffset());
    		}
    	};
    
    	/*
    	* Create a Singleton Instance
    	*/
    	$.timepicker = new Timepicker();
    
    	/**
    	 * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5)
    	 * @param {number} tzMinutes if not a number, less than -720 (-1200), or greater than 840 (+1400) this value is returned
    	 * @param {boolean} iso8601 if true formats in accordance to iso8601 "+12:45"
    	 * @return {string}
    	 */
    	$.timepicker.timezoneOffsetString = function (tzMinutes, iso8601) {
    		if (isNaN(tzMinutes) || tzMinutes > 840 || tzMinutes < -720) {
    			return tzMinutes;
    		}
    
    		var off = tzMinutes,
    			minutes = off % 60,
    			hours = (off - minutes) / 60,
    			iso = iso8601 ? ':' : '',
    			tz = (off >= 0 ? '+' : '-') + ('0' + Math.abs(hours)).slice(-2) + iso + ('0' + Math.abs(minutes)).slice(-2);
    
    		if (tz === '+00:00') {
    			return 'Z';
    		}
    		return tz;
    	};
    
    	/**
    	 * Get the number in minutes that represents a timezone string
    	 * @param  {string} tzString formatted like "+0500", "-1245", "Z"
    	 * @return {number} the offset minutes or the original string if it doesn't match expectations
    	 */
    	$.timepicker.timezoneOffsetNumber = function (tzString) {
    		var normalized = tzString.toString().replace(':', ''); // excuse any iso8601, end up with "+1245"
    
    		if (normalized.toUpperCase() === 'Z') { // if iso8601 with Z, its 0 minute offset
    			return 0;
    		}
    
    		if (!/^(\-|\+)\d{4}$/.test(normalized)) { // possibly a user defined tz, so just give it back
    			return parseInt(tzString, 10);
    		}
    
    		return ((normalized.substr(0, 1) === '-' ? -1 : 1) * // plus or minus
    					((parseInt(normalized.substr(1, 2), 10) * 60) + // hours (converted to minutes)
    					parseInt(normalized.substr(3, 2), 10))); // minutes
    	};
    
    	/**
    	 * No way to set timezone in js Date, so we must adjust the minutes to compensate. (think setDate, getDate)
    	 * @param  {Date} date
    	 * @param  {string} fromTimezone formatted like "+0500", "-1245"
    	 * @param  {string} toTimezone formatted like "+0500", "-1245"
    	 * @return {Date}
    	 */
    	$.timepicker.timezoneAdjust = function (date, fromTimezone, toTimezone) {
    		var fromTz = $.timepicker.timezoneOffsetNumber(fromTimezone);
    		var toTz = $.timepicker.timezoneOffsetNumber(toTimezone);
    		if (!isNaN(toTz)) {
    			date.setMinutes(date.getMinutes() + (-fromTz) - (-toTz));
    		}
    		return date;
    	};
    
    	/**
    	 * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to
    	 * enforce date range limits.
    	 * n.b. The input value must be correctly formatted (reformatting is not supported)
    	 * @param  {Element} startTime
    	 * @param  {Element} endTime
    	 * @param  {Object} options Options for the timepicker() call
    	 * @return {jQuery}
    	 */
    	$.timepicker.timeRange = function (startTime, endTime, options) {
    		return $.timepicker.handleRange('timepicker', startTime, endTime, options);
    	};
    
    	/**
    	 * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to
    	 * enforce date range limits.
    	 * @param  {Element} startTime
    	 * @param  {Element} endTime
    	 * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,
    	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
    	 * @param  {string} method Can be used to specify the type of picker to be added
    	 * @return {jQuery}
    	 */
    	$.timepicker.datetimeRange = function (startTime, endTime, options) {
    		$.timepicker.handleRange('datetimepicker', startTime, endTime, options);
    	};
    
    	/**
    	 * Calls `datepicker` on the `startTime` and `endTime` elements, and configures them to
    	 * enforce date range limits.
    	 * @param  {Element} startTime
    	 * @param  {Element} endTime
    	 * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,
    	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
    	 * @return {jQuery}
    	 */
    	$.timepicker.dateRange = function (startTime, endTime, options) {
    		$.timepicker.handleRange('datepicker', startTime, endTime, options);
    	};
    
    	/**
    	 * Calls `method` on the `startTime` and `endTime` elements, and configures them to
    	 * enforce date range limits.
    	 * @param  {string} method Can be used to specify the type of picker to be added
    	 * @param  {Element} startTime
    	 * @param  {Element} endTime
    	 * @param  {Object} options Options for the `timepicker()` call. Also supports `reformat`,
    	 *   a boolean value that can be used to reformat the input values to the `dateFormat`.
    	 * @return {jQuery}
    	 */
    	$.timepicker.handleRange = function (method, startTime, endTime, options) {
    		options = $.extend({}, {
    			minInterval: 0, // min allowed interval in milliseconds
    			maxInterval: 0, // max allowed interval in milliseconds
    			start: {},      // options for start picker
    			end: {}         // options for end picker
    		}, options);
    
    		// for the mean time this fixes an issue with calling getDate with timepicker()
    		var timeOnly = false;
    		if(method === 'timepicker'){
    			timeOnly = true;
    			method = 'datetimepicker';
    		}
    
    		function checkDates(changed, other) {
    			var startdt = startTime[method]('getDate'),
    				enddt = endTime[method]('getDate'),
    				changeddt = changed[method]('getDate');
    
    			if (startdt !== null) {
    				var minDate = new Date(startdt.getTime()),
    					maxDate = new Date(startdt.getTime());
    
    				minDate.setMilliseconds(minDate.getMilliseconds() + options.minInterval);
    				maxDate.setMilliseconds(maxDate.getMilliseconds() + options.maxInterval);
    
    				if (options.minInterval > 0 && minDate > enddt) { // minInterval check
    					endTime[method]('setDate', minDate);
    				}
    				else if (options.maxInterval > 0 && maxDate < enddt) { // max interval check
    					endTime[method]('setDate', maxDate);
    				}
    				else if (startdt > enddt) {
    					other[method]('setDate', changeddt);
    				}
    			}
    		}
    
    		function selected(changed, other, option) {
    			if (!changed.val()) {
    				return;
    			}
    			var date = changed[method].call(changed, 'getDate');
    			if (date !== null && options.minInterval > 0) {
    				if (option === 'minDate') {
    					date.setMilliseconds(date.getMilliseconds() + options.minInterval);
    				}
    				if (option === 'maxDate') {
    					date.setMilliseconds(date.getMilliseconds() - options.minInterval);
    				}
    			}
    
    			if (date.getTime) {
    				other[method].call(other, 'option', option, date);
    			}
    		}
    
    		$.fn[method].call(startTime, $.extend({
    			timeOnly: timeOnly,
    			onClose: function (dateText, inst) {
    				checkDates($(this), endTime);
    			},
    			onSelect: function (selectedDateTime) {
    				selected($(this), endTime, 'minDate');
    			}
    		}, options, options.start));
    		$.fn[method].call(endTime, $.extend({
    			timeOnly: timeOnly,
    			onClose: function (dateText, inst) {
    				checkDates($(this), startTime);
    			},
    			onSelect: function (selectedDateTime) {
    				selected($(this), startTime, 'maxDate');
    			}
    		}, options, options.end));
    
    		checkDates(startTime, endTime);
    
    		selected(startTime, endTime, 'minDate');
    		selected(endTime, startTime, 'maxDate');
    
    		return $([startTime.get(0), endTime.get(0)]);
    	};
    
    	/**
    	 * Log error or data to the console during error or debugging
    	 * @param  {Object} err pass any type object to log to the console during error or debugging
    	 * @return {void}
    	 */
    	$.timepicker.log = function () {
    		// Older IE (9, maybe 10) throw error on accessing `window.console.log.apply`, so check first.
    		if (window.console && window.console.log && window.console.log.apply) {
    			window.console.log.apply(window.console, Array.prototype.slice.call(arguments));
    		}
    	};
    
    	/*
    	 * Add util object to allow access to private methods for testability.
    	 */
    	$.timepicker._util = {
    		_extendRemove: extendRemove,
    		_isEmptyObject: isEmptyObject,
    		_convert24to12: convert24to12,
    		_detectSupport: detectSupport,
    		_selectLocalTimezone: selectLocalTimezone,
    		_computeEffectiveSetting: computeEffectiveSetting,
    		_splitDateTime: splitDateTime,
    		_parseDateTimeInternal: parseDateTimeInternal
    	};
    
    	/*
    	* Microsecond support
    	*/
    	if (!Date.prototype.getMicroseconds) {
    		Date.prototype.microseconds = 0;
    		Date.prototype.getMicroseconds = function () { return this.microseconds; };
    		Date.prototype.setMicroseconds = function (m) {
    			this.setMilliseconds(this.getMilliseconds() + Math.floor(m / 1000));
    			this.microseconds = m % 1000;
    			return this;
    		};
    	}
    
    	/*
    	* Keep up with the version
    	*/
    	$.timepicker.version = "@@version";
    
    }));