source: main/trunk/greenstone3/web/interfaces/default/style/themes/alt_theme_2/jquery-ui.js@ 36917

Last change on this file since 36917 was 36917, checked in by anupama, 17 months ago

With Carl's updates to jQuery UI 1.13.2 between revisions 36027 and 36028, the alt_themes 1 to 3 were removed from trac, I think because they used an older version of jQuery (v 1.11.x or 1.8.x I think). Following https://stackoverflow.com/questions/3802447/how-to-upgrade-a-custom-jquery-ui-theme, I used the URL with the instruction 'To view and modify this theme, visit (URL)' in each jquery-ui.theme.css or the 1.8 version of that css file to upgrade the old trac revision versions of the themes (recently missing from trac head) to version jQuery 1.13.2. Then I prefixed that content by copying in the CSS styles that preceded that upgrade URL in the defunct CSS stylesheet file. I am now committing the jQuery 1.13.2 compliant versions of the alt_theme_1 to alt_theme3.

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