Update Select Elements On The Fly
In the previous post,’Create Dynamic Date Selects‘, we ended up with select lists for the Month, Day and Year. In this post, we’ll make these more intuitive by only displaying the correct number of days for a given month/year combination; for example, choosing February on a leap year should produce 29 days to pick from.
The PHP from the previous post produces html like below (a truncated version).
<body> <form action="myform.php" method="post"> <select name="month" id="month"> <option value="1">January</option> <option value="2">February</option> <option value="3">March</option> <option value="4">April</option> <option value="5">May</option> <option value="6">June</option> <option value="7">July</option> <option value="8">August</option> <option value="9" selected="selected">September</option> <option value="10">October</option> <option value="11">November</option> <option value="12">December</option> </select> <select name="day" id="day"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4" selected="selected">4</option> <option value="5">5</option> <option value="6">6</option> <!-- other days here... --> <option value="31">31</option> </select> <select name="year" id="year"> <!--previous years here... --> <option value="2004">2004</option> <option value="2005">2005</option> <option value="2006">2006</option> <option value="2007">2007</option> <option value="2008">2008</option> <option value="2009" selected="selected">2009</option> </select> </form>
The respective select elements have ids that we’ll use in our JavaScript to target them. Before we start to manipulate the selects, let’s take a look at a piece of JavaScript that forms the basis of this script.
daysInMonth()
function daysInMonth(month,year) { return 32 - new Date(year,month, 32).getDate(); }
Although only a small function, it is rather clever. In essense we are asking for a date ‘32 June 2007′ for example. Obviously no month has 32 days so the Date object moves into the next month. In our example, ‘32 June 2007′ would become ‘2 July 2007′. We extract the day number (2) using the getDate() function and then subtract that from 32, giving us 30 (the number of days in the month we originally put in to the function, June). The Date object also takes care of accounting for leap years too
Now that we have that snippet out of the way, let’s start to build our function to change the ‘days’ select element on the fly.
changeDaySelect()
var selectedMonth = document.getElementById('month').value; var selectedYear = document.getElementById('year').value; var dayselect = document.getElementById('day');
The first three lines identify the select elements on the page. We put the values of the month and year selects into variables, ’selectedMonth’ and ’selectedYear’ and identify the ‘days’ select element as ‘dayselect’.
Next we store the currently selected day. Because the days are numbered 1-31 and the selectedIndex starts at 0, we need to add one to this value to get the right day.
var selectedDay = dayselect.selectedIndex + 1;
Following that, we find out how many days are in the selected month using our daysInMonth function. Note that we subtract 1 from the value of selectedMonth to get the correct month; our months have values from 1-12 but JavaScript counts months from 0-11. We also input the selectedYear variable.
var numdays = daysInMonth((selectedMonth - 1),selectedYear);
Next we clear any existing ‘options’ from the ‘days’ select element…
dayselect.options.length = 0;
…and then recreate them according the value of ‘numdays’ in a for loop.
for (var i = 1; i <= numdays; i++) { if (i == selectedDay) { dayselect.options[dayselect.options.length]=new Option(i, i, false, true); } else { dayselect.options[dayselect.options.length]=new Option(i, i, false, false); } }
You’ll see that we’re using ‘new Option()’. This takes four parameters, ‘text’, ‘value’,'defaultSelected’ and ’selected’. In the for loop, we change the ’selected’ parameter to ‘true’ for the option that matches our ’selectedDay’ variable.
And that’s about it. Putting the function together gives you this:
function changeDaySelect() { var selectedMonth = document.getElementById('month').value; var selectedYear = document.getElementById('year').value; var dayselect = document.getElementById('day'); var selectedDay = dayselect.selectedIndex + 1; var numdays = daysInMonth((selectedMonth - 1),selectedYear); dayselect.options.length = 0; for (var i = 1; i <= numdays; i++) { if (i == selectedDay) { dayselect.options[dayselect.options.length]=new Option(i, i, false, true); } else { dayselect.options[dayselect.options.length]=new Option(i, i, false, false); } } }
We want to call this function when the page loads and using the ‘onchange’ event for the month or year select elements.
window.onload = function() { changeDaySelect(); document.getElementById('month').onchange = function(evt) {changeDaySelect()}; document.getElementById('year').onchange = function(evt) {changeDaySelect()}; }
The complete JavaScript should look like the following:
window.onload = function() { changeDaySelect(); document.getElementById('month').onchange = function(evt) {changeDaySelect()}; document.getElementById('year').onchange = function(evt) {changeDaySelect()}; } function daysInMonth(month,year) { return 32 - new Date(year,month, 32).getDate(); } function changeDaySelect() { var selectedMonth = document.getElementById('month').value; var selectedYear = document.getElementById('year').value; var dayselect = document.getElementById('day'); var selectedDay = dayselect.selectedIndex + 1; var numdays = daysInMonth((selectedMonth - 1),selectedYear); dayselect.options.length = 0; for (var i = 1; i <= numdays; i++) { if (i == selectedDay) { dayselect.options[dayselect.options.length]=new Option(i, i, false, true); } else { dayselect.options[dayselect.options.length]=new Option(i, i, false, false); } } }
Save that as whatever you like and link to it from your ‘index.php’. You can check out a working example here


I read yesterday’s and enjoyed it a lot and today was just as good
Thanks Ben.
Hi Ben,
Cool little function (daysInMonth) and had no idea that JS counts months from 0.
Thanks
Thanks Mihai and Jack,
Welcome to the blog
New to .js
New to drop lists
EXACTLY what I needed!
My hero!
Thanks for sharing.