I’ve always loved the calendar date range selector in Google Analytics, it’s extremely user-friendly for the task of selecting a range of dates; much more so than the typical dual input boxes with independent calendars. There are a few options out there for replicating the Google Analytics range picker, however I couldn’t seem to find any that offered the functionality, looks, and ease of use right out of the box. The closest I could find was the DatePicker offered by Stefan Petre, so I decided to use that as a starting point and create a Google Analytics inspired DatePicker of my own.
My version builds off of Petre’s with the following changes:
- Split stylesheet into base.css to allow easier styling, and dark.css as the first full style.
- Created clean.css to provide a style similar to Google Analytics.
- Clicking the calendar month title selects the whole month when in ‘range’ mode.
- Removed the ‘week’ column.
- Heavy refactoring/commenting of the code.
- Created new examples page and documentation suite.
Documentation and Download
See the following links below for the source code, examples page and documentation page.
- DatePicker GitHub Repository
- DatePicker GitHub Project Page With Examples
- DatePicker Documentation
- Download the Latest DatePicker
Widget Code
To create the above date drop-down widget, you can use code like the following:
Includes
First download jQuery and DatePicker and include them:
<script type="text/javascript" src="/js/jquery/jquery.js"></script> <script type="text/javascript" src="/js/datepicker/js/datepicker.js"></script> <link rel="stylesheet" type="text/css" href="/js/datepicker/css/base.css" /> <link rel="stylesheet" type="text/css" href="/js/datepicker/css/clean.css" />
HTML Markup
Add the following HTML markup where you want the widget positioned:
<div id="date-range"> <div id="date-range-field"> <span></span> <a href="#">▼</a> </div> <div id="datepicker-calendar"></div> </div>
JavaScript
The following JavaScript will bind the DatePicker calendar to the <div>
, update the date display, and handle displaying/hiding the calendar on click.
<script type="text/javascript"> $(document).ready(function() { var to = new Date(); var from = new Date(to.getTime() - 1000 * 60 * 60 * 24 * 14); $('#datepicker-calendar').DatePicker({ inline: true, date: [from, to], calendars: 3, mode: 'range', current: new Date(to.getFullYear(), to.getMonth() - 1, 1), onChange: function(dates,el) { // update the range display $('#date-range-field span').text(dates[0].getDate()+' '+dates[0].getMonthName(true)+', '+dates[0].getFullYear()+' - '+ dates[1].getDate()+' '+dates[1].getMonthName(true)+', '+dates[1].getFullYear()); } }); // initialize the special date dropdown field $('#date-range-field span').text(from.getDate()+' '+from.getMonthName(true)+', '+from.getFullYear()+' - '+ to.getDate()+' '+to.getMonthName(true)+', '+to.getFullYear()); // bind a click handler to the date display field, which when clicked // toggles the date picker calendar, flips the up/down indicator arrow, // and keeps the borders looking pretty $('#date-range-field').bind('click', function(){ $('#datepicker-calendar').toggle(); if($('#date-range-field a').text().charCodeAt(0) == 9660) { // switch to up-arrow $('#date-range-field a').html('▲'); $('#date-range-field').css({borderBottomLeftRadius:0, borderBottomRightRadius:0}); $('#date-range-field a').css({borderBottomRightRadius:0}); } else { // switch to down-arrow $('#date-range-field a').html('▼'); $('#date-range-field').css({borderBottomLeftRadius:5, borderBottomRightRadius:5}); $('#date-range-field a').css({borderBottomRightRadius:5}); } return false; }); // global click handler to hide the widget calendar when it's open, and // some other part of the document is clicked. Note that this works best // defined out here rather than built in to the datepicker core because this // particular example is actually an 'inline' datepicker which is displayed // by an external event, unlike a non-inline datepicker which is automatically // displayed/hidden by clicks within/without the datepicker element and datepicker respectively $('html').click(function() { if($('#datepicker-calendar').is(":visible")) { $('#datepicker-calendar').hide(); $('#date-range-field a').html('▼'); $('#date-range-field').css({borderBottomLeftRadius:5, borderBottomRightRadius:5}); $('#date-range-field a').css({borderBottomRightRadius:5}); } }); // stop the click propagation when clicking on the calendar element // so that we don't close it $('#datepicker-calendar').click(function(event){ event.stopPropagation(); }); }); </script>
CSS
And finally the CSS to style the dropdown widget:
<style type="text/css"> /* Style the calendar custom widget */ #date-range { position:relative; } #date-range-field { width: 290px; height: 26px; overflow: hidden; position: relative; cursor:pointer; border: 1px solid #CCCCCC; border-radius: 5px 5px 5px 5px; } #date-range-field a { color:#B2B2B2; background-color:#F7F7F7; text-align:center; display: block; position: absolute; width: 26px; height: 23px; top: 0; right: 0; text-decoration: none; padding-top:6px; border-radius: 0 5px 5px 0; } #date-range-field span { font-size: 12px; font-weight: bold; color: #404040; position: relative; top: 0; height: 26px; line-height: 26px; left: 5px; width: 250px; text-align: center; } #datepicker-calendar { position: absolute; top: 27px; left: 0; overflow: hidden; width: 497px; height:153px; background-color: #F7F7F7; border: 1px solid #CCCCCC; border-radius: 0 5px 5px 5px; display:none; padding:10px 0 0 10px; } /* Remove default border from the custom widget since we're adding our own. */ #datepicker-calendar div.datepicker { background-color: transparent; border: none; border-radius: 0; padding: 0; } </style>
Awesome work, that’s exactly the kind of tool I was looking for. I too find the other date range selector not usable enough, yours is really clean.
Thanks for sharing this with the Internet.
Why you’re very welcome, I’d still like to simplify it some more, but I’m glad you like it!
this looks great! the only thing it seems to be missing from the GA version is the option to compare to past. is this something that can be added easily?
thanks!
Hmm, “compare to past”? Not entirely sure I know what you mean
Its a feature in Google analytics. If you’re looking to compare data from 2 time periods
Alright, I’ll have to play around with that and see whether it fits with the plugin. Thanks for the recommendation
how to get both date form span tag
Hey Arun, I’m sorry, what is your question exactly? Thanks,
Justin
is this compatible for IE 8?
As far as I know, it should be
hi justin,
did you ever look at the compare to date function of like google analytics has?
thanks
Ha, no, never really tried that out until just now. That’s pretty cool. Not sure what it would take to add something like that to my version
1.How to disable the future date? i.e. The user is no need to select the future date and it will not be a clickable, it will display like a disable state.
2.How to disable the past date? i.e. If the user is select one past date, then the selected dates before dates are display like a disable state.
Hey Raj, there’s no built-in configuration option to do what you’re describing. You should be able to achieve what you’re describing by providing a custom handler for the onRenderCell event. See the Events section of the documentation. By providing an onRenderCell handler, your function will be passed each calendar cell element, along with the displayed date, and you could compare the displayed date to the current date, setting the ‘disabled’ property on the element when needed. Hope this helps
so in that date range picker, if you are to send that form via a cgi script, what would the request look like to CGI? in other words, I copied your code and put it on my page and I can now see a data range picker but I don’t know how to use that in HTMl form. Any example you can provide would be very valuable.
Thanks
Take a look at the documentation page: http://foxrunsoftware.github.com/DatePicker/reference.html You have two basic approaches you can take: you can either grab the current value from the datepicker element when the form is submitted, with something like:
$('#datepicker-calendar').DatePickerGetDate()
. Or you can grab the date(s) by listening for theonChange
event. Either way, you’re going to have to use a bit of javascript to write out for example a hidden field element within your form, and figure out how you want to represent the date, or even date ranges, depending on the type of calendar widget you’re using. I didn’t show any code examples because the specifics depend too much on your particular page markup/date requirements, but it will take some JavaScript know-how to get working.Nice! Is it possible to select a date range in months (e.g. Feb 2011 to Oct 2012) with on the top year (instead of month and year) and the bottom the months rather than the days? (http://www.eyecon.ro/bootstrap-datepicker)
Thanks Man.
Hey justin, i cant figure out how i disable (not selectable, not clickable and with different color, red probably:)) a specific date with an array. Can you a simple example? thanks!
Hey Anna, unfortunately there’s no option to disable dates using an array. You’d have to make use of the onRenderCell event described in the API reference, and disable the cell based on the date; but to do so requires some JavaScript knowledge/know-how
On the GitHub page of the project, there is no detailed HTML plus JavaScript function example for “Calendar With Custom Widget”. I have tried looking at the source code but I can’t get it to work. A detailed example would be awesome for us beginners.
Hmm, actually that’s what the whole purpose of this page is supposed to be: a detailed example of that custom widget, with a working example followed by the full implementation under the ‘Custom Code’ section above. Were you able to follow the example on this page, or was anything confusing about it?
It took me a bit but I got it to work. Thanks a lot. An implementation with the option to disable furure/past dates like described here https://www.skyverge.com/articles/javascript/date-range-picker-similar-to-google-analytics/#comment-2665 would be awesome.
To disable past dates:
onRenderCell: function(el,date) {
var today = new Date();
if ( date < today ) {
return { disabled: true, classname: 'your OwnClass' };
}
else {return {}}
}
Dear Justin,
thanks for this! it’s really nice and what I’m one more looking for this like everyone else here 😀
Do you recommend to use it in production? Or it’s just still experimental? I ask that because it have almost a year that there is no updates… (1.0.0 version is from 3/12/2012)
And for that, I ask if has no incompatibility with the newest versions of jquery and jquery-ui?
anyway, thanks for the attention
How to use it for multiple datepicker in a form?
Hi justin,
Thanks it is nice. can i disable the future date/Month from the opened calender.is there any example of it. Thanks
Mohan
Hi justin,
It is working now. Can we disable all the dates which is not in our selection.
How we can we do this suppose i have selected 5 apr to 10 may then rest dates should be disable. Can we do this.
Thanks
Ashish
Is there an example when using the non inline events like onBeforeShow, onAfterShow? I can’t see that they’re triggered even if I set inline to false.
Thank you for the great widget,
I want to ask you if there’s a way to specify two dates in the current variable. for example to populate the range date that you have already in the database.
It would be really helpful!
Hey Amine, if I understand correctly I think you should be able to do this by passing two dates to the date option as described in the documentation. Ie
$('#datepicker-calendar').DatePicker({date: [new Date(), new Date() + 345600000});
Check out this JQuery UI based implementation: http://tamble.github.io/jquery-ui-daterangepicker/
This is really good framework. How to give facility to user to jump the year? Client want to have drop-down to change year /months or double arrows to jump year. Please suggest.
May I know where to edit if i need to add no week to be displayed?
I wonder Mr. Justin if it is possible to limit the number of days selected in the range of two dates.
For example; i want the user to select a maximum number of days that is less or equals 30 days between two dates.
Is there any workaround for this, i loved the widget and i wanted to integrate it in my website but this functional requirement is highly important to me and my endeavors.