IntervalCalendarclass and example is based on the
iCalendarGroupclass, graciously contributed to YUI by John Peloquin, of W. Hardy Interactive, Inc..
The Calendar widget is commonly used to select pairs of dates, representing the start and end dates of an interval, for example flight departure and return dates, or hotel check-in and check-out dates.
This example defines a custom
IntervalCalendar class, based on CalendarGroup, which is designed specifically for this use case.
IntervalCalendar class, defined in this example, allows users to select pairs of dates representing the start and end of a date interval. Applications which require interval selection, for example a hotel check-in/check-out date selector, frequently display separate calendar instances to select the beginning and ending dates of the interval. The IntervalCalendar provides an alternate solution, by allowing the selection of both dates within the same calendar instance. It's most suitable for applications in which the beginning and ending dates fall within the span of a few days, so that the entire range falls within the calendar's visible set of months.
IntervalCalendar class extends the
CalendarGroup class, so that it can support a multi-page view. A two page view would probably be the most common use case for the Interval Calendar.
We start by defining the constructor for the
By default Calendar and CalendarGroup are designed to allow open ended selection of dates, which don't neccessarily need to form a continuous date range. However the Interval Calendar needs to constrain the selection behavior, to limit selection to a maximum of two date values - the beginning and ending dates for the interval. The Interval Calendar enforces the interval selection state, using two main code constructs; the
_iState property and a set of event listeners for CalendarGroup's selection related events -
_iState property is used to determine which of 3 "modes" Interval Calendar date selection is currently in - no dates selected, one date selected or two dates selected. Since internally, CalendarGroup maintains an array for all of its selected dates (that is, the start date, the end date and any dates in between), the Interval Calendar does not rely on the length of the
"selected" dates array to determine which selection "mode" the Interval Calendar is in. Instead it maintains its own state using the
The default select and deselect events that CalendarGroup fires when the user selects or deselects a date are used to maintain the value of the
_iState property discussed above. This allows the Interval Calendar implementation to provide custom interval selection behavior without having to re-implement large portions of the Calendar or CalendarGroup date selection code.
All the logic required to provide the custom selection functionality is wrapped up neatly in 4 event listener methods:
_intervalOnDeselect all of which work with the existing CalendarGroup selection API and the
_iState property to ensure the user doesn't select more than two dates at any given time:
The constructor code, along with the above 4 methods provide the backbone for interval selection state handling. Additionally
IntervalCalendar provides a few supporting selection methods, to make it easier to work with intervals:
Since Calendar and CalendarGroup's underlying selection model is designed to allow you to select multiple, not neccessarily adjacent dates, the default selection methods and properties don't enforce the date selection constraints required by IntervalCalendar. The
IntervalCalendar class provides the
resetInterval methods as alternative selection methods, which follow the selection definitions required by the Interval Calendar, setting and returning dates as part of a continuous date range.
NOTE: For the purposes of this example, Interval Calendar doesn't go out of it's way to prevent developers from using the default
select method or
select configuration property, to select arbitrary dates outside of the currently selected interval, but it could override the corresponding methods to protect against such use if desired
IntervalCalendar class is straightforward. It's instantiated in the same way as the CalenderGroup, providing a container id and a configuration object, and
render is invoked to display it:
The example also registers a listener for the normal select event fired by the CalendarGroup, and uses the
getInterval method to populate text input elements representing beginning and ending dates for the interval selected:
The select event listener relies on the fact that
getInterval will either return an empty array if no dates have been selected, or a two element array with the first element representing the start date of the interval and the second element representing the end date of the interval. If only one date has been selected, the start date and end date will be the same.