[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

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


Generated: Sun Nov 29 01:00:04 2020 Cross-referenced by PHPXref 0.7.1