app/jquery/jquery-ui.datetimepicker.js
changeset 843 a086ff3888d3
parent 839 3e50c012a4a8
child 1451 ef134d062b83
equal deleted inserted replaced
842:ed494131f6e5 843:a086ff3888d3
     3 
     3 
     4    Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/ui-datetimepicker)
     4    Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/ui-datetimepicker)
     5    Dual licensed under the MIT (MIT-LICENSE.txt)
     5    Dual licensed under the MIT (MIT-LICENSE.txt)
     6    and GPL (GPL-LICENSE.txt) licenses.
     6    and GPL (GPL-LICENSE.txt) licenses.
     7    Date: 09-03-2007  */
     7    Date: 09-03-2007  */
     8 /* 
     8 /*
     9  * Time functionality added by Stanislav Dobry (stanislav.dobry@datesoft.cz)
     9  * Time functionality added by Stanislav Dobry (stanislav.dobry@datesoft.cz)
    10  * Date: 2008-06-04
    10  * Date: 2008-06-04
    11  */
    11  */
    12    
    12 
    13 ;(function($) { // hide the namespace
    13 ;(function($) { // hide the namespace
    14 
    14 
    15 /* Date picker manager.
    15 /* Date picker manager.
    16    Use the singleton instance of this class, $.datetimepicker, to interact with the date picker.
    16    Use the singleton instance of this class, $.datetimepicker, to interact with the date picker.
    17    Settings for (groups of) date pickers are maintained in an instance object
    17    Settings for (groups of) date pickers are maintained in an instance object
    78 		showOtherMonths: false, // True to show dates in other months, false to leave blank
    78 		showOtherMonths: false, // True to show dates in other months, false to leave blank
    79 		showWeeks: false, // True to show week of the year, false to omit
    79 		showWeeks: false, // True to show week of the year, false to omit
    80 		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
    80 		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
    81 			// takes a Date and returns the number of the week for it
    81 			// takes a Date and returns the number of the week for it
    82 		shortYearCutoff: '+10', // Short year values < this are in the current century,
    82 		shortYearCutoff: '+10', // Short year values < this are in the current century,
    83 			// > this are in the previous century, 
    83 			// > this are in the previous century,
    84 			// string value starting with '+' for current year + value
    84 			// string value starting with '+' for current year + value
    85 		showStatus: false, // True to show status bar at bottom, false to not show it
    85 		showStatus: false, // True to show status bar at bottom, false to not show it
    86 		statusForDate: this.dateStatus, // Function to provide status text for a date -
    86 		statusForDate: this.dateStatus, // Function to provide status text for a date -
    87 			// takes date and instance as parameters, returns display text
    87 			// takes date and instance as parameters, returns display text
    88 		minDate: null, // The earliest selectable date, or null for no limit
    88 		minDate: null, // The earliest selectable date, or null for no limit
   111 	/* Debug logging (if enabled). */
   111 	/* Debug logging (if enabled). */
   112 	log: function () {
   112 	log: function () {
   113 		if (this.debug)
   113 		if (this.debug)
   114 			console.log.apply('', arguments);
   114 			console.log.apply('', arguments);
   115 	},
   115 	},
   116 	
   116 
   117 	/* Register a new date picker instance - with custom settings. */
   117 	/* Register a new date picker instance - with custom settings. */
   118 	_register: function(inst) {
   118 	_register: function(inst) {
   119 		var id = this._nextId++;
   119 		var id = this._nextId++;
   120 		this._inst[id] = inst;
   120 		this._inst[id] = inst;
   121 		return id;
   121 		return id;
   124 	/* Retrieve a particular date picker instance based on its ID. */
   124 	/* Retrieve a particular date picker instance based on its ID. */
   125 	_getInst: function(id) {
   125 	_getInst: function(id) {
   126 		return this._inst[id] || id;
   126 		return this._inst[id] || id;
   127 	},
   127 	},
   128 
   128 
   129 	/* Override the default settings for all instances of the date picker. 
   129 	/* Override the default settings for all instances of the date picker.
   130 	   @param  settings  object - the new settings to use as defaults (anonymous object)
   130 	   @param  settings  object - the new settings to use as defaults (anonymous object)
   131 	   @return the manager object */
   131 	   @return the manager object */
   132 	setDefaults: function(settings) {
   132 	setDefaults: function(settings) {
   133 		extendRemove(this._defaults, settings || {});
   133 		extendRemove(this._defaults, settings || {});
   134 		return this;
   134 		return this;
   150 					inlineSettings[attrName] = attrValue;
   150 					inlineSettings[attrName] = attrValue;
   151 				}
   151 				}
   152 			}
   152 			}
   153 		}
   153 		}
   154 		var nodeName = target.nodeName.toLowerCase();
   154 		var nodeName = target.nodeName.toLowerCase();
   155 		var instSettings = (inlineSettings ? 
   155 		var instSettings = (inlineSettings ?
   156 			$.extend(settings || {}, inlineSettings || {}) : settings);
   156 			$.extend(settings || {}, inlineSettings || {}) : settings);
   157 		if (nodeName == 'input') {
   157 		if (nodeName == 'input') {
   158 			var inst = (inst && !inlineSettings ? inst :
   158 			var inst = (inst && !inlineSettings ? inst :
   159 				new DateTimepickerInstance(instSettings, false));
   159 				new DateTimepickerInstance(instSettings, false));
   160 			this._connectDatepicker(target, inst);
   160 			this._connectDatepicker(target, inst);
   321 			input.focus(this._showDatepicker);
   321 			input.focus(this._showDatepicker);
   322 		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
   322 		if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
   323 			input.wrap('<span class="datetimepicker_wrap">');
   323 			input.wrap('<span class="datetimepicker_wrap">');
   324 			var buttonText = inst._get('buttonText');
   324 			var buttonText = inst._get('buttonText');
   325 			var buttonImage = inst._get('buttonImage');
   325 			var buttonImage = inst._get('buttonImage');
   326 			var trigger = $(inst._get('buttonImageOnly') ? 
   326 			var trigger = $(inst._get('buttonImageOnly') ?
   327 				$('<img>').addClass('datetimepicker_trigger').attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
   327 				$('<img>').addClass('datetimepicker_trigger').attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
   328 				$('<button>').addClass('datetimepicker_trigger').attr({ type: 'button' }).html(buttonImage != '' ? 
   328 				$('<button>').addClass('datetimepicker_trigger').attr({ type: 'button' }).html(buttonImage != '' ?
   329 						$('<img>').attr({ src:buttonImage, alt:buttonText, title:buttonText }) : buttonText));
   329 						$('<img>').attr({ src:buttonImage, alt:buttonText, title:buttonText }) : buttonText));
   330 			if (isRTL)
   330 			if (isRTL)
   331 				input.before(trigger);
   331 				input.before(trigger);
   332 			else
   332 			else
   333 				input.after(trigger);
   333 				input.after(trigger);
   364 
   364 
   365 	/* Tidy up after displaying the date picker. */
   365 	/* Tidy up after displaying the date picker. */
   366 	_inlineShow: function(inst) {
   366 	_inlineShow: function(inst) {
   367 		var numMonths = inst._getNumberOfMonths(); // fix width for dynamic number of date pickers
   367 		var numMonths = inst._getNumberOfMonths(); // fix width for dynamic number of date pickers
   368 		inst._datetimepickerDiv.width(numMonths[1] * $('.datetimepicker', inst._datetimepickerDiv[0]).width());
   368 		inst._datetimepickerDiv.width(numMonths[1] * $('.datetimepicker', inst._datetimepickerDiv[0]).width());
   369 	}, 
   369 	},
   370 
   370 
   371 	/* Pop-up the date picker in a "dialog" box.
   371 	/* Pop-up the date picker in a "dialog" box.
   372 	   @param  input     element - ignored
   372 	   @param  input     element - ignored
   373 	   @param  dateText  string - the initial date to display (in the current format)
   373 	   @param  dateText  string - the initial date to display (in the current format)
   374 	   @param  onSelect  function - the function(dateText) to call when a date is selected
   374 	   @param  onSelect  function - the function(dateText) to call when a date is selected
   509 			inst._datetimepickerDiv.css('top', Math.max(scrollY,
   509 			inst._datetimepickerDiv.css('top', Math.max(scrollY,
   510 				pos[1] - (this._inDialog ? 0 : inst._datetimepickerDiv.height()) -
   510 				pos[1] - (this._inDialog ? 0 : inst._datetimepickerDiv.height()) -
   511 				(isFixed && $.browser.opera ? document.documentElement.scrollTop : 0)) + 'px');
   511 				(isFixed && $.browser.opera ? document.documentElement.scrollTop : 0)) + 'px');
   512 		}
   512 		}
   513 	},
   513 	},
   514 	
   514 
   515 	/* Find an object's position on the screen. */
   515 	/* Find an object's position on the screen. */
   516 	_findPos: function(obj) {
   516 	_findPos: function(obj) {
   517         while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
   517         while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
   518             obj = obj.nextSibling;
   518             obj = obj.nextSibling;
   519         }
   519         }
   612 		var inst = this._getInst(id);
   612 		var inst = this._getInst(id);
   613 		inst._selectingMonthYear = false;
   613 		inst._selectingMonthYear = false;
   614 		inst[period == 'M' ? '_drawMinute' : '_drawHour'] =
   614 		inst[period == 'M' ? '_drawMinute' : '_drawHour'] =
   615 			select.options[select.selectedIndex].value - 0;
   615 			select.options[select.selectedIndex].value - 0;
   616 		this._adjustDate(inst);
   616 		this._adjustDate(inst);
   617 		
   617 
   618 		this._doNotHide = true;
   618 		this._doNotHide = true;
   619 		$('td.datetimepicker_currentDay').each(function(){
   619 		$('td.datetimepicker_currentDay').each(function(){
   620 			$.datetimepicker._selectDay(inst, inst._selectedMonth, inst._selectedYear,$(this));
   620 			$.datetimepicker._selectDay(inst, inst._selectedMonth, inst._selectedYear,$(this));
   621 		});
   621 		});
   622 		this._doNotHide = false;
   622 		this._doNotHide = false;
   652 		var rangeSelect = inst._get('rangeSelect');
   652 		var rangeSelect = inst._get('rangeSelect');
   653 		if (rangeSelect) {
   653 		if (rangeSelect) {
   654 			if (!this._stayOpen) {
   654 			if (!this._stayOpen) {
   655 				$('.datetimepicker td').removeClass('datetimepicker_currentDay');
   655 				$('.datetimepicker td').removeClass('datetimepicker_currentDay');
   656 				$(td).addClass('datetimepicker_currentDay');
   656 				$(td).addClass('datetimepicker_currentDay');
   657 			} 
   657 			}
   658 			this._stayOpen = !this._stayOpen;
   658 			this._stayOpen = !this._stayOpen;
   659 		}
   659 		}
   660 		inst._selectedDay = inst._currentDay = $('a', td).html();
   660 		inst._selectedDay = inst._currentDay = $('a', td).html();
   661 		inst._selectedMonth = inst._currentMonth = month;
   661 		inst._selectedMonth = inst._currentMonth = month;
   662 		inst._selectedYear = inst._currentYear = year;
   662 		inst._selectedYear = inst._currentYear = year;
   723 	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
   723 	   @return [boolean, string] - is this date selectable?, what is its CSS class? */
   724 	noWeekends: function(date) {
   724 	noWeekends: function(date) {
   725 		var day = date.getDay();
   725 		var day = date.getDay();
   726 		return [(day > 0 && day < 6), ''];
   726 		return [(day > 0 && day < 6), ''];
   727 	},
   727 	},
   728 	
   728 
   729 	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
   729 	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
   730 	   @param  date  Date - the date to get the week for
   730 	   @param  date  Date - the date to get the week for
   731 	   @return  number - the number of the week within the year that contains this date */
   731 	   @return  number - the number of the week within the year that contains this date */
   732 	iso8601Week: function(date) {
   732 	iso8601Week: function(date) {
   733 		var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), (date.getTimezoneOffset() / -60));
   733 		var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), (date.getTimezoneOffset() / -60));
   744 				return $.datetimepicker.iso8601Week(checkDate);
   744 				return $.datetimepicker.iso8601Week(checkDate);
   745 			}
   745 			}
   746 		}
   746 		}
   747 		return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
   747 		return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
   748 	},
   748 	},
   749 	
   749 
   750 	/* Provide status text for a particular date.
   750 	/* Provide status text for a particular date.
   751 	   @param  date  the date to get the status for
   751 	   @param  date  the date to get the status for
   752 	   @param  inst  the current datetimepicker instance
   752 	   @param  inst  the current datetimepicker instance
   753 	   @return  the status display text for this date */
   753 	   @return  the status display text for this date */
   754 	dateStatus: function(date, inst) {
   754 	dateStatus: function(date, inst) {
   799 		// Check whether a format character is doubled
   799 		// Check whether a format character is doubled
   800 		var lookAhead = function(match) {
   800 		var lookAhead = function(match) {
   801 			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
   801 			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
   802 			if (matches)
   802 			if (matches)
   803 				iFormat++;
   803 				iFormat++;
   804 			return matches;	
   804 			return matches;
   805 		};
   805 		};
   806 		// Extract a number from the string value
   806 		// Extract a number from the string value
   807 		var getNumber = function(match) {
   807 		var getNumber = function(match) {
   808 			lookAhead(match);
   808 			lookAhead(match);
   809 			var size = (match == 'y' ? 4 : 2);
   809 			var size = (match == 'y' ? 4 : 2);
   856 						minute = getNumber('i');
   856 						minute = getNumber('i');
   857 						break;
   857 						break;
   858 					case 'd':
   858 					case 'd':
   859 						day = getNumber('d');
   859 						day = getNumber('d');
   860 						break;
   860 						break;
   861 					case 'D': 
   861 					case 'D':
   862 						getName('D', dayNamesShort, dayNames);
   862 						getName('D', dayNamesShort, dayNames);
   863 						break;
   863 						break;
   864 					case 'm': 
   864 					case 'm':
   865 						month = getNumber('m');
   865 						month = getNumber('m');
   866 						break;
   866 						break;
   867 					case 'M':
   867 					case 'M':
   868 						month = getName('M', monthNamesShort, monthNames); 
   868 						month = getName('M', monthNamesShort, monthNames);
   869 						break;
   869 						break;
   870 					case 'y':
   870 					case 'y':
   871 						year = getNumber('y');
   871 						year = getNumber('y');
   872 						break;
   872 						break;
   873 					case "'":
   873 					case "'":
   924 		// Check whether a format character is doubled
   924 		// Check whether a format character is doubled
   925 		var lookAhead = function(match) {
   925 		var lookAhead = function(match) {
   926 			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
   926 			var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
   927 			if (matches)
   927 			if (matches)
   928 				iFormat++;
   928 				iFormat++;
   929 			return matches;	
   929 			return matches;
   930 		};
   930 		};
   931 		// Format a number, with leading zero if necessary
   931 		// Format a number, with leading zero if necessary
   932 		var formatNumber = function(match, value) {
   932 		var formatNumber = function(match, value) {
   933 			return (lookAhead(match) && value < 10 ? '0' : '') + value;
   933 			return (lookAhead(match) && value < 10 ? '0' : '') + value;
   934 		};
   934 		};
   952 							break;
   952 							break;
   953 						case 'i':
   953 						case 'i':
   954 							output += formatNumber('i', date.getMinutes());
   954 							output += formatNumber('i', date.getMinutes());
   955 							break;
   955 							break;
   956 						case 'd':
   956 						case 'd':
   957 							output += formatNumber('d', date.getDate()); 
   957 							output += formatNumber('d', date.getDate());
   958 							break;
   958 							break;
   959 						case 'D': 
   959 						case 'D':
   960 							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
   960 							output += formatName('D', date.getDay(), dayNamesShort, dayNames);
   961 							break;
   961 							break;
   962 						case 'm': 
   962 						case 'm':
   963 							output += formatNumber('m', date.getMonth() + 1); 
   963 							output += formatNumber('m', date.getMonth() + 1);
   964 							break;
   964 							break;
   965 						case 'M':
   965 						case 'M':
   966 							output += formatName('M', date.getMonth(), monthNamesShort, monthNames); 
   966 							output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
   967 							break;
   967 							break;
   968 						case 'y':
   968 						case 'y':
   969 							output += (lookAhead('y') ? date.getFullYear() : 
   969 							output += (lookAhead('y') ? date.getFullYear() :
   970 								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
   970 								(date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
   971 							break;
   971 							break;
   972 						case "'":
   972 						case "'":
   973 							if (lookAhead("'"))
   973 							if (lookAhead("'"))
   974 								output += "'";
   974 								output += "'";
   994 				else
   994 				else
   995 					chars += format.charAt(iFormat);
   995 					chars += format.charAt(iFormat);
   996 			else
   996 			else
   997 				switch (format.charAt(iFormat)) {
   997 				switch (format.charAt(iFormat)) {
   998 					case 'd' || 'm' || 'y':
   998 					case 'd' || 'm' || 'y':
   999 						chars += '0123456789'; 
   999 						chars += '0123456789';
  1000 						break;
  1000 						break;
  1001 					case 'D' || 'M':
  1001 					case 'D' || 'M':
  1002 						return null; // Accept anything
  1002 						return null; // Accept anything
  1003 					case "'":
  1003 					case "'":
  1004 						if (lookAhead("'"))
  1004 						if (lookAhead("'"))
  1042 
  1042 
  1043 	/* Parse existing date and initialise date picker. */
  1043 	/* Parse existing date and initialise date picker. */
  1044 	_setDateFromField: function(input) {
  1044 	_setDateFromField: function(input) {
  1045 		this._input = $(input);
  1045 		this._input = $(input);
  1046 		var dateFormat = this._get('dateFormat')+' '+this._get('timeFormat');
  1046 		var dateFormat = this._get('dateFormat')+' '+this._get('timeFormat');
  1047 		var dates = this._input ? this._input.val().split(this._get('rangeSeparator')) : null; 
  1047 		var dates = this._input ? this._input.val().split(this._get('rangeSeparator')) : null;
  1048 		this._endDay = this._endMonth = this._endYear = null;
  1048 		this._endDay = this._endMonth = this._endYear = null;
  1049 		var date = defaultDate = this._getDefaultDate();
  1049 		var date = defaultDate = this._getDefaultDate();
  1050 		if (dates.length > 0) {
  1050 		if (dates.length > 0) {
  1051 			var settings = this._getFormatConfig();
  1051 			var settings = this._getFormatConfig();
  1052 			if (dates.length > 1) {
  1052 			if (dates.length > 1) {
  1070 		this._currentDay = (dates[0] ? date.getDate() : 0);
  1070 		this._currentDay = (dates[0] ? date.getDate() : 0);
  1071 		this._currentMonth = (dates[0] ? date.getMonth() : 0);
  1071 		this._currentMonth = (dates[0] ? date.getMonth() : 0);
  1072 		this._currentYear = (dates[0] ? date.getFullYear() : 0);
  1072 		this._currentYear = (dates[0] ? date.getFullYear() : 0);
  1073 		this._adjustDate();
  1073 		this._adjustDate();
  1074 	},
  1074 	},
  1075 	
  1075 
  1076 	/* Retrieve the default date shown on opening. */
  1076 	/* Retrieve the default date shown on opening. */
  1077 	_getDefaultDate: function() {
  1077 	_getDefaultDate: function() {
  1078 		var date = this._determineDate('defaultDate', new Date());
  1078 		var date = this._determineDate('defaultDate', new Date());
  1079 		var minDate = this._getMinMaxDate('min', true);
  1079 		var minDate = this._getMinMaxDate('min', true);
  1080 		var maxDate = this._getMinMaxDate('max');
  1080 		var maxDate = this._getMinMaxDate('max');
  1101 					case 'd' : case 'D' :
  1101 					case 'd' : case 'D' :
  1102 						day += (matches[1] - 0); break;
  1102 						day += (matches[1] - 0); break;
  1103 					case 'w' : case 'W' :
  1103 					case 'w' : case 'W' :
  1104 						day += (matches[1] * 7); break;
  1104 						day += (matches[1] * 7); break;
  1105 					case 'm' : case 'M' :
  1105 					case 'm' : case 'M' :
  1106 						month += (matches[1] - 0); 
  1106 						month += (matches[1] - 0);
  1107 						day = Math.min(day, getDaysInMonth(year, month));
  1107 						day = Math.min(day, getDaysInMonth(year, month));
  1108 						break;
  1108 						break;
  1109 					case 'y': case 'Y' :
  1109 					case 'y': case 'Y' :
  1110 						year += (matches[1] - 0);
  1110 						year += (matches[1] - 0);
  1111 						day = Math.min(day, getDaysInMonth(year, month));
  1111 						day = Math.min(day, getDaysInMonth(year, month));
  1159 		today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
  1159 		today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
  1160 		var showStatus = this._get('showStatus');
  1160 		var showStatus = this._get('showStatus');
  1161 		var isRTL = this._get('isRTL');
  1161 		var isRTL = this._get('isRTL');
  1162 		// build the date picker HTML
  1162 		// build the date picker HTML
  1163 		var clear = (this._get('mandatory') ? '' :
  1163 		var clear = (this._get('mandatory') ? '' :
  1164 			'<div class="datetimepicker_clear"><a onclick="jQuery.datetimepicker._clearDate(' + this._id + ');"' + 
  1164 			'<div class="datetimepicker_clear"><a onclick="jQuery.datetimepicker._clearDate(' + this._id + ');"' +
  1165 			(showStatus ? this._addStatus(this._get('clearStatus') || '&#xa0;') : '') + '>' +
  1165 			(showStatus ? this._addStatus(this._get('clearStatus') || '&#xa0;') : '') + '>' +
  1166 			this._get('clearText') + '</a></div>');
  1166 			this._get('clearText') + '</a></div>');
  1167 		var controls = '<div class="datetimepicker_control">' + (isRTL ? '' : clear) +
  1167 		var controls = '<div class="datetimepicker_control">' + (isRTL ? '' : clear) +
  1168 			'<div class="datetimepicker_close"><a onclick="jQuery.datetimepicker._hideDatepicker();"' +
  1168 			'<div class="datetimepicker_close"><a onclick="jQuery.datetimepicker._hideDatepicker();"' +
  1169 			(showStatus ? this._addStatus(this._get('closeStatus') || '&#xa0;') : '') + '>' +
  1169 			(showStatus ? this._addStatus(this._get('closeStatus') || '&#xa0;') : '') + '>' +
  1191 					drawYear--;
  1191 					drawYear--;
  1192 				}
  1192 				}
  1193 			}
  1193 			}
  1194 		}
  1194 		}
  1195 		// controls and links
  1195 		// controls and links
  1196 		var prev = '<div class="datetimepicker_prev">' + (this._canAdjustMonth(-1, drawYear, drawMonth) ? 
  1196 		var prev = '<div class="datetimepicker_prev">' + (this._canAdjustMonth(-1, drawYear, drawMonth) ?
  1197 			'<a onclick="jQuery.datetimepicker._adjustDate(' + this._id + ', -' + stepMonths + ', \'M\');"' +
  1197 			'<a onclick="jQuery.datetimepicker._adjustDate(' + this._id + ', -' + stepMonths + ', \'M\');"' +
  1198 			(showStatus ? this._addStatus(this._get('prevStatus') || '&#xa0;') : '') + '>' +
  1198 			(showStatus ? this._addStatus(this._get('prevStatus') || '&#xa0;') : '') + '>' +
  1199 			this._get('prevText') + '</a>' :
  1199 			this._get('prevText') + '</a>' :
  1200 			(hideIfNoPrevNext ? '' : '<label>' + this._get('prevText') + '</label>')) + '</div>';
  1200 			(hideIfNoPrevNext ? '' : '<label>' + this._get('prevText') + '</label>')) + '</div>';
  1201 		var next = '<div class="datetimepicker_next">' + (this._canAdjustMonth(+1, drawYear, drawMonth) ?
  1201 		var next = '<div class="datetimepicker_next">' + (this._canAdjustMonth(+1, drawYear, drawMonth) ?
  1215 			for (var col = 0; col < numMonths[1]; col++) {
  1215 			for (var col = 0; col < numMonths[1]; col++) {
  1216 				var selectedDate = new Date(drawYear, drawMonth, this._selectedDay, drawHour, drawMinute);
  1216 				var selectedDate = new Date(drawYear, drawMonth, this._selectedDay, drawHour, drawMinute);
  1217 				html += '<div class="datetimepicker_oneMonth' + (col == 0 ? ' datetimepicker_newRow' : '') + '">' +
  1217 				html += '<div class="datetimepicker_oneMonth' + (col == 0 ? ' datetimepicker_newRow' : '') + '">' +
  1218 					this._generateMonthYearHeader(drawMinute,drawHour,drawMonth, drawYear, minDate, maxDate,
  1218 					this._generateMonthYearHeader(drawMinute,drawHour,drawMonth, drawYear, minDate, maxDate,
  1219 					selectedDate, row > 0 || col > 0) + // draw month headers
  1219 					selectedDate, row > 0 || col > 0) + // draw month headers
  1220 					'<table class="datetimepicker" cellpadding="0" cellspacing="0"><thead>' + 
  1220 					'<table class="datetimepicker" cellpadding="0" cellspacing="0"><thead>' +
  1221 					'<tr class="datetimepicker_titleRow">' +
  1221 					'<tr class="datetimepicker_titleRow">' +
  1222 					(showWeeks ? '<td>' + this._get('weekHeader') + '</td>' : '');
  1222 					(showWeeks ? '<td>' + this._get('weekHeader') + '</td>' : '');
  1223 				var firstDay = this._get('firstDay');
  1223 				var firstDay = this._get('firstDay');
  1224 				var changeFirstDay = this._get('changeFirstDay');
  1224 				var changeFirstDay = this._get('changeFirstDay');
  1225 				var dayNames = this._get('dayNames');
  1225 				var dayNames = this._get('dayNames');
  1230 					var status = this._get('dayStatus') || '&#xa0;';
  1230 					var status = this._get('dayStatus') || '&#xa0;';
  1231 					status = (status.indexOf('DD') > -1 ? status.replace(/DD/, dayNames[day]) :
  1231 					status = (status.indexOf('DD') > -1 ? status.replace(/DD/, dayNames[day]) :
  1232 						status.replace(/D/, dayNamesShort[day]));
  1232 						status.replace(/D/, dayNamesShort[day]));
  1233 					html += '<td' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="datetimepicker_weekEndCell"' : '') + '>' +
  1233 					html += '<td' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="datetimepicker_weekEndCell"' : '') + '>' +
  1234 						(!changeFirstDay ? '<span' :
  1234 						(!changeFirstDay ? '<span' :
  1235 						'<a onclick="jQuery.datetimepicker._changeFirstDay(' + this._id + ', ' + day + ');"') + 
  1235 						'<a onclick="jQuery.datetimepicker._changeFirstDay(' + this._id + ', ' + day + ');"') +
  1236 						(showStatus ? this._addStatus(status) : '') + ' title="' + dayNames[day] + '">' +
  1236 						(showStatus ? this._addStatus(status) : '') + ' title="' + dayNames[day] + '">' +
  1237 						dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</td>';
  1237 						dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</td>';
  1238 				}
  1238 				}
  1239 				html += '</tr></thead><tbody>';
  1239 				html += '</tr></thead><tbody>';
  1240 				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
  1240 				var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
  1289 					drawMonth = 0;
  1289 					drawMonth = 0;
  1290 					drawYear++;
  1290 					drawYear++;
  1291 				}
  1291 				}
  1292 				html += '</tbody></table></div>';
  1292 				html += '</tbody></table></div>';
  1293 			}
  1293 			}
  1294 		html += (showStatus ? '<div style="clear: both;"></div><div id="datetimepicker_status_' + this._id + 
  1294 		html += (showStatus ? '<div style="clear: both;"></div><div id="datetimepicker_status_' + this._id +
  1295 			'" class="datetimepicker_status">' + (this._get('initStatus') || '&#xa0;') + '</div>' : '') +
  1295 			'" class="datetimepicker_status">' + (this._get('initStatus') || '&#xa0;') + '</div>' : '') +
  1296 			(!closeAtTop && !this._inline ? controls : '') +
  1296 			(!closeAtTop && !this._inline ? controls : '') +
  1297 			'<div style="clear: both;"></div>' + 
  1297 			'<div style="clear: both;"></div>' +
  1298 			($.browser.msie && parseInt($.browser.version) < 7 && !this._inline ? 
  1298 			($.browser.msie && parseInt($.browser.version) < 7 && !this._inline ?
  1299 			'<iframe src="javascript:false;" class="datetimepicker_cover"></iframe>' : '');
  1299 			'<iframe src="javascript:false;" class="datetimepicker_cover"></iframe>' : '');
  1300 		return html;
  1300 		return html;
  1301 	},
  1301 	},
  1302 	
  1302 
  1303 	/* Generate the month and year header. */
  1303 	/* Generate the month and year header. */
  1304 	_generateMonthYearHeader: function(drawMinute,drawHour,drawMonth, drawYear, minDate, maxDate, selectedDate, secondary) {
  1304 	_generateMonthYearHeader: function(drawMinute,drawHour,drawMonth, drawYear, minDate, maxDate, selectedDate, secondary) {
  1305 		minDate = (this._rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
  1305 		minDate = (this._rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
  1306 		var showStatus = this._get('showStatus');
  1306 		var showStatus = this._get('showStatus');
  1307 		var html = '<div class="datetimepicker_header">';
  1307 		var html = '<div class="datetimepicker_header">';
  1308 		// month selection
  1308 		// month selection
  1309 		var monthNames = this._get('monthNames');
  1309 		var monthNames = this._get('monthNames');
  1310 		if (secondary || !this._get('changeMonth'))
  1310 		if (secondary || !this._get('changeMonth'))
  1311 			html += monthNames[drawMonth] + '&#xa0;';
  1311 			html += monthNames[drawMonth] + '&#xa0;';
  1312 			
  1312 
  1313 		else {
  1313 		else {
  1314 			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
  1314 			var inMinYear = (minDate && minDate.getFullYear() == drawYear);
  1315 			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
  1315 			var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
  1316 			html += '<select class="datetimepicker_newMonth" ' +
  1316 			html += '<select class="datetimepicker_newMonth" ' +
  1317 				'onchange="jQuery.datetimepicker._selectMonthYear(' + this._id + ', this, \'M\');" ' +
  1317 				'onchange="jQuery.datetimepicker._selectMonthYear(' + this._id + ', this, \'M\');" ' +
  1411 		this._drawMonth = this._selectedMonth = date.getMonth();
  1411 		this._drawMonth = this._selectedMonth = date.getMonth();
  1412 		this._drawYear = this._selectedYear = date.getFullYear();
  1412 		this._drawYear = this._selectedYear = date.getFullYear();
  1413 		this._drawHour = this._selectedHour = date.getHours();
  1413 		this._drawHour = this._selectedHour = date.getHours();
  1414 		this._drawMinute = this._selectedMinute = date.getMinutes();
  1414 		this._drawMinute = this._selectedMinute = date.getMinutes();
  1415 	},
  1415 	},
  1416 	
  1416 
  1417 	/* Determine the number of months to show. */
  1417 	/* Determine the number of months to show. */
  1418 	_getNumberOfMonths: function() {
  1418 	_getNumberOfMonths: function() {
  1419 		var numMonths = this._get('numberOfMonths');
  1419 		var numMonths = this._get('numberOfMonths');
  1420 		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
  1420 		return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
  1421 	},
  1421 	},
  1459 		newMinDate = (newMinDate && this._rangeStart < newMinDate ? this._rangeStart : newMinDate);
  1459 		newMinDate = (newMinDate && this._rangeStart < newMinDate ? this._rangeStart : newMinDate);
  1460 		var minDate = newMinDate || this._getMinMaxDate('min');
  1460 		var minDate = newMinDate || this._getMinMaxDate('min');
  1461 		var maxDate = this._getMinMaxDate('max');
  1461 		var maxDate = this._getMinMaxDate('max');
  1462 		return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
  1462 		return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
  1463 	},
  1463 	},
  1464 	
  1464 
  1465 	/* Provide the configuration settings for formatting/parsing. */
  1465 	/* Provide the configuration settings for formatting/parsing. */
  1466 	_getFormatConfig: function() {
  1466 	_getFormatConfig: function() {
  1467 		var shortYearCutoff = this._get('shortYearCutoff');
  1467 		var shortYearCutoff = this._get('shortYearCutoff');
  1468 		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
  1468 		shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
  1469 			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
  1469 			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
  1511 			$.datetimepicker._attachDatepicker(this, options);
  1511 			$.datetimepicker._attachDatepicker(this, options);
  1512 	});
  1512 	});
  1513 };
  1513 };
  1514 
  1514 
  1515 $.datetimepicker = new DateTimepicker(); // singleton instance
  1515 $.datetimepicker = new DateTimepicker(); // singleton instance
  1516 	
  1516 
  1517 /* Initialise the date picker. */
  1517 /* Initialise the date picker. */
  1518 $(document).ready(function() {
  1518 $(document).ready(function() {
  1519 	$(document.body).append($.datetimepicker._datetimepickerDiv)
  1519 	$(document.body).append($.datetimepicker._datetimepickerDiv)
  1520 		.mousedown($.datetimepicker._checkExternalClick);
  1520 		.mousedown($.datetimepicker._checkExternalClick);
  1521 });
  1521 });