I needed a way to provide my users with a date picker that was automatically provided when a text area received focus. I was eager to use the excellent YUI calendar as a starting point, but the provided documentation didn’t provide a solid example for this type of implementation.
Dav Glass has provided a solid example of the Calendar tied to a text input. But, his example is highly dependent on the text input having specific ids. This doesn’t take advantage of YUI’s excellent Selector library really didn’t meet my need for a simple universal solution.
Key Requirements:
- Progressive Enhancement (No inline javascript)
- Yui based
- Universal implementation across all pages in a site.
- Support for multiple date inputs on a page.
Getting Started:
The bulk of the code used is pretty solidly Dav’s I’ve simply replaced all of the hard coded references to dynamically generated targets and moved from hard coded ID’s for the target fields to a css class. Lastly, I’ve added a “activeCal” class to the currently active target input so that one calendar can be recycled across multiple text areas on the page.
Source:
var cal1;
var over_cal = false;
function transmogCals() {
cal1 = new YAHOO.widget.Calendar("cal1","cal1Container");
cal1.selectEvent.subscribe(getDate, cal1, true);
cal1.renderEvent.subscribe(setupListeners, cal1, true);
var pickers = YAHOO.util.Selector.query('.date-picker');
for( i in pickers){
YAHOO.util.Event.addListener(pickers[i], 'focus', showCal);
YAHOO.util.Event.addListener(pickers[i], 'blur', hideCal);
}
cal1.render();
}
function setupListeners() {
YAHOO.util.Event.addListener('cal1Container', 'mouseover', overCal);
YAHOO.util.Event.addListener('cal1Container', 'mouseout', outCal);
}
function getDate() {
var calDate = this.getSelectedDates()[0];
calDate = (calDate.getMonth() + 1) + '/' + calDate.getDate() + '/' + calDate.getFullYear();
YAHOO.util.Selector.query('.activeCal')[0].value = calDate;
over_cal = false;
hideCal();
}
function showCal(e, targ) {
var xy = YAHOO.util.Dom.getXY(this);
var el = new YAHOO.util.Element(this);
el.addClass('activeCal');
var date = this.value;
if (date) {
cal1.cfg.setProperty('selected', date);
cal1.cfg.setProperty('pagedate', new Date(date), true);
cal1.render();
}
YAHOO.util.Dom.setStyle('cal1Container', 'display', 'block');
xy[1] = xy[1] + 20;
YAHOO.util.Dom.setXY('cal1Container', xy);
}
function hideCal() {
if (!over_cal) {
var el = new YAHOO.util.Element(this);
el.removeClass('activeCal');
YAHOO.util.Dom.setStyle('cal1Container', 'display', 'none');
}
}
function overCal() {
over_cal = true;
}
function outCal() {
over_cal = false;
}
YAHOO.util.Event.addListener(window, 'load', transmogCals);
Adding it to your page
Integrating the code into the page is VERY easy.
In the header of the page add the following css includes.
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?2.6.0/build/calendar/assets/skins/sam/calendar.css">
In the footer add the following script include and include the date-picker.js file
| <script type=“text/javascript” src=“http://yui.yahooapis.com/combo?2.6.0/build/yahoo-dom-event/yahoo-dom-event.js&2.6.0/build/calendar/calendar-min.js&2.6.0/build/selector/selector-beta-min.js”></script> |
Lastly, place a class of date-picker to any text fields you want to tie to the input and add the following to your pages markup:
<div class='yui-skin-sam' style="position:absolute; left:-1000px;">
<div id="cal1Container"></div>
</div>