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

Paste is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.