]> source.dussan.org Git - jquery-ui.git/commitdiff
Refactor to use $.data for instance settings
authorKeith Wood <kbwood.au@gmail.com>
Sun, 6 Jul 2008 05:27:47 +0000 (05:27 +0000)
committerKeith Wood <kbwood.au@gmail.com>
Sun, 6 Jul 2008 05:27:47 +0000 (05:27 +0000)
ui/ui.datepicker.js

index 3f8cb216d7e4b1ddc1d2cb5544a565d8b087c86d..a14327ec4a8b63b991f040b8c66590db06009338 100644 (file)
    
 (function($) { // hide the namespace
 
+var PROP_NAME = 'datepicker';
+
 /* Date picker manager.
    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
-   Settings for (groups of) date pickers are maintained in an instance object
-   (DatepickerInstance), allowing multiple different settings on the same page. */
+   Settings for (groups of) date pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
 
 function Datepicker() {
        this.debug = false; // Change this to true to start debugging
-       this._nextId = 0; // Next ID for a date picker instance
-       this._inst = []; // List of instances indexed by ID
        this._curInst = null; // The current instance in use
        this._disabledInputs = []; // List of date picker inputs that have been disabled
        this._datepickerShowing = false; // True if the popup picker is showing , false if not
        this._inDialog = false; // True if showing within a "dialog", false if not
        this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
        this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
-       this._wrapClass = 'ui-datepicker-wrap'; // The name of the wrapper marker class
        this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
        this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
        this._promptClass = 'ui-datepicker-prompt'; // The name of the dialog prompt marker class
@@ -116,7 +115,7 @@ function Datepicker() {
                altFormat: '' // The date format to use for the alternate field
        };
        $.extend(this._defaults, this.regional['']);
-       this._datepickerDiv = $('<div id="' + this._mainDivId + '" style="display: none;"></div>');
+       this.dpDiv = $('<div id="' + this._mainDivId + '" style="display: none;"></div>');
 }
 
 $.extend(Datepicker.prototype, {
@@ -129,18 +128,6 @@ $.extend(Datepicker.prototype, {
                        console.log.apply('', arguments);
        },
        
-       /* Register a new date picker instance - with custom settings. */
-       _register: function(inst) {
-               var id = this._nextId++;
-               this._inst[id] = inst;
-               return id;
-       },
-
-       /* Retrieve a particular date picker instance based on its ID. */
-       _getInst: function(id) {
-               return this._inst[id] || id;
-       },
-
        /* Override the default settings for all instances of the date picker. 
           @param  settings  object - the new settings to use as defaults (anonymous object)
           @return the manager object */
@@ -167,49 +154,158 @@ $.extend(Datepicker.prototype, {
                        }
                }
                var nodeName = target.nodeName.toLowerCase();
-               var instSettings = (inlineSettings ? 
-                       $.extend(settings || {}, inlineSettings) : settings);
+               var inline = (nodeName == 'div' || nodeName == 'span');
+               if (!target.id)
+                       target.id = 'dp' + new Date().getTime();
+               var inst = this._newInst($(target), inline);
+               inst.settings = $.extend({}, settings || {}, inlineSettings || {}); 
                if (nodeName == 'input') {
-                       var inst = (inst && !inlineSettings ? inst :
-                               new DatepickerInstance(instSettings, false));
                        this._connectDatepicker(target, inst);
-               } else if (nodeName == 'div' || nodeName == 'span') {
-                       var inst = new DatepickerInstance(instSettings, true);
+               } else if (inline) {
                        this._inlineDatepicker(target, inst);
                }
        },
 
+       /* Create a new instance object. */
+       _newInst: function(target, inline) {
+               return {id: target[0].id, input: target, // associated target
+                       selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+                       drawMonth: 0, drawYear: 0, // month being drawn
+                       inline: inline, // is datepicker inline or not
+                       dpDiv: (!inline ? this.dpDiv : // presentation div
+                       $('<div class="ui-datepicker-inline"></div>'))};
+       },
+
+       /* Attach the date picker to an input field. */
+       _connectDatepicker: function(target, inst) {
+               var input = $(target);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               var appendText = this._get(inst, 'appendText');
+               var isRTL = this._get(inst, 'isRTL');
+               if (appendText)
+                       input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
+               var showOn = this._get(inst, 'showOn');
+               if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
+                       input.focus(this._showDatepicker);
+               if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
+                       var buttonText = this._get(inst, 'buttonText');
+                       var buttonImage = this._get(inst, 'buttonImage');
+                       var trigger = $(this._get(inst, 'buttonImageOnly') ? 
+                               $('<img/>').addClass(this._triggerClass).
+                                       attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+                               $('<button type="button"></button>').addClass(this._triggerClass).
+                                       html(buttonImage == '' ? buttonText : $('<img/>').attr(
+                                       { src:buttonImage, alt:buttonText, title:buttonText })));
+                       input[isRTL ? 'before' : 'after'](trigger);
+                       trigger.click(function() {
+                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
+                                       $.datepicker._hideDatepicker();
+                               else
+                                       $.datepicker._showDatepicker(target);
+                               return false;
+                       });
+               }
+               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
+                       bind("setData.datepicker", function(event, key, value) {
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key) {
+                               return this._get(inst, key);
+                       });
+               $.data(target, PROP_NAME, inst);
+       },
+
+       /* Attach an inline date picker to a div. */
+       _inlineDatepicker: function(target, inst) {
+               var input = $(target);
+               if (input.hasClass(this.markerClassName))
+                       return;
+               input.addClass(this.markerClassName).append(inst.dpDiv).
+                       bind("setData.datepicker", function(event, key, value){
+                               inst.settings[key] = value;
+                       }).bind("getData.datepicker", function(event, key){
+                               return this._get(inst, key);
+                       });
+               $.data(target, PROP_NAME, inst);
+               this._setDate(inst, this._getDefaultDate(inst));
+               this._updateDatepicker(inst);
+       },
+
+       /* Tidy up after displaying the date picker. */
+       _inlineShow: function(inst) {
+               var numMonths = this._getNumberOfMonths(inst); // fix width for dynamic number of date pickers
+               inst.dpDiv.width(numMonths[1] * $('.ui-datepicker', inst.dpDiv[0]).width());
+       }, 
+
+       /* Pop-up the date picker in a "dialog" box.
+          @param  input     element - ignored
+          @param  dateText  string - the initial date to display (in the current format)
+          @param  onSelect  function - the function(dateText) to call when a date is selected
+          @param  settings  object - update the dialog date picker instance's settings (anonymous object)
+          @param  pos       int[2] - coordinates for the dialog's position within the screen or
+                            event - with x/y coordinates or
+                            leave empty for default (screen centre)
+          @return the manager object */
+       _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
+               var inst = this._dialogInst; // internal instance
+               if (!inst) {
+                       var id = 'dp' + new Date().getTime();
+                       this._dialogInput = $('<input type="text" id="' + id +
+                               '" size="1" style="position: absolute; top: -100px;"/>');
+                       this._dialogInput.keydown(this._doKeyDown);
+                       $('body').append(this._dialogInput);
+                       inst = this._dialogInst = this._newInst(this._dialogInput, false);
+                       inst.settings = {};
+                       $.data(this._dialogInput[0], PROP_NAME, inst);
+               }
+               extendRemove(inst.settings, settings || {});
+               this._dialogInput.val(dateText);
+
+               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+               if (!this._pos) {
+                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
+                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
+                       var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+                       var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+                       this._pos = // should use actual width/height below
+                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+               }
+
+               // move input on screen for focus, but hidden behind dialog
+               this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
+               inst.settings.onSelect = onSelect;
+               this._inDialog = true;
+               this.dpDiv.addClass(this._dialogClass);
+               this._showDatepicker(this._dialogInput[0]);
+               if ($.blockUI)
+                       $.blockUI(this.dpDiv);
+               $.data(this._dialogInput[0], PROP_NAME, inst);
+               return this;
+       },
+
        /* Detach a datepicker from its control.
           @param  target    element - the target input field or division or span */
        _destroyDatepicker: function(target) {
                var nodeName = target.nodeName.toLowerCase();
-               var calId = target._calId;
                var $target = $(target);
-               $target.removeAttr('_calId');
+               $.removeData(target, PROP_NAME);
                if (nodeName == 'input') {
-                       $target.siblings('.' + this._appendClass).replaceWith('').end()
-                               .siblings('.' + this._triggerClass).replaceWith('').end()
-                               .removeClass(this.markerClassName)
-                               .unbind('focus', this._showDatepicker)
-                               .unbind('keydown', this._doKeyDown)
-                               .unbind('keypress', this._doKeyPress);
-                       var wrapper = $target.parents('.' + this._wrapClass);
-                       if (wrapper)
-                               wrapper.siblings('.' + this._appendClass).replaceWith('').end()
-                                       .replaceWith(wrapper.html());
+                       $target.siblings('.' + this._appendClass).remove().end().
+                               siblings('.' + this._triggerClass).remove().end().
+                               removeClass(this.markerClassName).
+                               unbind('focus', this._showDatepicker).
+                               unbind('keydown', this._doKeyDown).
+                               unbind('keypress', this._doKeyPress);
                } else if (nodeName == 'div' || nodeName == 'span')
                        $target.removeClass(this.markerClassName).empty();
-               if ($('input[_calId=' + calId + ']').length == 0)
-                       // clean up if last for this ID
-                       this._inst[calId] = null;
        },
 
        /* Enable the date picker to a jQuery selection.
           @param  target    element - the target input field or division or span */
        _enableDatepicker: function(target) {
                target.disabled = false;
-               $(target).siblings('button.' + this._triggerClass).each(function() { this.disabled = false; }).end()
-                       .siblings('img.' + this._triggerClass).css({opacity: '1.0', cursor: ''});
+               $(target).siblings('button.' + this._triggerClass).each(function() { this.disabled = false; }).end().
+                       siblings('img.' + this._triggerClass).css({opacity: '1.0', cursor: ''});
                this._disabledInputs = $.map(this._disabledInputs,
                        function(value) { return (value == target ? null : value); }); // delete entry
        },
@@ -218,11 +314,11 @@ $.extend(Datepicker.prototype, {
           @param  target    element - the target input field or division or span */
        _disableDatepicker: function(target) {
                target.disabled = true;
-               $(target).siblings('button.' + this._triggerClass).each(function() { this.disabled = true; }).end()
-                       .siblings('img.' + this._triggerClass).css({opacity: '0.5', cursor: 'default'});
-               this._disabledInputs = $.map($.datepicker._disabledInputs,
+               $(target).siblings('button.' + this._triggerClass).each(function() { this.disabled = true; }).end().
+                       siblings('img.' + this._triggerClass).css({opacity: '0.5', cursor: 'default'});
+               this._disabledInputs = $.map(this._disabledInputs,
                        function(value) { return (value == target ? null : value); }); // delete entry
-               this._disabledInputs[$.datepicker._disabledInputs.length] = target;
+               this._disabledInputs[this._disabledInputs.length] = target;
        },
 
        /* Is the first field in a jQuery collection disabled as a datepicker?
@@ -240,8 +336,8 @@ $.extend(Datepicker.prototype, {
 
        /* Update the settings for a date picker attached to an input field or division.
           @param  target  element - the target input field or division or span
-          @param  name    string - the name of the setting to change or
-                          object - the new settings to update
+          @param  name    object - the new settings to update or
+                          string - the name of the setting to change or
           @param  value   any - the new value for the setting (omit if above is an object) */
        _changeDatepicker: function(target, name, value) {
                var settings = name || {};
@@ -249,8 +345,8 @@ $.extend(Datepicker.prototype, {
                        settings = {};
                        settings[name] = value;
                }
-               if (inst = this._getInst(target._calId)) {
-                       extendRemove(inst._settings, settings);
+               if (inst = $.data(target, PROP_NAME)) {
+                       extendRemove(inst.settings, settings);
                        this._updateDatepicker(inst);
                }
        },
@@ -260,8 +356,9 @@ $.extend(Datepicker.prototype, {
           @param  date     Date - the new date
           @param  endDate  Date - the new end date for a range (optional) */
        _setDateDatepicker: function(target, date, endDate) {
-               if (inst = this._getInst(target._calId)) {
-                       inst._setDate(date, endDate);
+               var inst = $.data(target, PROP_NAME);
+               if (inst) {
+                       this._setDate(inst, date, endDate);
                        this._updateDatepicker(inst);
                }
        },
@@ -271,158 +368,64 @@ $.extend(Datepicker.prototype, {
           @return Date - the current date or
                   Date[2] - the current dates for a range */
        _getDateDatepicker: function(target) {
-               var inst = this._getInst(target._calId);
+               var inst = $.data(target, PROP_NAME);
                if (inst)
-                       inst._setDateFromField($(target)); 
-               return (inst ? inst._getDate() : null);
+                       this._setDateFromField(inst); 
+               return (inst ? this._getDate(inst) : null);
        },
 
        /* Handle keystrokes. */
        _doKeyDown: function(e) {
-               var inst = $.datepicker._getInst(this._calId);
+               var inst = $.data(e.target, PROP_NAME);
+               var handled = true;
                if ($.datepicker._datepickerShowing)
                        switch (e.keyCode) {
                                case 9:  $.datepicker._hideDatepicker(null, '');
                                                break; // hide on tab out
-                               case 13: $.datepicker._selectDay(inst, inst._selectedMonth, inst._selectedYear,
-                                                       $('td.ui-datepicker-days-cell-over', inst._datepickerDiv)[0]);
+                               case 13: $.datepicker._selectDay(e.target, inst.selectedMonth, inst.selectedYear,
+                                                       $('td.ui-datepicker-days-cell-over', inst.dpDiv)[0]);
                                                return false; // don't submit the form
                                                break; // select the value on enter
-                               case 27: $.datepicker._hideDatepicker(null, inst._get('speed'));
+                               case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'speed'));
                                                break; // hide on escape
-                               case 33: $.datepicker._adjustDate(inst,
-                                                       (e.ctrlKey ? -1 : -inst._get('stepMonths')), (e.ctrlKey ? 'Y' : 'M'));
+                               case 33: $.datepicker._adjustDate(e.target, (e.ctrlKey ? -1 :
+                                                       -$.datepicker._get(inst, 'stepMonths')), (e.ctrlKey ? 'Y' : 'M'));
                                                break; // previous month/year on page up/+ ctrl
-                               case 34: $.datepicker._adjustDate(inst,
-                                                       (e.ctrlKey ? +1 : +inst._get('stepMonths')), (e.ctrlKey ? 'Y' : 'M'));
+                               case 34: $.datepicker._adjustDate(e.target, (e.ctrlKey ? +1 :
+                                                       +$.datepicker._get(inst, 'stepMonths')), (e.ctrlKey ? 'Y' : 'M'));
                                                break; // next month/year on page down/+ ctrl
-                               case 35: if (e.ctrlKey) $.datepicker._clearDate(inst);
+                               case 35: if (e.ctrlKey) $.datepicker._clearDate(e.target);
                                                break; // clear on ctrl+end
-                               case 36: if (e.ctrlKey) $.datepicker._gotoToday(inst);
+                               case 36: if (e.ctrlKey) $.datepicker._gotoToday(e.target);
                                                break; // current on ctrl+home
-                               case 37: if (e.ctrlKey) $.datepicker._adjustDate(inst, -1, 'D');
+                               case 37: if (e.ctrlKey) $.datepicker._adjustDate(e.target, -1, 'D');
                                                break; // -1 day on ctrl+left
-                               case 38: if (e.ctrlKey) $.datepicker._adjustDate(inst, -7, 'D');
+                               case 38: if (e.ctrlKey) $.datepicker._adjustDate(e.target, -7, 'D');
                                                break; // -1 week on ctrl+up
-                               case 39: if (e.ctrlKey) $.datepicker._adjustDate(inst, +1, 'D');
+                               case 39: if (e.ctrlKey) $.datepicker._adjustDate(e.target, +1, 'D');
                                                break; // +1 day on ctrl+right
-                               case 40: if (e.ctrlKey) $.datepicker._adjustDate(inst, +7, 'D');
+                               case 40: if (e.ctrlKey) $.datepicker._adjustDate(e.target, +7, 'D');
                                                break; // +1 week on ctrl+down
+                               default: handled = false;
                        }
                else if (e.keyCode == 36 && e.ctrlKey) // display the date picker on ctrl+home
                        $.datepicker._showDatepicker(this);
+               else
+                       handled = false;
+               if (handled) {
+                       e.preventDefault();
+                       e.stopPropagation();
+               }
        },
 
        /* Filter entered characters - based on date format. */
        _doKeyPress: function(e) {
-               var inst = $.datepicker._getInst(this._calId);
-               var chars = $.datepicker._possibleChars(inst._get('dateFormat'));
+               var inst = $.data(e.target, PROP_NAME);
+               var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
                var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode);
                return e.ctrlKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
        },
 
-       /* Attach the date picker to an input field. */
-       _connectDatepicker: function(target, inst) {
-               var input = $(target);
-               if (input.hasClass(this.markerClassName))
-                       return;
-               var appendText = inst._get('appendText');
-               var isRTL = inst._get('isRTL');
-               if (appendText)
-                       input[isRTL ? 'before' : 'after']('<span class="' + this._appendClass + '">' + appendText + '</span>');
-               var showOn = inst._get('showOn');
-               if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
-                       input.focus(this._showDatepicker);
-               if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
-                       input.wrap('<span class="' + this._wrapClass + '"></span>');
-                       var buttonText = inst._get('buttonText');
-                       var buttonImage = inst._get('buttonImage');
-                       var trigger = $(inst._get('buttonImageOnly') ? 
-                               $('<img/>').addClass(this._triggerClass).attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
-                               $('<button></button>').addClass(this._triggerClass).html(buttonImage != '' ? 
-                                               $('<img/>').attr({ src:buttonImage, alt:buttonText, title:buttonText }) : buttonText));
-                       input[isRTL ? 'before' : 'after'](trigger);
-                       trigger.click(function() {
-                               if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
-                                       $.datepicker._hideDatepicker();
-                               else
-                                       $.datepicker._showDatepicker(target);
-                                       
-                               return false;
-                       });
-        }
-               input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress)
-                       .bind("setData.datepicker", function(event, key, value) {
-                               inst._settings[key] = value;
-                       }).bind("getData.datepicker", function(event, key) {
-                               return inst._get(key);
-                       });
-               input[0]._calId = inst._id;
-       },
-
-       /* Attach an inline date picker to a div. */
-       _inlineDatepicker: function(target, inst) {
-               var input = $(target);
-               if (input.hasClass(this.markerClassName))
-                       return;
-               input.addClass(this.markerClassName).append(inst._datepickerDiv)
-                       .bind("setData.datepicker", function(event, key, value){
-                               inst._settings[key] = value;
-                       }).bind("getData.datepicker", function(event, key){
-                               return inst._get(key);
-                       });
-               input[0]._calId = inst._id;
-               this._updateDatepicker(inst);
-       },
-
-       /* Tidy up after displaying the date picker. */
-       _inlineShow: function(inst) {
-               var numMonths = inst._getNumberOfMonths(); // fix width for dynamic number of date pickers
-               inst._datepickerDiv.width(numMonths[1] * $('.ui-datepicker', inst._datepickerDiv[0]).width());
-       }, 
-
-       /* Pop-up the date picker in a "dialog" box.
-          @param  input     element - ignored
-          @param  dateText  string - the initial date to display (in the current format)
-          @param  onSelect  function - the function(dateText) to call when a date is selected
-          @param  settings  object - update the dialog date picker instance's settings (anonymous object)
-          @param  pos       int[2] - coordinates for the dialog's position within the screen or
-                            event - with x/y coordinates or
-                            leave empty for default (screen centre)
-          @return the manager object */
-       _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
-               var inst = this._dialogInst; // internal instance
-               if (!inst) {
-                       inst = this._dialogInst = new DatepickerInstance({}, false);
-                       this._dialogInput = $('<input type="text" size="1" style="position: absolute; top: -100px;"/>');
-                       this._dialogInput.keydown(this._doKeyDown);
-                       $('body').append(this._dialogInput);
-                       this._dialogInput[0]._calId = inst._id;
-               }
-               extendRemove(inst._settings, settings || {});
-               this._dialogInput.val(dateText);
-
-               this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
-               if (!this._pos) {
-                       var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
-                       var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
-                       var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
-                       var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
-                       this._pos = // should use actual width/height below
-                               [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
-               }
-
-               // move input on screen for focus, but hidden behind dialog
-               this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
-               inst._settings.onSelect = onSelect;
-               this._inDialog = true;
-               this._datepickerDiv.addClass(this._dialogClass);
-               this._showDatepicker(this._dialogInput[0]);
-               if ($.blockUI)
-                       $.blockUI(this._datepickerDiv);
-               return this;
-       },
-
        /* Pop-up the date picker for a given input field.
           @param  input  element - the input field attached to the date picker or
                          event - if triggered by focus */
@@ -432,12 +435,12 @@ $.extend(Datepicker.prototype, {
                        input = $('input', input.parentNode)[0];
                if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
                        return;
-               var inst = $.datepicker._getInst(input._calId);
-               var beforeShow = inst._get('beforeShow');
-               extendRemove(inst._settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
+               var inst = $.data(input, PROP_NAME);
+               var beforeShow = $.datepicker._get(inst, 'beforeShow');
+               extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
                $.datepicker._hideDatepicker(null, '');
                $.datepicker._lastInput = input;
-               inst._setDateFromField(input);
+               $.datepicker._setDateFromField(inst);
                if ($.datepicker._inDialog) // hide cursor
                        input.value = '';
                if (!$.datepicker._pos) { // position below input
@@ -455,76 +458,70 @@ $.extend(Datepicker.prototype, {
                }
                var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
                $.datepicker._pos = null;
-               inst._rangeStart = null;
+               inst.rangeStart = null;
                // determine sizing offscreen
-               inst._datepickerDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
+               inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
                $.datepicker._updateDatepicker(inst);
                // fix width for dynamic number of date pickers
-               inst._datepickerDiv.width(inst._getNumberOfMonths()[1] *
-                       $('.ui-datepicker', inst._datepickerDiv[0])[0].offsetWidth);
+               inst.dpDiv.width($.datepicker._getNumberOfMonths(inst)[1] *
+                       $('.ui-datepicker', inst.dpDiv[0])[0].offsetWidth);
                // and adjust position before showing
                offset = $.datepicker._checkOffset(inst, offset, isFixed);
-               inst._datepickerDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+               inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
                        'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
                        left: offset.left + 'px', top: offset.top + 'px'});
-               if (!inst._inline) {
-                       var showAnim = inst._get('showAnim') || 'show';
-                       var speed = inst._get('speed');
+               if (!inst.inline) {
+                       var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
+                       var speed = $.datepicker._get(inst, 'speed');
                        var postProcess = function() {
                                $.datepicker._datepickerShowing = true;
                                if ($.browser.msie && parseInt($.browser.version) < 7) // fix IE < 7 select problems
-                                       $('iframe.ui-datepicker-cover').css({width: inst._datepickerDiv.width() + 4,
-                                               height: inst._datepickerDiv.height() + 4});
+                                       $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
+                                               height: inst.dpDiv.height() + 4});
                        };
-                       inst._datepickerDiv[showAnim](speed, postProcess);
+                       inst.dpDiv[showAnim](speed, postProcess);
                        if (speed == '')
                                postProcess();
-                       if (inst._input[0].type != 'hidden')
-                               inst._input[0].focus();
+                       if (inst.input[0].type != 'hidden')
+                               inst.input[0].focus();
                        $.datepicker._curInst = inst;
                }
        },
 
        /* Generate the date picker content. */
        _updateDatepicker: function(inst) {
-               var dims = {width: inst._datepickerDiv.width() + 4,
-                       height: inst._datepickerDiv.height() + 4};
-               inst._datepickerDiv.empty().append(inst._generateDatepicker()).
+               var dims = {width: inst.dpDiv.width() + 4,
+                       height: inst.dpDiv.height() + 4};
+               inst.dpDiv.empty().append(this._generateDatepicker(inst)).
                        find('iframe.ui-datepicker-cover').
                        css({width: dims.width, height: dims.height});
-               var numMonths = inst._getNumberOfMonths();
-               if (numMonths[0] != 1 || numMonths[1] != 1)
-                       inst._datepickerDiv.addClass('ui-datepicker-multi');
-               else
-                       inst._datepickerDiv.removeClass('ui-datepicker-multi');
-
-               if (inst._get('isRTL'))
-                       inst._datepickerDiv.addClass('ui-datepicker-rtl');
-               else
-                       inst._datepickerDiv.removeClass('ui-datepicker-rtl');
-
-               if (inst._input && inst._input[0].type != 'hidden')
-                       $(inst._input[0]).focus();
+               var numMonths = this._getNumberOfMonths(inst);
+               inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-multi');
+               inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
+                       'Class']('ui-datepicker-rtl');
+               if (inst.input && inst.input[0].type != 'hidden')
+                       $(inst.input[0]).focus();
        },
 
        /* Check positioning to remain on screen. */
        _checkOffset: function(inst, offset, isFixed) {
-               var pos = inst._input ? $.datepicker._findPos(inst._input[0]) : null;
+               var pos = inst.input ? this._findPos(inst.input[0]) : null;
                var browserWidth = window.innerWidth || document.documentElement.clientWidth;
                var browserHeight = window.innerHeight || document.documentElement.clientHeight;
                var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
                var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
                // reposition date picker horizontally if outside the browser window
-               if ((offset.left + inst._datepickerDiv.width() - scrollX) > browserWidth)
+               if ((offset.left + inst.dpDiv.width() - scrollX) > browserWidth)
                        offset.left = Math.max((isFixed ? 0 : scrollX),
-                               pos[0] + (inst._input ? inst._input.width() : 0) - (isFixed ? scrollX : 0) - inst._datepickerDiv.width() -
+                               pos[0] + (inst.input ? inst.input.width() : 0) - (isFixed ? scrollX : 0) - inst.dpDiv.width() -
                                (isFixed && $.browser.opera ? document.documentElement.scrollLeft : 0));
                else
                        offset.left -= (isFixed ? scrollX : 0);
                // reposition date picker vertically if outside the browser window
-               if ((offset.top + inst._datepickerDiv.height() - scrollY) > browserHeight)
+               if ((offset.top + inst.dpDiv.height() - scrollY) > browserHeight)
                        offset.top = Math.max((isFixed ? 0 : scrollY),
-                               pos[1] - (isFixed ? scrollY : 0) - (this._inDialog ? 0 : inst._datepickerDiv.height()) -
+                               pos[1] - (isFixed ? scrollY : 0) - (this._inDialog ? 0 : inst.dpDiv.height()) -
                                (isFixed && $.browser.opera ? document.documentElement.scrollTop : 0));
                else
                        offset.top -= (isFixed ? scrollY : 0);
@@ -547,32 +544,32 @@ $.extend(Datepicker.prototype, {
                var inst = this._curInst;
                if (!inst)
                        return;
-               var rangeSelect = inst._get('rangeSelect');
+               var rangeSelect = this._get(inst, 'rangeSelect');
                if (rangeSelect && this._stayOpen)
-                       this._selectDate(inst, inst._formatDate(
-                               inst._currentDay, inst._currentMonth, inst._currentYear));
+                       this._selectDate('#' + inst.id, this._formatDate(inst,
+                               inst.currentDay, inst.currentMonth, inst.currentYear));
                this._stayOpen = false;
                if (this._datepickerShowing) {
-                       speed = (speed != null ? speed : inst._get('speed'));
-                       var showAnim = inst._get('showAnim');
-                       inst._datepickerDiv[(showAnim == 'slideDown' ? 'slideUp' :
+                       speed = (speed != null ? speed : this._get(inst, 'speed'));
+                       var showAnim = this._get(inst, 'showAnim');
+                       inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
                                (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))](speed, function() {
                                $.datepicker._tidyDialog(inst);
                        });
                        if (speed == '')
                                this._tidyDialog(inst);
-                       var onClose = inst._get('onClose');
+                       var onClose = this._get(inst, 'onClose');
                        if (onClose)
-                               onClose.apply((inst._input ? inst._input[0] : null),
-                                       [inst._getDate(), inst]);  // trigger custom callback
+                               onClose.apply((inst.input ? inst.input[0] : null),
+                                       [this._getDate(inst), inst]);  // trigger custom callback
                        this._datepickerShowing = false;
                        this._lastInput = null;
-                       inst._settings.prompt = null;
+                       inst.settings.prompt = null;
                        if (this._inDialog) {
                                this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
                                if ($.blockUI) {
                                        $.unblockUI();
-                                       $('body').append(this._datepickerDiv);
+                                       $('body').append(this.dpDiv);
                                }
                        }
                        this._inDialog = false;
@@ -582,8 +579,8 @@ $.extend(Datepicker.prototype, {
 
        /* Tidy up after a dialog display. */
        _tidyDialog: function(inst) {
-               inst._datepickerDiv.removeClass(this._dialogClass).unbind('.ui-datepicker');
-               $('.' + this._promptClass, inst._datepickerDiv).remove();
+               inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker');
+               $('.' + this._promptClass, inst.dpDiv).remove();
        },
 
        /* Close date picker if clicked elsewhere. */
@@ -600,44 +597,49 @@ $.extend(Datepicker.prototype, {
 
        /* Adjust one of the date sub-fields. */
        _adjustDate: function(id, offset, period) {
-               var inst = this._getInst(id);
-               inst._adjustDate(offset, period);
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               this._adjustInstDate(inst, offset, period);
                this._updateDatepicker(inst);
        },
 
        /* Action for current link. */
        _gotoToday: function(id) {
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
                var date = new Date();
-               var inst = this._getInst(id);
-               inst._selectedDay = date.getDate();
-               inst._drawMonth = inst._selectedMonth = date.getMonth();
-               inst._drawYear = inst._selectedYear = date.getFullYear();
-               this._adjustDate(inst);
-               inst._notifyChange();
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               this._adjustDate(target);
+               this._notifyChange(inst);
        },
 
        /* Action for selecting a new month/year. */
        _selectMonthYear: function(id, select, period) {
-               var inst = this._getInst(id);
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
                inst._selectingMonthYear = false;
-               inst[period == 'M' ? '_drawMonth' : '_drawYear'] =
+               inst[period == 'M' ? 'drawMonth' : 'drawYear'] =
                        select.options[select.selectedIndex].value - 0;
-               this._adjustDate(inst);
-               inst._notifyChange();
+               this._adjustDate(target);
+               this._notifyChange(inst);
        },
 
        /* Restore input focus after not changing month/year. */
        _clickMonthYear: function(id) {
-               var inst = this._getInst(id);
-               if (inst._input && inst._selectingMonthYear && !$.browser.msie)
-                       inst._input[0].focus();
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               if (inst.input && inst._selectingMonthYear && !$.browser.msie)
+                       inst.input[0].focus();
                inst._selectingMonthYear = !inst._selectingMonthYear;
        },
 
        /* Action for changing the first week day. */
        _changeFirstDay: function(id, day) {
-               var inst = this._getInst(id);
-               inst._settings.firstDay = day;
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               inst.settings.firstDay = day;
                this._updateDatepicker(inst);
        },
 
@@ -645,8 +647,9 @@ $.extend(Datepicker.prototype, {
        _selectDay: function(id, month, year, td) {
                if ($(td).hasClass(this._unselectableClass))
                        return;
-               var inst = this._getInst(id);
-               var rangeSelect = inst._get('rangeSelect');
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               var rangeSelect = this._get(inst, 'rangeSelect');
                if (rangeSelect) {
                        this._stayOpen = !this._stayOpen;
                        if (this._stayOpen) {
@@ -654,80 +657,82 @@ $.extend(Datepicker.prototype, {
                                $(td).addClass(this._currentClass);
                        } 
                }
-               inst._selectedDay = inst._currentDay = $('a', td).html();
-               inst._selectedMonth = inst._currentMonth = month;
-               inst._selectedYear = inst._currentYear = year;
+               inst.selectedDay = inst.currentDay = $('a', td).html();
+               inst.selectedMonth = inst.currentMonth = month;
+               inst.selectedYear = inst.currentYear = year;
                if (this._stayOpen) {
-                       inst._endDay = inst._endMonth = inst._endYear = null;
+                       inst.endDay = inst.endMonth = inst.endYear = null;
                }
                else if (rangeSelect) {
-                       inst._endDay = inst._currentDay;
-                       inst._endMonth = inst._currentMonth;
-                       inst._endYear = inst._currentYear;
+                       inst.endDay = inst.currentDay;
+                       inst.endMonth = inst.currentMonth;
+                       inst.endYear = inst.currentYear;
                }
-               this._selectDate(id, inst._formatDate(
-                       inst._currentDay, inst._currentMonth, inst._currentYear));
+               this._selectDate(id, this._formatDate(inst,
+                       inst.currentDay, inst.currentMonth, inst.currentYear));
                if (this._stayOpen) {
-                       inst._rangeStart = new Date(inst._currentYear, inst._currentMonth, inst._currentDay);
+                       inst.rangeStart = new Date(inst.currentYear, inst.currentMonth, inst.currentDay);
                        this._updateDatepicker(inst);
                }
                else if (rangeSelect) {
-                       inst._selectedDay = inst._currentDay = inst._rangeStart.getDate();
-                       inst._selectedMonth = inst._currentMonth = inst._rangeStart.getMonth();
-                       inst._selectedYear = inst._currentYear = inst._rangeStart.getFullYear();
-                       inst._rangeStart = null;
-                       if (inst._inline)
+                       inst.selectedDay = inst.currentDay = inst.rangeStart.getDate();
+                       inst.selectedMonth = inst.currentMonth = inst.rangeStart.getMonth();
+                       inst.selectedYear = inst.currentYear = inst.rangeStart.getFullYear();
+                       inst.rangeStart = null;
+                       if (inst.inline)
                                this._updateDatepicker(inst);
                }
        },
 
        /* Erase the input field and hide the date picker. */
        _clearDate: function(id) {
-               var inst = this._getInst(id);
-               if (inst._get('mandatory'))
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               if (this._get(inst, 'mandatory'))
                        return;
                this._stayOpen = false;
-               inst._endDay = inst._endMonth = inst._endYear = inst._rangeStart = null;
-               this._selectDate(inst, '');
+               inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
+               this._selectDate(target, '');
        },
 
        /* Update the input field with the selected date. */
        _selectDate: function(id, dateStr) {
-               var inst = this._getInst(id);
-               dateStr = (dateStr != null ? dateStr : inst._formatDate());
-               if (inst._get('rangeSelect') && dateStr)
-                       dateStr = (inst._rangeStart ? inst._formatDate(inst._rangeStart) :
-                               dateStr) + inst._get('rangeSeparator') + dateStr;
-               if (inst._input)
-                       inst._input.val(dateStr);
+               var target = $(id);
+               var inst = $.data(target[0], PROP_NAME);
+               dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+               if (this._get(inst, 'rangeSelect') && dateStr)
+                       dateStr = (inst.rangeStart ? this._formatDate(inst, inst.rangeStart) :
+                               dateStr) + this._get(inst, 'rangeSeparator') + dateStr;
+               if (inst.input)
+                       inst.input.val(dateStr);
                this._updateAlternate(inst);
-               var onSelect = inst._get('onSelect');
+               var onSelect = this._get(inst, 'onSelect');
                if (onSelect)
-                       onSelect.apply((inst._input ? inst._input[0] : null), [dateStr, inst]);  // trigger custom callback
-               else if (inst._input)
-                       inst._input.trigger('change'); // fire the change event
-               if (inst._inline)
+                       onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
+               else if (inst.input)
+                       inst.input.trigger('change'); // fire the change event
+               if (inst.inline)
                        this._updateDatepicker(inst);
                else if (!this._stayOpen) {
-                       this._hideDatepicker(null, inst._get('speed'));
-                       this._lastInput = inst._input[0];
-                       if (typeof(inst._input[0]) != 'object')
-                               inst._input[0].focus(); // restore focus
+                       this._hideDatepicker(null, this._get(inst, 'speed'));
+                       this._lastInput = inst.input[0];
+                       if (typeof(inst.input[0]) != 'object')
+                               inst.input[0].focus(); // restore focus
                        this._lastInput = null;
                }
        },
        
        /* Update any alternate field to synchronise with the main field. */
        _updateAlternate: function(inst) {
-               var altField = inst._get('altField');
+               var altField = this._get(inst, 'altField');
                if (altField) { // update alternate field too
-                       var altFormat = inst._get('altFormat');
-                       var date = inst._getDate();
+                       var altFormat = this._get(inst, 'altFormat');
+                       var date = this._getDate(inst);
                        dateStr = (isArray(date) ? (!date[0] && !date[1] ? '' :
-                               $.datepicker.formatDate(altFormat, date[0], inst._getFormatConfig()) +
-                               inst._get('rangeSeparator') + $.datepicker.formatDate(
-                               altFormat, date[1] || date[0], inst._getFormatConfig())) :
-                               $.datepicker.formatDate(altFormat, date, inst._getFormatConfig()));
+                               this.formatDate(altFormat, date[0], this._getFormatConfig(inst)) +
+                               this._get(inst, 'rangeSeparator') + this.formatDate(
+                               altFormat, date[1] || date[0], this._getFormatConfig(inst))) :
+                               this.formatDate(altFormat, date, this._getFormatConfig(inst)));
                        $(altField).each(function() { $(this).val(dateStr); });
                }
        },
@@ -766,7 +771,8 @@ $.extend(Datepicker.prototype, {
           @param  inst  the current datepicker instance
           @return  the status display text for this date */
        dateStatus: function(date, inst) {
-               return $.datepicker.formatDate(inst._get('dateStatus'), date, inst._getFormatConfig());
+               return $.datepicker.formatDate($.datepicker._get(inst, 'dateStatus'),
+                       date, $.datepicker._getFormatConfig(inst));
        },
 
        /* Parse a string value into a date object.
@@ -1007,80 +1013,59 @@ $.extend(Datepicker.prototype, {
                                                chars += format.charAt(iFormat);
                                }
                return chars;
-       }
-});
-
-/* Individualised settings for date picker functionality applied to one or more related inputs.
-   Instances are managed and manipulated through the Datepicker manager. */
-function DatepickerInstance(settings, inline) {
-       this._id = $.datepicker._register(this);
-       this._selectedDay = 0; // Current date for selection
-       this._selectedMonth = 0; // 0-11
-       this._selectedYear = 0; // 4-digit year
-       this._drawMonth = 0; // Current month at start of datepicker
-       this._drawYear = 0;
-       this._input = null; // The attached input field
-       this._inline = inline; // True if showing inline, false if used in a popup
-       this._datepickerDiv = (!inline ? $.datepicker._datepickerDiv :
-               $('<div id="' + $.datepicker._mainDivId + '-' + this._id + '" class="ui-datepicker-inline">'));
-       // customise the date picker object - uses manager defaults if not overridden
-       this._settings = extendRemove(settings || {}); // clone
-       if (inline)
-               this._setDate(this._getDefaultDate());
-}
+       },
 
-$.extend(DatepickerInstance.prototype, {
        /* Get a setting value, defaulting if necessary. */
-       _get: function(name) {
-               return this._settings[name] !== undefined ? this._settings[name] : $.datepicker._defaults[name];
+       _get: function(inst, name) {
+               return inst.settings[name] !== undefined ?
+                       inst.settings[name] : this._defaults[name];
        },
 
        /* Parse existing date and initialise date picker. */
-       _setDateFromField: function(input) {
-               this._input = $(input);
-               var dateFormat = this._get('dateFormat');
-               var dates = this._input ? this._input.val().split(this._get('rangeSeparator')) : null; 
-               this._endDay = this._endMonth = this._endYear = null;
-               var date = defaultDate = this._getDefaultDate();
+       _setDateFromField: function(inst) {
+               var dateFormat = this._get(inst, 'dateFormat');
+               var dates = inst.input ? inst.input.val().split(this._get(inst, 'rangeSeparator')) : null; 
+               inst.endDay = inst.endMonth = inst.endYear = null;
+               var date = defaultDate = this._getDefaultDate(inst);
                if (dates.length > 0) {
-                       var settings = this._getFormatConfig();
+                       var settings = this._getFormatConfig(inst);
                        if (dates.length > 1) {
-                               date = $.datepicker.parseDate(dateFormat, dates[1], settings) || defaultDate;
-                               this._endDay = date.getDate();
-                               this._endMonth = date.getMonth();
-                               this._endYear = date.getFullYear();
+                               date = this.parseDate(dateFormat, dates[1], settings) || defaultDate;
+                               inst.endDay = date.getDate();
+                               inst.endMonth = date.getMonth();
+                               inst.endYear = date.getFullYear();
                        }
                        try {
-                               date = $.datepicker.parseDate(dateFormat, dates[0], settings) || defaultDate;
+                               date = this.parseDate(dateFormat, dates[0], settings) || defaultDate;
                        } catch (e) {
-                               $.datepicker.log(e);
+                               this.log(e);
                                date = defaultDate;
                        }
                }
-               this._selectedDay = date.getDate();
-               this._drawMonth = this._selectedMonth = date.getMonth();
-               this._drawYear = this._selectedYear = date.getFullYear();
-               this._currentDay = (dates[0] ? date.getDate() : 0);
-               this._currentMonth = (dates[0] ? date.getMonth() : 0);
-               this._currentYear = (dates[0] ? date.getFullYear() : 0);
-               this._adjustDate();
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
+               inst.currentDay = (dates[0] ? date.getDate() : 0);
+               inst.currentMonth = (dates[0] ? date.getMonth() : 0);
+               inst.currentYear = (dates[0] ? date.getFullYear() : 0);
+               this._adjustInstDate(inst);
        },
        
        /* Retrieve the default date shown on opening. */
-       _getDefaultDate: function() {
-               var date = this._determineDate('defaultDate', new Date());
-               var minDate = this._getMinMaxDate('min', true);
-               var maxDate = this._getMinMaxDate('max');
+       _getDefaultDate: function(inst) {
+               var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
                date = (minDate && date < minDate ? minDate : date);
                date = (maxDate && date > maxDate ? maxDate : date);
                return date;
        },
 
        /* A date may be specified as an exact value or a relative one. */
-       _determineDate: function(name, defaultDate) {
+       _determineDate: function(date, defaultDate) {
                var offsetNumeric = function(offset) {
                        var date = new Date();
-                       date.setDate(date.getDate() + offset);
+                       date.setUTCDate(date.getUTCDate() + offset);
                        return date;
                };
                var offsetString = function(offset, getDaysInMonth) {
@@ -1109,68 +1094,76 @@ $.extend(DatepickerInstance.prototype, {
                        }
                        return new Date(year, month, day);
                };
-               var date = this._get(name);
                return (date == null ? defaultDate :
                        (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
                        (typeof date == 'number' ? offsetNumeric(date) : date)));
        },
 
        /* Set the date(s) directly. */
-       _setDate: function(date, endDate) {
-               this._selectedDay = this._currentDay = date.getDate();
-               this._drawMonth = this._selectedMonth = this._currentMonth = date.getMonth();
-               this._drawYear = this._selectedYear = this._currentYear = date.getFullYear();
-               if (this._get('rangeSelect')) {
+       _setDate: function(inst, date, endDate) {
+               var clear = !(date);
+               date = this._determineDate(date, new Date());
+               inst.selectedDay = inst.currentDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
+               if (this._get(inst, 'rangeSelect')) {
                        if (endDate) {
-                               this._endDay = endDate.getDate();
-                               this._endMonth = endDate.getMonth();
-                               this._endYear = endDate.getFullYear();
+                               endDate = this._determineDate(endDate, null);
+                               inst.endDay = endDate.getDate();
+                               inst.endMonth = endDate.getMonth();
+                               inst.endYear = endDate.getFullYear();
                        } else {
-                               this._endDay = this._currentDay;
-                               this._endMonth = this._currentMonth;
-                               this._endYear = this._currentYear;
+                               inst.endDay = inst.currentDay;
+                               inst.endMonth = inst.currentMonth;
+                               inst.endYear = inst.currentYear;
                        }
                }
-               this._adjustDate();
+               this._adjustInstDate(inst);
+               if (inst.input)
+                       inst.input.val(clear ? '' : this._formatDate(inst) +
+                               (!this._get(inst, 'rangeSelect') ? '' : this._get(inst, 'rangeSeparator') +
+                               this._formatDate(inst, inst.endDay, inst.endMonth, inst.endYear)));
        },
 
        /* Retrieve the date(s) directly. */
-       _getDate: function() {
-               var startDate = (!this._currentYear || (this._input && this._input.val() == '') ? null :
-                       new Date(this._currentYear, this._currentMonth, this._currentDay));
-               if (this._get('rangeSelect')) {
-                       return [this._rangeStart || startDate, (!this._endYear ? null :
-                               new Date(this._endYear, this._endMonth, this._endDay))];
+       _getDate: function(inst) {
+               var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
+                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+               if (this._get(inst, 'rangeSelect')) {
+                       return [inst.rangeStart || startDate, (!inst.endYear ? null :
+                               new Date(inst.endYear, inst.endMonth, inst.endDay))];
                } else
                        return startDate;
        },
 
        /* Generate the HTML for the current state of the date picker. */
-       _generateDatepicker: function() {
+       _generateDatepicker: function(inst) {
                var today = new Date();
                today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
-               var showStatus = this._get('showStatus');
-               var isRTL = this._get('isRTL');
+               var showStatus = this._get(inst, 'showStatus');
+               var isRTL = this._get(inst, 'isRTL');
                // build the date picker HTML
-               var clear = (this._get('mandatory') ? '' :
-                       '<div class="ui-datepicker-clear"><a onclick="jQuery.datepicker._clearDate(' + this._id + ');"' + 
-                       (showStatus ? this._addStatus(this._get('clearStatus') || '&#xa0;') : '') + '>' +
-                       this._get('clearText') + '</a></div>');
+               var clear = (this._get(inst, 'mandatory') ? '' :
+                       '<div class="ui-datepicker-clear"><a onclick="jQuery.datepicker._clearDate(\'#' + inst.id + '\');"' +
+                       (showStatus ? this._addStatus(inst, this._get(inst, 'clearStatus') || '&#xa0;') : '') + '>' +
+                       this._get(inst, 'clearText') + '</a></div>');
                var controls = '<div class="ui-datepicker-control">' + (isRTL ? '' : clear) +
                        '<div class="ui-datepicker-close"><a onclick="jQuery.datepicker._hideDatepicker();"' +
-                       (showStatus ? this._addStatus(this._get('closeStatus') || '&#xa0;') : '') + '>' +
-                       this._get('closeText') + '</a></div>' + (isRTL ? clear : '')  + '</div>';
-               var prompt = this._get('prompt');
-               var closeAtTop = this._get('closeAtTop');
-               var hideIfNoPrevNext = this._get('hideIfNoPrevNext');
-               var navigationAsDateFormat = this._get('navigationAsDateFormat');
-               var numMonths = this._getNumberOfMonths();
-               var stepMonths = this._get('stepMonths');
+                       (showStatus ? this._addStatus(inst, this._get(inst, 'closeStatus') || '&#xa0;') : '') + '>' +
+                       this._get(inst, 'closeText') + '</a></div>' + (isRTL ? clear : '')  + '</div>';
+               var prompt = this._get(inst, 'prompt');
+               var closeAtTop = this._get(inst, 'closeAtTop');
+               var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
+               var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
+               var numMonths = this._getNumberOfMonths(inst);
+               var stepMonths = this._get(inst, 'stepMonths');
                var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
-               var minDate = this._getMinMaxDate('min', true);
-               var maxDate = this._getMinMaxDate('max');
-               var drawMonth = this._drawMonth;
-               var drawYear = this._drawYear;
+               var currentDate = (!inst.currentDay ? new Date(9999, 9, 9) :
+                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
+               var drawMonth = inst.drawMonth;
+               var drawYear = inst.drawYear;
                if (maxDate) {
                        var maxDraw = new Date(maxDate.getFullYear(),
                                maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate());
@@ -1184,89 +1177,88 @@ $.extend(DatepickerInstance.prototype, {
                        }
                }
                // controls and links
-               var prevText = this._get('prevText');
-               prevText = (!navigationAsDateFormat ? prevText : $.datepicker.formatDate(
-                       prevText, new Date(drawYear, drawMonth - stepMonths, 1), this._getFormatConfig()));
-               var prev = '<div class="ui-datepicker-prev">' + (this._canAdjustMonth(-1, drawYear, drawMonth) ? 
-                       '<a onclick="jQuery.datepicker._adjustDate(' + this._id + ', -' + stepMonths + ', \'M\');"' +
-                       (showStatus ? this._addStatus(this._get('prevStatus') || '&#xa0;') : '') + '>' + prevText + '</a>' :
+               var prevText = this._get(inst, 'prevText');
+               prevText = (!navigationAsDateFormat ? prevText : this.formatDate(
+                       prevText, new Date(drawYear, drawMonth - stepMonths, 1), this._getFormatConfig(inst)));
+               var prev = '<div class="ui-datepicker-prev">' + (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 
+                       '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+                       (showStatus ? this._addStatus(inst, this._get(inst, 'prevStatus') || '&#xa0;') : '') + '>' + prevText + '</a>' :
                        (hideIfNoPrevNext ? '' : '<label>' + prevText + '</label>')) + '</div>';
-               var nextText = this._get('nextText');
-               nextText = (!navigationAsDateFormat ? nextText : $.datepicker.formatDate(
-                       nextText, new Date(drawYear, drawMonth + stepMonths, 1), this._getFormatConfig()));
-               var next = '<div class="ui-datepicker-next">' + (this._canAdjustMonth(+1, drawYear, drawMonth) ?
-                       '<a onclick="jQuery.datepicker._adjustDate(' + this._id + ', +' + stepMonths + ', \'M\');"' +
-                       (showStatus ? this._addStatus(this._get('nextStatus') || '&#xa0;') : '') + '>' + nextText + '</a>' :
+               var nextText = this._get(inst, 'nextText');
+               nextText = (!navigationAsDateFormat ? nextText : this.formatDate(
+                       nextText, new Date(drawYear, drawMonth + stepMonths, 1), this._getFormatConfig(inst)));
+               var next = '<div class="ui-datepicker-next">' + (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+                       '<a onclick="jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+                       (showStatus ? this._addStatus(inst, this._get(inst, 'nextStatus') || '&#xa0;') : '') + '>' + nextText + '</a>' :
                        (hideIfNoPrevNext ? '' : '<label>' + nextText + '</label>')) + '</div>';
-               var currentText = this._get('currentText');
-               currentText = (!navigationAsDateFormat ? currentText: $.datepicker.formatDate(
-                       currentText, today, this._getFormatConfig()));
-               var html = (prompt ? '<div class="' + $.datepicker._promptClass + '">' + prompt + '</div>' : '') +
-                       (closeAtTop && !this._inline ? controls : '') +
+               var currentText = this._get(inst, 'currentText');
+               currentText = (!navigationAsDateFormat ? currentText: this.formatDate(
+                       currentText, today, this._getFormatConfig(inst)));
+               var html = (prompt ? '<div class="' + this._promptClass + '">' + prompt + '</div>' : '') +
+                       (closeAtTop && !inst.inline ? controls : '') +
                        '<div class="ui-datepicker-links">' + (isRTL ? next : prev) +
-                       (this._isInRange(today) ? '<div class="ui-datepicker-current">' +
-                       '<a onclick="jQuery.datepicker._gotoToday(' + this._id + ');"' +
-                       (showStatus ? this._addStatus(this._get('currentStatus') || '&#xa0;') : '') + '>' +
+                       (this._isInRange(inst, today) ? '<div class="ui-datepicker-current">' +
+                       '<a onclick="jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+                       (showStatus ? this._addStatus(inst, this._get(inst, 'currentStatus') || '&#xa0;') : '') + '>' +
                        currentText + '</a></div>' : '') + (isRTL ? prev : next) + '</div>';
-               var showWeeks = this._get('showWeeks');
+               var firstDay = this._get(inst, 'firstDay');
+               var changeFirstDay = this._get(inst, 'changeFirstDay');
+               var dayNames = this._get(inst, 'dayNames');
+               var dayNamesShort = this._get(inst, 'dayNamesShort');
+               var dayNamesMin = this._get(inst, 'dayNamesMin');
+               var monthNames = this._get(inst, 'monthNames');
+               var beforeShowDay = this._get(inst, 'beforeShowDay');
+               var highlightWeek = this._get(inst, 'highlightWeek');
+               var showOtherMonths = this._get(inst, 'showOtherMonths');
+               var showWeeks = this._get(inst, 'showWeeks');
+               var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+               var status = (showStatus ? this._get(inst, 'dayStatus') || '&#xa0;' : '');
+               var dateStatus = this._get(inst, 'statusForDate') || this.dateStatus;
+               var endDate = inst.endDay ? new Date(inst.endYear, inst.endMonth, inst.endDay) : currentDate;
                for (var row = 0; row < numMonths[0]; row++)
                        for (var col = 0; col < numMonths[1]; col++) {
-                               var selectedDate = new Date(drawYear, drawMonth, this._selectedDay);
+                               var selectedDate = new Date(drawYear, drawMonth, inst.selectedDay);
                                html += '<div class="ui-datepicker-one-month' + (col == 0 ? ' ui-datepicker-new-row' : '') + '">' +
-                                       this._generateMonthYearHeader(drawMonth, drawYear, minDate, maxDate,
-                                       selectedDate, row > 0 || col > 0) + // draw month headers
+                                       this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+                                       selectedDate, row > 0 || col > 0, showStatus, monthNames) + // draw month headers
                                        '<table class="ui-datepicker" cellpadding="0" cellspacing="0"><thead>' + 
                                        '<tr class="ui-datepicker-title-row">' +
-                                       (showWeeks ? '<td>' + this._get('weekHeader') + '</td>' : '');
-                               var firstDay = this._get('firstDay');
-                               var changeFirstDay = this._get('changeFirstDay');
-                               var dayNames = this._get('dayNames');
-                               var dayNamesShort = this._get('dayNamesShort');
-                               var dayNamesMin = this._get('dayNamesMin');
+                                       (showWeeks ? '<td>' + this._get(inst, 'weekHeader') + '</td>' : '');
                                for (var dow = 0; dow < 7; dow++) { // days of the week
                                        var day = (dow + firstDay) % 7;
-                                       var status = this._get('dayStatus') || '&#xa0;';
-                                       status = (status.indexOf('DD') > -1 ? status.replace(/DD/, dayNames[day]) :
+                                       var dayStatus = (status.indexOf('DD') > -1 ? status.replace(/DD/, dayNames[day]) :
                                                status.replace(/D/, dayNamesShort[day]));
                                        html += '<td' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end-cell"' : '') + '>' +
                                                (!changeFirstDay ? '<span' :
-                                               '<a onclick="jQuery.datepicker._changeFirstDay(' + this._id + ', ' + day + ');"') + 
-                                               (showStatus ? this._addStatus(status) : '') + ' title="' + dayNames[day] + '">' +
+                                               '<a onclick="jQuery.datepicker._changeFirstDay(\'#' + inst.id + '\', ' + day + ');"') + 
+                                               (showStatus ? this._addStatus(inst, dayStatus) : '') + ' title="' + dayNames[day] + '">' +
                                                dayNamesMin[day] + (changeFirstDay ? '</a>' : '</span>') + '</td>';
                                }
                                html += '</tr></thead><tbody>';
                                var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
-                               if (drawYear == this._selectedYear && drawMonth == this._selectedMonth)
-                                       this._selectedDay = Math.min(this._selectedDay, daysInMonth);
+                               if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
+                                       inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
                                var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
-                               var currentDate = (!this._currentDay ? new Date(9999, 9, 9) :
-                                       new Date(this._currentYear, this._currentMonth, this._currentDay));
-                               var endDate = this._endDay ? new Date(this._endYear, this._endMonth, this._endDay) : currentDate;
                                var printDate = new Date(drawYear, drawMonth, 1 - leadDays);
                                var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
-                               var beforeShowDay = this._get('beforeShowDay');
-                               var highlightWeek = this._get('highlightWeek');
-                               var showOtherMonths = this._get('showOtherMonths');
-                               var calculateWeek = this._get('calculateWeek') || $.datepicker.iso8601Week;
-                               var dateStatus = this._get('statusForDate') || $.datepicker.dateStatus;
                                for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
                                        html += '<tr class="ui-datepicker-days-row">' +
                                                (showWeeks ? '<td class="ui-datepicker-week-col">' + calculateWeek(printDate) + '</td>' : '');
                                        for (var dow = 0; dow < 7; dow++) { // create date picker days
                                                var daySettings = (beforeShowDay ?
-                                                       beforeShowDay.apply((this._input ? this._input[0] : null), [printDate]) : [true, '']);
+                                                       beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
                                                var otherMonth = (printDate.getMonth() != drawMonth);
                                                var unselectable = otherMonth || !daySettings[0] ||
                                                        (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
                                                html += '<td class="ui-datepicker-days-cell' +
                                                        ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end-cell' : '') + // highlight weekends
                                                        (otherMonth ? ' ui-datepicker-otherMonth' : '') + // highlight days from other months
-                                                       (printDate.getTime() == selectedDate.getTime() && drawMonth == this._selectedMonth ?
+                                                       (printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth ?
                                                        ' ui-datepicker-days-cell-over' : '') + // highlight selected day
-                                                       (unselectable ? ' ' + $.datepicker._unselectableClass : '') +  // highlight unselectable days
+                                                       (unselectable ? ' ' + this._unselectableClass : '') +  // highlight unselectable days
                                                        (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
                                                        (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ?  // in current range
-                                                       ' ' + $.datepicker._currentClass : '') + // highlight selected day
+                                                       ' ' + this._currentClass : '') + // highlight selected day
                                                        (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
                                                        ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
                                                        (unselectable ? (highlightWeek ? ' onmouseover="jQuery(this).parent().addClass(\'ui-datepicker-week-over\');"' + // highlight selection week
@@ -1274,16 +1266,16 @@ $.extend(DatepickerInstance.prototype, {
                                                        ' onmouseover="jQuery(this).addClass(\'ui-datepicker-days-cell-over\')' + // highlight selection
                                                        (highlightWeek ? '.parent().addClass(\'ui-datepicker-week-over\')' : '') + ';' + // highlight selection week
                                                        (!showStatus || (otherMonth && !showOtherMonths) ? '' : 'jQuery(\'#ui-datepicker-status-' +
-                                                       this._id + '\').html(\'' + (dateStatus.apply((this._input ? this._input[0] : null),
-                                                       [printDate, this]) || '&#xa0;') +'\');') + '"' +
+                                                       inst.id + '\').html(\'' + (dateStatus.apply((inst.input ? inst.input[0] : null),
+                                                       [printDate, inst]) || '&#xa0;') +'\');') + '"' +
                                                        ' onmouseout="jQuery(this).removeClass(\'ui-datepicker-days-cell-over\')' + // unhighlight selection
                                                        (highlightWeek ? '.parent().removeClass(\'ui-datepicker-week-over\')' : '') + ';' + // unhighlight selection week
                                                        (!showStatus || (otherMonth && !showOtherMonths) ? '' : 'jQuery(\'#ui-datepicker-status-' +
-                                                       this._id + '\').html(\'&#xa0;\');') + '" onclick="jQuery.datepicker._selectDay(' +
-                                                       this._id + ',' + drawMonth + ',' + drawYear + ', this);"') + '>' + // actions
+                                                       inst.id + '\').html(\'&#xa0;\');') + '" onclick="jQuery.datepicker._selectDay(\'#' +
+                                                       inst.id + '\',' + drawMonth + ',' + drawYear + ', this);"') + '>' + // actions
                                                        (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
                                                        (unselectable ? printDate.getDate() : '<a>' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
-                                               printDate.setDate(printDate.getDate() + 1);
+                                               printDate.setUTCDate(printDate.getUTCDate() + 1);
                                        }
                                        html += '</tr>';
                                }
@@ -1294,31 +1286,30 @@ $.extend(DatepickerInstance.prototype, {
                                }
                                html += '</tbody></table></div>';
                        }
-               html += (showStatus ? '<div style="clear: both;"></div><div id="ui-datepicker-status-' + this._id + 
-                       '" class="ui-datepicker-status">' + (this._get('initStatus') || '&#xa0;') + '</div>' : '') +
-                       (!closeAtTop && !this._inline ? controls : '') +
+               html += (showStatus ? '<div style="clear: both;"></div><div id="ui-datepicker-status-' + inst.id + 
+                       '" class="ui-datepicker-status">' + (this._get(inst, 'initStatus') || '&#xa0;') + '</div>' : '') +
+                       (!closeAtTop && !inst.inline ? controls : '') +
                        '<div style="clear: both;"></div>' + 
-                       ($.browser.msie && parseInt($.browser.version) < 7 && !this._inline ? 
+                       ($.browser.msie && parseInt($.browser.version) < 7 && !inst.inline ? 
                        '<iframe src="javascript:false;" class="ui-datepicker-cover"></iframe>' : '');
                return html;
        },
        
        /* Generate the month and year header. */
-       _generateMonthYearHeader: function(drawMonth, drawYear, minDate, maxDate, selectedDate, secondary) {
-               minDate = (this._rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
-               var showStatus = this._get('showStatus');
+       _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+                       selectedDate, secondary, showStatus, monthNames) {
+               minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
                var html = '<div class="ui-datepicker-header">';
                // month selection
-               var monthNames = this._get('monthNames');
-               if (secondary || !this._get('changeMonth'))
+               if (secondary || !this._get(inst, 'changeMonth'))
                        html += monthNames[drawMonth] + '&#xa0;';
                else {
                        var inMinYear = (minDate && minDate.getFullYear() == drawYear);
                        var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
                        html += '<select class="ui-datepicker-new-month" ' +
-                               'onchange="jQuery.datepicker._selectMonthYear(' + this._id + ', this, \'M\');" ' +
-                               'onclick="jQuery.datepicker._clickMonthYear(' + this._id + ');"' +
-                               (showStatus ? this._addStatus(this._get('monthStatus') || '&#xa0;') : '') + '>';
+                               'onchange="jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+                               'onclick="jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               (showStatus ? this._addStatus(inst, this._get(inst, 'monthStatus') || '&#xa0;') : '') + '>';
                        for (var month = 0; month < 12; month++) {
                                if ((!inMinYear || month >= minDate.getMonth()) &&
                                                (!inMaxYear || month <= maxDate.getMonth()))
@@ -1329,11 +1320,11 @@ $.extend(DatepickerInstance.prototype, {
                        html += '</select>';
                }
                // year selection
-               if (secondary || !this._get('changeYear'))
+               if (secondary || !this._get(inst, 'changeYear'))
                        html += drawYear;
                else {
                        // determine range of years to display
-                       var years = this._get('yearRange').split(':');
+                       var years = this._get(inst, 'yearRange').split(':');
                        var year = 0;
                        var endYear = 0;
                        if (years.length != 2) {
@@ -1350,9 +1341,9 @@ $.extend(DatepickerInstance.prototype, {
                        year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
                        endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
                        html += '<select class="ui-datepicker-new-year" ' +
-                               'onchange="jQuery.datepicker._selectMonthYear(' + this._id + ', this, \'Y\');" ' +
-                               'onclick="jQuery.datepicker._clickMonthYear(' + this._id + ');"' +
-                               (showStatus ? this._addStatus(this._get('yearStatus') || '&#xa0;') : '') + '>';
+                               'onchange="jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+                               'onclick="jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+                               (showStatus ? this._addStatus(inst, this._get(inst, 'yearStatus') || '&#xa0;') : '') + '>';
                        for (; year <= endYear; year++) {
                                html += '<option value="' + year + '"' +
                                        (year == drawYear ? ' selected="selected"' : '') +
@@ -1365,55 +1356,55 @@ $.extend(DatepickerInstance.prototype, {
        },
 
        /* Provide code to set and clear the status panel. */
-       _addStatus: function(text) {
-               return ' onmouseover="jQuery(\'#ui-datepicker-status-' + this._id + '\').html(\'' + text + '\');" ' +
-                       'onmouseout="jQuery(\'#ui-datepicker-status-' + this._id + '\').html(\'&#xa0;\');"';
+       _addStatus: function(inst, text) {
+               return ' onmouseover="jQuery(\'#ui-datepicker-status-' + inst.id + '\').html(\'' + text + '\');" ' +
+                       'onmouseout="jQuery(\'#ui-datepicker-status-' + inst.id + '\').html(\'&#xa0;\');"';
        },
 
        /* Adjust one of the date sub-fields. */
-       _adjustDate: function(offset, period) {
-               var year = this._drawYear + (period == 'Y' ? offset : 0);
-               var month = this._drawMonth + (period == 'M' ? offset : 0);
-               var day = Math.min(this._selectedDay, this._getDaysInMonth(year, month)) +
+       _adjustInstDate: function(inst, offset, period) {
+               var year = inst.drawYear + (period == 'Y' ? offset : 0);
+               var month = inst.drawMonth + (period == 'M' ? offset : 0);
+               var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
                        (period == 'D' ? offset : 0);
                var date = new Date(year, month, day);
                // ensure it is within the bounds set
-               var minDate = this._getMinMaxDate('min', true);
-               var maxDate = this._getMinMaxDate('max');
+               var minDate = this._getMinMaxDate(inst, 'min', true);
+               var maxDate = this._getMinMaxDate(inst, 'max');
                date = (minDate && date < minDate ? minDate : date);
                date = (maxDate && date > maxDate ? maxDate : date);
-               this._selectedDay = date.getDate();
-               this._drawMonth = this._selectedMonth = date.getMonth();
-               this._drawYear = this._selectedYear = date.getFullYear();
+               inst.selectedDay = date.getDate();
+               inst.drawMonth = inst.selectedMonth = date.getMonth();
+               inst.drawYear = inst.selectedYear = date.getFullYear();
                if (period == 'M' || period == 'Y')
-                       this._notifyChange();
+                       this._notifyChange(inst);
        },
 
        /* Notify change of month/year. */
-       _notifyChange: function() {
-               var onChange = this._get('onChangeMonthYear');
+       _notifyChange: function(inst) {
+               var onChange = this._get(inst, 'onChangeMonthYear');
                if (onChange)
-                       onChange.apply((this._input ? this._input[0] : null),
-                               [new Date(this._selectedYear, this._selectedMonth, 1), this]);
+                       onChange.apply((inst.input ? inst.input[0] : null),
+                               [new Date(inst.selectedYear, inst.selectedMonth, 1), inst]);
        },
        
        /* Determine the number of months to show. */
-       _getNumberOfMonths: function() {
-               var numMonths = this._get('numberOfMonths');
+       _getNumberOfMonths: function(inst) {
+               var numMonths = this._get(inst, 'numberOfMonths');
                return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
        },
 
        /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
-       _getMinMaxDate: function(minMax, checkRange) {
-               var date = this._determineDate(minMax + 'Date', null);
+       _getMinMaxDate: function(inst, minMax, checkRange) {
+               var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
                if (date) {
                        date.setHours(0);
                        date.setMinutes(0);
                        date.setSeconds(0);
                        date.setMilliseconds(0);
                }
-               return (!checkRange || !this._rangeStart ? date :
-                       (!date || this._rangeStart > date ? this._rangeStart : date));
+               return (!checkRange || !inst.rangeStart ? date :
+                       (!date || inst.rangeStart > date ? inst.rangeStart : date));
        },
 
        /* Find the number of days in a given month. */
@@ -1427,45 +1418,45 @@ $.extend(DatepickerInstance.prototype, {
        },
 
        /* Determines if we should allow a "next/prev" month display change. */
-       _canAdjustMonth: function(offset, curYear, curMonth) {
-               var numMonths = this._getNumberOfMonths();
+       _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+               var numMonths = this._getNumberOfMonths(inst);
                var date = new Date(curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1);
                if (offset < 0)
                        date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
-               return this._isInRange(date);
+               return this._isInRange(inst, date);
        },
 
        /* Is the given date in the accepted range? */
-       _isInRange: function(date) {
+       _isInRange: function(inst, date) {
                // during range selection, use minimum of selected date and range start
-               var newMinDate = (!this._rangeStart ? null :
-                       new Date(this._selectedYear, this._selectedMonth, this._selectedDay));
-               newMinDate = (newMinDate && this._rangeStart < newMinDate ? this._rangeStart : newMinDate);
-               var minDate = newMinDate || this._getMinMaxDate('min');
-               var maxDate = this._getMinMaxDate('max');
+               var newMinDate = (!inst.rangeStart ? null :
+                       new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay));
+               newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
+               var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+               var maxDate = this._getMinMaxDate(inst, 'max');
                return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
        },
        
        /* Provide the configuration settings for formatting/parsing. */
-       _getFormatConfig: function() {
-               var shortYearCutoff = this._get('shortYearCutoff');
+       _getFormatConfig: function(inst) {
+               var shortYearCutoff = this._get(inst, 'shortYearCutoff');
                shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
                        new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
                return {shortYearCutoff: shortYearCutoff,
-                       dayNamesShort: this._get('dayNamesShort'), dayNames: this._get('dayNames'),
-                       monthNamesShort: this._get('monthNamesShort'), monthNames: this._get('monthNames')};
+                       dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
+                       monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
        },
 
        /* Format the given date for display. */
-       _formatDate: function(day, month, year) {
+       _formatDate: function(inst, day, month, year) {
                if (!day) {
-                       this._currentDay = this._selectedDay;
-                       this._currentMonth = this._selectedMonth;
-                       this._currentYear = this._selectedYear;
+                       inst.currentDay = inst.selectedDay;
+                       inst.currentMonth = inst.selectedMonth;
+                       inst.currentYear = inst.selectedYear;
                }
                var date = (day ? (typeof day == 'object' ? day : new Date(year, month, day)) :
-                       new Date(this._currentYear, this._currentMonth, this._currentDay));
-               return $.datepicker.formatDate(this._get('dateFormat'), date, this._getFormatConfig());
+                       new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
+               return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
        }
 });
 
@@ -1491,10 +1482,12 @@ function isArray(a) {
 $.fn.datepicker = function(options){
        var otherArgs = Array.prototype.slice.call(arguments, 1);
        if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
-               return $.datepicker['_' + options + 'Datepicker'].apply($.datepicker, [this[0]].concat(otherArgs));
+               return $.datepicker['_' + options + 'Datepicker'].
+                       apply($.datepicker, [this[0]].concat(otherArgs));
        return this.each(function() {
                typeof options == 'string' ?
-                       $.datepicker['_' + options + 'Datepicker'].apply($.datepicker, [this].concat(otherArgs)) :
+                       $.datepicker['_' + options + 'Datepicker'].
+                               apply($.datepicker, [this].concat(otherArgs)) :
                        $.datepicker._attachDatepicker(this, options);
        });
 };
@@ -1503,7 +1496,7 @@ $.datepicker = new Datepicker(); // singleton instance
        
 /* Initialise the date picker. */
 $(document).ready(function() {
-       $(document.body).append($.datepicker._datepickerDiv).
+       $(document.body).append($.datepicker.dpDiv).
                mousedown($.datepicker._checkExternalClick);
 });