JavaScript date chooser

Download date-chooser v1.1

I wrote this date chooser because the ones I could find on the Internet were crummy, too complicated, or not free. The point is to make form entry more usable and help the user enter valid data (of course, you still need to validate your input when processing). I also wanted to code to be compact and fast, and not require a bunch of ugly code injected into the web page.

I made a demo so you can see it in action.

This code uses some code from my article about date formatting and parsing via dynamic code generation, to implement a date-formatting syntax similar to PHP’s date function.

The script depends upon date-functions.js, datechooser.js, select-free.css, and datechooser.css.

How to use it

To create a date-chooser on your HTML document, follow these steps:

  1. Include the CSS and JavaScript files in the head of your document.
  2. Wrap select-free.css in a conditional comment for IE, as in the demo.
  3. Create a form, a div to hold the date chooser, a form field to hold the results, and an image to trigger showing and hiding the chooser, as below.

Here’s some sample code:

<input id="dob" name="dob" size="10" maxlength="10" type="text"/><img src="/files/calendar.gif" onclick="showChooser(this, 'dob', 'chooserSpan', 1950, 2010, 'Y-m-d', false);"/>
<div id="chooserSpan" class="dateChooser select-free" style="display: none; visibility: hidden; width: 160px;">
</div>

This code causes the date chooser to be shown with a date range of 1950 to 2010, with the date formatted in ISO-8601 date format.

Updates

On May 26 2006, I decided I could no longer procrastinate and integrated many of the helpful suggestions from the comments into the code. Thanks to all who wrote in comments suggesting improvements, and a big thanks to Jared for integrating a bunch of code for me and sending me a comment about it. Changes include a fix for the IE problem of select fields showing through, no conflicts with the Prototype library, and a cleaner show/hide behavior.

Technorati Tags:No Tags

You might also like:

  1. Javascript date parsing and formatting, Part 2
  2. JavaScript combo box
  3. Announcement: Xaprb scripts are re-licensed
  4. JavaScript date parsing and formatting, Part 1
  5. JavaScript formatting library update

52 Responses to “JavaScript date chooser”


  1. 1 Geoff Whittington

    Great JavaScript!

    Worked perfectly right off the bat! You’re right - it was SO hard to find something useful and elegant until I saw yours.

    Thanks again!

  2. 2 air

    Thanks for a great DateChooser, I use it and modified it for my own needs. As I often need to choose months nearby, I added some buttons to step to the previous / next month. If someone wants to try it, here is what you need:

    Change row number 178 in datechooser.js from:

    var formHtml = "
    // Creates the extra HTML for monthStepper.
    DateChooser.prototype.createMonthStepperHtml = function() {
    	var result = "  "
        	+ "' onclick=\""
        	+ "if(document.forms[0]." + this._prefix + "month.selectedIndex != 11){"
    	+ "document.forms[0]."+ this._prefix + "month.selectedIndex++;"
    	+ "dateChooserDateChange(this.form, '"+ this._prefix + "');"
    	+ "}else{"
    	+ "document.forms[0]." + this._prefix + "year.selectedIndex++;"
    	+ "document.forms[0]." + this._prefix + "month.selectedIndex = 0;"
    	+ "dateChooserDateChange(this.form, '"+ this._prefix + "');"
    	+ "}\">"
    	return result;
    }

    [ED: It looks like some of the code might have gotten zapped by the comment form. I gotta fix that so people can submit comments with code in them. I think the idea comes through though. Thanks air!

  3. 3 Anonymous

    Here is the code correcting the previous post. I suppose it can be written more ‘elegant’. Though it works :)

    DateChooser.prototype.createChooserHtml = function() {
        var formHtml = ""
            + "rn  "
            +"<a>&lt;&lt;”
            +”";
        for (var mon in Date.monthNames) {
            formHtml += “rn    ” + Date.monthNames[mon] + “”;
        }
        formHtml += “rn  rn  “;
        for (var i = this._start; i ” + i + “”;
        }
        formHtml += “rn  rn”
            +”<a>&gt;&gt;</a>rn”;
        formHtml += this.createCalendarHtml();
        if (this._isTimeChooser) {
            formHtml += this.createTimeChooserHtml();
        }
        return formHtml;
    }

    Enjoy!

  4. 4 Mike

    Thanks for sharing this great little tool with us.

  5. 5 Jay Johnston

    SELECT CAUSES PROBLEM IN IE (FIX?)

    Note that I really needed to use this for an internal intranet site but the necessary iframe code was, of course, missing.

    Using some code from http://www.hedgerwow.com/360/bugs/css-select-free.html I altered the second to last line of datechooser.js:

        return result + "rn  </tr>rn</table><!--[if lte IE
    6.5]><iframe></iframe><![endif]-->";

    Note you will need (1) to add the class ’select-free’ to the dateChooser div and (2) add the following css style definition for the iframe to fix the select options from bleeding through:

    .select-free
    {
    	position:absolute;
    	z-index:10;
    	cursor:hand;
    	overflow:hidden;/*must have*/
    	width:33em;/*must have for any value*/;
    
    }
    .select-free iframe
    {
    	display:none;/*sorry for IE5*/
    	display/**/:block;/*sorry for IE5*/
    	position:absolute;/*must have*/
    	top:0;/*must have*/
    	left:0;/*must have*/
    	z-index:-1;/*must have*/
    	filter:mask();/*must have*/
    	width:3000px;/*must have for any big value*/
    	height:3000px/*must have for any big value*/;
    }

    Thank you so much, your open source code is clean and brief. I hope this small contribution can serve as my portion of payment for your work!

    Jay

  6. 6 Kim

    Excellent little script. I love the variety of ways that the date text is returned as well.. THANK YOU!!!!

  7. 7 Ben

    This is a great script. Thanks for posting it!

  8. 8 Jared

    I noticed that the onChange event was not being fired by this script when the date was changed. As I had other JS code watching for when the date value changed, I inserted this single line:

    input.onchange();

    I put it immediately after the input value changes, so lines 61-63 of function dateChooserSetDate() in datechooser.js look like this:

    input.value = input.DateChooser.getValue();
    input.onchange();
    input.DateChooser.hide();

    Hope that helps someone.

  9. 9 NixerX

    Excellent work! Thank you very much. Rarely do scripts work “out of the box” for both IE and FF. Kudos to you my friend.

    -nX

  10. 10 Sam

    Any chance you could LGPL this? It’s a nice piece of work, but I can’t use it with the GPL license.

  11. 11 Xaprb

    Sam, that’s a great suggestion. I have always GPL’ed everything I’ve let other people have, without much further thought, but now that I’m writing re-usable components and libraries that’s not the best idea. I will re-license this and all the other scripts I’ve released, and announce it when I’m done. Subscribe via feed or email to be notified when I do that (should be this weekend).

  12. 12 vericgar

    The code to position the div does not seem to work correctly if used with fieldsets.

  13. 13 Xaprb

    I use it with fieldsets all the time, so there must be something else that’s conflicting as well. Perhaps the combination of fieldsets and something else? If you can take a page that has a problem, and trim everything out until you have as small a test case as possible that demonstrates the problem, I’d appreciate it. You can email me directly at .

  14. 14 Sean

    Great script! I love it!

    Has anyone, or does anyone know if, I can modify this so only weekdays are selectable? I’m sure it’s easy. But I can’t find it for the life of me. Thanks in advance!

    Sean

  15. 15 Deepak

    Awesome… I only know one other guy who did this. How do you guys do it! Amazing!

  16. 16 francis

    Hello, nice calendar:) I seem to have a problem when placing them side by side. The calendar shows too far the right.

  17. 17 Vince

    I’m glad that you make this script as it is very useful. However, I find some problems. The code

    Must be enclosed inside a form, or else it does not refresh the calendar when the pulldown menu is changed. And I discovered another interesting bug (which almost made me kill myself :P). Consider the following code:

    Notice that the form tag is inside the table tag.This works just fine with IE. However, if you’re using Opera / Firefox, the calendar doesn’t refresh when the pulldown menu is changed. Interestingly, if the form tag is moved outside the table tag it’ll work just fine. I cannot fix them as I am not really that familiar with JavaScript and I don’t have the time to learn at the moment. I would really appreciate if you can mail me the solution to fix these problems.

    Cheers,

    Vince

  18. 18 Zach

    I’ve encapsulated your date chooser into an ASP .NET 2.0 User Control if you are interested. Your javascript provided the foundation for one of the best Date Choosers I’ve seen to date, so I just wanted to make it available for any .Netters who may want such a capable control. Please email me if you would like me to email you the source for your posting.

  19. 19 Xaprb

    Vince, sorry the blog software deleted your code segments :-( However, I have these comments in reply: a form control must always be enclosed inside a FORM element according to the HTML 4 spec, and placing the form directly inside a TABLE element is also invalid HTML 4. These may help you solve your problems. Also, it may help to use a validator — the Web Developer extension for Firefox has one, and there is also a HTML Tidy extension that may be more convenient; and Opera has a right-click option (or used to) to validate the page too. Browsers are beginning to be pickier about valid HTML, which I think is great.

    I hope that helps!

  20. 20 Xaprb

    Hi Francis, it sounds like you may be having a problem with floating elements stacking next to each other. Can you make a test case and post it somewhere, then post another comment with a link to it?

  21. 21 joucek

    Fix for the positioning problem reported by vericgar:

    DateChooser.prototype.show = function() {
        // calculate the position before making it visible
        var inputPos = getAbsolutePosition(this._input);
    
        // JV 20060724 Fix where _div was not positioned correctly when rendered inside another absolutely positioned div
        this._div.style.top = (inputPos[0] + this._input.offsetHeight - parseInt(this._div.offsetParent.style.top)) + "px";
        this._div.style.left = (inputPos[1] + this._input.offsetWidth - parseInt(this._div.offsetParent.style.left)) + "px";

    I found that when you use the datechooser within another absolutely positioned div, the code

    _div.style.left = X

    has the _div actually display itself at X + the parent div’s left. This resolved the problem for me.

  22. 22 Austin

    Hmm, it still seems as if I am having a problem getting the “selection field” to show up in IE still.

    I think I tried to follow the instructions, but I’m having trouble getting it to work.

    I’m new to CSS and JS so this is a little difficult for me.

    Thank you.

  23. 23 joucek

    Positioning problem afterburner:

    On my previous post, I provided code that seemed to solve the positioning problem for the date-time chooser popup. However, when testing in other context and with other browser, this code failed. Now I’ve solved it in another way by changing the getAbsolutePosition function as follows :

    // Gets the absolute position on the page of the element passed in
    function getAbsolutePosition(obj) {
        var result = [0, 0];
        // JV 15082006 : stop at first absolutely positioned element
        while ((obj != null)&&(obj.style.position != 'absolute')) {
           result[0] += obj.offsetTop;
           result[1] += obj.offsetLeft;
           obj = obj.offsetParent;
       }

    This now seems to do the job for me - at least, the popup now show up where you expect it independent of the page structures I’ve tested and identically between IE and FF.

  24. 24 Kaa

    Zach, if Xaprb isn’t interested, I certainly am. Let me know if the offer is still available. It’ll keep me from reinventing several wheels. My email is [deleted].

  25. 25 Xaprb

    Kaa, Zach never followed through, sorry. I was very interested and offered to bundle it all together, and we had some emails about it. I’ll ping him back again and see if he’s still willing to put it together.

  26. 26 Tim

    Excellent.

  27. 27 bhadresh

    Hi,

    This is very good control.

    How do I show date control as is? Without a need of clicking on image icon.

    Thanks

  28. 28 bhadresh

    Can it be used in Inline calendar mode? The calendar is displayed on the page as part of its design. The example illustrates it use as a popup. It needs click on image.

  29. 29 Xaprb

    You could with some modification. I have neglected this script for quite a while, but you can look for me to put more time into it in the next couple of articles. There are several problems — it is not independent of other elements on the page, its CSS isn’t well-separated from other elements, it assumes you’ll want a pop-up, it makes global JavaScript variables and functions, etc etc. I am going to put some time into that and remedy it, if for no other reason than we need it at work and it’s not working well because of CSS conflicts.

  30. 30 Ugo

    Many thanks for a very functional script.

    Regards

    Ugo

  31. 31 martinlubpl

    great job. i’m gonna use it.

  32. 32 Lars Olesen

    Great script. However, perhaps you should consider making it completely unobtrusive. The span container needed could be written in by the dom, as could the image - and then you could hook the script up on a input-field with a class=”date-field”, and the title attribute could contain the format for the response from the calender.

  33. 33 Xaprb

    Yep, I’ve been meaning to do that. That, and move everything into a Xaprb namespace to avoid conflicts with other scripts. I’ve learned a lot since I banged this out a few years ago.

  34. 34 Michael

    Very nice! This is something I needed yet did not know how to create from scratch.
    Would it be very difficult to put a little “x” in the top right corner so that the user could close the calendar (say if they are just looking at it or otherwise don’t click on a date)?

  35. 35 Xaprb

    Not too hard I think, but I’m still struggling to get time to rewrite this. Right now I’m in the middle of a rewrite of innotop, which I consider more important.

  36. 36 rowan

    Hi-

    first off- brilliant calendar script! really has helped me a lot. I have a question tho- i’ve put the script alteration in above that’s supposed to fix the positioning problem but it doesn’t seem to work.

    I have 2 layers going on (including the datechooser) and it seems to take the positioning from the containing layer even if I put another layer in between. Consequently, the chooser opens up miles away from the image.

    I don’t know enough about JavaScript to know where the problem is- could anyone help out?

  37. 37 wizzie

    Great script buddy I’ve looked everywhere but I couldnt get anything close to what you’ve done, congrats. I tried modifying the demo above to suit my use which is pretty much similar to what is done in the demo. However I wasnt successful so I tried the exact script as that for the demo and it didnt work. The image click is not triggering the pop-up response. Can you please advise me on how i can work around this. Thank you

  38. 38 Xaprb

    I’m sorry, I simply don’t have time to work on this at the moment, and probably won’t for months… I hope someone else can jump in and make some improvements to this script, including fixing some CSS and positioning bugs (or at least advising people how to solve it themselves in some common situations), making more options for how to show and hide the chooser, and using unobtrusive Javascript.

  39. 39 Tom Nazelli

    Thank you for this wonderful script!

    I found that the following 2 enhancements to the showChooser() script have made this a little easier. If the date chooser is showing, clicking in the document outside of the chooser, or on a subsequent chooser icon should cause the chooser to hide. This script causes this behavior. see comments below…

    function showChooser(obj, inputId, divId, start, end, format, isTimeChooser) {
        if (document.getElementById) {
            var input = document.getElementById(inputId);
            var div = document.getElementById(divId);
            if (input !== undefined && div !== undefined) {
                if (input.DateChooser === undefined) {
                    input.DateChooser = new DateChooser(input, div, start, end, format, isTimeChooser);
                }
                input.DateChooser.setDate(Date.parseDate(input.value, format));
                if (input.DateChooser.isVisible()) {
                    input.DateChooser.hide();
                }
                else {
                    input.DateChooser.show();
                }
                input.focus();// add this line
                input.onblur=function(){this.DateChooser.hide();} // and this line too
            }
        }
    }
  40. 40 Tom Gallagher

    This script is awesome, thank you. Just to let you know the iframe tag datechooser.js causes a security warning if used on an https domain. I attempted to get around this by setting up a dummy src for the iframe, but it did not work so I just dropped support for IE 6.5. Let me know if you have any solution for this, I played around with it for awhile and couldn’t come up with anything

  41. 41 BigG010

    I know I saw a couple post asking about this…didn’t see a response. I too noticed the bug with using the drop downs to change the month and year. Apparently IE dies if you add the form tag in there….and all the other GOOD browser need it to work. so here is what I did to fix it.

    Here is the link for the browser detect if anyone needs it.
    http://www.quirksmode.org/js/detect.html

    Hope this helps.

    DateChooser.prototype.createChooserHtml = function() {
    	var browserName = BrowserDetect.browser;
        var formHtml = "";
    	if(browserName != "Explorer")
    		formHtml += "<form id='dateChooserForm'>";
    	formHtml += "<input type="hidden" name=""
            + this._prefix + "inputId" value=""
            + this._input.getAttribute('id') + "">"
    
    	formHtml += "rn  <select name="" + this._prefix
            + "month" onChange="dateChooserDateChange(this.form, '"
            + this._prefix + "');">";
        for (var mon in Date.monthNames) {
    		// Patch: 2007-03-29, Need to test mon to be an integer since monthNames contain added functions from the prototype.js script
    		var mon_int = parseInt(mon);
    		if(mon_int == mon-0)
    		{
    			formHtml += "rn    <option value="" + mon + """
    				+ (mon == this._date.getMonth() ? " selected="1"" : "")
    				+ ">" + Date.monthNames[mon] + "</option>";
    		}
        }
    	formHtml += "rn  </select>rn";
    	//var formHtml += "rn  <select name="" + this._prefix
        //    + "month" onChange="dateChooserDateChange(this.form, '"
        //    + this._prefix + "');">";
        //for (var mon in Date.monthNames) {
        //    formHtml += "rn    <option value="" + mon + """
        //        + (mon == this._date.getMonth() ? " selected="1"" : "")
        //        + ">" + Date.monthNames[mon] + "</option>";
        //}
        //formHtml += "rn  </select>rn";
    
    	formHtml += "<select name=""
            + this._prefix + "year" onChange="dateChooserDateChange(this.form, '"
            + this._prefix + "');">";
        for (var i = this._start; i <= this._end; ++i) {
            formHtml += "rn    <option value="" + i + """
                + (i == this._date.getFullYear() ? " selected="1"" : "")
                + ">" + i + "</option>";
        }
        formHtml += "rn  </select>";
        formHtml += this.createCalendarHtml();
        if (this._isTimeChooser) {
            formHtml += this.createTimeChooserHtml();
        }
    	if(browserName != "Explorer")
    		formHtml += "</form>";
    
        return formHtml;
    }
  42. 42 reche

    Your script is fantastic. I’m in Brazil. Thanks!

  43. 43 Danje

    Hi guys,

    Not sure if this is possible to fix, but I have hit upon a problem using this script. I have the demo code placed within a div that has this CSS tag assigned to it:

    #main-copy {
    color: black;
    background-color: white;
    margin: auto;
    padding: 0.5mm 5mm 5mm 5mm;
    min-height: 479px;
    border: 1px solid #000;
    width: 200px;
    }

    * html #main-copy {
    height: 479px;
    position: relative;
    left: -3px;
    }

    Firefox and IE7 display the popup exactly underneath the small calendar.gif whereas in IE6, the popup jumps along way to the right and below it! The only thing that seems to stop this behaviour is removing the position: relative, and left: -3px styles, but i would ideally like to keep these. Is there an easy way around this? Many thanks,

    Dan

  44. 44 george

    Thank you so much, that code very useful and easy to use

  45. 45 Matt Foster

    What if the user has an arbitrary amount of date fields that they wish to enable this date chooser behavior. And given that they have no way to implement explicit IDs for each date field. Due to the nature of passing HTML with embedded onclick events this prevents any kind of DOM oriented implementations. I was really hoping to get away with passing the showChooser method actual elements instead of just their IDs and have it run that way. but the method createCalendarHtml completely fubars that approach.

  46. 46 Xaprb

    I totally hear you. I’d write it differently now if I were to do it over again. If you fix this issue, please send your changes to me.

  47. 47 Antonio

    This script is fantastic. Congratulations!!

    – always looking for simple code –

  48. 48 avarus

    excellent.

  49. 49 Jonathan

    It seems that in the demo the nice mouse-over “navy” background in FF is not seen in IE. I have created a workaround for this:

    1) Added a fake link in datechooser.js (line 258 or so):
    result = “\r\n ” “  ” i ” ” “”;

    2) Added following css code in datechooser.css:

    a.test123 {
    .color:black;
    .text-decoration:none;
    }
    a.test123:hover {
    .background:navy;
    }

    Hope this helps someone who had struggles like me with IE.

    -Jonathan

  50. 50 Jonathan

    I was trying to add a bug fix but it seems not taking it.

    If I make a link out of “i” in line 260 of datechooser.js, I am able to add a css class to datechooser.css file. Then I will be able to see the nice mouse-over background in IE just as in FF.

  51. 51 Arun

    Thanks for this tool, it was very helpful!

  52. 52 Charu Ab

    I wish to use the \DateChooser with the calender and time choice. However, I do not want the time to be the current time, though the date is ok shown as hte current date in case no date is supplied. However, I do nto want time ot be chosen as the current time.
    I cannot get it to work around.
    The idea being the user may choose only date or both date and time. The default time is not appropriate for this.

    Can anyone give any ideas?

Leave a Reply

Please do not use this blog to get help with problems or bugs in Maatkit or innotop: use the Sourceforge forums, mailing list, or bug trackers. If you're asking for help with MySQL, please use the MySQL mailing list instead. I'm writing a book and my time is extremely limited :-)