[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/js/jquery/ui/ -> datepicker.js (source)

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


Generated : Wed Dec 25 08:20:01 2024 Cross-referenced by PHPXref