jQuery Birthday Picker Form Plugin
I recently had a need to create a form where somebody entered their birthday and decided it would be a good idea to explore various ways of solving this. I essentially had the following requirements:
- Make the data entry as easy as possible
- Do as many validations as I could on the client side
- Use jQuery
Date’s are always tricky for people to enter into forms and the best solution really depends on the situation. Birthdays present their own unique features:
- You always know the exact date you’re entering
- The date is always in the past, and often many years in the past
Because of this a common date picker such as the jQuery Datepicker, which works great for things like airline reservations, isn’t quite as suited for choosing a birthday. Instead most people end up creating an empty text field and adding validation to it, either on the client, on the server, or both (I strongly recommend both).
<form id="myForm" method="post"> <input id="birthday" name="birthday" type="text" /> <input type="submit" value="submit" /> </form>
This is where something like the jQuery Validation plugin comes in really handy. With very little effort you can ask it to ensure a valid date is entered.
$("#myForm").validate({
rules: {
birthday: {
required: true,
date: true
}
}
});
This is a pretty easy solution, and probably sufficient in almost all cases. If you go this route I would suggest adding a placeholder to the input field to show the user a sample date in the format you’re expecting.
<input id="birthday" name="birthday" placeholder="10/17/1980" type="text" />
However if you want to be especially picky, this solution does allow invalid birthdays because you can enter a future date.
So I decided to continue my search to see how other people had solved this. The first place I looked was Facebook, and behold, they had their own implementation. If you’re interested you can have a look at their homepage (you must be signed out). The basic markup is as follows (with slight modifications and option menus omitted):
<select name="birthday[month]"></select> <select name="birthday[day]"></select> <select name="birthday[year]"></select>
I think if you were a user interaction purist you’d quickly find the faults with this solution. It requires three different fields, all of which are dropdowns, ugghh! That being said, it does have some things going for it. The format is forced which means the user should almost always get it right on the first try. It also allows you to restrict the date range which can solve the future date issue.
So I decided I might give Facebook’s implementation a try and quickly realized it is not without some complexity. For it to be worth anything it requires that the dropdown menus dynamically update themselves in the following ways:
- The number of days in the day select menu should reflect the chosen month
- The number of days in February should account for leap years
- The dropdowns should selectively reset to prevent display of an invalid date
After giving it some thought, I decided this would be a good opportunity for me to learn how to write a jQuery plugin to mimic this implementation. While writing the plugin I decided it would be fun to add some additional options which are all outlined on the plugin page, github, and the demo page. But as a quick guide to how it works, you can make the following call on any block element in the page:
$("div#birthday-picker").birthdaypicker();
By default this will generate the following markup (with option menus of course):
<fieldset class="birthday-picker"> <select class="birth-year" name="birth[year]"></select> <select class="birth-month" name="birth[month]"></select> <select class="birth-day" name="birth[day]"></select> </fieldset>
I believe that I’ve solved the requirements I listed above. And, as mentioned, there are a number of options that give the plugin some flexibility, both in the range of dates it will support, and the markup it will generate. I think there are still many ways it could be improved, but I’m going to hold off on those until/unless people ask for them.
As a final thought, this is probably not the best solution. In fact I would lean toward using the basic text field with client side form validation. However I have to assume that Facebook takes a critical look at their usability, and since they’re still using this implementation it must be working. Post in comments if there are any implementations that you particularly like. I’d love to find more.
I updated the plugin to include support for a default date. I also added a hidden text field called “birthdate” that gets updated as the select lists change. This single date field is easier to handle on the server.
Please visit the Github repository for the latest discussion on this plugin. There you can clone the repo and submit fixes. Cheers!
I'm a software guy. Find out more on the
How do you grab the value of the generated form in jquery … thanks.
I’m not sure what you mean by the value of the generated form. You can grab the value of any of the select fields using jQuery. Using the example I cover in the post you could get the value of the birth-year with the following:
$("div#birthday-picker select.birth-year").val();It is a great and timely plugin!!
I have one question: How can handle validation, did I have to use the jQuery Validation plugin? Thank you!
You shouldn’t have to do validation because the drop down menus force the user to enter valid dates (see example). If you want to create a specific date format from the fields (i.e. ISO 8601) you’d have to write code either on the client or server to do that.
Thanks!
As I can see, if a user enters an “invalid” date (“Day”, “5″, “2001″ or “Day”, “Month”, “Year”) on a form create action, the form is refreshed without displaying any error message. (like this field is required) [note: I set prompt value (month, day...) to nil (""). if I do not, I'll get an error on assignment of multiparameter attributes (I use rails)]
Validate date is really painful in rails so I wonder if there is a way to do this with jquery (but i am not a js guy..). maybe with the jQuery Validation plugin? I would be pleased to get your thought!
You could extend the plugin to force the user to select a date before moving to the next field in the form. However I would probably assign the validation checks to the form “submit” event. This might look like the following:
$(“#myForm”).submit(function(e){
// do some validations
if( $(“div#birthday-picker select.birth-year”).val() == ’0′ ) { return false; }
}
You could also use the validation plugin for this but it would probably be easier to just write your own logic unless you have a really complex form.
Am I missing something or is there no way to enter a default date?
Otherwise excellent plugin.
I just updated the plugin to support a default date and a hidden date field to make server side processing easier. Let me know if you run into any issues.
@Soc I just updated the plugin to support a default date and a hidden date field to make server side processing easier. Let me know if you run into any issues.
Abe, small question, say we have a form with two “birthday picker” dates, typical for a “from” “to” type of form such as when you need to enter periods of time.
Would that generate any issues of having both several fields with the same name?. I know I could place them under enclosing divs and pinpoint them through selectors, but perhaps a parameter like dateName for the hidden would be a good addition.
Best regards,
Willie
Hey Abe,
We started using Birthday picker plugin. It is working fine in all the browsers except IE. We tested in IE7 and IE8. The issue is that it is not showing up the dynamically added options in the day select box. Below are the steps to reproduce the issue
1. Select Feb and select a day, say 28
2. Select Jan
Now in the day dropdown only 28 days are visible even though 31 days are present in the dom. We tried cloning the select box and appending, then selecting the day stopped working.
It is failing to hide the days as well. To reproduce that we need to first select some date in Jan and then select Feb. 31 days will show up.
Can you please suggest some fixes?
Thanks,
Rema.
hey boss,
your plugins great…
I’m developing a website using ASP.Net, and i’m using your plugin for the birthdate, but I encountered a problem for editing the birthdate using you plugin, Im a newbie to JavaScript btw,
here’s the problem:
on editing, a user clicks on his profile and he wishes to edit his birthday, the birthday is then queried from the database, Im using a textbox in the page as a sort of buffer for the birthday, but it is hidden from the user. so now my question would be, how do i set the default date of the plugin to be the same as the value the user has inputted upon registration,
thanks
jacques
I too checked its not working well in IE7,8.
I fixed it.
@Rema
http://anandwebtech.wordpress.com/2011/09/02/jquery-birthday-picker-facebook-type/
@Rema and @anand I believe I’ve fixed the bugs that were showing up in IE7 and IE8. Let me know if you still see those.
@abecoffman – I’m using the latest release of the bday-picker.min.js, however, I’m getting null in IE7 and IE8 instead of it passing the birthdate to the hidden field. It works great in all other browers. Is ther something I’m missing? Maybe an IE hack somewher?
Thanks
Many thanks for a very useful plugin! Here’s one small idea for the next version: support for tabindexes (set for the first select, e.g. birthday-year, and computed for other ones). Sure it was easy to add them thru attr(), but native support would be even cooler.
usefull plugin, i came across problems with the hidden input that would not change his value, but when i submit the form it has the correct value, so there’s no biggie
I had tried using the plugin but I can’t make it display any dates and I don’t really understand the part about option_hash. Anyone willing to teach me? =/
Hey! I had tried your plugin, it is cool but whenever I tried to pass the value into database, it shows undefined. Any solution?
Great plugin!
I’m trying to use it and it works fine for me.
However i had some reports from people from different timezones that it does not display propper date for them when feed with custom default date. It shows the previous day.
So if they enter 2001-02-05 save the form and come back to it later the form is feed with 2001-02-05 but displays 2001-02-04… if they enter 2001-01-01 then after coming back they get 2000-12-31.
Date gets properly stored in the database and properly retrieves. I’m not experiencing that myself, but some of the testers are.
Does any of you have any idea what might be causing that? AFAIK I’m not doing any date-arythmetics where timezone might mess things up.
Great plugin but ‘defaultDate’ doesn’t work in Firefox 3.6 or Firefox 5. any idea how to fix?
forget that… looks like I suffer from code dyslexia
Hey boss, this is a great plugin, we ran in to a little bit of hiccup though, we’re using it for our registration page, when the user submits the registration and logout and come back to the registration page again, the dd’s are not set to their placeholder value and still showing the date that the user previously entered but the hidden selects shows the placeholders as currently selected.
Ignore my above post, someone else wrote a code that’s doing this, again great plugin!
This code works great… on desktop browsers. For whatever reason it doesn’t work on iphone though. Both my local test code and your demo page do not fill in default dates.
Haven’t pulled out the android phone yet to check that.
FYI, the problem with safari mobile is in the date format. It doesn’t accept the hyphen in new Date(). If you change defaultDate to slashes (2012/01/06) and hiddenDate line 92 to
hiddenDate = defYear + “/” + defMonth + “/” + defDay;
then it works fine.
Was attempting to utilize your nice plugin when I noticed a few things.
First if you attempt to select February you should be able to select the 29th day until the year is selected which it then should revert the day back to default ‘Day:’ if a non-leap year is selected.
While testing the above it appears if you select “Feb” then “28″ then “2012″ the month list reverts back to “Month:” with the only selectable option in month being just “Jan”. Wiping out all of the other months. The quick fix for this was to set minAge not equal to 0.
i am trying out your code and it always returns the months as the value 8 in the hidden field.
Also is it possible to append the date and month value with a 0 if lesson than 10 so 9 would become 09 in the hidden field?
This is a great script, thank you for creating it. Have you ever integrated it within WordPress
or have any experience in doing that?
I am trying to use it for a plugin in WordPress and I cannot get it to work, does this look correct for loading the script in the plugin in the admin_init action hook.
$pluginfolder = plugins_url();
wp_enqueue_script(‘jquery’);
wp_enqueue_script(‘jquery-ui-core’);
wp_enqueue_script(‘bday-picker’, $pluginfolder . ‘/bday-picker.js’, array(‘jquery’, ‘jquery-ui-core’) );
Ok… I got it working…problem was my path to the js file ($pluginfolder) nothing to see here!
$pluginfolder = $pluginfolder = plugins_url() . ‘/’ . dirname(plugin_basename(__FILE__));
wp_enqueue_script(‘jquery’);
wp_enqueue_script(‘jquery-ui-core’);
wp_enqueue_script(‘bday-picker’, $pluginfolder . ‘/bday-picker.js’, array(‘jquery’) );
how could get the jquery file?
I generally like the idea but this plugin is really bad if you consider accessibility and progressive enhancement. By starting your HTML with a div instead of real form fields means there is nothing to fall back to when JavaScript is disabled which will make the whole form useless.
As I said, the idea is good but it needs to be usable even without JS.
Birthday Picker is not the right name. Birthdays don’t have years. “Hey, when is your birthday?” “My birthday is May 1st”. See?
Date of Birth has a year. “What is your date of birth?” “May 1, 1980″. That has a year.
Hi, i was using your plugin in one of my websotes. It great! Thanks!!
I realized that it have a minor bug. If you use the decompressed version, if you set the default date, look at line 117:
var date = new Date(settings["defaultDate"] + “T00:00:00″);
There is a “T” that causes the var date and invalid date!.
Well, thanks for your job, it’s was very helpful!!
Oh, and sorry for my bad english =P
I’ve noticed a few issues with the way the defaultDate is handled in this script. Specifically on some versions of Chrome and FireFox if a defaultDate is provided as YYYY-MM-DD then the pull down for day will be one day off. So if given 1977-3-4 as the input then the date will be set as “Mar 3 1977″ instead of “Mar 4 1977″. It also doesn’t seem to work in some versions of Safari at all – defDate remains undefined even after being set as a date object built off of defaultDate +t00:00:00.
@Jason
I did some tests on giving this different date formats in different browsers to try and find one that worked in all of them. The only way I was able to get it to work reliably in all browsers I had available to test was to remove the +”T00:00:00″ bits. Once those were removed I got much more consistent results with more date formats in more browsers. But it still seems JS is very unreliable for converting dates from strings into date objects.
Hi all, I am closing the comments here. Please see the github site for future discussion and fixes.
birthdaypicker plugin