jQuery

CSS/Javascript Calendar

Works with:
FF3
Safari
IE6
IE7
IE8
Chrome
Opera

Note: A bug has recently been fixed where the current day was not determined accurately. Please redownload the calendar if you have used it anywhere.

This project has recently been updated.
Now includes completely rewritten JavaScript that is more robust and reliable. Also, all PHP has been removed so it can be used as a standalone JavaScript application.

Description

This is a pure CSS/Javascript calendar. Hyperlinked dates, highlighted current day, accommodates for leap years, fully themable.

Demo

JavaScript

  1. //constants
  2. var days = new Array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday");
  3. var months = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
  4.  
  5. $(function() {
  6.     //global variables
  7.     var date = new Date();
  8.     var date_day = parseInt(date.getDate());
  9.     var date_month = parseInt(date.getMonth());
  10.     var date_year = parseInt(date.getFullYear());
  11.    
  12.     $.each($(".calendar"), function() {
  13.         //private variables
  14.         var current_date = $(this).find(".current_date a");
  15.         var current_day = $(this).find(".curr_day");
  16.         var current_month = $(this).find(".curr_month");
  17.         var current_year = $(this).find(".curr_year");
  18.        
  19.         var month_value = $(this).find(".month_value");
  20.         var year_value = $(this).find(".year");
  21.        
  22.         var month = $(this).find(".month");
  23.         var month_button = month.find(".option_button");
  24.         var month_options = month.find(".month_options");
  25.         var month_options_items = month_options.find("li a");
  26.        
  27.         var year_up = $(this).find(".increase_year");
  28.         var year_down = $(this).find(".decrease_year");
  29.        
  30.         var weeks_alldays = $(this).find(".weeks");
  31.         var weeksdays = weeks_alldays.find(".currMonthDay");
  32.        
  33.         //event - month_options
  34.         $(window).bind("click", function () {
  35.             month_options.slideUp("fast");
  36.         });
  37.  
  38.         month_button.live("click", function() {
  39.             month_options.slideToggle("fast");
  40.             return false;
  41.         });
  42.        
  43.         //event - select month
  44.         month_options_items.click(function() {
  45.             date_month = month_options_items.index(this);
  46.             month_options.slideUp("fast");
  47.             loadDate(date_month, date_year);
  48.             return false;
  49.         });
  50.        
  51.         //event - move year up
  52.         year_up.bind("click", function() {
  53.             date_year = date_year+1;
  54.             loadDate(date_month, date_year);
  55.             return false;
  56.         });
  57.        
  58.         //event - move year down
  59.         year_down.bind("click", function() {
  60.             date_year = date_year-1;
  61.             loadDate(date_month, date_year);
  62.             return false;
  63.         });
  64.        
  65.         //event - select current date
  66.         current_date.bind("click", function() {
  67.             date_day = parseInt(current_day.text());
  68.             date_month = parseInt(current_month.text())-1;
  69.             date_year = parseInt(current_year.text());
  70.            
  71.             loadDate(date_month, date_year);
  72.             return false;
  73.         });
  74.        
  75.         //event - select a day
  76.         weeksdays.live("click", function() {
  77.             var selectedDay = parseInt($(this).text());
  78.        
  79.             //formulate a date from the selected day
  80.             var selectedDate = new Date();
  81.            
  82.             selectedDate.setDate(selectedDay);
  83.             selectedDate.setMonth(date_month);
  84.             selectedDate.setFullYear(date_year);
  85.            
  86.             //just ouput a nicely formated date for now
  87.             var dayExt = getDateExt(selectedDay);
  88.            
  89.             var weekDayNum = parseInt(selectedDate.getDay())-1;
  90.             if (weekDayNum==-1) weekDayNum=6;
  91.            
  92.             var dayTitle = days[weekDayNum];
  93.             var monthTitle = months[date_month].substring(0,3); //nice short month
  94.  
  95.             alert("Selected: " + dayTitle + " " + $(this).text() + dayExt + " " + monthTitle + " " + date_year);
  96.        
  97.             return false;
  98.         });
  99.        
  100.         //START - load the defaults
  101.         current_day.text(date_day.toString());
  102.         current_month.text((date_month+1).toString());
  103.         current_year.text(date_year.toString());
  104.        
  105.         loadDate(date_month, date_year);
  106.        
  107.         //load a date into the calendar
  108.         function loadDate(date_month, date_year) {
  109.             var month_name = months[date_month];
  110.            
  111.             //set the titles
  112.             month_value.text(month_name);
  113.             year_value.text(date_year.toString());
  114.            
  115.             //set the selected month option
  116.             month_options.find(".current_month_option").removeClass("current_month_option");
  117.             month_options.find("li:contains(" + month_name + ")").addClass("current_month_option");
  118.            
  119.             //make an actual date out of the given day/month/year
  120.             var selectedDate = new Date();
  121.            
  122.             selectedDate.setDate(1); //get the first day of the selected month
  123.             selectedDate.setMonth(date_month);
  124.             selectedDate.setFullYear(date_year);
  125.            
  126.             //populate the days
  127.             var startDay = selectedDate.getDay()-1;
  128.             if (startDay==-1) startDay=6;
  129.            
  130.             var weekNum = 0, dayNum=0;
  131.             var numDaysThisMonth = getDaysInMonth(date_month, date_year);
  132.            
  133.             //note: do not need to consider overflow as jan and dec have same num days
  134.             var numDaysLastMonth = getDaysInMonth(date_month-1, date_year);
  135.            
  136.             //write out last month
  137.             var weekDaysStr="<div class=\"week\">";
  138.            
  139.             for (var monthNum=numDaysLastMonth-startDay+1; dayNum<startDay; dayNum++, monthNum++) {
  140.                 weekDaysStr += "<a>" + monthNum.toString() + "</a>";
  141.             }
  142.            
  143.             //write out this month
  144.             for (var monthNum=1; monthNum < (numDaysThisMonth+1); dayNum++, monthNum++) {
  145.                 if (dayNum%7 == 0) weekDaysStr += "</div><div class=\"week\">";
  146.                 weekDaysStr += "<a href=\"#\" class=\"currMonthDay\">" + monthNum.toString() + "</a>";
  147.             }
  148.            
  149.             //write out next month
  150.             for (var monthNum=1; dayNum<42; dayNum++, monthNum++) {
  151.                 if (dayNum%7 == 0) weekDaysStr += "</div><div class=\"week\">";
  152.                 weekDaysStr += "<a>" + monthNum.toString() + "</a>";
  153.             }
  154.             weekDaysStr += "</div>";
  155.            
  156.             weeks_alldays.html(weekDaysStr);
  157.            
  158.             //highlight the current day
  159.             weeks_alldays.find(".currDay").removeClass("currDay");
  160.             if ((date_month == parseInt(current_month.text())-1) && (date_year == parseInt(current_year.text()))) {
  161.                 $.each(weeks_alldays.find(".currMonthDay"), function() {
  162.                     if ($(this).text()==current_day.text()) {
  163.                         $(this).addClass("currDay");
  164.                         return;
  165.                     }
  166.                 });
  167.             }
  168.         }
  169.     });
  170. });
  171.  
  172. /**
  173. * Get number of days in a month
  174. * @param month::int (0-11)
  175. * @param year::int
  176. * @return number of days in month::int
  177. */
  178. function getDaysInMonth(month, year) {
  179.     var numDays = 31;
  180.    
  181.     switch (parseInt(month)) {
  182.         case 3: case 5: case 8: case 10:
  183.             numDays=30;
  184.             break;
  185.         case 1:
  186.             if (parseInt(year)%4==0) numDays=29; //compensate for leap years
  187.             else numDays = 28;
  188.             break;
  189.     }
  190.    
  191.     return numDays;
  192. }
  193.  
  194. /*
  195. * Get the extra 'st'/'nd','rd'/'th' extension on a given day
  196. * @param day number of month::int
  197. * @return extension::String
  198. */
  199. function getDateExt(day) {
  200.     //get the last character
  201.     var dayStr = day.toString();
  202.    
  203.     //exception: if second to last character is a 1, then is is definately 'th'
  204.     if ((dayStr.length>1) && (parseInt(dayStr[dayStr.length-2])==1))
  205.         return "th";
  206.    
  207.     //otherwise, decide from the last character
  208.     var lastChar = parseInt(dayStr[dayStr.length-1]);
  209.     var ext = "th";
  210.     switch (lastChar) {
  211.         case 1: ext="st"; break;
  212.         case 2: ext="nd"; break;
  213.         case 3: ext="rd"; break;
  214.     }
  215.     return ext;
  216. }

CSS

  1. .calendar {
  2.     border: 1px solid black;
  3.     display: block;
  4.     float: left;
  5.     font-family: Tahoma;
  6.     font-size: 90%;
  7.     margin-bottom: 10px;
  8.     background-color: white;
  9.     z-index: 50;
  10.     width: 170px;
  11. }
  12.  
  13. .calendar .current_date {
  14.     text-align: center;
  15.     background-color: #999999;
  16.     color: white;
  17.     padding: 10px;
  18.     border: 1px solid #CCCCCC;
  19.     font-size: 85%;
  20.     cursor: pointer;
  21.     line-height: 1em;
  22. }
  23. .calendar .current_date a {
  24.     color: white;
  25.     text-decoration: none;
  26. }
  27. .calendar .controls {
  28.     background-color: #DD4466;
  29.     border: 1px solid #BB2244;
  30.     z-index: 100;
  31.     height: 23px;
  32. }
  33. .calendar .month {
  34.     margin: 0px;
  35.     padding: 0px;
  36.     list-style: none;
  37.     display: block;
  38.     position: relative;
  39.     float: left;
  40.     z-index: 100;
  41.     color: black;
  42. }
  43. .calendar .month_options {
  44.     margin: 0px;
  45.     padding: 0px;
  46.     position: absolute;
  47.     list-style: none;
  48.     border: 1px #555555 solid;
  49.     background-color: white;
  50.     z-index: 100;
  51.     width: 80px;
  52.     top: 22px;
  53.     display: none;
  54.     max-height: 100px;
  55.     overflow: auto;
  56.     left: 0px;
  57. }
  58. .calendar .month_options a {
  59.     text-indent: 3px;
  60.     color: black;
  61.     background-color: white;
  62.     display: block;
  63.     height: 20px;
  64.     line-height: 20px;
  65.     text-decoration: none;
  66.     font-size: 85%;
  67.     outline: none;
  68.     z-index: 400;
  69. }
  70. .calendar .month_options .current_month_option a {
  71.     background-color: #FFDDEE;
  72.     color: #EE5577;
  73. }
  74. .calendar .month_options a:hover {
  75.     background-color: #EE5577;
  76.     color: white;
  77. }
  78. .calendar .month_value {
  79.     background-color: white;
  80.     display: block;
  81.     float: left;
  82.     border: 1px solid black;
  83.     border-right: none;
  84.     height: 1.3em;
  85.     position: relative;
  86.     height: 20px;
  87.     width: 60px;
  88.     line-height: 20px;
  89.     vertical-align: middle;
  90.     font-size: 85%;
  91.     text-indent: 4px;
  92. }
  93. .calendar .option_button {
  94.     position: relative;
  95.     border: 1px solid black;
  96.     float: left;
  97.     display: block;
  98.     height: 20px;
  99.     width: 20px;
  100.     line-height: 20px;
  101.     text-align: center;
  102.     vertical-align: middle;
  103.     text-decoration: none;
  104.     color: black;
  105.     cursor: pointer;
  106.     background: url("images/month_option.gif") white center center no-repeat;
  107. }
  108. .calendar .option_button:hover {
  109.     background-color: #CCCCCC;
  110.     color: white;
  111. }
  112. .calendar .year {
  113.     position: relative;
  114.     background-color: white;
  115.     margin: 0px;
  116.     padding: 0px;
  117.     color: black;
  118.     float: left;
  119.     height: 20px;
  120.     width: 40px;
  121.     border: 1px black solid;
  122.     line-height: 20px;
  123.     vertical-align: middle;
  124.     text-align: center;
  125.     font-size: 85%;
  126.     display: block;
  127.     margin-left: 3px;
  128. }
  129. .calendar .change_year {
  130.     width: 14px;
  131.     float: left;
  132.     display: block;
  133.     height: 20px;
  134. }
  135. .calendar .increase_year,
  136. .calendar .decrease_year {
  137.     cursor: pointer;
  138.     display: block;
  139.     float: left;
  140.     height: 9px;
  141.     width: 12px;
  142.     background-color: white;
  143.     color: black;
  144.     text-decoration: none;
  145.     border: 1px solid black;
  146.     text-align: center;
  147.     vertical-align: middle;
  148.     line-height: 9px;
  149.     border-left: none;
  150.     outline: none;
  151.     background-position: center center;
  152.     background-repeat: no-repeat;
  153. }
  154. .calendar .increase_year span,
  155. .calendar .decrease_year span,
  156. .calendar .option_button span{
  157.     visibility: hidden;
  158. }
  159. .calendar .increase_year {
  160.     height: 10px;
  161.     border-bottom: none;
  162.     background-image: url("images/increase_year.gif");
  163. }
  164. .calendar .decrease_year {
  165.     background-image: url("images/decrease_year.gif");
  166. }
  167. .calendar .increase_year:hover,
  168. .calendar .decrease_year:hover {
  169.     background-color: #CCCCCC;
  170.     color: white;
  171. }
  172.  
  173. .calendar .week_titles span,
  174. .calendar .week a {
  175.     display: inline-block;
  176.     width: 20px;
  177.     height: 20px;
  178.     vertical-align: middle;
  179.     line-height: 20px;
  180.     text-align: center;
  181.     margin: 1px;
  182.     text-decoration: none;
  183.     font-size: 95%;
  184. }
  185.  
  186. .calendar .week_titles span {
  187.     border: 1px white solid;
  188. }
  189.  
  190. .calendar .week a {
  191.     border: 1px white solid;
  192.     background-color: #EEEEEE;
  193.     color: #BBBBBB;
  194. }
  195.  
  196. .calendar .week a.currMonthDay {
  197.     border: 1px solid #666666;
  198.     background-color: #EEEEEE;
  199.     color: black;
  200. }
  201.  
  202. .calendar .week a.currMonthDay:hover {
  203.     background-color: #EE5577;
  204.     color: white;
  205. }
  206.  
  207. .calendar .week a.currDay {
  208.     border: 1px #EE5577 solid;
  209.     background-color: #FFDDEE;
  210.     color: #EE5577;
  211. }
  212.  
  213. .calendar .week a.currDay:hover {
  214.     background-color: #EE5577;
  215.     color: white;
  216. }
  217.  
  218. .calendar .weeks {
  219.     display: block;
  220.     width: auto;
  221. }

XHTML

  1. <div class="calendar">
  2.     <div class="current_date">
  3.         <a href="#" title="Click here to go to today">Today: <span class="curr_day"></span>/<span class="curr_month"></span>/<span class="curr_year"></span></a>
  4.     </div>
  5.    
  6.     <div class="controls">
  7.         <ul class="month">
  8.             <li><span class="month_value"></span><a class="option_button" href="#" title="Change the month"><span>&#x25BC;</span></a>
  9.                 <ul class="month_options">
  10.                     <li><a href="#" title="Select the month January">January</a></li>
  11.                     <li><a href="#" title="Select the month February">February</a></li>
  12.                     <li><a href="#" title="Select the month March">March</a></li>
  13.                     <li><a href="#" title="Select the month April">April</a></li>
  14.                     <li><a href="#" title="Select the month May">May</a></li>
  15.                     <li><a href="#" title="Select the month June">June</a></li>
  16.                     <li><a href="#" title="Select the month July">July</a></li>
  17.                     <li><a href="#" title="Select the month August">August</a></li>
  18.                     <li><a href="#" title="Select the month September">September</a></li>
  19.                     <li><a href="#" title="Select the month October">October</a></li>
  20.                     <li><a href="#" title="Select the month November">November</a></li>
  21.                     <li><a href="#" title="Select the month December">December</a></li>
  22.                 </ul>
  23.             </li>
  24.         </ul>
  25.        
  26.         <div class="year"></div>
  27.         <div class="change_year">
  28.             <a class="increase_year" href="#" title="Increase the year"><span>&#x25B4;</span></a>
  29.             <a class="decrease_year" href="#" title="Decrease the year"><span>&#x25BE;</span></a>
  30.         </div>
  31.     </div>
  32.    
  33.     <div class="week_titles"><span title="Monday">Mon</span><span title="Tuesday">Tue</span><span title="Wednesday">Wed</span><span title="Thursday">Thu</span><span title="Friday">Fri</span><span title="Saturday">Sat</span><span title="Sunday">Sun</span></div>
  34.     <div class="weeks">
  35.     </div>
  36. </div>