PageSourceSearch

https://diocesan.com/wp-content/plugins/woocommerce-tm-extra-produ…/assets/js/tm-datepicker.js?ver=7.6.1

js diocesan.com collected 2026-09-24 10:28:05 UTC 88,455 bytes, 2,287 lines download raw bytes

1/*! jQuery UI - v1.12.1 - 2019-02-17
2 * http://jqueryui.com
3 * Modified version of jQuery Datepicker
4 * Copyright jQuery Foundation and other contributors; Licensed MIT */
5
6( function( factory ) {
7	'use strict';
8	if ( typeof window.define === 'function' && window.define.amd ) {
9		// AMD. Register as an anonymous module.
10		window.define( [ 'jquery' ], factory );
11	} else {
12		// Browser globals
13		factory( window.jQuery );
14	}
15}( function( $ ) {
16	'use strict';
17	/*!
18	 * jQuery UI Datepicker 1.12.1 (Modified version of jQuery Datepicker)
19	 * http://jqueryui.com
20	 *
21	 * Copyright jQuery Foundation and other contributors
22	 * Released under the MIT license.
23	 * http://jquery.org/license
24	 *
25	 * http://api.jqueryui.com/datepicker/
26	 */
27
28	var datepicker_instActive;
29
30	$.ui.tm_datepicker = $.ui.tm_datepicker || {};
31	if ( $.ui.tm_datepicker.version ) {
32		return;
33	}
34
35	$.extend( $.ui, { tm_datepicker: { version: '1.11.4' } } );
36
37	function datepicker_getZindex( elem ) {
38		var position, value;
39		while ( elem.length && elem[ 0 ] !== document ) {
40			// Ignore z-index if position is set to a value where z-index is ignored by the browser
41			// This makes behavior of this function consistent across browsers
42			// WebKit always returns auto if the element is positioned
43			position = elem.css( 'position' );
44			if ( position === 'absolute' || position === 'relative' || position === 'fixed' ) {
45				// IE returns 0 when zIndex is not specified
46				// other browsers return a string
47				// we ignore the case of nested elements with an explicit value of 0
48				value = parseInt( elem.css( 'zIndex' ), 10 );
49				if ( ! isNaN( value ) && value !== 0 ) {
50					return value;
51				}
52			}
53			elem = elem.parent();
54		}
55
56		return 0;
57	}
58
59	/*
60	 * Bind hover events for datepicker elements.
61	 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
62	 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
63	 */
64	function datepicker_handleMouseover( that ) {
65		if ( ! $.tm_datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
66			$( that ).parents( '.ui-tm-datepicker-calendar' ).find( 'a' ).removeClass( 'ui-state-hover' );
67			$( that ).addClass( 'ui-state-hover' );
68			if ( that.className.indexOf( 'ui-tm-datepicker-prev' ) !== -1 ) {
69				$( that ).addClass( 'ui-tm-datepicker-prev-hover' );
70			}
71			if ( that.className.indexOf( 'ui-tm-datepicker-next' ) !== -1 ) {
72				$( that ).addClass( 'ui-tm-datepicker-next-hover' );
73			}
74		}
75	}
76
77	function datepicker_bindHover( dpDiv ) {
78		var selector = 'button, .ui-tm-datepicker-prev, .ui-tm-datepicker-next, .ui-tm-datepicker-calendar td a';
79		return dpDiv
80			.on( 'mouseout', selector, function() {
81				$( this ).removeClass( 'ui-state-hover' );
82				if ( this.className.indexOf( 'ui-tm-datepicker-prev' ) !== -1 ) {
83					$( this ).removeClass( 'ui-tm-datepicker-prev-hover' );
84				}
85				if ( this.className.indexOf( 'ui-tm-datepicker-next' ) !== -1 ) {
86					$( this ).removeClass( 'ui-tm-datepicker-next-hover' );
87				}
88			} )
89			.on( 'mouseover', selector, function() {
90				datepicker_handleMouseover( this );
91			} );
92	}
93
94	/* jQuery extend now ignores nulls! */
95	function datepicker_extendRemove( target, props ) {
96		var name;
97
98		$.extend( target, props );
99		for ( name in props ) {
100			if ( props[ name ] === null ) {
101				target[ name ] = props[ name ];
102			}
103		}
104		return target;
105	}
106
107	/* Date picker manager.
108     Use the singleton instance of this class, $.tm_datepicker, to interact with the date picker.
109     Settings for (groups of) date pickers are maintained in an instance object,
110     allowing multiple different settings on the same page. */
111
112	function Datepicker() {
113		this._curInst = null; // The current instance in use
114		this._keyEvent = false; // If the last event was a key event
115		this._disabledInputs = []; // List of date picker inputs that have been disabled
116		this._datepickerShowing = false; // True if the popup picker is showing , false if not
117		this._inDialog = false; // True if showing within a "dialog", false if not
118		this._mainDivId = 'ui-tm-datepicker-div'; // The ID of the main datepicker division
119		this._inlineClass = 'ui-tm-datepicker-inline'; // The name of the inline marker class
120		this._appendClass = 'ui-tm-datepicker-append'; // The name of the append marker class
121		this._triggerClass = 'ui-tm-datepicker-trigger'; // The name of the trigger marker class
122		this._dialogClass = 'ui-tm-datepicker-dialog'; // The name of the dialog marker class
123		this._disableClass = 'ui-tm-datepicker-disabled'; // The name of the disabled covering marker class
124		this._unselectableClass = 'ui-tm-datepicker-unselectable'; // The name of the unselectable cell marker class
125		this._currentClass = 'ui-tm-datepicker-current-day'; // The name of the current day marker class
126		this._dayOverClass = 'ui-tm-datepicker-days-cell-over'; // The name of the day hover marker class
127		this.regional = []; // Available regional settings, indexed by language code
128		this.regional[ '' ] = {
129			// Default regional settings
130			closeText: 'Done', // Display text for close link
131			prevText: 'Prev', // Display text for previous month link
132			nextText: 'Next', // Display text for next month link
133			currentText: 'Today', // Display text for current month link
134			monthNames: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ], // Names of months for drop-down and formatting
135			monthNamesShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ], // For formatting
136			dayNames: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ], // For formatting
137			dayNamesShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ], // For formatting
138			dayNamesMin: [ 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa' ], // Column headings for days starting at Sunday
139			weekHeader: 'Wk', // Column header for week of the year
140			dateFormat: 'mm/dd/yy', // See format options on parseDate
141			firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
142			isRTL: false, // True if right-to-left language, false if left-to-right
143			showMonthAfterYear: false, // True if the year select precedes month, false for month then year
144			yearSuffix: '' // Additional text to append to the year in the month headers
145		};
146		this._defaults = {
147			// Global defaults for all the date picker instances
148			showOn: 'focus', // "focus" for popup on focus,
149			// "button" for trigger button, or "both" for either
vendor: 5,956 bytes, lines 150-264
150			showAnim: 'fadeIn', // Name of jQuery animation for popup
151			showOptions: {}, // Options for enhanced animations
152			defaultDate: null, // Used when field is blank: actual date,
153			// +/-number for offset from today, null for today
154			appendText: '', // Display text following the input box, e.g. showing the format
155			buttonText: '...', // Text for trigger button
156			buttonImage: '', // URL for trigger button image
157			buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
158			hideIfNoPrevNext: false, // True to hide next/previous month links
159			// if not applicable, false to just disable them
160			navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
161			gotoCurrent: false, // True if today link goes back to current selection instead
162			changeMonth: false, // True if month can be selected directly, false if only prev/next
163			changeYear: false, // True if year can be selected directly, false if only prev/next
164			yearRange: 'c-10:c+10', // Range of years to display in drop-down,
165			// either relative to today's year (-nn:+nn), relative to currently displayed year
166			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
167			showOtherMonths: false, // True to show dates in other months, false to leave blank
168			selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
169			showWeek: false, // True to show week of the year, false to not show it
170			calculateWeek: this.iso8601Week, // How to calculate the week of the year,
171			// takes a Date and returns the number of the week for it
172			shortYearCutoff: '+10', // Short year values < this are in the current century,
173			// > this are in the previous century,
174			// string value starting with "+" for current year + value
175			minDate: null, // The earliest selectable date, or null for no limit
176			maxDate: null, // The latest selectable date, or null for no limit
177			duration: 'fast', // Duration of display/closure
178			beforeShowDay: null, // Function that takes a date and returns an array with
179			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
180			// [2] = cell title (optional), e.g. $.tm_datepicker.noWeekends
181			beforeShow: null, // Function that takes an input field and
182			// returns a set of custom settings for the date picker
183			onSelect: null, // Define a callback function when a date is selected
184			onChangeMonthYear: null, // Define a callback function when the month or year is changed
185			onClose: null, // Define a callback function when the datepicker is closed
186			numberOfMonths: 1, // Number of months to show at a time
187			showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
188			stepMonths: 1, // Number of months to step back/forward
189			stepBigMonths: 12, // Number of months to step back/forward for the big links
190			altField: '', // Selector for an alternate field to store selected dates into
191			altFormat: '', // The date format to use for the alternate field
192			constrainInput: true, // The input is constrained by the current date format
193			showButtonPanel: false, // True to show button panel, false to not show it
194			autoSize: false, // True to size the input for the date format, false to leave as is
195			disabled: false // The initial disabled state
196		};
197		$.extend( this._defaults, this.regional[ '' ] );
198		this.regional.en = $.extend( true, {}, this.regional[ '' ] );
199		this.regional[ 'en-US' ] = $.extend( true, {}, this.regional.en );
200		this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-tm-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
201	}
202
203	$.extend( Datepicker.prototype, {
204		/* Class name added to elements to indicate already configured with a date picker. */
205		markerClassName: 'hasDatepicker',
206
207		//Keep track of the maximum number of rows displayed (see #7043)
208		maxRows: 4,
209
210		// TODO rename to "widget" when switching to widget factory
211		_widgetDatepicker: function() {
212			return this.dpDiv;
213		},
214
215		/* Override the default settings for all instances of the date picker.
216		 * @param  settings  object - the new settings to use as defaults (anonymous object)
217		 * @return the manager object
218		 */
219		setDefaults: function( settings ) {
220			datepicker_extendRemove( this._defaults, settings || {} );
221			return this;
222		},
223
224		/* Attach the date picker to a jQuery selection.
225		 * @param  target   element - the target input field or division or span
226		 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
227		 */
228		_attachDatepicker: function( target, settings ) {
229			var nodeName, inline, inst;
230			nodeName = target.nodeName.toLowerCase();
231			inline = nodeName === 'div' || nodeName === 'span';
232			if ( ! target.id ) {
233				this.uuid += 1;
234				target.id = 'dp' + this.uuid;
235			}
236			inst = this._newInst( $( target ), inline );
237			inst.settings = $.extend( {}, settings || {} );
238			if ( nodeName === 'input' ) {
239				this._connectDatepicker( target, inst );
240			} else if ( inline ) {
241				this._inlineDatepicker( target, inst );
242			}
243		},
244
245		/* Create a new instance object. */
246		_newInst: function( target, inline ) {
247			var id = target[ 0 ].id.replace( /([^A-Za-z0-9_-])/g, '\\\\$1' ); // escape jQuery meta chars
248			return {
249				id: id,
250				input: target, // associated target
251				selectedDay: 0,
252				selectedMonth: 0,
253				selectedYear: 0, // current selection
254				drawMonth: 0,
255				drawYear: 0, // month being drawn
256				inline: inline, // is datepicker inline or not
257				// presentation div
258				dpDiv: ! inline ? this.dpDiv : datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-tm-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) )
259			};
260		},
261
262		/* Attach the date picker to an input field. */
263		_connectDatepicker: function( target, inst ) {
264			var input = $( target );
vendor: 4,072 bytes, lines 265-382
265			inst.append = $( [] );
266			inst.trigger = $( [] );
267			if ( input.hasClass( this.markerClassName ) ) {
268				return;
269			}
270			this._attachments( input, inst );
271			input.addClass( this.markerClassName ).on( 'keydown', this._doKeyDown ).on( 'keypress', this._doKeyPress ).on( 'keyup', this._doKeyUp );
272			this._autoSize( inst );
273			$.data( target, 'datepicker', inst );
274
275			//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
276			if ( inst.settings.disabled ) {
277				this._disableDatepicker( target );
278			}
279		},
280
281		/* Make attachments based on settings. */
282		_attachments: function( input, inst ) {
283			var showOn,
284				buttonText,
285				buttonImage,
286				appendText = this._get( inst, 'appendText' ),
287				isRTL = this._get( inst, 'isRTL' );
288
289			if ( inst.append ) {
290				inst.append.remove();
291			}
292			if ( appendText ) {
293				inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + '</span>' );
294				input[ isRTL ? 'before' : 'after' ]( inst.append );
295			}
296
297			input.off( 'focus', this._showDatepicker );
298
299			if ( inst.trigger ) {
300				inst.trigger.remove();
301			}
302
303			showOn = this._get( inst, 'showOn' );
304			if ( showOn === 'focus' || showOn === 'both' ) {
305				// pop-up date picker when in the marked field
306				input.on( 'focus', this._showDatepicker );
307			}
308			if ( showOn === 'button' || showOn === 'both' ) {
309				// pop-up date picker when button clicked
310				buttonText = this._get( inst, 'buttonText' );
311				buttonImage = this._get( inst, 'buttonImage' );
312				inst.trigger = $(
313					this._get( inst, 'buttonImageOnly' )
314						? $( '<img/>' ).addClass( this._triggerClass ).attr( { src: buttonImage, alt: buttonText, title: buttonText } )
315						: $( "<button type='button'></button>" )
316							.addClass( this._triggerClass )
317							.html( ! buttonImage ? buttonText : $( '<img/>' ).attr( { src: buttonImage, alt: buttonText, title: buttonText } ) )
318				);
319				input[ isRTL ? 'before' : 'after' ]( inst.trigger );
320				inst.trigger.on( 'click', function() {
321					if ( $.tm_datepicker._datepickerShowing && $.tm_datepicker._lastInput === input[ 0 ] ) {
322						$.tm_datepicker._hideDatepicker();
323					} else if ( $.tm_datepicker._datepickerShowing && $.tm_datepicker._lastInput !== input[ 0 ] ) {
324						$.tm_datepicker._hideDatepicker();
325						$.tm_datepicker._showDatepicker( input[ 0 ] );
326					} else {
327						$.tm_datepicker._showDatepicker( input[ 0 ] );
328					}
329					return false;
330				} );
331			}
332		},
333
334		/* Apply the maximum length for the date format. */
335		_autoSize: function( inst ) {
336			var findMax;
337			var max;
338			var maxI;
339			var i;
340			var date;
341			var dateFormat = this._get( inst, 'dateFormat' );
342
343			if ( this._get( inst, 'autoSize' ) && ! inst.inline ) {
344				date = new Date( 2009, 12 - 1, 20 ); // Ensure double digits
345				dateFormat = this._get( inst, 'dateFormat' );
346
347				if ( dateFormat.match( /[DM]/ ) ) {
348					findMax = function( names ) {
349						max = 0;
350						maxI = 0;
351						for ( i = 0; i < names.length; i += 1 ) {
352							if ( names[ i ].length > max ) {
353								max = names[ i ].length;
354								maxI = i;
355							}
356						}
357						return maxI;
358					};
359					date.setMonth( findMax( this._get( inst, dateFormat.match( /MM/ ) ? 'monthNames' : 'monthNamesShort' ) ) );
360					date.setDate( findMax( this._get( inst, dateFormat.match( /DD/ ) ? 'dayNames' : 'dayNamesShort' ) ) + 20 - date.getDay() );
361				}
362				inst.input.attr( 'size', this._formatDate( inst, date ).length );
363			}
364		},
365
366		/* Attach an inline date picker to a div. */
367		_inlineDatepicker: function( target, inst ) {
368			var divSpan = $( target );
369			if ( divSpan.hasClass( this.markerClassName ) ) {
370				return;
371			}
372			divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
373			$.data( target, 'datepicker', inst );
374			this._setDate( inst, this._getDefaultDate( inst ), true );
375			this._updateDatepicker( inst );
376			this._updateAlternate( inst );
377
378			//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
379			if ( inst.settings.disabled ) {
380				this._disableDatepicker( target );
381			}
382
vendor: 3,023 bytes, lines 383-459
383			// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
384			// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
385			inst.dpDiv.css( 'display', 'block' );
386		},
387
388		/* Pop-up the date picker in a "dialog" box.
389		 * @param  input element - ignored
390		 * @param  date string or Date - the initial date to display
391		 * @param  onSelect  function - the function to call when a date is selected
392		 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
393		 * @param  pos int[2] - coordinates for the dialog's position within the screen or
394		 *                  event - with x/y coordinates or
395		 *                  leave empty for default (screen centre)
396		 * @return the manager object
397		 */
398		_dialogDatepicker: function( input, date, onSelect, settings, pos ) {
399			var id,
400				browserWidth,
401				browserHeight,
402				scrollX,
403				scrollY,
404				inst = this._dialogInst; // internal instance
405
406			if ( ! inst ) {
407				this.uuid += 1;
408				id = 'dp' + this.uuid;
409				this._dialogInput = $( "<input type='text' id='" + id + "'>" );
410				this._dialogInput.on( 'keydown', this._doKeyDown );
411				$( 'body' ).append( this._dialogInput );
412				inst = this._newInst( this._dialogInput, false );
413				this._dialogInst = inst;
414				inst.settings = {};
415				$.data( this._dialogInput[ 0 ], 'datepicker', inst );
416			}
417			datepicker_extendRemove( inst.settings, settings || {} );
418			date = date && date.constructor === Date ? this._formatDate( inst, date ) : date;
419			this._dialogInput.val( date );
420
421			this._pos = pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null;
422			if ( ! this._pos ) {
423				browserWidth = document.documentElement.clientWidth;
424				browserHeight = document.documentElement.clientHeight;
425				scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
426				scrollY = document.documentElement.scrollTop || document.body.scrollTop;
427				this._pos =
428					// should use actual width/height below
429					[ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
430			}
431
432			// Move input on screen for focus, but hidden behind dialog
433			this._dialogInput.css( 'left', this._pos[ 0 ] + 20 + 'px' ).css( 'top', this._pos[ 1 ] + 'px' );
434			inst.settings.onSelect = onSelect;
435			this._inDialog = true;
436			this.dpDiv.addClass( this._dialogClass );
437			this._showDatepicker( this._dialogInput[ 0 ] );
438			if ( $.blockUI ) {
439				$.blockUI( this.dpDiv );
440			}
441			$.data( this._dialogInput[ 0 ], 'datepicker', inst );
442			return this;
443		},
444
445		/* Detach a datepicker from its control.
446		 * @param  target   element - the target input field or division or span
447		 */
448		_destroyDatepicker: function( target ) {
449			var nodeName,
450				$target = $( target ),
451				inst = $.data( target, 'datepicker' );
452
453			if ( ! $target.hasClass( this.markerClassName ) ) {
454				return;
455			}
456
457			nodeName = target.nodeName.toLowerCase();
458			$.removeData( target, 'datepicker' );
459			if ( nodeName === 'input' ) {
vendor: 7,441 bytes, lines 460-684
460				inst.append.remove();
461				inst.trigger.remove();
462				$target.removeClass( this.markerClassName ).off( 'focus', this._showDatepicker ).off( 'keydown', this._doKeyDown ).off( 'keypress', this._doKeyPress ).off( 'keyup', this._doKeyUp );
463			} else if ( nodeName === 'div' || nodeName === 'span' ) {
464				$target.removeClass( this.markerClassName ).empty();
465			}
466
467			if ( datepicker_instActive === inst ) {
468				datepicker_instActive = null;
469			}
470		},
471
472		/* Enable the date picker to a jQuery selection.
473		 * @param  target   element - the target input field or division or span
474		 */
475		_enableDatepicker: function( target ) {
476			var nodeName,
477				inline,
478				$target = $( target ),
479				inst = $.data( target, 'datepicker' );
480
481			if ( ! $target.hasClass( this.markerClassName ) ) {
482				return;
483			}
484
485			nodeName = target.nodeName.toLowerCase();
486			if ( nodeName === 'input' ) {
487				target.disabled = false;
488				inst.trigger
489					.filter( 'button' )
490					.each( function() {
491						this.disabled = false;
492					} )
493					.end()
494					.filter( 'img' )
495					.css( { opacity: '1.0', cursor: '' } );
496			} else if ( nodeName === 'div' || nodeName === 'span' ) {
497				inline = $target.children( '.' + this._inlineClass );
498				inline.children().removeClass( 'ui-state-disabled' );
499				inline.find( 'select.ui-tm-datepicker-month, select.ui-tm-datepicker-year' ).prop( 'disabled', false );
500			}
501			this._disabledInputs = $.map( this._disabledInputs, function( value ) {
502				return value === target ? null : value;
503			} ); // delete entry
504		},
505
506		/* Disable the date picker to a jQuery selection.
507		 * @param  target   element - the target input field or division or span
508		 */
509		_disableDatepicker: function( target ) {
510			var nodeName,
511				inline,
512				$target = $( target ),
513				inst = $.data( target, 'datepicker' );
514
515			if ( ! $target.hasClass( this.markerClassName ) ) {
516				return;
517			}
518
519			nodeName = target.nodeName.toLowerCase();
520			if ( nodeName === 'input' ) {
521				target.disabled = true;
522				inst.trigger
523					.filter( 'button' )
524					.each( function() {
525						this.disabled = true;
526					} )
527					.end()
528					.filter( 'img' )
529					.css( { opacity: '0.5', cursor: 'default' } );
530			} else if ( nodeName === 'div' || nodeName === 'span' ) {
531				inline = $target.children( '.' + this._inlineClass );
532				inline.children().addClass( 'ui-state-disabled' );
533				inline.find( 'select.ui-tm-datepicker-month, select.ui-tm-datepicker-year' ).prop( 'disabled', true );
534			}
535			this._disabledInputs = $.map( this._disabledInputs, function( value ) {
536				return value === target ? null : value;
537			} ); // delete entry
538			this._disabledInputs[ this._disabledInputs.length ] = target;
539		},
540
541		/* Is the first field in a jQuery collection disabled as a datepicker?
542		 * @param  target   element - the target input field or division or span
543		 * @return boolean - true if disabled, false if enabled
544		 */
545		_isDisabledDatepicker: function( target ) {
546			var i;
547			if ( ! target ) {
548				return false;
549			}
550			for ( i = 0; i < this._disabledInputs.length; i += 1 ) {
551				if ( this._disabledInputs[ i ] === target ) {
552					return true;
553				}
554			}
555			return false;
556		},
557
558		/* Retrieve the instance data for the target control.
559		 * @param  target  element - the target input field or division or span
560		 * @return  object - the associated instance data
561		 * @throws  error if a jQuery problem getting data
562		 */
563		_getInst: function( target ) {
564			try {
565				return $.data( target, 'datepicker' );
566			} catch ( err ) {
567				throw 'Missing instance data for this datepicker';
568			}
569		},
570
571		/* Update or retrieve the settings for a date picker attached to an input field or division.
572		 * @param  target  element - the target input field or division or span
573		 * @param  name object - the new settings to update or
574		 *              string - the name of the setting to change or retrieve,
575		 *              when retrieving also "all" for all instance settings or
576		 *              "defaults" for all global defaults
577		 * @param  value   any - the new value for the setting
578		 *              (omit if above is an object or to retrieve a value)
579		 */
580		_optionDatepicker: function( target, name, value ) {
581			var settings,
582				date,
583				minDate,
584				maxDate,
585				inst = this._getInst( target );
586
587			if ( arguments.length === 2 && typeof name === 'string' ) {
588				return name === 'defaults' ? $.extend( {}, $.tm_datepicker._defaults ) : inst ? ( name === 'all' ? $.extend( {}, inst.settings ) : this._get( inst, name ) ) : null;
589			}
590
591			settings = name || {};
592			if ( typeof name === 'string' ) {
593				settings = {};
594				settings[ name ] = value;
595			}
596
597			if ( inst ) {
598				if ( this._curInst === inst ) {
599					this._hideDatepicker();
600				}
601
602				date = this._getDateDatepicker( target, true );
603				minDate = this._getMinMaxDate( inst, 'min' );
604				maxDate = this._getMinMaxDate( inst, 'max' );
605				datepicker_extendRemove( inst.settings, settings );
606
607				// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
608				if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
609					inst.settings.minDate = this._formatDate( inst, minDate );
610				}
611				if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
612					inst.settings.maxDate = this._formatDate( inst, maxDate );
613				}
614				if ( 'disabled' in settings ) {
615					if ( settings.disabled ) {
616						this._disableDatepicker( target );
617					} else {
618						this._enableDatepicker( target );
619					}
620				}
621				this._attachments( $( target ), inst );
622				this._autoSize( inst );
623				this._setDate( inst, date );
624				this._updateAlternate( inst );
625				this._updateDatepicker( inst );
626			}
627		},
628
629		// Change method deprecated
630		_changeDatepicker: function( target, name, value ) {
631			this._optionDatepicker( target, name, value );
632		},
633
634		/* Redraw the date picker attached to an input field or division.
635		 * @param  target  element - the target input field or division or span
636		 */
637		_refreshDatepicker: function( target ) {
638			var inst = this._getInst( target );
639			if ( inst ) {
640				this._updateDatepicker( inst );
641			}
642		},
643
644		/* Set the dates for a jQuery selection.
645		 * @param  target element - the target input field or division or span
646		 * @param  date Date - the new date
647		 */
648		_setDateDatepicker: function( target, date ) {
649			var inst = this._getInst( target );
650			if ( inst ) {
651				this._setDate( inst, date );
652				this._updateDatepicker( inst );
653				this._updateAlternate( inst );
654			}
655		},
656
657		/* Get the date(s) for the first entry in a jQuery selection.
658		 * @param  target element - the target input field or division or span
659		 * @param  noDefault boolean - true if no default date is to be used
660		 * @return Date - the current date
661		 */
662		_getDateDatepicker: function( target, noDefault ) {
663			var inst = this._getInst( target );
664			if ( inst && ! inst.inline ) {
665				this._setDateFromField( inst, noDefault );
666			}
667			return inst ? this._getDate( inst ) : null;
668		},
669
670		/* Handle keystrokes. */
671		_doKeyDown: function( event ) {
672			var onSelect,
673				dateStr,
674				sel,
675				inst = $.tm_datepicker._getInst( event.target ),
676				handled = true,
677				isRTL = inst.dpDiv.is( '.ui-tm-datepicker-rtl' );
678
679			inst._keyEvent = true;
680			if ( $.tm_datepicker._datepickerShowing ) {
681				switch ( event.keyCode ) {
682					case 9:
683						$.tm_datepicker._hideDatepicker();
684						handled = false;
vendor: 4,548 bytes, lines 685-803
685						break; // hide on tab out
686					case 13:
687						sel = $( 'td.' + $.tm_datepicker._dayOverClass + ':not(.' + $.tm_datepicker._currentClass + ')', inst.dpDiv );
688						if ( sel[ 0 ] ) {
689							$.tm_datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
690						}
691
692						onSelect = $.tm_datepicker._get( inst, 'onSelect' );
693						if ( onSelect ) {
694							dateStr = $.tm_datepicker._formatDate( inst );
695
696							// Trigger custom callback
697							onSelect.apply( inst.input ? inst.input[ 0 ] : null, [ dateStr, inst ] );
698						} else {
699							$.tm_datepicker._hideDatepicker();
700						}
701
702						return false; // don't submit the form
703					case 27:
704						$.tm_datepicker._hideDatepicker();
705						break; // hide on escape
706					case 33:
707						$.tm_datepicker._adjustDate( event.target, event.ctrlKey ? -$.tm_datepicker._get( inst, 'stepBigMonths' ) : -$.tm_datepicker._get( inst, 'stepMonths' ), 'M' );
708						break; // previous month/year on page up/+ ctrl
709					case 34:
710						$.tm_datepicker._adjustDate( event.target, event.ctrlKey ? +$.tm_datepicker._get( inst, 'stepBigMonths' ) : +$.tm_datepicker._get( inst, 'stepMonths' ), 'M' );
711						break; // next month/year on page down/+ ctrl
712					case 35:
713						if ( event.ctrlKey || event.metaKey ) {
714							$.tm_datepicker._clearDate( event.target );
715						}
716						handled = event.ctrlKey || event.metaKey;
717						break; // clear on ctrl or command +end
718					case 36:
719						if ( event.ctrlKey || event.metaKey ) {
720							$.tm_datepicker._gotoToday( event.target );
721						}
722						handled = event.ctrlKey || event.metaKey;
723						break; // current on ctrl or command +home
724					case 37:
725						if ( event.ctrlKey || event.metaKey ) {
726							$.tm_datepicker._adjustDate( event.target, isRTL ? +1 : -1, 'D' );
727						}
728						handled = event.ctrlKey || event.metaKey;
729						// -1 day on ctrl or command +left
730						if ( event.originalEvent.altKey ) {
731							$.tm_datepicker._adjustDate( event.target, event.ctrlKey ? -$.tm_datepicker._get( inst, 'stepBigMonths' ) : -$.tm_datepicker._get( inst, 'stepMonths' ), 'M' );
732						}
733						// next month/year on alt +left on Mac
734						break;
735					case 38:
736						if ( event.ctrlKey || event.metaKey ) {
737							$.tm_datepicker._adjustDate( event.target, -7, 'D' );
738						}
739						handled = event.ctrlKey || event.metaKey;
740						break; // -1 week on ctrl or command +up
741					case 39:
742						if ( event.ctrlKey || event.metaKey ) {
743							$.tm_datepicker._adjustDate( event.target, isRTL ? -1 : +1, 'D' );
744						}
745						handled = event.ctrlKey || event.metaKey;
746						// +1 day on ctrl or command +right
747						if ( event.originalEvent.altKey ) {
748							$.tm_datepicker._adjustDate( event.target, event.ctrlKey ? +$.tm_datepicker._get( inst, 'stepBigMonths' ) : +$.tm_datepicker._get( inst, 'stepMonths' ), 'M' );
749						}
750						// next month/year on alt +right
751						break;
752					case 40:
753						if ( event.ctrlKey || event.metaKey ) {
754							$.tm_datepicker._adjustDate( event.target, +7, 'D' );
755						}
756						handled = event.ctrlKey || event.metaKey;
757						break; // +1 week on ctrl or command +down
758					default:
759						handled = false;
760				}
761			} else if ( event.keyCode === 36 && event.ctrlKey ) {
762				// display the date picker on ctrl+home
763				$.tm_datepicker._showDatepicker( this );
764			} else {
765				handled = false;
766			}
767
768			if ( handled ) {
769				event.preventDefault();
770				event.stopPropagation();
771			}
772		},
773
774		/* Filter entered characters - based on date format. */
775		_doKeyPress: function( event ) {
776			var chars,
777				chr,
778				inst = $.tm_datepicker._getInst( event.target );
779
780			if ( $.tm_datepicker._get( inst, 'constrainInput' ) ) {
781				chars = $.tm_datepicker._possibleChars( $.tm_datepicker._get( inst, 'dateFormat' ) );
782				chr = String.fromCharCode( event.charCode === null ? event.keyCode : event.charCode );
783				return event.ctrlKey || event.metaKey || chr < ' ' || ! chars || chars.indexOf( chr ) > -1;
784			}
785		},
786
787		/* Synchronise manual entry and field/alternate field. */
788		_doKeyUp: function( event ) {
789			var date,
790				inst = $.tm_datepicker._getInst( event.target );
791
792			if ( inst.input.val() !== inst.lastVal ) {
793				try {
794					date = $.tm_datepicker.parseDate( $.tm_datepicker._get( inst, 'dateFormat' ), inst.input ? inst.input.val() : null, $.tm_datepicker._getFormatConfig( inst ) );
795
796					if ( date ) {
797						// only if valid
798						$.tm_datepicker._setDateFromField( inst );
799						$.tm_datepicker._updateAlternate( inst );
800						$.tm_datepicker._updateDatepicker( inst );
801					}
802				} catch ( err ) {
803					return false;
vendor: 14,218 bytes, lines 804-1219
804				}
805			}
806			return true;
807		},
808
809		/* Pop-up the date picker for a given input field.
810		 * If false returned from beforeShow event handler do not show.
811		 * @param  input  element - the input field attached to the date picker or
812		 *                  event - if triggered by focus
813		 */
814		_showDatepicker: function( input ) {
815			var inst;
816			var beforeShow;
817			var beforeShowSettings;
818			var isFixed;
819			var offset;
820			var showAnim;
821			var duration;
822
823			input = input.target || input;
824			if ( input.nodeName.toLowerCase() !== 'input' ) {
825				// find from button/image trigger
826				input = $( 'input', input.parentNode )[ 0 ];
827			}
828
829			if ( $.tm_datepicker._isDisabledDatepicker( input ) || $.tm_datepicker._lastInput === input ) {
830				// already here
831				return;
832			}
833
834			inst = $.tm_datepicker._getInst( input );
835			if ( $.tm_datepicker._curInst && $.tm_datepicker._curInst !== inst ) {
836				$.tm_datepicker._curInst.dpDiv.stop( true, true );
837				if ( inst && $.tm_datepicker._datepickerShowing ) {
838					$.tm_datepicker._hideDatepicker( $.tm_datepicker._curInst.input[ 0 ] );
839				}
840			}
841
842			beforeShow = $.tm_datepicker._get( inst, 'beforeShow' );
843			beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
844			if ( beforeShowSettings === false ) {
845				return;
846			}
847			datepicker_extendRemove( inst.settings, beforeShowSettings );
848
849			inst.lastVal = null;
850			$.tm_datepicker._lastInput = input;
851			$.tm_datepicker._setDateFromField( inst );
852
853			if ( $.tm_datepicker._inDialog ) {
854				// hide cursor
855				input.value = '';
856			}
857			if ( ! $.tm_datepicker._pos ) {
858				// position below input
859				$.tm_datepicker._pos = $.tm_datepicker._findPos( input );
860				$.tm_datepicker._pos[ 1 ] += input.offsetHeight; // add the height
861			}
862
863			isFixed = false;
864			$( input )
865				.parents()
866				.each( function() {
867					isFixed = isFixed || $( this ).css( 'position' ) === 'fixed';
868					return ! isFixed;
869				} );
870
871			offset = { left: $.tm_datepicker._pos[ 0 ], top: $.tm_datepicker._pos[ 1 ] };
872			$.tm_datepicker._pos = null;
873			//to avoid flashes on Firefox
874			inst.dpDiv.empty();
875			// determine sizing offscreen
876			inst.dpDiv.css( { position: 'absolute', display: 'block', top: '-1000px' } );
877			$.tm_datepicker._updateDatepicker( inst );
878			// fix width for dynamic number of date pickers
879			// and adjust position before showing
880			offset = $.tm_datepicker._checkOffset( inst, offset, isFixed );
881			inst.dpDiv.css( {
882				position: $.tm_datepicker._inDialog && $.blockUI ? 'static' : isFixed ? 'fixed' : 'absolute',
883				display: 'none',
884				left: offset.left + 'px',
885				top: offset.top + 'px'
886			} );
887
888			if ( ! inst.inline ) {
889				showAnim = $.tm_datepicker._get( inst, 'showAnim' );
890				duration = $.tm_datepicker._get( inst, 'duration' );
891				inst.dpDiv.css( 'z-index', datepicker_getZindex( $( input ) ) + 1 );
892				$.tm_datepicker._datepickerShowing = true;
893
894				if ( $.effects && $.effects.effect[ showAnim ] ) {
895					inst.dpDiv.show( showAnim, $.tm_datepicker._get( inst, 'showOptions' ), duration );
896				} else {
897					inst.dpDiv[ showAnim || 'show' ]( showAnim ? duration : null );
898				}
899
900				if ( $.tm_datepicker._shouldFocusInput( inst ) ) {
901					inst.input.trigger( 'focus' );
902				}
903
904				$.tm_datepicker._curInst = inst;
905			}
906		},
907
908		/* Generate the date picker content. */
909		_updateDatepicker: function( inst ) {
910			var origyearshtml;
911			var numMonths;
912			var cols;
913			var width = 17;
914			var activeCell;
915
916			this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
917			datepicker_instActive = inst; // for delegate hover events
918			inst.dpDiv.empty().append( this._generateHTML( inst ) );
919			this._attachHandlers( inst );
920
921			numMonths = this._getNumberOfMonths( inst );
922			cols = numMonths[ 1 ];
923			activeCell = inst.dpDiv.find( '.' + this._dayOverClass + ' a' );
924
925			if ( activeCell.length > 0 ) {
926				datepicker_handleMouseover.apply( activeCell.get( 0 ), [ activeCell.get( 0 ) ] );
927			}
928
929			inst.dpDiv.removeClass( 'ui-tm-datepicker-multi-2 ui-tm-datepicker-multi-3 ui-tm-datepicker-multi-4' ).width( '' );
930			if ( cols > 1 ) {
931				inst.dpDiv.addClass( 'ui-tm-datepicker-multi-' + cols ).css( 'width', ( width * cols ) + 'em' );
932			}
933			inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? 'add' : 'remove' ) + 'Class' ]( 'ui-tm-datepicker-multi' );
934			inst.dpDiv[ ( this._get( inst, 'isRTL' ) ? 'add' : 'remove' ) + 'Class' ]( 'ui-tm-datepicker-rtl' );
935
936			if ( inst === $.tm_datepicker._curInst && $.tm_datepicker._datepickerShowing && $.tm_datepicker._shouldFocusInput( inst ) ) {
937				inst.input.trigger( 'focus' );
938			}
939
940			// deffered render of the years select (to avoid flashes on Firefox)
941			if ( inst.yearshtml ) {
942				origyearshtml = inst.yearshtml;
943				setTimeout( function() {
944					//assure that inst.yearshtml didn't change.
945					if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
946						inst.dpDiv.find( 'select.ui-tm-datepicker-year:first' ).replaceWith( inst.yearshtml );
947					}
948					origyearshtml = null;
949					inst.yearshtml = null;
950				}, 0 );
951			}
952		},
953
954		// #6694 - don't focus the input if it's already focused
955		// this breaks the change event in IE
956		// Support: IE and jQuery <1.9
957		_shouldFocusInput: function( inst ) {
958			return inst.input && inst.input.is( ':visible' ) && ! inst.input.is( ':disabled' ) && ! inst.input.is( ':focus' );
959		},
960
961		/* Check positioning to remain on screen. */
962		_checkOffset: function( inst, offset, isFixed ) {
963			var dpWidth = inst.dpDiv.outerWidth(),
964				dpHeight = inst.dpDiv.outerHeight(),
965				inputWidth = inst.input ? inst.input.outerWidth() : 0,
966				inputHeight = inst.input ? inst.input.outerHeight() : 0,
967				viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
968				viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
969
970			offset.left -= this._get( inst, 'isRTL' ) ? dpWidth - inputWidth : 0;
971			offset.left -= isFixed && offset.left === inst.input.offset().left ? $( document ).scrollLeft() : 0;
972			offset.top -= isFixed && offset.top === inst.input.offset().top + inputHeight ? $( document ).scrollTop() : 0;
973
974			// Now check if datepicker is showing outside window viewport - move to a better place if so.
975			offset.left -= Math.min( offset.left, offset.left + dpWidth > viewWidth && viewWidth > dpWidth ? Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
976			offset.top -= Math.min( offset.top, offset.top + dpHeight > viewHeight && viewHeight > dpHeight ? Math.abs( dpHeight + inputHeight ) : 0 );
977
978			return offset;
979		},
980
981		/* Find an object's position on the screen. */
982		_findPos: function( obj ) {
983			var position,
984				inst = this._getInst( obj ),
985				isRTL = this._get( inst, 'isRTL' );
986
987			while ( obj && ( obj.type === 'hidden' || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
988				obj = obj[ isRTL ? 'previousSibling' : 'nextSibling' ];
989			}
990
991			position = $( obj ).offset();
992			return [ position.left, position.top ];
993		},
994
995		/* Hide the date picker from view.
996		 * @param  input  element - the input field attached to the date picker
997		 */
998		_hideDatepicker: function( input ) {
999			var showAnim,
1000				duration,
1001				postProcess,
1002				onClose,
1003				inst = this._curInst;
1004
1005			if ( ! inst || ( input && inst !== $.data( input, 'datepicker' ) ) ) {
1006				return;
1007			}
1008
1009			if ( this._datepickerShowing ) {
1010				showAnim = this._get( inst, 'showAnim' );
1011				duration = this._get( inst, 'duration' );
1012				postProcess = function() {
1013					$.tm_datepicker._tidyDialog( inst );
1014				};
1015
1016				// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
1017				if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
1018					inst.dpDiv.hide( showAnim, $.tm_datepicker._get( inst, 'showOptions' ), duration, postProcess );
1019				} else {
1020					inst.dpDiv[ showAnim === 'slideDown' ? 'slideUp' : showAnim === 'fadeIn' ? 'fadeOut' : 'hide' ]( showAnim ? duration : null, postProcess );
1021				}
1022
1023				if ( ! showAnim ) {
1024					postProcess();
1025				}
1026				this._datepickerShowing = false;
1027
1028				onClose = this._get( inst, 'onClose' );
1029				if ( onClose ) {
1030					onClose.apply( inst.input ? inst.input[ 0 ] : null, [ inst.input ? inst.input.val() : '', inst ] );
1031				}
1032
1033				this._lastInput = null;
1034				if ( this._inDialog ) {
1035					this._dialogInput.css( { position: 'absolute', left: '0', top: '-100px' } );
1036					if ( $.blockUI ) {
1037						$.unblockUI();
1038						$( 'body' ).append( this.dpDiv );
1039					}
1040				}
1041				this._inDialog = false;
1042			}
1043		},
1044
1045		/* Tidy up after a dialog display. */
1046		_tidyDialog: function( inst ) {
1047			inst.dpDiv.removeClass( this._dialogClass ).off( '.ui-tm-datepicker-calendar' );
1048		},
1049
1050		/* Close date picker if clicked elsewhere. */
1051		_checkExternalClick: function( event ) {
1052			var $target;
1053			var inst;
1054
1055			if ( ! $.tm_datepicker._curInst ) {
1056				return;
1057			}
1058
1059			$target = $( event.target );
1060			inst = $.tm_datepicker._getInst( $target[ 0 ] );
1061
1062			if ( ( $target[ 0 ].id !== $.tm_datepicker._mainDivId && $target.parents( '#' + $.tm_datepicker._mainDivId ).length === 0 && ! $target.hasClass( $.tm_datepicker.markerClassName ) && ! $target.closest( '.' + $.tm_datepicker._triggerClass ).length && $.tm_datepicker._datepickerShowing && ! ( $.tm_datepicker._inDialog && $.blockUI ) ) || ( $target.hasClass( $.tm_datepicker.markerClassName ) && $.tm_datepicker._curInst !== inst ) ) {
1063				$.tm_datepicker._hideDatepicker();
1064			}
1065		},
1066
1067		/* Adjust one of the date sub-fields. */
1068		_adjustDate: function( id, offset, period ) {
1069			var target = $( id ),
1070				inst = this._getInst( target[ 0 ] );
1071
1072			if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
1073				return;
1074			}
1075			this._adjustInstDate(
1076				inst,
1077				offset + ( period === 'M' ? this._get( inst, 'showCurrentAtPos' ) : 0 ), // undo positioning
1078				period
1079			);
1080			this._updateDatepicker( inst );
1081		},
1082
1083		/* Action for current link. */
1084		_gotoToday: function( id ) {
1085			var date,
1086				target = $( id ),
1087				inst = this._getInst( target[ 0 ] );
1088
1089			if ( this._get( inst, 'gotoCurrent' ) && inst.currentDay ) {
1090				inst.selectedDay = inst.currentDay;
1091				inst.drawMonth = inst.currentMonth;
1092				inst.selectedMonth = inst.currentMonth;
1093				inst.drawYear = inst.currentYear;
1094				inst.selectedYear = inst.currentYear;
1095			} else {
1096				date = new Date();
1097				inst.selectedDay = date.getDate();
1098				inst.drawMonth = date.getMonth();
1099				inst.selectedMonth = inst.drawMonth;
1100				inst.drawYear = date.getFullYear();
1101				inst.selectedYear = inst.drawYear;
1102			}
1103			this._notifyChange( inst );
1104			this._adjustDate( target );
1105		},
1106
1107		/* Action for selecting a new month/year. */
1108		_selectMonthYear: function( id, select, period ) {
1109			var target = $( id ),
1110				inst = this._getInst( target[ 0 ] );
1111
1112			inst[ 'selected' + ( period === 'M' ? 'Month' : 'Year' ) ] = parseInt( select.options[ select.selectedIndex ].value, 10 );
1113			inst[ 'draw' + ( period === 'M' ? 'Month' : 'Year' ) ] = parseInt( select.options[ select.selectedIndex ].value, 10 );
1114
1115			this._notifyChange( inst );
1116			this._adjustDate( target );
1117		},
1118
1119		/* Action for selecting a day. */
1120		_selectDay: function( id, month, year, td ) {
1121			var inst,
1122				target = $( id );
1123
1124			if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
1125				return;
1126			}
1127
1128			inst = this._getInst( target[ 0 ] );
1129			inst.selectedDay = $( 'a', td ).html();
1130			inst.currentDay = inst.selectedDay;
1131			inst.selectedMonth = month;
1132			inst.currentMonth = month;
1133			inst.selectedYear = year;
1134			inst.currentYear = year;
1135			this._selectDate( id, this._formatDate( inst, inst.currentDay, inst.currentMonth, inst.currentYear ) );
1136		},
1137
1138		/* Erase the input field and hide the date picker. */
1139		_clearDate: function( id ) {
1140			var target = $( id );
1141			this._selectDate( target, '' );
1142		},
1143
1144		/* Update the input field with the selected date. */
1145		_selectDate: function( id, dateStr ) {
1146			var onSelect,
1147				target = $( id ),
1148				inst = this._getInst( target[ 0 ] );
1149
1150			dateStr = dateStr !== null ? dateStr : this._formatDate( inst );
1151			if ( inst.input ) {
1152				inst.input.val( dateStr );
1153			}
1154			this._updateAlternate( inst );
1155
1156			onSelect = this._get( inst, 'onSelect' );
1157			if ( onSelect ) {
1158				onSelect.apply( inst.input ? inst.input[ 0 ] : null, [ dateStr, inst ] ); // trigger custom callback
1159			} else if ( inst.input ) {
1160				inst.input.trigger( 'change' ); // fire the change event
1161			}
1162
1163			if ( inst.inline ) {
1164				this._updateDatepicker( inst );
1165			} else {
1166				this._hideDatepicker();
1167				this._lastInput = inst.input[ 0 ];
1168				if ( typeof inst.input[ 0 ] !== 'object' ) {
1169					inst.input.trigger( 'focus' ); // restore focus
1170				}
1171				this._lastInput = null;
1172			}
1173		},
1174
1175		/* Update any alternate field to synchronise with the main field. */
1176		_updateAlternate: function( inst ) {
1177			var altFormat,
1178				date,
1179				dateStr,
1180				altField = this._get( inst, 'altField' );
1181
1182			if ( altField ) {
1183				// update alternate field too
1184				altFormat = this._get( inst, 'altFormat' ) || this._get( inst, 'dateFormat' );
1185				date = this._getDate( inst );
1186				dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
1187				$( altField ).val( dateStr );
1188			}
1189		},
1190
1191		/* Set as beforeShowDay function to prevent selection of weekends.
1192		 * @param  date  Date - the date to customise
1193		 * @return [boolean, string] - is this date selectable?, what is its CSS class?
1194		 */
1195		noWeekends: function( date ) {
1196			var day = date.getDay();
1197			return [ day > 0 && day < 6, '' ];
1198		},
1199
1200		/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
1201		 * @param  date  Date - the date to get the week for
1202		 * @return  number - the number of the week within the year that contains this date
1203		 */
1204		iso8601Week: function( date ) {
1205			var time,
1206				checkDate = new Date( date.getTime() );
1207
1208			// Find Thursday of this week starting on Monday
1209			checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
1210
1211			time = checkDate.getTime();
1212			checkDate.setMonth( 0 ); // Compare with Jan 1
1213			checkDate.setDate( 1 );
1214			return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
1215		},
1216
1217		/* Parse a string value into a date object.
1218		 * See formatDate below for the possible formats.
1219		 *
1220		 * @param  format string - the expected format of the date
1221		 * @param  value string - the date in the above format
1222		 * @param  settings Object - attributes include:
1223		 *                  shortYearCutoff  number - the cutoff year for determining the century (optional)
1224		 *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
1225		 *                  dayNames        string[7] - names of the days from Sunday (optional)
1226		 *                  monthNamesShort string[12] - abbreviated names of the months (optional)
1227		 *                  monthNames      string[12] - names of the months (optional)
1228		 * @return  Date - the extracted date value or null if value is blank
1229		 */
1230		parseDate: function( format, value, settings ) {
1231			var iFormat;
1232			var dim;
1233			var extra;
1234			var iValue = 0;
1235			var shortYearCutoffTemp;
1236			var shortYearCutoff;
1237			var dayNamesShort;
1238			var dayNames;
1239			var monthNamesShort;
1240			var monthNames;
1241			var year = -1;
1242			var month = -1;
1243			var day = -1;
1244			var doy = -1;
1245			var literal = false;
1246			var date;
1247			var lookAhead;
1248			var getNumber;
1249			var getName;
1250			var checkLiteral;
1251			var condition;
1252
1253			if ( format === null || value === null ) {
1254				throw 'Invalid arguments';
1255			}
1256
1257			value = typeof value === 'object' ? value.toString() : value + '';
1258			if ( value === '' ) {
1259				return null;
1260			}
1261
1262			shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff;
1263			shortYearCutoff = typeof shortYearCutoffTemp !== 'string' ? shortYearCutoffTemp : ( new Date().getFullYear() % 100 ) + parseInt( shortYearCutoffTemp, 10 );
1264			dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort;
1265			dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames;
1266			monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort;
1267			monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames;
1268
1269			// Check whether a format character is doubled
1270			lookAhead = function( match ) {
1271				var matches = iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match;
1272				if ( matches ) {
1273					iFormat = iFormat + 1;
1274				}
1275				return matches;
1276			};
1277
1278			// Extract a number from the string value
1279			getNumber = function( match ) {
1280				var isDoubled = lookAhead( match ),
1281					size = match === '@' ? 14 : match === '!' ? 20 : match === 'y' && isDoubled ? 4 : match === 'o' ? 3 : 2,
1282					minSize = match === 'y' ? size : 1,
1283					digits = new RegExp( '^\\d{' + minSize + ',' + size + '}' ),
1284					num = value.substring( iValue ).match( digits );
1285				if ( ! num ) {
1286					throw 'Missing number at position ' + iValue;
1287				}
1288				iValue += num[ 0 ].length;
1289				return parseInt( num[ 0 ], 10 );
1290			};
1291
1292			// Extract a name from the string value and convert to an index
1293			getName = function( match, shortNames, longNames ) {
1294				var index = -1,
1295					names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
1296						return [ [ k, v ] ];
1297					} ).sort( function( a, b ) {
1298						return -( a[ 1 ].length - b[ 1 ].length );
1299					} );
1300
1301				$.each( names, function( i, pair ) {
1302					var name = pair[ 1 ];
1303					if ( value.substring( iValue, parseInt( iValue, 10 ) + name.length ).toLowerCase() === name.toLowerCase() ) {
1304						index = pair[ 0 ];
1305						iValue += name.length;
1306						return false;
1307					}
1308				} );
1309				if ( index !== -1 ) {
1310					return index + 1;
1311				}
1312				throw 'Unknown name at position ' + iValue;
1313			};
1314
1315			// Confirm that a literal character matches the string value
1316			checkLiteral = function() {
1317				if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
1318					throw 'Unexpected literal at position ' + iValue;
1319				}
1320				iValue = iValue + 1;
1321			};
1322
1323			for ( iFormat = 0; iFormat < format.length; iFormat += 1 ) {
1324				if ( literal ) {
1325					if ( format.charAt( iFormat ) === "'" && ! lookAhead( "'" ) ) {
1326						literal = false;
1327					} else {
1328						checkLiteral();
1329					}
1330				} else {
1331					switch ( format.charAt( iFormat ) ) {
1332						case 'd':
1333							day = getNumber( 'd' );
1334							break;
1335						case 'D':
1336							getName( 'D', dayNamesShort, dayNames );
1337							break;
1338						case 'o':
1339							doy = getNumber( 'o' );
1340							break;
1341						case 'm':
1342							month = getNumber( 'm' );
1343							break;
1344						case 'M':
1345							month = getName( 'M', monthNamesShort, monthNames );
1346							break;
1347						case 'y':
1348							year = getNumber( 'y' );
1349							break;
1350						case '@':
1351							date = new Date( getNumber( '@' ) );
1352							year = date.getFullYear();
1353							month = date.getMonth() + 1;
1354							day = date.getDate();
1355							break;
1356						case '!':
1357							date = new Date( ( getNumber( '!' ) - this._ticksTo1970 ) / 10000 );
1358							year = date.getFullYear();
1359							month = date.getMonth() + 1;
1360							day = date.getDate();
1361							break;
1362						case "'":
1363							if ( lookAhead( "'" ) ) {
1364								checkLiteral();
1365							} else {
1366								literal = true;
1367							}
1368							break;
1369						default:
1370							checkLiteral();
1371					}
1372				}
1373			}
1374
1375			if ( iValue < value.length ) {
1376				extra = value.substring( iValue );
1377				if ( ! /^\s+/.test( extra ) ) {
1378					throw 'Extra/unparsed characters found in date: ' + extra;
1379				}
1380			}
1381
1382			if ( year === -1 ) {
1383				year = new Date().getFullYear();
1384			} else if ( year < 100 ) {
1385				year += new Date().getFullYear() - ( new Date().getFullYear() % 100 ) + ( year <= shortYearCutoff ? 0 : -100 );
1386			}
1387
1388			if ( doy > -1 ) {
1389				month = 1;
1390				day = doy;
1391				condition = true;
1392				do {
1393					dim = this._getDaysInMonth( year, month - 1 );
1394					if ( day <= dim ) {
1395						condition = false;
1396					} else {
1397						month = month + 1;
1398						day -= dim;
1399					}
1400				} while ( condition );
1401			}
1402
1403			date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
1404			if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
1405				throw 'Invalid date'; // E.g. 31/02/00
1406			}
1407			return date;
1408		},
1409
1410		/* Standard date formats. */
1411		ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
1412		COOKIE: 'D, dd M yy',
1413		ISO_8601: 'yy-mm-dd',
1414		RFC_822: 'D, d M y',
1415		RFC_850: 'DD, dd-M-y',
1416		RFC_1036: 'D, d M y',
1417		RFC_1123: 'D, d M yy',
1418		RFC_2822: 'D, d M yy',
1419		RSS: 'D, d M y', // RFC 822
1420		TICKS: '!',
1421		TIMESTAMP: '@',
1422		W3C: 'yy-mm-dd', // ISO 8601
1423
1424		_ticksTo1970: ( ( ( 1970 - 1 ) * 365 ) + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000,
1425
1426		/* Format a date object into a string value.
1427		 * The format can be combinations of the following:
1428		 * d  - day of month (no leading zero)
1429		 * dd - day of month (two digit)
1430		 * o  - day of year (no leading zeros)
1431		 * oo - day of year (three digit)
1432		 * D  - day name short
1433		 * DD - day name long
1434		 * m  - month of year (no leading zero)
1435		 * mm - month of year (two digit)
1436		 * M  - month name short
1437		 * MM - month name long
1438		 * y  - year (two digit)
1439		 * yy - year (four digit)
1440		 * @ - Unix timestamp (ms since 01/01/1970)
1441		 * ! - Windows ticks (100ns since 01/01/0001)
1442		 * "..." - literal text
1443		 * '' - single quote
1444		 *
1445		 * @param  format string - the desired format of the date
1446		 * @param  date Date - the date value to format
1447		 * @param  settings Object - attributes include:
1448		 *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
1449		 *                  dayNames        string[7] - names of the days from Sunday (optional)
1450		 *                  monthNamesShort string[12] - abbreviated names of the months (optional)
1451		 *                  monthNames      string[12] - names of the months (optional)
1452		 * @return  string - the date in the above format
1453		 */
1454		formatDate: function( format, date, settings ) {
1455			var iFormat,
1456				dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
1457				dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
1458				monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
1459				monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
1460				// Check whether a format character is doubled
1461				lookAhead = function( match ) {
1462					var matches = iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match;
1463					if ( matches ) {
1464						iFormat = iFormat + 1;
1465					}
1466					return matches;
1467				},
1468				// Format a number, with leading zero if necessary
1469				formatNumber = function( match, value, len ) {
1470					var num = '' + value;
1471					if ( lookAhead( match ) ) {
1472						while ( num.length < len ) {
1473							num = '0' + num;
1474						}
1475					}
1476					return num;
1477				},
1478				// Format a name, short or long as requested
1479				formatName = function( match, value, shortNames, longNames ) {
1480					return lookAhead( match ) ? longNames[ value ] : shortNames[ value ];
1481				},
1482				output = '',
1483				literal = false;
1484
1485			if ( ! date ) {
1486				return '';
1487			}
1488
1489			if ( date ) {
1490				for ( iFormat = 0; iFormat < format.length; iFormat += 1 ) {
1491					if ( literal ) {
1492						if ( format.charAt( iFormat ) === "'" && ! lookAhead( "'" ) ) {
1493							literal = false;
1494						} else {
1495							output += format.charAt( iFormat );
1496						}
1497					} else {
1498						switch ( format.charAt( iFormat ) ) {
1499							case 'd':
1500								output += formatNumber( 'd', date.getDate(), 2 );
1501								break;
1502							case 'D':
1503								output += formatName( 'D', date.getDay(), dayNamesShort, dayNames );
1504								break;
1505							case 'o':
1506								output += formatNumber( 'o', Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
1507								break;
1508							case 'm':
1509								output += formatNumber( 'm', date.getMonth() + 1, 2 );
1510								break;
1511							case 'M':
1512								output += formatName( 'M', date.getMonth(), monthNamesShort, monthNames );
1513								break;
1514							case 'y':
1515								output += lookAhead( 'y' ) ? date.getFullYear() : ( date.getFullYear() % 100 < 10 ? '0' : '' ) + ( date.getFullYear() % 100 );
1516								break;
1517							case '@':
1518								output += date.getTime();
1519								break;
1520							case '!':
1521								output += ( date.getTime() * 10000 ) + this._ticksTo1970;
1522								break;
1523							case "'":
1524								if ( lookAhead( "'" ) ) {
1525									output += "'";
1526								} else {
1527									literal = true;
1528								}
1529								break;
1530							default:
1531								output += format.charAt( iFormat );
1532						}
1533					}
1534				}
1535			}
1536			return output;
1537		},
1538
1539		/* Extract all possible characters from the date format. */
1540		_possibleChars: function( format ) {
1541			var iFormat,
1542				chars = '',
1543				literal = false,
1544				// Check whether a format character is doubled
1545				lookAhead = function( match ) {
1546					var matches = iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match;
1547					if ( matches ) {
1548						iFormat = iFormat + 1;
1549					}
1550					return matches;
1551				};
1552
1553			for ( iFormat = 0; iFormat < format.length; iFormat += 1 ) {
1554				if ( literal ) {
1555					if ( format.charAt( iFormat ) === "'" && ! lookAhead( "'" ) ) {
1556						literal = false;
1557					} else {
1558						chars += format.charAt( iFormat );
1559					}
1560				} else {
1561					switch ( format.charAt( iFormat ) ) {
1562						case 'd':
1563						case 'm':
1564						case 'y':
1565						case '@':
1566							chars += '0123456789';
1567							break;
1568						case 'D':
1569						case 'M':
1570							return null; // Accept anything
1571						case "'":
1572							if ( lookAhead( "'" ) ) {
1573								chars += "'";
1574							} else {
1575								literal = true;
1576							}
1577							break;
1578						default:
1579							chars += format.charAt( iFormat );
1580					}
1581				}
1582			}
1583			return chars;
1584		},
1585
1586		/* Get a setting value, defaulting if necessary. */
1587		_get: function( inst, name ) {
1588			return inst.settings[ name ] !== undefined ? inst.settings[ name ] : this._defaults[ name ];
1589		},
1590
1591		/* Parse existing date and initialise date picker. */
1592		_setDateFromField: function( inst, noDefault ) {
1593			var dateFormat;
1594			var dates;
1595			var defaultDate;
1596			var date;
1597			var settings;
1598
1599			if ( inst.input.val() === inst.lastVal ) {
1600				return;
1601			}
1602
1603			dateFormat = this._get( inst, 'dateFormat' );
1604			dates = inst.input ? inst.input.val() : null;
1605			defaultDate = this._getDefaultDate( inst );
1606			date = defaultDate;
1607			settings = this._getFormatConfig( inst );
1608
1609			inst.lastVal = dates;
1610
1611			try {
1612				date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
1613			} catch ( event ) {
1614				dates = noDefault ? '' : dates;
1615			}
1616			inst.selectedDay = date.getDate();
1617			inst.selectedMonth = date.getMonth();
1618			inst.drawMonth = inst.selectedMonth;
1619			inst.selectedYear = date.getFullYear();
1620			inst.drawYear = inst.selectedYear;
1621			inst.currentDay = dates ? date.getDate() : 0;
1622			inst.currentMonth = dates ? date.getMonth() : 0;
1623			inst.currentYear = dates ? date.getFullYear() : 0;
1624			this._adjustInstDate( inst );
1625		},
1626
1627		/* Retrieve the default date shown on opening. */
1628		_getDefaultDate: function( inst ) {
1629			return this._restrictMinMax( inst, this._determineDate( inst, this._get( inst, 'defaultDate' ), new Date() ) );
1630		},
1631
1632		/* A date may be specified as an exact value or a relative one. */
1633		_determineDate: function( inst, date, defaultDate ) {
1634			var offsetNumeric = function( offset ) {
1635					var sdate = new Date();
1636					sdate.setDate( sdate.getDate() + offset );
1637					return sdate;
1638				},
1639				offsetString = function( offset ) {
1640					var sdate;
1641					var year;
1642					var month;
1643					var day;
1644					var pattern;
1645					var matches;
1646
1647					try {
1648						return $.tm_datepicker.parseDate( $.tm_datepicker._get( inst, 'dateFormat' ), offset, $.tm_datepicker._getFormatConfig( inst ) );
1649					} catch ( e ) {
1650						// Ignore
1651					}
1652
1653					sdate = ( offset.toLowerCase().match( /^c/ ) ? $.tm_datepicker._getDate( inst ) : null ) || new Date();
1654					year = sdate.getFullYear();
vendor: 4,468 bytes, lines 1655-1780
1655					month = sdate.getMonth();
1656					day = sdate.getDate();
1657					pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
1658					matches = pattern.exec( offset );
1659
1660					while ( matches ) {
1661						switch ( matches[ 2 ] || 'd' ) {
1662							case 'd':
1663							case 'D':
1664								day += parseInt( matches[ 1 ], 10 );
1665								break;
1666							case 'w':
1667							case 'W':
1668								day += parseInt( matches[ 1 ], 10 ) * 7;
1669								break;
1670							case 'm':
1671							case 'M':
1672								month += parseInt( matches[ 1 ], 10 );
1673								day = Math.min( day, $.tm_datepicker._getDaysInMonth( year, month ) );
1674								break;
1675							case 'y':
1676							case 'Y':
1677								year += parseInt( matches[ 1 ], 10 );
1678								day = Math.min( day, $.tm_datepicker._getDaysInMonth( year, month ) );
1679								break;
1680						}
1681						matches = pattern.exec( offset );
1682					}
1683					return new Date( year, month, day );
1684				},
1685				newDate = date === null || date === '' ? defaultDate : typeof date === 'string' ? offsetString( date ) : typeof date === 'number' ? ( ! Number.isFinite( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() );
1686
1687			newDate = newDate && newDate.toString() === 'Invalid Date' ? defaultDate : newDate;
1688			if ( newDate ) {
1689				newDate.setHours( 0 );
1690				newDate.setMinutes( 0 );
1691				newDate.setSeconds( 0 );
1692				newDate.setMilliseconds( 0 );
1693			}
1694			return this._daylightSavingAdjust( newDate );
1695		},
1696
1697		/* Handle switch to/from daylight saving.
1698		 * Hours may be non-zero on daylight saving cut-over:
1699		 * > 12 when midnight changeover, but then cannot generate
1700		 * midnight datetime, so jump to 1AM, otherwise reset.
1701		 * @param  date  (Date) the date to check
1702		 * @return  (Date) the corrected date
1703		 */
1704		_daylightSavingAdjust: function( date ) {
1705			if ( ! date ) {
1706				return null;
1707			}
1708			date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
1709			return date;
1710		},
1711
1712		/* Set the date(s) directly. */
1713		_setDate: function( inst, date, noChange ) {
1714			var clear = ! date,
1715				origMonth = inst.selectedMonth,
1716				origYear = inst.selectedYear,
1717				newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
1718
1719			inst.currentDay = newDate.getDate();
1720			inst.selectedDay = inst.currentDay;
1721			inst.currentMonth = newDate.getMonth();
1722			inst.drawMonth = inst.currentMonth;
1723			inst.selectedMonth = inst.currentMonth;
1724			inst.currentYear = newDate.getFullYear();
1725			inst.drawYear = inst.currentYear;
1726			inst.selectedYear = inst.currentYear;
1727			if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && ! noChange ) {
1728				this._notifyChange( inst );
1729			}
1730			this._adjustInstDate( inst );
1731			if ( inst.input ) {
1732				inst.input.val( clear ? '' : this._formatDate( inst ) );
1733			}
1734		},
1735
1736		/* Retrieve the date(s) directly. */
1737		_getDate: function( inst ) {
1738			var startDate = ! inst.currentYear || ( inst.input && inst.input.val() === '' ) ? null : this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) );
1739			return startDate;
1740		},
1741
1742		/* Attach the onxxx handlers.  These are declared statically so
1743		 * they work with static code transformers like Caja.
1744		 */
1745		_attachHandlers: function( inst ) {
1746			var stepMonths = this._get( inst, 'stepMonths' ),
1747				id = '#' + inst.id.replace( /\\\\/g, '\\' );
1748			inst.dpDiv.find( '[data-handler]' ).map( function() {
1749				var handler = {
1750					prevM: function() {
1751						$.tm_datepicker._adjustDate( id, -1, 'M' );
1752					},
1753					nextM: function() {
1754						$.tm_datepicker._adjustDate( id, +1, 'M' );
1755					},
1756					prevY: function() {
1757						$.tm_datepicker._adjustDate( id, -1, 'Y' );
1758					},
1759					nextY: function() {
1760						$.tm_datepicker._adjustDate( id, +1, 'Y' );
1761					},
1762					prev: function() {
1763						$.tm_datepicker._adjustDate( id, -stepMonths, 'M' );
1764					},
1765					next: function() {
1766						$.tm_datepicker._adjustDate( id, +stepMonths, 'M' );
1767					},
1768					hide: function() {
1769						$.tm_datepicker._hideDatepicker();
1770					},
1771					today: function() {
1772						/*var tempDate = new Date(),
1773                         today = $.tm_datepicker._daylightSavingAdjust(
1774                         new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate()));
1775                         $.tm_datepicker._setDate(inst, today);
1776                         $.tm_datepicker._gotoToday(id);*/
1777					},
1778					selectDay: function() {
1779						$.tm_datepicker._selectDay( id, +this.getAttribute( 'data-month' ), +this.getAttribute( 'data-year' ), this );
1780						return false;
1781					},
1782					selectMonth: function() {
1783						$.tm_datepicker._selectMonthYear( id, this, 'M' );
1784						return false;
1785					},
1786					selectYear: function() {
1787						$.tm_datepicker._selectMonthYear( id, this, 'Y' );
1788						return false;
1789					}
1790				};
1791				$( this ).on( this.getAttribute( 'data-event' ), handler[ this.getAttribute( 'data-handler' ) ] );
1792				return null;
1793			} );
1794		},
1795		/* Determines if we should allow a "next/prev" month display change. */
1796		_tm_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
1797			var date = this._daylightSavingAdjust( new Date( curYear, curMonth + offset, 1 ) );
1798
1799			if ( offset < 0 ) {
1800				date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
1801			}
1802			return this._isInRange( inst, date );
1803		},
1804
1805		/* Generate the HTML for the current state of the date picker. */
1806		_generateHTML: function( inst ) {
1807			var maxDraw,
1808				prevText,
1809				prev,
1810				nextText,
1811				next,
1812				currentText,
1813				gotoDate,
1814				firstDay,
1815				showWeek,
1816				dayNames,
1817				dayNamesMin,
1818				monthNames,
1819				beforeShowDay,
1820				showOtherMonths,
1821				selectOtherMonths,
1822				defaultDate,
1823				html,
1824				dow,
1825				row,
1826				group,
1827				col,
1828				selectedDate,
1829				cornerClass,
1830				calender,
1831				thead,
1832				day,
1833				daysInMonth,
1834				leadDays,
1835				curRows,
1836				numRows,
1837				printDate,
1838				dRow,
1839				tbody,
1840				daySettings,
1841				otherMonth,
1842				unselectable,
1843				tempDate = new Date(),
1844				today = this._daylightSavingAdjust( new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
1845				isRTL = this._get( inst, 'isRTL' ),
1846				showButtonPanel = this._get( inst, 'showButtonPanel' ),
1847				hideIfNoPrevNext = this._get( inst, 'hideIfNoPrevNext' ),
1848				navigationAsDateFormat = this._get( inst, 'navigationAsDateFormat' ),
1849				numMonths = this._getNumberOfMonths( inst ),
1850				showCurrentAtPos = this._get( inst, 'showCurrentAtPos' ),
1851				stepMonths = this._get( inst, 'stepMonths' ),
1852				isMultiMonth = numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1,
1853				currentDate = this._daylightSavingAdjust( ! inst.currentDay ? new Date( 9999, 9, 9 ) : new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ),
1854				minDate = this._getMinMaxDate( inst, 'min' ),
1855				maxDate = this._getMinMaxDate( inst, 'max' ),
1856				drawMonth = inst.drawMonth - showCurrentAtPos,
1857				drawYear = inst.drawYear,
1858				tm_month,
1859				tm_year,
1860				tm_prev_arrow_m,
1861				tm_next_arrow_m,
1862				tm_prev_arrow_y,
1863				tm_next_arrow_y,
1864				tm_controls,
1865				tm_buttonPanel;
1866			var can_adjust_1;
1867			var can_adjust_2;
1868			var can_adjust_3;
1869			var can_adjust_4;
1870
1871			if ( drawMonth < 0 ) {
1872				drawMonth += 12;
1873				drawYear -= 1;
1874			}
1875			if ( maxDate ) {
1876				maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
1877				maxDraw = minDate && maxDraw < minDate ? minDate : maxDraw;
1878				while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
1879					drawMonth -= 1;
1880					if ( drawMonth < 0 ) {
1881						drawMonth = 11;
1882						drawYear -= 1;
1883					}
1884				}
1885			}
1886			inst.drawMonth = drawMonth;
1887			inst.drawYear = drawYear;
1888
1889			prevText = this._get( inst, 'prevText' );
1890			prevText = ! navigationAsDateFormat ? prevText : this.formatDate( prevText, this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), this._getFormatConfig( inst ) );
1891
1892			prev = this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ? "<a class='ui-tm-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? 'e' : 'w' ) + "'>" + prevText + '</span></a>' : hideIfNoPrevNext ? '' : "<a class='ui-tm-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? 'e' : 'w' ) + "'>" + prevText + '</span></a>';
1893
1894			nextText = this._get( inst, 'nextText' );
1895			nextText = ! navigationAsDateFormat ? nextText : this.formatDate( nextText, this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), this._getFormatConfig( inst ) );
1896
1897			next = this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ? "<a class='ui-tm-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? 'w' : 'e' ) + "'>" + nextText + '</span></a>' : hideIfNoPrevNext ? '' : "<a class='ui-tm-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? 'w' : 'e' ) + "'>" + nextText + '</span></a>';
1898
1899			currentText = this._get( inst, 'currentText' );
1900			gotoDate = this._get( inst, 'gotoCurrent' ) && inst.currentDay ? currentDate : today;
1901			currentText = ! navigationAsDateFormat ? currentText : this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) );
1902
1903			tm_controls = ! inst.inline ? "<div class='tm-ui-dp-btn-wrap tm-ui-dp-close'><div role='button' class='tm-ui-dp-btn ui-tm-datepicker-close' data-handler='hide' data-event='click'>" + this._get( inst, 'closeText' ) + '</div></div>' : '';
1904
1905			tm_buttonPanel = showButtonPanel ? "<div class='tm-ui-dp-buttonpane'>" + ( isRTL ? tm_controls : '' ) + ( this._isInRange( inst, gotoDate ) ? "<div class='tm-ui-dp-btn-wrap tm-ui-dp-current'><div role='button' class='tm-ui-dp-btn ui-tm-datepicker-current' data-handler='today' data-event='click'" + '>' + currentText + '</div></div>' : '' ) + ( isRTL ? '' : tm_controls ) + '</div>' : '';
1906
1907			firstDay = parseInt( this._get( inst, 'firstDay' ), 10 );
1908			firstDay = isNaN( firstDay ) ? 0 : firstDay;
1909
1910			showWeek = this._get( inst, 'showWeek' );
1911			dayNames = this._get( inst, 'dayNames' );
1912			dayNamesMin = this._get( inst, 'dayNamesMin' );
1913			monthNames = this._get( inst, 'monthNames' );
1914			//monthNamesShort = this._get(inst, "monthNamesShort");
1915			beforeShowDay = this._get( inst, 'beforeShowDay' );
1916			showOtherMonths = this._get( inst, 'showOtherMonths' );
1917			selectOtherMonths = this._get( inst, 'selectOtherMonths' );
1918			defaultDate = this._getDefaultDate( inst );
1919			html = '';
1920
1921			can_adjust_1 = this._tm_canAdjustMonth( inst, -1, drawYear, drawMonth );
1922			can_adjust_2 = this._tm_canAdjustMonth( inst, +1, drawYear, drawMonth );
1923			can_adjust_3 = this._tm_canAdjustMonth( inst, -12, drawYear, drawMonth );
1924			can_adjust_4 = this._tm_canAdjustMonth( inst, +12, drawYear, drawMonth );
1925
1926			tm_prev_arrow_m = '<div class="tm-ui-dp-button-prev tm-ui-dp-button">' + '<div ' + ( can_adjust_1 ? 'data-handler="prevM" data-event="click" ' : '' ) + 'aria-label="' + prevText + '" class="' + ( can_adjust_1 ? '' : 'tm-ui-dp-button-disabled ' ) + 'tm-ui-dp-button-arrow tcfa tcfa-angle-left" tabindex="0" role="button"></div>' + '</div>';
1927			tm_next_arrow_m = '<div class="tm-ui-dp-button-next tm-ui-dp-button">' + '<div ' + ( can_adjust_2 ? 'data-handler="nextM" data-event="click" ' : '' ) + 'aria-label="' + nextText + '" class="' + ( can_adjust_2 ? '' : 'tm-ui-dp-button-disabled ' ) + 'tm-ui-dp-button-arrow tcfa tcfa-angle-right" tabindex="0" role="button"></div>' + '</div>';
1928			tm_prev_arrow_y = '<div class="tm-ui-dp-button-prev tm-ui-dp-button">' + '<div ' + ( can_adjust_3 ? 'data-handler="prevY" data-event="click" ' : '' ) + 'aria-label="' + prevText + '" class="' + ( can_adjust_3 ? '' : 'tm-ui-dp-button-disabled ' ) + 'tm-ui-dp-button-arrow tcfa tcfa-angle-left" tabindex="0" role="button"></div>' + '</div>';
1929			tm_next_arrow_y = '<div class="tm-ui-dp-button-next tm-ui-dp-button">' + '<div ' + ( can_adjust_4 ? 'data-handler="nextY" data-event="click" ' : '' ) + 'aria-label="' + nextText + '" class="' + ( can_adjust_4 ? '' : 'tm-ui-dp-button-disabled ' ) + 'tm-ui-dp-button-arrow tcfa tcfa-angle-right" tabindex="0" role="button"></div>' + '</div>';
1930
1931			tm_month = hideIfNoPrevNext ? '' : '<div class="tm-ui-dp-title-button">' + ( isRTL ? tm_next_arrow_m : tm_prev_arrow_m ) + '<span aria-label="' + monthNames[ drawMonth ] + '" role="button" class="tm-ui-dp-month">' + monthNames[ drawMonth ] + '</span>' + ( isRTL ? tm_prev_arrow_m : tm_next_arrow_m ) + '</div>';
1932
1933			tm_year = hideIfNoPrevNext ? '' : '<div class="tm-ui-dp-title-button">' + ( isRTL ? tm_next_arrow_y : tm_prev_arrow_y ) + '<span class="tm-ui-dp-year" role="button" aria-label="' + drawYear + '">' + drawYear + '</span>' + ( isRTL ? tm_prev_arrow_y : tm_next_arrow_y ) + '</div>';
1934
1935			html += "<div class='tm-ui-dp-wrap'>" + "<div class='tm-ui-dp-overlay'></div>" + "<div class='tm-ui-dp'>" + "<div class='tm-ui-dp-container'>" + "<div class='tm-ui-dp-inner-container'>" + "<div class='tm-ui-dp-ui'>" + "<div class='tm-ui-dp-ui-inner'>" + "<div class='tm-ui-dp-main-wrap'>" + "<div class='tm-ui-dp-main'>";
1936
1937			for ( row = 0; row < numMonths[ 0 ]; row += 1 ) {
1938				group = '';
1939				this.maxRows = 4;
1940				for ( col = 0; col < numMonths[ 1 ]; col += 1 ) {
1941					selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
1942					cornerClass = ' ui-corner-all';
1943					calender = '';
1944					if ( isMultiMonth ) {
1945						calender += "<div class='ui-tm-datepicker-group";
1946						if ( numMonths[ 1 ] > 1 ) {
1947							switch ( col ) {
1948								case 0:
1949									calender += ' ui-tm-datepicker-group-first';
1950									cornerClass = ' ui-corner-' + ( isRTL ? 'right' : 'left' );
1951									break;
1952								case numMonths[ 1 ] - 1:
1953									calender += ' ui-tm-datepicker-group-last';
1954									cornerClass = ' ui-corner-' + ( isRTL ? 'left' : 'right' );
1955									break;
1956								default:
1957									calender += ' ui-tm-datepicker-group-middle';
1958									cornerClass = '';
1959									break;
1960							}
1961						}
1962						calender += "'>";
1963					}
1964					calender +=
1965						"<div class='tm-ui-dp-header ui-tm-datepicker-header ui-widget-header ui-helper-clearfix" +
1966						cornerClass +
1967						"'>" +
1968						( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : '' ) +
1969						( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : '' ) +
1970						// month headers
1971
1972						'<div class="ui-tm-datepicker-title tm-ui-dp-title">' +
1973						( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? tm_year + tm_month : tm_month + tm_year ) : '' ) +
1974						'</div>' +
1975						'</div>';
1976
1977					calender += "<div class='tm-ui-dp-main-content'>";
1978
1979					/* Days start */
1980					calender += "<div class='tm-ui-dp-main-header-wrap'><div class='tm-ui-dp-main-header'>";
1981					calender += "<table class='ui-tm-datepicker-calendar'><tbody>" + '<tr>';
1982					thead = showWeek ? "<th class='ui-tm-datepicker-week-col'>" + this._get( inst, 'weekHeader' ) + '</th>' : '';
1983					for ( dow = 0; dow < 7; dow += 1 ) {
1984						// days of the week
1985						day = ( dow + firstDay ) % 7;
1986						thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-tm-datepicker-week-end'" : '' ) + '>
1986' + "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + '</span></th>';
1987					}
1988					calender += thead + '</tr></tbody></table>';
1989					calender += '</div></div>';
1990					/* Days end */
1991
1992					calender += "<div class='tm-ui-dp-main-table'>";
1993
1994					daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
1995					if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
1996						inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
1997					}
1998					leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
1999					curRows = 6;
2000					numRows = isMultiMonth ? ( this.maxRows > curRows ? this.maxRows : curRows ) : curRows; //If multiple months, use the higher number of rows
2001					// (see #7043)
2002					this.maxRows = numRows;
2003					printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
2004					for ( dRow = 0; dRow < numRows; dRow += 1 ) {
2005						// create date picker rows
2006						calender += "<div class='tm-ui-dp-main-row'>";
2007						tbody = ! showWeek ? '' : "<div class='ui-tm-datepicker-week-col'>" + this._get( inst, 'calculateWeek' )( printDate ) + '</div>';
2008						for ( dow = 0; dow < 7; dow += 1 ) {
2009							// create date picker days
2010							daySettings = beforeShowDay ? beforeShowDay.apply( inst.input ? inst.input[ 0 ] : null, [ printDate ] ) : [ true, '' ];
2011							otherMonth = printDate.getMonth() !== drawMonth;
2012							unselectable = ( otherMonth && ! selectOtherMonths ) || ! daySettings[ 0 ] || ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
2013
2014							tbody +=
2015								"<div class='tm-ui-dp-main-cell " +
2016								( ( dow + firstDay + 6 ) % 7 >= 5 ? ' ui-tm-datepicker-week-end' : '' ) + // highlight weekends
2017								( otherMonth ? ' ui-tm-datepicker-other-month' : '' ) + // highlight days from other months
2018								( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? ' ' + this._dayOverClass : '' ) +
2019								( unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled' : '' ) + // highlight unselectable days
2020								( otherMonth && ! showOtherMonths ? '' : ' ' + daySettings[ 1 ] + ( printDate.getTime() === currentDate.getTime() ? ' ' + this._currentClass : '' ) + ( printDate.getTime() === today.getTime() ? ' ui-tm-datepicker-today' : '' ) ) +
2021								"'" + // highlight today (if different)
2022								( ( ! otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, '&#39;' ) + "'" : '' ) + // cell
2023								// title
2024								( unselectable ? '' : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) +
2025								'>' + // actions
2026								"<div class='tm-ui-dp-main-cell-inner'>" +
2027								"<div class='tm-ui-dp-main-cell-content'>" +
2028								( otherMonth && ! showOtherMonths ? '&#xa0;' : unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + '</span>' : "<a class='ui-state-default" + ( printDate.getTime() === today.getTime() ? ' ui-state-highlight' : '' ) + ( printDate.getTime() === currentDate.getTime() ? ' ui-state-active' : '' ) + ( otherMonth ? ' ui-priority-secondary' : '' ) + "' href='#'>" + printDate.getDate() + '</a>' ) +
2029								'</div></div>' +
2030								'</div>'; // display selectable date
2031							printDate.setDate( printDate.getDate() + 1 );
2032							printDate = this._daylightSavingAdjust( printDate );
2033						}
2034						calender += tbody + '</div>';
2035					}
2036					drawMonth += 1;
2037					if ( drawMonth > 11 ) {
2038						drawMonth = 0;
2039						drawYear += 1;
2040					}
2041
2042					calender += '</div>';
2043
2044					calender += '</div>' + ( isMultiMonth ? '</div>' + ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ? "<div class='ui-tm-datepicker-row-break'></div>" : '' ) : '' );
2045					group += calender;
2046				}
2047				html += group;
2048			}
2049			html += '</div></div></div></div></div>';
2050			html += tm_buttonPanel;
2051			html += '</div></div></div>';
2052			inst._keyEvent = false;
2053			return html;
2054		},
2055
2056		/* Generate the month and year header. */
2057		_generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, secondary, monthNames, monthNamesShort ) {
2058			var inMinYear,
2059				inMaxYear,
2060				month,
2061				years,
2062				thisYear,
2063				determineYear,
2064				year,
2065				endYear,
2066				changeMonth = this._get( inst, 'changeMonth' ),
2067				changeYear = this._get( inst, 'changeYear' ),
2068				showMonthAfterYear = this._get( inst, 'showMonthAfterYear' ),
2069				html = "<div class='ui-tm-datepicker-title'>",
2070				monthHtml = '';
2071
2072			// month selection
2073			if ( secondary || ! changeMonth ) {
2074				monthHtml += "<span class='ui-tm-datepicker-month'>" + monthNames[ drawMonth ] + '</span>';
2075			} else {
2076				inMinYear = minDate && minDate.getFullYear() === drawYear;
2077				inMaxYear = maxDate && maxDate.getFullYear() === drawYear;
2078				monthHtml += "<select class='ui-tm-datepicker-month' data-handler='selectMonth' data-event='change'>";
2079				for ( month = 0; month < 12; month += 1 ) {
2080					if ( ( ! inMinYear || month >= minDate.getMonth() ) && ( ! inMaxYear || month <= maxDate.getMonth() ) ) {
2081						monthHtml += "<option value='" + month + "'" + ( month === drawMonth ? " selected='selected'" : '' ) + '>
2081' + monthNamesShort[ month ] + '</option>';
2082					}
2083				}
2084				monthHtml += '</select>';
2085			}
2086
2087			if ( ! showMonthAfterYear ) {
2088				html += monthHtml + ( secondary || ! ( changeMonth && changeYear ) ? '&#xa0;' : '' );
2089			}
2090
2091			// year selection
2092			if ( ! inst.yearshtml ) {
2093				inst.yearshtml = '';
2094				if ( secondary || ! changeYear ) {
2095					html += "<span class='ui-tm-datepicker-year'>" + drawYear + '</span>';
2096				} else {
2097					// determine range of years to display
2098					years = this._get( inst, 'yearRange' ).split( ':' );
2099					thisYear = new Date().getFullYear();
2100					determineYear = function( value ) {
2101						var syear = value.match( /c[+-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : value.match( /[+-].*/ ) ? thisYear + parseInt( value, 10 ) : parseInt( value, 10 );
2102						return isNaN( syear ) ? thisYear : syear;
2103					};
2104					year = determineYear( years[ 0 ] );
2105					endYear = Math.max( year, determineYear( years[ 1 ] || '' ) );
2106					year = minDate ? Math.max( year, minDate.getFullYear() ) : year;
2107					endYear = maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear;
2108					inst.yearshtml += "<select class='ui-tm-datepicker-year' data-handler='selectYear' data-event='change'>";
2109					for ( ; year <= endYear; year += 1 ) {
2110						inst.yearshtml += "<option value='" + year + "'" + ( year === drawYear ? " selected='selected'" : '' ) + '>
vendor: 6,708 bytes, lines 2110-2284
2110' + year + '</option>';
2111					}
2112					inst.yearshtml += '</select>';
2113
2114					html += inst.yearshtml;
2115					inst.yearshtml = null;
2116				}
2117			}
2118
2119			html += this._get( inst, 'yearSuffix' );
2120			if ( showMonthAfterYear ) {
2121				html += ( secondary || ! ( changeMonth && changeYear ) ? '&#xa0;' : '' ) + monthHtml;
2122			}
2123			html += '</div>'; // Close datepicker_header
2124			return html;
2125		},
2126
2127		/* Adjust one of the date sub-fields. */
2128		_adjustInstDate: function( inst, offset, period ) {
2129			var year = inst.selectedYear + ( period === 'Y' ? offset : 0 ),
2130				month = inst.selectedMonth + ( period === 'M' ? offset : 0 ),
2131				day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === 'D' ? offset : 0 ),
2132				date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
2133
2134			inst.selectedDay = date.getDate();
2135			inst.selectedMonth = date.getMonth();
2136			inst.drawMonth = inst.selectedMonth;
2137			inst.selectedYear = date.getFullYear();
2138			inst.drawYear = inst.selectedYear;
2139			if ( period === 'M' || period === 'Y' ) {
2140				this._notifyChange( inst );
2141			}
2142		},
2143
2144		/* Ensure a date is within any min/max bounds. */
2145		_restrictMinMax: function( inst, date ) {
2146			var minDate = this._getMinMaxDate( inst, 'min' ),
2147				maxDate = this._getMinMaxDate( inst, 'max' ),
2148				newDate = minDate && date < minDate ? minDate : date;
2149			return maxDate && newDate > maxDate ? maxDate : newDate;
2150		},
2151
2152		/* Notify change of month/year. */
2153		_notifyChange: function( inst ) {
2154			var onChange = this._get( inst, 'onChangeMonthYear' );
2155			if ( onChange ) {
2156				onChange.apply( inst.input ? inst.input[ 0 ] : null, [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
2157			}
2158		},
2159
2160		/* Determine the number of months to show. */
2161		_getNumberOfMonths: function( inst ) {
2162			var numMonths = this._get( inst, 'numberOfMonths' );
2163			return numMonths === null ? [ 1, 1 ] : typeof numMonths === 'number' ? [ 1, numMonths ] : numMonths;
2164		},
2165
2166		/* Determine the current maximum date - ensure no time components are set. */
2167		_getMinMaxDate: function( inst, minMax ) {
2168			return this._determineDate( inst, this._get( inst, minMax + 'Date' ), null );
2169		},
2170
2171		/* Find the number of days in a given month. */
2172		_getDaysInMonth: function( year, month ) {
2173			return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
2174		},
2175
2176		/* Find the day of the week of the first of a month. */
2177		_getFirstDayOfMonth: function( year, month ) {
2178			return new Date( year, month, 1 ).getDay();
2179		},
2180
2181		/* Determines if we should allow a "next/prev" month display change. */
2182		_canAdjustMonth: function( inst, offset, curYear, curMonth ) {
2183			var numMonths = this._getNumberOfMonths( inst ),
2184				date = this._daylightSavingAdjust( new Date( curYear, curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
2185
2186			if ( offset < 0 ) {
2187				date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
2188			}
2189			return this._isInRange( inst, date );
2190		},
2191
2192		/* Is the given date in the accepted range? */
2193		_isInRange: function( inst, date ) {
2194			var yearSplit,
2195				currentYear,
2196				minDate = this._getMinMaxDate( inst, 'min' ),
2197				maxDate = this._getMinMaxDate( inst, 'max' ),
2198				minYear = null,
2199				maxYear = null,
2200				years = this._get( inst, 'yearRange' );
2201			if ( years ) {
2202				yearSplit = years.split( ':' );
2203				currentYear = new Date().getFullYear();
2204				minYear = parseInt( yearSplit[ 0 ], 10 );
2205				maxYear = parseInt( yearSplit[ 1 ], 10 );
2206				if ( yearSplit[ 0 ].match( /[+-].*/ ) ) {
2207					minYear += currentYear;
2208				}
2209				if ( yearSplit[ 1 ].match( /[+-].*/ ) ) {
2210					maxYear += currentYear;
2211				}
2212			}
2213
2214			return ( ! minDate || date.getTime() >= minDate.getTime() ) && ( ! maxDate || date.getTime() <= maxDate.getTime() ) && ( ! minYear || date.getFullYear() >= minYear ) && ( ! maxYear || date.getFullYear() <= maxYear );
2215		},
2216
2217		/* Provide the configuration settings for formatting/parsing. */
2218		_getFormatConfig: function( inst ) {
2219			var shortYearCutoff = this._get( inst, 'shortYearCutoff' );
2220			shortYearCutoff = typeof shortYearCutoff !== 'string' ? shortYearCutoff : ( new Date().getFullYear() % 100 ) + parseInt( shortYearCutoff, 10 );
2221			return {
2222				shortYearCutoff: shortYearCutoff,
2223				dayNamesShort: this._get( inst, 'dayNamesShort' ),
2224				dayNames: this._get( inst, 'dayNames' ),
2225				monthNamesShort: this._get( inst, 'monthNamesShort' ),
2226				monthNames: this._get( inst, 'monthNames' )
2227			};
2228		},
2229
2230		/* Format the given date for display. */
2231		_formatDate: function( inst, day, month, year ) {
2232			var date;
2233
2234			if ( ! day ) {
2235				inst.currentDay = inst.selectedDay;
2236				inst.currentMonth = inst.selectedMonth;
2237				inst.currentYear = inst.selectedYear;
2238			}
2239			date = day ? ( typeof day === 'object' ? day : this._daylightSavingAdjust( new Date( year, month, day ) ) ) : this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) );
2240			return this.formatDate( this._get( inst, 'dateFormat' ), date, this._getFormatConfig( inst ) );
2241		}
2242	} );
2243
2244	/* Invoke the datepicker functionality.
2245     @param  options  string - a command, optionally followed by additional parameters or
2246     Object - settings for attaching new datepicker functionality
2247     @return  jQuery object */
2248	$.fn.tm_datepicker = function( options ) {
2249		var otherArgs;
2250
2251		/* Verify an empty collection wasn't passed - Fixes #6976 */
2252		if ( ! this.length ) {
2253			return this;
2254		}
2255
2256		/* Initialise the date picker. */
2257		if ( ! $.tm_datepicker.initialized ) {
2258			$( document ).on( 'mousedown', $.tm_datepicker._checkExternalClick );
2259			$.tm_datepicker.initialized = true;
2260		}
2261
2262		/* Append datepicker main container to body if not exist. */
2263		if ( $( '#' + $.tm_datepicker._mainDivId ).length === 0 ) {
2264			$( 'body' ).append( $.tm_datepicker.dpDiv );
2265		}
2266
2267		otherArgs = Array.prototype.slice.call( arguments, 1 );
2268		if ( typeof options === 'string' && ( options === 'isDisabled' || options === 'getDate' || options === 'widget' ) ) {
2269			return $.tm_datepicker[ '_' + options + 'Datepicker' ].apply( $.tm_datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2270		}
2271		if ( options === 'option' && arguments.length === 2 && typeof arguments[ 1 ] === 'string' ) {
2272			return $.tm_datepicker[ '_' + options + 'Datepicker' ].apply( $.tm_datepicker, [ this[ 0 ] ].concat( otherArgs ) );
2273		}
2274		return this.each( function() {
2275			if ( typeof options === 'string' ) {
2276				$.tm_datepicker[ '_' + options + 'Datepicker' ].apply( $.tm_datepicker, [ this ].concat( otherArgs ) );
2277			} else {
2278				$.tm_datepicker._attachDatepicker( this, options );
2279			}
2280		} );
2281	};
2282
2283	$.tm_datepicker = new Datepicker(); // singleton instance
2284	$.tm_datepicker.initialized = false;
2285	$.tm_datepicker.uuid = new Date().getTime();
2286	$.tm_datepicker.version = '1.11.4';
2287} ) );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.