Example Start

:

Example End

Example Description

Type: Best Practice

Simple example of a date picker widget.

Keyboard Support

  • Left: Move focus to the previous day. Will move to the last day of the previous month, if the current day is the first day of a month.
  • Right: Move focus to the next day. Will move to the first day of the following month, if the current day is the last day of a month.
  • Up: Move focus to the same day of the previous week. Will wrap to the appropriate day in the previous month.
  • Down: Move focus to the same day of the following week. Will wrap to the appropriate day in the following month.
  • PgUp: Move focus to the same date of the previous month. If that date does not exist, focus is placed on the last day of the month.
  • PgUp: Move focus to the same date of the following month. If that date does not exist, focus is placed on the last day of the month.
  • Ctrl+PgUp: Move focus to the same date of the previous year. If that date does not exist (e.g leap year), focus is placed on the last day of the month.
  • Ctrl+PgDn: Move focus to the same date of the following year. If that date does not exist (e.g leap year), focus is placed on the last day of the month.
  • Home: Move to the first day of the month.
  • End: Move to the last day of the month
  • Tab: Navigate between calander grid and previous/next selection buttons
  • Enter/Space: Select date

Example Markup

Browser Compatibility

HTML Source Code


<div id="application" role="application">
   <label id="date_label" for="date">Date</label>:
   <input id="date" type="text"/>
   <button id="bn_date">Select Date...</button>
   <div id="dp1" class="datepicker" aria-hidden="true">
      <div id="month-wrap">
         <div id="bn_prev" role="button" aria-labelledby="bn_prev-label" tabindex="0"><img class="bn_img" src="http://www.oaa-accessibility.org/media/examples/images/prev.png" alt="<<"/></div>
         <div id="month" role="heading" aria-live="assertive" aria-atomic="true">February 2011</div>
         <div id="bn_next" role="button" aria-labelledby="bn_next-label" tabindex="0"><img class="bn_img" src="http://www.oaa-accessibility.org/media/examples/images/next.png" alt=">>"/></div>
      </div>
      <table id="cal" role="grid" aria-activedescendant="errMsg" aria-labelledby="month" tabindex="0">
         <thead>
            <tr id="weekdays">
               <th id="Sunday"><abbr title="Sunday">Su</abbr></th>
               <th id="Monday"><abbr title="Monday">Mo</abbr></th>
               <th id="Tuesday"><abbr title="Tuesday">Tu</abbr></th>
               <th id="Wednesday"><abbr title="Wednesday">We</abbr></th>
               <th id="Thursday"><abbr title="Thursday">Th</abbr></th>
               <th id="Friday"><abbr title="Friday">Fr</abbr></th>
               <th id="Saturday"><abbr title="Saturday">Sa</abbr></th>
            </tr>
         </thead>
         <tbody>
            <tr><td id="errMsg" colspan="7">Javascript must be enabled</td></tr>
         </tbody>
      </table>
      <div id="bn_prev-label" class="offscreen">Go to previous month</div>
      <div id="bn_next-label" class="offscreen">Go to next month</div>
   </div>
</div>

CSS Code


.datepicker {
   margin: 10px;
   padding: 2px;
   position: absolute;
   width: 261px;
   background-color: #fff;
   border: 1px solid #ccc;
   -webkit-border-radius: 4px;
   -moz-border-radius: 4px;
   border-radius: 4px;
}
div#month-wrap {
   height: 30px;
   background-color: #ddd;
   border: 1px solid black;
   -webkit-border-radius: 4px;
   -moz-border-radius: 4px;
   border-radius: 4px;
}
div#bn_prev {
   margin: 3px;
   float: left;
   width: 24px;
   height: 24px;
}
div#bn_next {
   margin: 3px;
   float: right;
   width: 24px;
   height: 24px;
}

div#bn_prev:hover,
div#bn_prev:focus,
div#bn_next:hover,
div#bn_next:focus {
   margin: 2px;
   background-color: #fc3;
   border: 1px solid #800;
   -webkit-border-radius: 4px;
   -moz-border-radius: 4px;
   border-radius: 4px;
}
img.bn_img {
   margin: 0;
   padding: 2px;
}
div#month {
   float: left;
   padding-top: 6px;
   width: 199px;
   height: 24px;
   text-align: center;
   font-weight: bold;
   font-size: 1.2em;
}
table#cal {
   width: 261px;
   font-size: 1.2em;
   text-align: center;
}
table#cal th,
table#cal td {
   width: 35px;
   height: 30px;
   padding: 0;
}
table#cal td {
   background-color: #ddd;
   border: 1px solid #999;
}

table#cal td.today {
   background-color: #FFF0C4;
   border: 1px solid #999;
}

table#cal td.empty {
   background-color: #f9f9f9;
   border: 1px solid #eee;
}

table#cal td:hover,
table#cal td.focus {
   border-color: #800;
   background-color: #fc3;
}

table#cal td.empty:hover {
   background-color: #f9f9f9;
   border: 1px solid #eee;
}

.offscreen {
   position: absolute;
   left: -200em;
   top: -100em;
}
[aria-hidden="true"] {
   display: none;
}

Javascript Source Code


$(document).ready(function() {
   var dp1 = new datepicker('dp1', 'date', true);

   $('#bn_date').click(function(e) {
      dp1.showDlg();

      e.stopPropagation();
      return false;
   });
});

function datepicker(id, target, modal) {


   this.$id = $('#' + id); // element to attach widget to
   this.$monthObj = this.$id.find('#month');
   this.$prev = this.$id.find('#bn_prev');
   this.$next = this.$id.find('#bn_next');
   this.$grid = this.$id.find('#cal');
   this.$target = $('#' + target); // div or text box that will receive the selected date string and focus (if modal)
   this.bModal = modal; // true if datepicker should appear in a modal dialog box.

   this.monthNames = ['January', 'February', 'March', 'April','May','June',
         'July', 'August', 'September', 'October', 'November', 'December'];

   this.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

   this.dateObj = new Date();

   this.curYear = this.dateObj.getFullYear();
   this.year = this.curYear;

   this.curMonth = this.dateObj.getMonth();
   this.month = this.curMonth;
   this.currentDate = true;

   this.date = this.dateObj.getDate();

   this.keys = {
                tab:       9,
                enter:    13,
                esc:      27,
                space:    32,
                pageup:   33,
                pagedown: 34,
                end:      35,
                home:     36,
                left:     37,
                up:       38,
                right:    39,
                down:     40
               };
  
   // display the current month
   this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year);

   // populate the calendar grid
   this.popGrid();

   // update the table's activedescdendant to point to the current day
   this.$grid.attr('aria-activedescendant', this.$grid.find('.today').attr('id'));

   this.bindHandlers();

   // hide dialog if in modal mode
   if (this.bModal == true) {
      this.$id.attr('aria-hidden', 'true');
   }
}

//
// popGrid() is a member function to populate the datepicker grid with calendar days
// representing the current month
//
// @return N/A
//
datepicker.prototype.popGrid = function() {
  
   var numDays = this.calcNumDays(this.year, this.month);
   var startWeekday = this.calcStartWeekday(this.year, this.month);
   var weekday = 0;
   var curDay = 1;
   var rowCount = 1;
   var $tbody = this.$grid.find('tbody');

   var gridCells = '\t<tr id="row1">\n';

   // clear the grid
   $tbody.empty();
   $('#msg').empty();

   // Insert the leading empty cells
   for (weekday = 0; weekday < startWeekday; weekday++) {

      gridCells += '\t\t<td class="empty">&nbsp;</td>\n';
   }

   // insert the days of the month.
   for (curDay = 1; curDay <= numDays; curDay++) {

      if (curDay == this.date && this.currentDate == true) {

         gridCells += '\t\t<td id="day' + curDay + '" class="today" headers="row' +
                      rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false">' + curDay + '</td>';

      }
      else {
         gridCells += '\t\t<td id="day' + curDay + '" headers="row' +
                      rowCount + ' ' + this.dayNames[weekday] + '" role="gridcell" aria-selected="false">' + curDay + '</td>';
      }


      if (weekday == 6 && curDay < numDays) {
         // This was the last day of the week, close it out
         // and begin a new one
         gridCells += '\t</tr>\n\t<tr id="row' + rowCount + '">\n';
         rowCount++;
         weekday = 0;
      }
      else {
         weekday++;
      }
   }

   // Insert any trailing empty cells
   for (weekday; weekday < 7; weekday++) {

      gridCells += '\t\t<td class="empty">&nbsp;</td>\n';
   }

   gridCells += '\t</tr>';

   $tbody.append(gridCells);
}

//
// calcNumDays() is a member function to calculate the number of days in a given month
//
// @return (integer) number of days
//
datepicker.prototype.calcNumDays = function(year, month) {
  
   return 32 - new Date(year, month, 32).getDate();
}

//
// calcstartWeekday() is a member function to calculate the day of the week the first day of a
// month lands on
//
// @return (integer) number representing the day of the week (0=Sunday....6=Saturday)
//
datepicker.prototype.calcStartWeekday = function(year, month) {
  
   return  new Date(year, month, 1).getDay();

} // end calcStartWeekday()

//
// showPrevMonth() is a member function to show the previous month
//
// @param (offset int) offset may be used to specify an offset for setting
//                      focus on a day the specified number of days from
//                      the end of the month.
// @return N/A
//
datepicker.prototype.showPrevMonth = function(offset) {
   // show the previous month
   if (this.month == 0) {
      this.month = 11;
      this.year--;
   }
   else {
      this.month--;
   }
  
   if (this.month != this.curMonth || this.year != this.curYear) {
      this.currentDate = false;
   }
   else {
      this.currentDate = true;
   }

   // populate the calendar grid
   this.popGrid();

   this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year);

   // if offset was specified, set focus on the last day - specified offset
   if (offset != null) {
      var numDays = this.calcNumDays(this.year, this.month);
      var day = 'day' + (numDays - offset);
      
      this.$grid.attr('aria-activedescendant', day);
      $('#' + day).addClass('focus').attr('aria-selected', 'true');
   }

} // end showPrevMonth()

//
// showNextMonth() is a member function to show the next month
//
// @param (offset int) offset may be used to specify an offset for setting
//                      focus on a day the specified number of days from
//                      the beginning of the month.
// @return N/A
//
datepicker.prototype.showNextMonth = function(offset) {

   // show the next month
   if (this.month == 11) {
      this.month = 0;
      this.year++;
   }
   else {
      this.month++;
   }

   if (this.month != this.curMonth || this.year != this.curYear) {
      this.currentDate = false;
   }
   else {
      this.currentDate = true;
   }
  
   // populate the calendar grid
   this.popGrid();

   this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year);

      // if offset was specified, set focus on the first day + specified offset
      if (offset != null) {
         var day = 'day' + offset;
        
         this.$grid.attr('aria-activedescendant', day);
         $('#' + day).addClass('focus').attr('aria-selected', 'true');
      }

} // end showNextMonth()

//
// showPrevYear() is a member function to show the previous year
//
// @return N/A
//
datepicker.prototype.showPrevYear = function() {

      // decrement the year
      this.year--;
      
      if (this.month != this.curMonth || this.year != this.curYear) {
         this.currentDate = false;
      }
      else {
         this.currentDate = true;
      }

      // populate the calendar grid
      this.popGrid();

      this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year);

} // end showPrevYear()

//
// showNextYear() is a member function to show the next year
//
// @return N/A
//
datepicker.prototype.showNextYear = function() {

   // increment the year
   this.year++;

   if (this.month != this.curMonth || this.year != this.curYear) {
      this.currentDate = false;
   }
   else {
      this.currentDate = true;
   }
  
   // populate the calendar grid
   this.popGrid();

   this.$monthObj.html(this.monthNames[this.month] + ' ' + this.year);

} // end showNextYear()

//
// bindHandlers() is a member function to bind event handlers for the widget
//
// @return N/A
//
datepicker.prototype.bindHandlers = function() {

   var thisObj = this;

   ////////////////////// bind button handlers //////////////////////////////////
   this.$prev.click(function(e) {
      return thisObj.handlePrevClick(e);
   });

   this.$next.click(function(e) {
      return thisObj.handleNextClick(e);
   });

   this.$prev.keydown(function(e) {
      return thisObj.handlePrevKeyDown(e);
   });

   this.$next.keydown(function(e) {
      return thisObj.handleNextKeyDown(e);
   });

   ///////////// bind grid handlers //////////////
  
   this.$grid.keydown(function(e) {
      return thisObj.handleGridKeyDown(e);
   });

   this.$grid.keypress(function(e) {
      return thisObj.handleGridKeyPress(e);
   });

   this.$grid.focus(function(e) {
      return thisObj.handleGridFocus(e);
   });

   this.$grid.blur(function(e) {
      return thisObj.handleGridBlur(e);
   });

   this.$grid.delegate('td', 'click', function(e) {
      return thisObj.handleGridClick(this, e);
   });

} // end bindHandlers();

//
// handlePrevClick() is a member function to process click events for the prev month button
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handlePrevClick = function(e) {

   var active = this.$grid.attr('aria-activedescendant');

   if (e.ctrlKey) {
      this.showPrevYear();
   }
   else {
      this.showPrevMonth();
   }

   if (this.currentDate == false) {
      this.$grid.attr('aria-activedescendant', 'day1');
   }
   else {
      this.$grid.attr('aria-activedescendant', active);
   }

   e.stopPropagation();
   return false;

} // end handlePrevClick()

//
// handleNextClick() is a member function to process click events for the next month button
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handleNextClick = function(e) {

   var active = this.$grid.attr('aria-activedescendant');

   if (e.ctrlKey) {
      this.showNextYear();
   }
   else {
      this.showNextMonth();
   }

   if (this.currentDate == false) {
      this.$grid.attr('aria-activedescendant', 'day1');
   }
   else {
      this.$grid.attr('aria-activedescendant', active);
   }

   e.stopPropagation();
   return false;

} // end handleNextClick()

//
// handlePrevKeyDown() is a member function to process keydown events for the prev month button
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handlePrevKeyDown = function(e) {

   if (e.altKey) {
      return true;
   }

   switch (e.keyCode) {
      case this.keys.tab: {
         if (this.bModal == false || !e.shiftKey || e.ctrlKey) {
            return true;
         }

         this.$grid.focus();
         e.stopPropagation();
         return false;
      }
      case this.keys.enter:
      case this.keys.space: {
         if (e.shiftKey) {
            return true;
         }

         if (e.ctrlKey) {
            this.showPrevYear();
         }
         else {
            this.showPrevMonth();
         }

         e.stopPropagation();
         return false;
      }
   }

   return true;

} // end handlePrevKeyDown()

//
// handleNextKeyDown() is a member function to process keydown events for the next month button
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handleNextKeyDown = function(e) {

   if (e.altKey) {
      return true;
   }

   switch (e.keyCode) {
      case this.keys.enter:
      case this.keys.space: {

         if (e.ctrlKey) {
            this.showNextYear();
         }
         else {
            this.showNextMonth();
         }

         e.stopPropagation();
         return false;
      }
   }

   return true;

} // end handleNextKeyDown()

//
// handleGridKeyDown() is a member function to process keydown events for the datepicker grid
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handleGridKeyDown = function(e) {

      var $rows = this.$grid.find('tbody tr');
      var $curDay = $('#' + this.$grid.attr('aria-activedescendant'));
      var $days = this.$grid.find('td').not('.empty');
      var $curRow = $curDay.parent();

      if (e.altKey) {
         return true;
      }

      switch(e.keyCode) {
         case this.keys.tab: {

            if (this.bModal == true) {
               if (e.shiftKey) {
                  this.$next.focus();
               }
               else {
                  this.$prev.focus();
               }
               e.stopPropagation()
               return false;
            }
            break;
         }
         case this.keys.enter:
         case this.keys.space: {

            if (e.ctrlKey) {
               return true;
            }

            // update the target box
            this.$target.val((this.month < 9 ? '0' : '') + (this.month+1) + '/' + $curDay.html() + '/' + this.year);

            // fall through
         }
         case this.keys.esc: {
            // dismiss the dialog box
            this.hideDlg();
          
            e.stopPropagation();
            return false;
         }
         case this.keys.left: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            var dayIndex = $days.index($curDay) - 1;
            var $prevDay = null;

            if (dayIndex >= 0) {
               $prevDay = $days.eq(dayIndex);

               $curDay.removeClass('focus').attr('aria-selected', 'false');
               $prevDay.addClass('focus').attr('aria-selected', 'true');

               this.$grid.attr('aria-activedescendant', $prevDay.attr('id'));
            }
            else {
               this.showPrevMonth(0);
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.right: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            var dayIndex = $days.index($curDay) + 1;
            var $nextDay = null;

            if (dayIndex < $days.length) {
               $nextDay = $days.eq(dayIndex);
               $curDay.removeClass('focus').attr('aria-selected', 'false');
               $nextDay.addClass('focus').attr('aria-selected', 'true');

               this.$grid.attr('aria-activedescendant', $nextDay.attr('id'));
            }
            else {
               // move to the next month
               this.showNextMonth(1);
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.up: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            var dayIndex = $days.index($curDay) - 7;
            var $prevDay = null;

            if (dayIndex >= 0) {
               $prevDay = $days.eq(dayIndex);

               $curDay.removeClass('focus').attr('aria-selected', 'false');
               $prevDay.addClass('focus').attr('aria-selected', 'true');

               this.$grid.attr('aria-activedescendant', $prevDay.attr('id'));
            }
            else {
               // move to appropriate day in previous month
               dayIndex = 6 - $days.index($curDay);

               this.showPrevMonth(dayIndex);
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.down: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            var dayIndex = $days.index($curDay) + 7;
            var $prevDay = null;

            if (dayIndex < $days.length) {
               $prevDay = $days.eq(dayIndex);

               $curDay.removeClass('focus').attr('aria-selected', 'false');
               $prevDay.addClass('focus').attr('aria-selected', 'true');

               this.$grid.attr('aria-activedescendant', $prevDay.attr('id'));
            }
            else {
               // move to appropriate day in next month
               dayIndex = 8 - ($days.length - $days.index($curDay));

               this.showNextMonth(dayIndex);
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.pageup: {
            var active = this.$grid.attr('aria-activedescendant');


            if (e.shiftKey) {
               return true;
            }


            if (e.ctrlKey) {
               this.showPrevYear();
            }
            else {
               this.showPrevMonth();
            }

            if ($('#' + active).attr('id') == undefined) {
               var lastDay = 'day' + this.calcNumDays(this.year, this.month);
               $('#' + lastDay).addClass('focus').attr('aria-selected', 'true');
            }
            else {
               $('#' + active).addClass('focus').attr('aria-selected', 'true');
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.pagedown: {
            var active = this.$grid.attr('aria-activedescendant');


            if (e.shiftKey) {
               return true;
            }

            if (e.ctrlKey) {
               this.showNextYear();
            }
            else {
               this.showNextMonth();
            }

            if ($('#' + active).attr('id') == undefined) {
               var lastDay = 'day' + this.calcNumDays(this.year, this.month);
               $('#' + lastDay).addClass('focus').attr('aria-selected', 'true');
            }
            else {
               $('#' + active).addClass('focus').attr('aria-selected', 'true');
            }

            e.stopPropagation();
            return false;
         }
         case this.keys.home: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            $curDay.removeClass('focus').attr('aria-selected', 'false');

            $('#day1').addClass('focus').attr('aria-selected', 'true');

            this.$grid.attr('aria-activedescendant', 'day1');

            e.stopPropagation();
            return false;
         }
         case this.keys.end: {

            if (e.ctrlKey || e.shiftKey) {
               return true;
            }

            var lastDay = 'day' + this.calcNumDays(this.year, this.month);

            $curDay.removeClass('focus').attr('aria-selected', 'false');

            $('#' + lastDay).addClass('focus').attr('aria-selected', 'true');

            this.$grid.attr('aria-activedescendant', lastDay);

            e.stopPropagation();
            return false;
         }
      }

      return true;

} // end handleGridKeyDown()

//
// handleGridKeyPress() is a member function to consume keypress events for browsers that
// use keypress to scroll the screen and manipulate tabs
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handleGridKeyPress = function(e) {

      if (e.altKey) {
         return true;
      }

      switch(e.keyCode) {
         case this.keys.tab:
         case this.keys.enter:
         case this.keys.space:
         case this.keys.esc:
         case this.keys.left:
         case this.keys.right:
         case this.keys.up:
         case this.keys.down:
         case this.keys.pageup:
         case this.keys.pagedown:
         case this.keys.home:
         case this.keys.end: {
            e.stopPropagation();
            return false;
         }
      }

      return true;

} // end handleGridKeyPress()

//
// handleGridClick() is a member function to process mouse click events for the datepicker grid
//
// @input (id obj) e is the id of the object triggering the event
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) false if consuming event, true if propagating
//
datepicker.prototype.handleGridClick = function(id, e) {
   var $cell = $(id);

   if ($cell.is('.empty')) {
      return true;
   }

   this.$grid.find('.focus').removeClass('focus').attr('aria-selected', 'false');
   $cell.addClass('focus').attr('aria-selected', 'true');
   this.$grid.attr('aria-activedescendant', $cell.attr('id'));

   var $curDay = $('#' + this.$grid.attr('aria-activedescendant'));

   // update the target box
   this.$target.val((this.month < 9 ? '0' : '') + (this.month+1) + '/' + $curDay.html() + '/' + this.year);

   // dismiss the dialog box
   this.hideDlg();

   e.stopPropagation();
   return false;

} // end handleGridClick()

//
// handleGridFocus() is a member function to process focus events for the datepicker grid
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) true
//
datepicker.prototype.handleGridFocus = function(e) {
   var active = this.$grid.attr('aria-activedescendant');

   if ($('#' + active).attr('id') == undefined) {
      var lastDay = 'day' + this.calcNumDays(this.year, this.month);
      $('#' + lastDay).addClass('focus').attr('aria-selected', 'true');
   }
   else {
      $('#' + active).addClass('focus').attr('aria-selected', 'true');
   }

   return true;

} // end handleGridFocus()

//
// handleGridBlur() is a member function to process blur events for the datepicker grid
//
// @input (e obj) e is the event object associated with the event
//
// @return (boolean) true
//
datepicker.prototype.handleGridBlur = function(e) {
   $('#' + this.$grid.attr('aria-activedescendant')).removeClass('focus').attr('aria-selected', 'false');

   return true;

} // end handleGridBlur()

//
// showDlg() is a member function to show the datepicker and give it focus. This function is only called if
// the datepicker is used in modal dialog mode.
//
// @return N/A
//
datepicker.prototype.showDlg = function() {

   var thisObj = this;

  // Bind an event listener to the document to capture all mouse events to make dialog modal
  $(document).bind('click mousedown mouseup mousemove mouseover', function(e) {

    //ensure focus remains on the dialog
    thisObj.$grid.focus();

    // Consume all mouse events and do nothing
    e.stopPropagation;
    return false;
  });

   // show the dialog
   this.$id.attr('aria-hidden', 'false');

   this.$grid.focus();

} // end showDlg()

//
// hideDlg() is a member function to hide the datepicker and remove focus. This function is only called if
// the datepicker is used in modal dialog mode.
//
// @return N/A
//
datepicker.prototype.hideDlg = function() {

   var thisObj = this;

  // unbind the modal event sinks
  $(document).unbind('click mousedown mouseup mousemove mouseover');

   // hide the dialog
   this.$id.attr('aria-hidden', 'true');

   // set focus on the focus target
   this.$target.focus();

} // end showDlg()