Dynamic Calendar For Forms
Some forms have 3 or more dropdown lists to select a date. Others provide a calendar to choose a date.
Clicking on a date in a calendar generally is easier than selecting a date from 3 dropdowns - day, month, and year.
This article contains code and instructions for publishing a calendar with a date form field. The month and year of the calendar can be changed until the correct date is found.
Clicking on the date fills in the form field. The form field is read-only. Choosing a date with the calendar is required to fill in or change the form field.
after page
completes loading.]
Here is a live example of a dynamic calendar to use for filling the read-only form field with a date.
A calendar for the previous or next month, or for the month in the previous or next year, can be displayed by clicking on the «, <, >, or » characters.
When a date in the calendar is clicked, the form field is filled in. The field can be changed only by using the calendar.
The formatting for the date in the form field is specified in the JavaScript. I'll address that and other options further below.
The source code for a basic installation of the calendar is copy and paste with one change: The id value in the date form field needs to match the value specified in the JavaScript.
That's all it takes for a basic working installation.
Optionally, there are many different ways the calendar may be styled.
Installing a Working Example
Here is the code for a complete working example web page. Copy the source code, save it as calendartest.html, and load it into your browser. No edits necessary.
<html> <head> <title>Working Example Dynamic Calendar For Forms</title> <!-- The CSS definitions for the calendar. --> <style type="text/css"> .cal_table { background-color:beige; } .cal_box { padding:3px; } .cal_dow { font-family:verdana,sans-serif; font-size:11px; font-weight:bold; text-align:center; } .cal_num { font-family:verdana,sans-serif; font-size:12px; font-weight:normal; text-align:right; } .cal_monyear { line-height:18px; font-family:verdana,sans-serif; font-size:11px; font-weight:bold; text-align:center; } .cal_nextchar { line-height:18px; font-family:verdana,sans-serif; font-size:14px; } .cal_nextlink { text-decoration:none; } .cal_numlink { text-decoration:none; } </style> </head> <body> <div style="margin:50px 0 50px 200px; width:500px;"> <h1> Working Example Dynamic Calendar For Forms </h1> <p> Clicking on the date fills in the form field. The form field is read-only. Choosing a date with the calendar is required to fill in or change the form field. </p> <!-- This is the div within which the calendar gets published. --> <div id="calspot" style="width:187px; height:214px; background-color:transparent; float:right; margin-left:10px;"> </div> <p> Here is a live example of a dynamic calendar to use for filling the read-only form field with a date. </p> <form> <p style="margin:0; font-weight:bold;"> Use calendar to select date: </p> <!-- This is the date form field that will contain the chosen date. --> <input type="text" id="datevalue" style="color:#333; width:260px; font-size:15px; font-weight:bold; border:solid 1px #666; background-color: #CCC;" readonly="readonly" /> </form> <script type="text/javascript"> /* Dynamic Calendar For Forms Version 1.0 May 15, 2010 Will Bontrager https://www.willmaster.com/ Copyright 2010 Bontrager Connection, LLC Bontrager Connection, LLC grants you a royalty free license to use or modify this software provided this notice appears on all copies. This software is provided "AS IS," without a warranty of any kind. */ // // Five sections to customize: // Section 1 -- // Specify the id value of the div to contain the calendar. var CalDivID = "calspot"; // Section 2 -- // Specify the id value of the form field to contain the // selected date. var DateContainerID = "datevalue"; // Section 3 -- // Specify the template of the date when it is inserted // into the form field. The following symbols can br // used as placeholders: // ~Y~ = Year // ~M~ = Month number // ~MS~ = Month spelled out // ~D~ = Day of the month // ~WS~ = Day of the week spelled out var DateFormatTemplate = "~WS~, ~MS~ ~D~, ~Y~"; // Section 4 -- // Specify the source code of images or characters for // previous/next month/year symbols. var PreviousMonthSymbol = "<"; var PreviousYearSymbol = "«"; var NextMonthSymbol = ">"; var NextYearSymbol = "»"; // Section 5 -- // If your preferred language is other than English, or if // you prefer abbreviations, change the month and weekday // names accordingly. MonthNames = new Array("January","February","March", "April","May","June", "July","August","September", "October","November","December"); WeekdayNames = new Array("Sunday","Monday","Tuesday", "Wednesday","Thursday", "Friday","Saturday"); // // No other customization required in this JavaScript. // function NumDaysInMonth(month,year) { if( month == 1 ) { return (new Date("Feb 29, "+year).getMonth()===1) ? 29 : 28; } if( month == 3 || month == 5 || month == 8 || month == 10 ) { return 30; } return 31; } // function NumDaysInMonth() function MakeMonthCalendar(thismonth,thisyear) { var start = new Date(MonthNames[thismonth]+" 1, "+thisyear); var maxrownum = 6; var calarray = new Array(); for( var i=0; i<=maxrownum; i++ ) { calarray[i] = new Array(); } calarray[0][0] = 'S'; calarray[0][1] = 'M'; calarray[0][2] = 'T'; calarray[0][3] = 'W'; calarray[0][4] = 'T'; calarray[0][5] = 'F'; calarray[0][6] = 'S'; var limit = start.getDay(); for( var i=0; i<=limit; i++ ) { calarray[1][i] = ' '; } var lastday = NumDaysInMonth(start.getMonth(),start.getFullYear()); var nowrownum = 1; var indice = limit; for( var i=1; i<=lastday; i++ ) { calarray[nowrownum][indice] = i; indice++; if( indice > 6 && i < lastday ) { indice = 0; nowrownum++; } } for( var i=indice; i<=6; i++) { calarray[nowrownum][i] = ''; } var cal = new String; cal += '<table class="cal_table" border="1" cellpadding="2" cellspacing="0">'; cal += '<tr><td colspan="7">'; cal += '<table width="100%" border="0" cellpadding="0" cellspacing="0">'; cal += '<tr><td class="cal_nextchar"><a href="javascript:getPrevYear('+thismonth+','+thisyear+')" class="cal_nextlink">'+PreviousYearSymbol+'</a> <a href="javascript:getPrevMonth('+thismonth+','+thisyear+')" class="cal_nextlink">'+PreviousMonthSymbol+'</a></td>'; cal += '<td class="cal_monyear">'+MonthNames[start.getMonth()]+' '+start.getFullYear()+'</td>'; cal += '<td align="right" class="cal_nextchar"><a href="javascript:getNextMonth('+thismonth+','+thisyear+')" class="cal_nextlink">'+NextMonthSymbol+'</a> <a href="javascript:getNextYear('+thismonth+','+thisyear+')" class="cal_nextlink">'+NextYearSymbol+'</a></td></tr>'; cal += '</table>'; cal += '</td></tr>'; var i = 0; cal += '<tr>'; for( var ii=0; ii<=6; ii++ ) { cal += '<td class="cal_box cal_dow">'+calarray[i][ii]+'</td>'; } cal += '</tr>'; for( var i=1; i<=nowrownum; i++ ) { cal += '<tr>'; for( var ii=0; ii<=6; ii++ ) { cal += '<td class="cal_box cal_num">'; cal += (parseInt(calarray[i][ii])>0) ? '<a href="javascript:DateSelected('+calarray[i][ii]+','+thismonth+','+thisyear+')" class="cal_numlink">'+calarray[i][ii]+'</a>' : ' '; cal += '</td>'; } cal += '</tr>'; } cal += '</table>'; return cal; } // function MakeMonthCalendar() function PublishCalendar(id,month,year) { document.getElementById(id).innerHTML = MakeMonthCalendar(month,year); } function getPrevMonth(month,year) { month--; if( month < 0 ) { month = 11; year--; } PublishCalendar(CalDivID,month,year); } // function getPrevMonth() function getPrevYear(month,year) { year--; PublishCalendar(CalDivID,month,year); } // function getPrevYear() function getNextMonth(month,year) { month++; if( month > 11 ) { month = 0; year++; } PublishCalendar(CalDivID,month,year); } // function getNextMonth() function getNextYear(month,year) { year++; PublishCalendar(CalDivID,month,year); } // function getNextYear() function DateSelected(day,month,year) { var fieldval = DateFormatTemplate.replace("~Y~",year); fieldval = fieldval.replace("~M~",(month+1)); fieldval = fieldval.replace("~MS~",MonthNames[month]); fieldval = fieldval.replace("~D~",day); fieldval = fieldval.replace("~WS~",WeekdayNames[(new Date(MonthNames[month]+" "+day+", "+year).getDay())]); document.getElementById(DateContainerID).value = fieldval; } // function DateSelected() function PublishCurrentCalendar() { today = new Date(); start = new Date(MonthNames[today.getMonth()]+', 1 '+today.getFullYear()); PublishCalendar(CalDivID,start.getMonth(),start.getFullYear()); } // function PublishCurrentCalendar() function AppendOnloadEvent(f) { var cache = window.onload; if(typeof window.onload != 'function') { window.onload = f; } else { window.onload = function() { if (cache) { cache(); } f(); }; } } // function AppendOnloadEvent() AppendOnloadEvent(PublishCurrentCalendar); </script> <p> A calendar for the previous or next month, or for the month in the previous or next year, can be displayed by clicking on the «, <, >, or » characters. </p> <p> When a date in the calendar is clicked, the form field is filled in. The field can be changed only by using the calendar. </p> </body> </html>
One use for the working example is for making changes here and there to see what the effects are. Things to play with:
-
The CSS styles in the head area of the example web page source code.
-
The inline style of the div within which the calendar is published.
-
The customizable values in the JavaScript.
-
The inline style of the form field where the chosen date is inserted.
Have fun with it. If you mess up, grab another copy from the above text box and start over.
Installing Dynamic Calendar For Your Form
Three blocks of source code need to be put on the web page with your form.
-
The CSS style.
-
The div within which the calendar is to be published.
-
The JavaScript.
Then, the id value of the date form field needs to match the corresponding variable in the JavaScript.
The instructions —
1. The CSS style. Paste this CSS style into the web page source code. The head area is preferred, generally, but it will also work pasted in the body area somewhere above the form.
<style type="text/css"> .cal_table { background-color:beige; } .cal_box { padding:3px; } .cal_dow { font-family:verdana,sans-serif; font-size:11px; font-weight:bold; text-align:center; } .cal_num { font-family:verdana,sans-serif; font-size:12px; font-weight:normal; text-align:right; } .cal_monyear { line-height:18px; font-family:verdana,sans-serif; font-size:11px; font-weight:bold; text-align:center; } .cal_nextchar { line-height:18px; font-family:verdana,sans-serif; font-size:14px; } .cal_nextlink { text-decoration:none; } .cal_numlink { text-decoration:none; } </style>
2. The div within which the calendar is to be published. Position the calendar div in your form where the form users can use it. Here is the div's source code. (The div has no content in this source code because JavaScript inserts the calendar.)
<div id="calspot" style="width:187px; height:214px; background-color:transparent; float:right; margin-left:10px;"> </div>
3. The JavaScript. Paste this JavaScript somewhere in the body area of the source code. It can be above or below the form.
<script type="text/javascript"> /* Dynamic Calendar For Forms Version 1.0 May 15, 2010 Will Bontrager https://www.willmaster.com/ Copyright 2010 Bontrager Connection, LLC Bontrager Connection, LLC grants you a royalty free license to use or modify this software provided this notice appears on all copies. This software is provided "AS IS," without a warranty of any kind. */ // // Five sections to customize: // Section 1 -- // Specify the id value of the div to contain the calendar. var CalDivID = "calspot"; // Section 2 -- // Specify the id value of the form field to contain the // selected date. var DateContainerID = "datevalue"; // Section 3 -- // Specify the template of the date when it is inserted // into the form field. The following symbols can br // used as placeholders: // ~Y~ = Year // ~M~ = Month number // ~MS~ = Month spelled out // ~D~ = Day of the month // ~WS~ = Day of the week spelled out var DateFormatTemplate = "~WS~, ~MS~ ~D~, ~Y~"; // Section 4 -- // Specify the source code of images or characters for // previous/next month/year symbols. var PreviousMonthSymbol = "<"; var PreviousYearSymbol = "«"; var NextMonthSymbol = ">"; var NextYearSymbol = "»"; // Section 5 -- // If your preferred language is other than English, or if // you prefer abbreviations, change the month and weekday // names accordingly. MonthNames = new Array("January","February","March", "April","May","June", "July","August","September", "October","November","December"); WeekdayNames = new Array("Sunday","Monday","Tuesday", "Wednesday","Thursday", "Friday","Saturday"); // // No other customization required in this JavaScript. // function NumDaysInMonth(month,year) { if( month == 1 ) { return (new Date("Feb 29, "+year).getMonth()===1) ? 29 : 28; } if( month == 3 || month == 5 || month == 8 || month == 10 ) { return 30; } return 31; } // function NumDaysInMonth() function MakeMonthCalendar(thismonth,thisyear) { var start = new Date(MonthNames[thismonth]+" 1, "+thisyear); var maxrownum = 6; var calarray = new Array(); for( var i=0; i<=maxrownum; i++ ) { calarray[i] = new Array(); } calarray[0][0] = 'S'; calarray[0][1] = 'M'; calarray[0][2] = 'T'; calarray[0][3] = 'W'; calarray[0][4] = 'T'; calarray[0][5] = 'F'; calarray[0][6] = 'S'; var limit = start.getDay(); for( var i=0; i<=limit; i++ ) { calarray[1][i] = ' '; } var lastday = NumDaysInMonth(start.getMonth(),start.getFullYear()); var nowrownum = 1; var indice = limit; for( var i=1; i<=lastday; i++ ) { calarray[nowrownum][indice] = i; indice++; if( indice > 6 && i < lastday ) { indice = 0; nowrownum++; } } for( var i=indice; i<=6; i++) { calarray[nowrownum][i] = ''; } var cal = new String; cal += '<table class="cal_table" border="1" cellpadding="2" cellspacing="0">'; cal += '<tr><td colspan="7">'; cal += '<table width="100%" border="0" cellpadding="0" cellspacing="0">'; cal += '<tr><td class="cal_nextchar"><a href="javascript:getPrevYear('+thismonth+','+thisyear+')" class="cal_nextlink">'+PreviousYearSymbol+'</a> <a href="javascript:getPrevMonth('+thismonth+','+thisyear+')" class="cal_nextlink">'+PreviousMonthSymbol+'</a></td>'; cal += '<td class="cal_monyear">'+MonthNames[start.getMonth()]+' '+start.getFullYear()+'</td>'; cal += '<td align="right" class="cal_nextchar"><a href="javascript:getNextMonth('+thismonth+','+thisyear+')" class="cal_nextlink">'+NextMonthSymbol+'</a> <a href="javascript:getNextYear('+thismonth+','+thisyear+')" class="cal_nextlink">'+NextYearSymbol+'</a></td></tr>'; cal += '</table>'; cal += '</td></tr>'; var i = 0; cal += '<tr>'; for( var ii=0; ii<=6; ii++ ) { cal += '<td class="cal_box cal_dow">'+calarray[i][ii]+'</td>'; } cal += '</tr>'; for( var i=1; i<=nowrownum; i++ ) { cal += '<tr>'; for( var ii=0; ii<=6; ii++ ) { cal += '<td class="cal_box cal_num">'; cal += (parseInt(calarray[i][ii])>0) ? '<a href="javascript:DateSelected('+calarray[i][ii]+','+thismonth+','+thisyear+')" class="cal_numlink">'+calarray[i][ii]+'</a>' : ' '; cal += '</td>'; } cal += '</tr>'; } cal += '</table>'; return cal; } // function MakeMonthCalendar() function PublishCalendar(id,month,year) { document.getElementById(id).innerHTML = MakeMonthCalendar(month,year); } function getPrevMonth(month,year) { month--; if( month < 0 ) { month = 11; year--; } PublishCalendar(CalDivID,month,year); } // function getPrevMonth() function getPrevYear(month,year) { year--; PublishCalendar(CalDivID,month,year); } // function getPrevYear() function getNextMonth(month,year) { month++; if( month > 11 ) { month = 0; year++; } PublishCalendar(CalDivID,month,year); } // function getNextMonth() function getNextYear(month,year) { year++; PublishCalendar(CalDivID,month,year); } // function getNextYear() function DateSelected(day,month,year) { var fieldval = DateFormatTemplate.replace("~Y~",year); fieldval = fieldval.replace("~M~",(month+1)); fieldval = fieldval.replace("~MS~",MonthNames[month]); fieldval = fieldval.replace("~D~",day); fieldval = fieldval.replace("~WS~",WeekdayNames[(new Date(MonthNames[month]+" "+day+", "+year).getDay())]); document.getElementById(DateContainerID).value = fieldval; } // function DateSelected() function PublishCurrentCalendar() { today = new Date(); start = new Date(MonthNames[today.getMonth()]+', 1 '+today.getFullYear()); PublishCalendar(CalDivID,start.getMonth(),start.getFullYear()); } // function PublishCurrentCalendar() function AppendOnloadEvent(f) { var cache = window.onload; if(typeof window.onload != 'function') { window.onload = f; } else { window.onload = function() { if (cache) { cache(); } f(); }; } } // function AppendOnloadEvent() AppendOnloadEvent(PublishCurrentCalendar); </script>
~ The id value. The id value of the date form field needs to correspond to the value specified in the JavaScript.
If the date form field currently has no id value, give it this attribute:
id="calspot"
Otherwise, specify the date form field's id value in the first place of the JavaScript's customization section, at variable CalDivID.
When the id value in the date form field matches the id value in the JavaScript variable, installation is complete.
Test the form and the calendar to verify they work as they should. Then, if you wish, you may customize the calendar or the style of the date form field.
Customizing The Dynamic Calendar
All customization is optional.
-
The CSS styles define the calendar's visual design. Change them as desired.
-
The inline style of the div within which the calendar is published can be changed.
-
The JavaScript has customization sections that affect various aspects of the dynamic calendar, including the text/image icons and the format of the date inserted into the form field.
-
The form field where the chosen date is inserted can be custom designed with an inline style.
The CSS styles —
The CSS definitions used in the calendar may be changed. Here is a table of CSS class names the calendar uses.
Class name | Description | cal_table | Specified in the <table...> tag. Style for the table as a whole. |
---|---|
cal_box | Style for the table cells. |
ccal_monyear | Style for the month and year text at the top of the calendar. | cal_nextchar | Style for the table cell containing the characters/images serving as previous/next month/year icons. (The JavaScript has a place to specify the characters and/or images to use as icons.) |
cal_nextlink | Style for the previous/next month/year icon links. |
cal_dow | Style for the table cell containing the characters representing the days of the week. |
cal_num | Style for the table cell containing the month date numbers in the calendar. |
cal_numlink | Style for the month date number links. |
The div within which the calendar is published —
If the id value of the div is changed, the value of the corresponding variable (CalDivID) in the JavaScript must also be changed.
All inline styles in the div may be changed. Any may be removed. Others may be added. A class may be defined in a style sheet to be used instead of or in addition to the inline styles.
If the CSS style is changed, the calendar size may change.
In that case, the inline width and height style of the div within which the calendar is published may need to change. If the width and height styles are missing or specify a dimension less than the calendar, the rest of the content on the page may shift around as different calendar months are displayed.
To determine the maximum width (if there is any width difference from month to month), display a calendar of the month of September. That's the widest calendar because it is the longest month name. Use that width as the width style for the div.
To determine the maximum height, find a calendar month that uses 6 rows of numbers for the days. That will be the highest calendar. Use that height as the height style for the div.
Customizable values in the JavaScript —
The JavaScript has 5 sections that may be customized.
-
The id value of the div within which the calendar is published.
-
The id value of the date form field.
-
The template for formatting the date inserted into the form field.
The template uses certain symbols for inserting the real-time value of the weekday, month, day, and year. The month may be a number or spelled out.
The JavaScript contains the symbols. The template value in the JavaScript when it is downloaded from this article is an example of use.
-
The text/image to be used for the previous/net month/year icons.
A value is specified for each of the four symbols. When the JavaScript is downloaded from this article, the values are:
Previous Year. The left angle quotation
mark: « ("«") Previous Month. The left angle bracket, less-than
symbol: < ("<") Next Month. The right angle bracket, greater-than
symbol: > (">") Next Year. The right angle quotation
mark: » ("»")
The icons can be changed to any characters or image. If image, specify the entire image tag. Example:
var NextYearSymbol = "<img src='myimage.gif' width='10' height='10'>";
-
If you prefer abbreviations for weekday or month names, or if your preferred written language is other than English, change the month and weekday names accordingly.
The form field where the chosen date is inserted —
If the id value of the date form field is changed, the value of the corresponding variable (DateContainerID) in the JavaScript must also be changed.
All inline styles in the date form field may be changed. Any may be removed. Others may be added. A class may be defined in a style sheet to be used instead of or in addition to the inline styles.
The readonly attribute prevents the form user from changing the date form field except by choosing a date with the calendar. To allow the user to make changes directly to the form field, remove the readonly attribute.
The readonly attribute looks like this.
readonly="readonly"
The Dynamic Calendar For Forms
The dynamic calendar is fairly easy to install. It provides for lots of optional customization, including non-English weekday and month names.
The calendar is embedded in the web page.
The calendar month changes when a previous or next month or year icon is clicked.
When a calendar day is clicked on, the chosen date is inserted into a date form field. The date can be formatted in a seemingly infinite number of ways.
Will Bontrager