jQuery Birthday Picker Form Plugin

February 28th, 2011 | Tags: , , | Links: github, plugin, examples

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 pagegithub, 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.

Update: March 21, 2011Birthday Picker Version 1.2 Released

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.

Update: July 30, 2012Moved to Github

Please visit the Github repository for the latest discussion on this plugin. There you can clone the repo and submit fixes. Cheers!

  1. Passerby
    March 2nd, 2011 at 11:40
    Reply | Quote | #1

    How do you grab the value of the generated form in jquery … thanks.

  2. March 3rd, 2011 at 08:21
    Reply | Quote | #2

    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();

  3. Ben
    March 8th, 2011 at 22:07
    Reply | Quote | #3

    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!

  4. March 8th, 2011 at 22:54
    Reply | Quote | #4

    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.

  5. Ben
    March 9th, 2011 at 14:42
    Reply | Quote | #5

    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!

  6. March 11th, 2011 at 03:34
    Reply | Quote | #6

    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.

  7. Soc
    March 21st, 2011 at 17:27
    Reply | Quote | #7

    Am I missing something or is there no way to enter a default date?

    Otherwise excellent plugin.

  8. March 22nd, 2011 at 06:17
    Reply | Quote | #8

    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.

  9. abecoffman
    March 23rd, 2011 at 05:33
    Reply | Quote | #9

    @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.

  10. Willie
    June 21st, 2011 at 19:47

    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

  11. August 11th, 2011 at 11:39

    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.

  12. August 19th, 2011 at 10:50

    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

  13. anand
    September 2nd, 2011 at 02:46

    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/

  14. abecoffman
    September 15th, 2011 at 03:05

    @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.

  15. James
    September 16th, 2011 at 19:42

    @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

  16. pjj
    October 7th, 2011 at 16:04

    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.

  17. October 11th, 2011 at 07:57

    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

  18. Jolline
    October 13th, 2011 at 08:21

    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? =/

  19. Jolline
    October 14th, 2011 at 03:13

    Hey! I had tried your plugin, it is cool but whenever I tried to pass the value into database, it shows undefined. Any solution?

  20. October 23rd, 2011 at 10:04

    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.

  21. Peter
    November 7th, 2011 at 22:33

    Great plugin but ‘defaultDate’ doesn’t work in Firefox 3.6 or Firefox 5. any idea how to fix?

  22. Peter
    November 10th, 2011 at 16:17

    forget that… looks like I suffer from code dyslexia 🙂

  23. Jerico
    November 21st, 2011 at 15:28

    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.

  24. Jerico
    November 21st, 2011 at 15:41

    Ignore my above post, someone else wrote a code that’s doing this, again great plugin!

  25. Mike
    January 6th, 2012 at 03:03

    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.

  26. Mike
    January 6th, 2012 at 14:06

    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.

  27. Chris
    January 13th, 2012 at 18:07

    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.

  28. ian
    February 8th, 2012 at 18:24

    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?

  29. Alex
    March 7th, 2012 at 22:00

    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’) );

  30. Alex
    March 7th, 2012 at 22:39

    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’) );

  31. jotheeswaran
    April 17th, 2012 at 04:06

    how could get the jquery file?

  32. April 24th, 2012 at 14:33

    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.

  33. Neil
    June 26th, 2012 at 06:17

    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.

  34. July 11th, 2012 at 14:21

    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

  35. Jason
    July 24th, 2012 at 22:01

    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.

  36. Jason
    July 24th, 2012 at 23:11

    @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.

  37. abecoffman
    July 30th, 2012 at 18:18

    Hi all, I am closing the comments here. Please see the github site for future discussion and fixes.

    birthdaypicker plugin

Comments are closed.