Update: Date Range Picker with jQuery UI

Posted by Scott on 10/24/2008

Topics:

01/05/2009 Note: This script is built for an old version of jQuery UI (v1.5.3). We have updated it to work with the new jQuery UI and posted a new article detailing its changes. To read the article and download the script, visit Date Range Picker using jQuery UI 1.6 and jQuery UI CSS Framework. If you need this plugin to work with jQuery UI 1.5.3, read on.

Back in May, we demonstrated a date range picker we had built using jQuery UI, and it continues to be one of our most popular articles. We have since completely rewritten the component to make it much easier to work with, and we're releasing the code for download.

Notable Updates

  • Uses jQuery UI.latest: The range picker now uses the latest version of jQuery UI's datepicker, and allows passing of native datepicker options.
  • Date.js Integration: We've integrated the fantastic date.js library to allow for easy preset development.Date JS
  • Functional Arrows: More of a bug fix than a feature, the optional forward and back arrows allow a user to jump forward and backward by range duration.
  • Flexible Presets: The menu presets are now optional and very easy to add and modify.
  • ThemeRoller-Ready: The range picker is now entirely customizable with jQuery UI ThemeRoller.ThemeRoller-Ready

Working Demo:

The demo above was generated off the following code:

HTML

<input type="text" />

jQuery:


$('input').daterangepicker({
  arrows: true, 
  dateFormat: 'M d, yy'
}); 

Download This Code

01/05/2009 Note: This script is built for an old version of jQuery UI (v1.5.3). We have updated it to work with the new jQuery UI and posted a new article detailing its changes. To read the article and download the script, visit Date Range Picker using jQuery UI 1.6 and jQuery UI CSS Framework.

Version 1.0: FilamentGroup_daterangepicker.jQuery.js.zip (13kb Zip)

Developer Options

The following options are available in this plugin:

  • presetRanges: Array of objects to be made into menu range presets. Each object requires 3 properties:
    • text: string, text for menu item
    • dateStart: date.js string, or function which returns a date object, start of date range
    • dateEnd: date.js string, or function which returns a date object, end of date range
  • presets: Array, datepicker toggle options. Available options are: 'Specific Date', 'All Dates Before', 'All Dates After', 'Date Range'
  • earliestDate: Date.js string, earliest date allowed in system
  • latestDate: Date.js string, latest date allowed in system
  • rangeSplitter: String, character between two dates in a range.
  • dateFormat String, date formatting, see available values
  • closeOnSelect: Boolean, true will close the rangepicker when a full range is selected.
  • arrows: Boolean, true will add date range advancing arrows to input.
  • posX: int or string, left absolute position of rangepicker
  • posY: int or string, top absolute position of rangepicker
  • appendTo: jQuery selector or element, element to append range picker to.
  • datepickeroptions: Object, Options to pass directly to the datepickers inside the range picker. See UI datepicker options.

Development Notes

This plugin is a work-in-progress, and we would love to hear your input on how it could be improved. We've tested it in Firefox 2/3, Safari 3, and IE6/7.

Dependencies

This plugin requires jQuery and jQuery UI Datepicker (needs UI Core). It also uses ThemeRoller CSS as well as one additional custom CSS file. The demo in the zip file links to all necessary dependencies.

Setting Menu Presets

Setting preset ranges is now very easy and powerful with the help of date.js. To add a preset, simply pass an array to the presetRanges option like this:

$('input').daterangepicker( {
  presetRanges: [
    {text: 'My Range', dateStart: '03/07/08', dateEnd: 'Today' }
  ]
 } );

Note that the dateStart and dateEnd properties can accept strings (as shown), or functions which return a date object. The string will be parsed by date.js to generate a date (visit Date.js for a list of values). For more custom dates, you can write a function that returns a date object. Keep in mind that you can use Date.js within that function for any helpers you might need.

About Date.js

Date.js is an open source date parsing library written by Coolite. Essentially, you can pass some text into it and get a date in return. For example, it would parse the words "next week" and return a date object for a day 7 days from today - VERY slick! The library does a heck of a lot more than that too, and we strongly advise checking it out at Datejs.com to find out more.

Multiple Inputs

If you'd like to use this plugin with 2 inputs for the start and end dates, simply call the plugin on two inputs instead of one. The plugin will update them in order of appearance.

Demo page using 2 inputs

Driven by Input Value

The datepickers will be generated based on any values that are in the inputs at page load. For single inputs, it will split the input value by the rangeSplitter character (default: '-'). Each value is parsed by date.js, so you could even begin with a range like "today - next week" in the input, and the datepickers will be set accordingly.

Still to do...

  • Collision detection: At the moment, the rangepicker simply gets placed on the page by coordinates. There's no collision detection yet.
  • Automatic positioning: The rangepicker does not currently position itself in relation to the input. You'll need to pass in coordinates manually through the posX and posY options.
  • Date formatting: We'd like to integrate this tighter with the datepicker to better support internationalization on date formats. Thanks Alex!
  • Instance management: Currently, 2 rangepickers on one page won't play well together. We'll look to improve this soon.

Your thoughts?

We'd love to hear what you think of this plugin and any suggestions you have for how it could be improved. Please use our form below.

Comments

It is pretty, and amazing.. In fact, it is pretty amazing.  I can’t wait to get it integrated into our dashboard filters.

Comment by Daniel Einspanjer on 10/24  at  08:22 PM

This is simply sweet! Will you consider doing a Prototype version?

Comment by Jacques on 10/24  at  09:05 PM

looks very nice

Comment by alexander farkas on 10/25  at  05:20 AM

The range picker doesn’t seem to work properly in Opera. Clicking on the second date changes the first one. Otherwise, this is exactly what I’m looking for.

Comment by Brad Abrahams on 10/25  at  08:11 AM

Thanks for the nice comments everyone - glad you like it!

@Brad: I just tested in Opera 9.2 and 9.6 and I couldn’t find any problems. Which version and platform are you using?

Comment by Scott (Filament) on 10/25  at  08:39 AM

I mentioned a couple of problems I noticed over on my blog (linked on my name).

Also, I’m happy to report it works on my Android G1 browser. smile

Comment by Daniel Einspanjer on 10/25  at  09:08 AM

@Daniel: Thanks! I had just read it actually. Those darn arrows… :/
I’m not sure I’m seeing the off by one error you mentioned, so I’ll respond on your blog to discuss and hopefully we’ll figure it out.

Also, good news on Android!

Comment by Scott (Filament) on 10/25  at  09:42 AM

The arrows don’t work for me - they work for maybe a couple of clicks then seem to stop working.

Also, would be nice to be able to start typing in a humanised date, eg. “next thursday” and see the datejs parsed date appearing underneath or above so I know it’s got the right date.

Other than that, very sweet control!

Comment by Guy Fraser on 10/25  at  04:28 PM

@Scott: Just tested it on Opera at work (9.52) and it works fine. No idea what was causing it to act funny at home… I choose to ignore it and pretend that it never happened.

Comment by Brad on 10/27  at  04:17 AM

A slight oddity in the demo when I looked at it today, in that there seems to be an extra blank line in the display for November 2008.

Comment by Neil on 10/27  at  04:38 AM

This is great script. I really liked it. Thanks.

Comment by Veera on 10/28  at  05:08 AM

@Daniel, @Guy Fraser : We updated the script and ZIP with a couple of fixes. First, the arrows are now more stable. This appears to have been fixed through an update to the UI datepicker itself, rather than any changes on our part.
As for the ‘off-by-one’ error, this is now fixed as well. The arrows will always increment by the difference between dates, plus one day.
This ends up simplifying our code by a line as well, since we don’t have to check if the difference is zero before adding a day (which we were doing for single date choices).

By the way, if anyone comes up with new ThemeRoller themes for this component, please share the URL in the comments!

Comment by Scott (Filament) on 10/31  at  10:46 AM

It is a master piece, and match to my requirement but i am unable to customize the drop down calendar that should appear exact the below of text box, I think it is aligned left side and i m unable to move it till the textbox

All in all good and it will be best i will be able to use it.

Comment by Khan Tanveer Alam on 11/01  at  01:56 AM

This is a very nice datepicker but I am having trouble with the “today” option. When I load the page and click on the datepicker and then click “today” nothing seems to happen. If I select a date or a range and then click “today”, again nothing happens. Tried this in FF 3, Safari 3.1, Webkit, Opera all on OS X 10.5.5. Same results in all of them.

It seems to be behaving oddly when I select a range like “month to date” and then try to use the left or right arrow (does not change the displayed date). After I’ve used the arrow as described above when I choose another option (or even the same one again) it updates to the date the arrow should have moved it to.

It seems like the same behavior is happening for the “today” and the left and right arrows. They both seem to be applied to the user’s next selection, not the date currently displaying in the box. Hope that helps with the issue.

I realize that this may not be your issue, but I thought I’d point it out here because I’m seeing it here.

The animation and style look great, it will be super when all the kinks are ironed out.

Comment by Dan Evans on 11/03  at  05:37 AM

If the text box contains a date range, the “Month to Date” and “Year to Date” perform different actions to the end date in the range.  I would expect the start date in the range to be the first of the month or year accordingly _and_ the end date in the range changed to be the current date.  Alas, this is not what happens to the end date for both options.  To demonstrate, populate the text box with a date range where the end date is *not* today. Then select “Month to Date”, and note the end date. Reset the text box with the original date range, then select “Year to Date”.

Comment by Brian Patrick on 11/04  at  02:12 PM

On os x and FF2 (.0.0.17), ‘today’, ‘last 7 days’ and ‘month till today’ on your demopage don’t work.

However, it really looks great!

When selecting a daterange, you might want to color the intermediate days also with the ‘date selected’ color

Comment by Werner Teeling on 11/10  at  05:48 AM

I can’t seem to get the picker to show up appended to the text input. It keeps showing up at the bottom of the page after all other HTML.

Am I missing something really obvious, or do you suspect I have some sort of CSS somewhere messing stuff up?

Comment by Kris on 11/11  at  04:24 PM

@Kris: you’ll want to either use the appendTo option to append the datepicker to a relatively positioned div that comes directly after the input, or use the posX and posY to postion your current datepicker to the right postion on your page.
The first option might give you better control, but depending on z-index conflicts, you might not have the luxury of placing it there in the DOM. In that case, you might need to append the picker to the end of the body, which is the default. Then you can position it dynamically by using the offset of the input, like posY: $(this).offset().top + $(this).height().

Let us know if that works for you.

Comment by Scott (Filament) on 11/11  at  04:31 PM

@dan @Werner: The bugs you pointed out were working a week ago, so I’m concerned that the bug is the result of changes in the jQuery UI library file we’ve linked to (on google’s hosting). I’ll check with the jQuery team about it.

Comment by Scott (Filament) on 11/11  at  04:34 PM

Cool, here’s what I got:

<!--html-->
<input type="text" id="datepicker" />
<div id="datePickerContainer" style="position:relative;z-index:999;"></div>

// javascript
$(document).ready(function() {
$(’#datepicker’).daterangepicker({appendTo:"#datePickerContainer"});
});

But now instead of showing it at the bottom of the body, it doesn’t show at all. (By the way, no errors in the Firebug console)

Am I using the “appendTo” wrong?

Comment by Kris on 11/11  at  04:37 PM

Just wanted to follow up:

I got the posY and posX to work splendidly. Thanks!

Comment by Kris on 11/11  at  04:57 PM

@dan @Werner: The demos should be better now. Let us know. Thanks!

Comment by Scott (Filament) on 11/11  at  05:06 PM

Under ‘Developer Options’, the dateFormat option is listed as:

> dateFormat String, See UI datepicker options

I’ve tried things like:

> dateFormat: ‘M dd, yy’

And I’ve tried more straightforward variations like:

> dateFormat: ‘MM’

In all cases I get garbage returned.

The documentation does also say:

> Date formatting: We’d like to integrate this tighter with the datepicker to better support internationalization on date formats.

This would imply that the dateFormat option is not fully functional.

Any guidance would be appreciated.

Comment by Alex on 11/12  at  08:13 AM

@Alex: dateFormat is functional, just very limited. Right now it only really lets you change the order of ‘MDY’ to something like ‘DMY’, for European formatting. And the last character can be changed to something other than a slash if you’d like.
Formatting like you are trying to do is something we have yet to implement. Patches are welcome smile

Comment by Scott (Filament) on 11/12  at  09:41 AM

Hey Scott,

When setting “earliestDate” to

earliestDate: ‘7/1/2008’

I get “05/21/2008 - 11/12/2008” back when I select “All Dates Before > 11/12/2008”

Do you know what’s up?

Comment by Kris on 11/12  at  10:54 AM

How would you like patches submitted?

I don’t know if you are interested in rolling this into your official version however I have altered the fDate function (see below).

This allows the dateFormat option to be set to anything that UI datepicker can accept:

http://docs.jquery.com/UI/Datepicker/&#x24;.datepicker.formatDate

For anybody reading this that wants more control over the way dates are formatted, my revised function looks like:

//function to format a date string
function fDate(date){
if(!date.getDate()){return ‘’;}
var day = date.getDate();
var month = date.getMonth();
var year = date.getFullYear();
month++; // adjust javascript month
var dateFormat = settings.dateFormat;
return jQuery.datepicker.formatDate( dateFormat, date );
}

Comment by Alex on 11/12  at  11:01 AM

Hey Scott,

I was a bit off before. Here is the bug with the “All Dates Before”:

- Setting earliestDate:’07/01/08’ gives “11/28/2008 - 11/12/2008” in the input

- Setting earliestDate:’07/01/2008’ gives “05/21/2014 - 11/12/2008” in the input

Comment by Kris on 11/12  at  11:11 AM

@Alex: THANKS! Great update. We’ve rolled your changes into the “official” version.

This means that ‘dateFormat’ now accepts the same variety of values that the jQuery UI datepicker’s dateFormat option does. It defaults to ‘m/d/yy’ so your dates will look like 3/8/2008 if you don’t change the option. But as you can see in our demos, we’ve set the option to ‘M d, yy’ for a more friendly look.

For returning visitors, a hard refresh is probably necessary.

Thanks again Alex!

Comment by Scott (Filament) on 11/12  at  12:12 PM

Lovely work. What I’d love to see is some kind of time picker integrated, or another component to do this. Judging by the lack of well-written timepickers it would seem I am alone in needing to build booking forms with time ranges!

Comment by Peter on 11/13  at  04:50 AM

(I apologize if this is a duplicate, I think I may have made a mistake in which page this posted to and don’t know if it submitted at all)

I found that to get the datepicker to work in noConflict() mode, line 233 needed to be changed from:
$(settings.appendTo).append(rp);
to
jQuery(settings.appendTo).append(rp);

After this, I was able to get datepicker working with Prototype and jQuery both included on the page.  However, when including Scriptaculous things break.  At line 104 there begins a block of code that makes ‘this.text’ undefined.  (immediately before that its defined, immediately after that it is undefined).

There seems to be some sort of conflict going on with the way that block is written, does anybody with better javascript skills than me know of a simple way to rewrite that line to the same effect?  Unfortunately our entire app was written on prototype/scriptaculous before we saw a lot of the benefits of jQuery!

Thanks!
Mike

Comment by Mike on 11/19  at  08:49 PM

This is fantastic work, Scott.  Could you point me towards where in the code I could make changes to help it accommodate multiple instances?  I’d love to use this in a current project but I do need to have two or three daterangepickers on the same form.

One very minor thing I found, I wanted to add a line to my document.ready to instantiate a daterangepicker on any elements of a certain class - using something like ... $(’input.daterangepicker’).daterangepicker();

... but this chucks up an error if the selector doesn’t match any elements.  Should just be silent in this case?

Great work Scott, many thanks

Comment by Martin on 12/06  at  02:28 PM

Hi, nice work! If I run the demo on Firefox 3.1 Beta 2 it works.
If I run it on Internet Explorer 7 it does not work. Can that be? Or do I just face a local browser issue.

Would be nice if you could tell it the demo works for you and is specified to work on IE 7.

Thanks, Peter

Comment by Peter on 12/17  at  01:56 PM

Broken on Google Chrome

Comment by Sanz on 12/24  at  05:09 AM

This is really amazing,
but there seems to be some problem with the site today as the demo is not working and only textbox appear.

Comment by PSR on 01/02  at  02:40 AM

Hey Guys,

Really love this plugin but it DOESNT work on Google Chrome/Safari ?

Is it possible to update it so it works ?

Comment by Andy on 01/05  at  07:37 AM

Thanks for the comments everyone. Seems we’ve linked to some javascript files which have changed location on us. We’ll be posting an update shortly that ports this plugin to the new version of jQuery UI. Stay tuned and thanks for your patience.

Comment by Scott (Filament) on 01/05  at  09:57 AM

These demos are now working again. Keep in mind that this uses jQuery UI 1.5.3, which is not the latest version. Stay tuned for an update to the new UI version!

Comment by Scott (Filament) on 01/05  at  11:04 AM

We’ve updated the Date Range Picker plugin for the new jQuery UI v1.6rc4 and have posted a new article detailing the changes. The new plugin has some new features and uses the new jQuery UI CSS Framework for a fresh new look and feel. Please discontinue using this plugin unless you are tied to jQuery UI 1.5.3.

Here’s a link to the new Date Range Picker article:
http://www.filamentgroup.com/lab/date_range_picker_using_jquery_ui_16_and_jquery_ui_css_framework

Comments are welcome. Thanks!!

Comment by Scott (Filament) on 01/05  at  07:01 PM

Add a Comment:* required fields

3 hours ago...

@ericmmartin I just tried downloading a custom ThemeRoller theme and a few from the gallery and both worked fine. Give it a try now.

@filamentgroup on twitter