ASP.NET
Booking Calendar Custom Control
When developing enterprise ASP.NET applications it is common to have a calendar
booking facility. This article presents a booking calendar Custom Control which
can be used for reservations and accommodation letting's. Links to a javascript
version and a more advanced booking
solution (see also our Holiday Booking page) are
provided for your information.

Introduction
When developing enterprise ASP.NET applications it is common
to have a calendar booking facility. The calendar control supported by .NET
and Visual Studio do not provide such a facility. Although the control can
be customised it does not offer the same level of sophistication and completeness
offered by the calendar control presented here.
Background
The control renders
a calendar for the month/year selected. Each of the current/future days generate
a postback event when selected as does the rate combobox. The combobox dropdown
menu being triggered by a right mouse button click.
The control has three events, which are:
-
OnDayRender - called for each rendered day, program must return whether day is "Available", "Booked",
or "Unavailable".
-
OnRateRender - called for each rendered rate, program must return a "Rate" and "Available" strings
(see Using the Control section below for further details).
-
OnSelectionChange - called when a user request (postback event) is made for a day or rate change.
The control includes the following properties:
- Available day background colour.
- Booked day background colour.
- Heading month background colour.
- Dropdown list hover colour.
- Rate combobox colour.
- Unavailable day colour.
- Number of calendar columns.
- Listbox entry string collection.
- Rate length (maximum number of characters in string).
- Rate Combobox width.
- Rate Combobox height.
- Number of calendar rows.
- Calendar Month.
- Calendar Year.

The demonstration application
(CalTest) displays a 2 by 2 Calendar array starting from the current month
(the example above was run on 3 July 2006). It generates a 53 week string array
(rac)
which holds availability and rate information which is intialised as available
i.e.
all
current dates
with
green backgrounds. The SelectionChange event updates this array
through user request
(postback event) for a day or rate change.
Using the code
The control properties
allow for a level of customisation and are fairly self explanatory. To use
the control the user will need to maintain information on booking availability
and rates, the demonstration application (CalTest) shows a simple implementation
of the control. Access to this data will be required when the control is
rendered, the control generating events OnDayRender for day and OnRateRender
for rate information.
There are two event arguments
for OnDayRender, Date and Available. The Date argument
is used to pass the day to be rendered and hence is used to recover the
availability for that day. The Available argument is used
by the control and hence must receive the availability status (Avail or Booked)
for the requested day.
OnRateRender has three
event arguments, Date, Available and Rate,
and functions similar to OnDayRender. The control requires the return of
two arguments Available and Rate.
A postback event is generated
when a user request is made for a day or rate change. The control on receiving
this postback event uses the event argument to populate the SelectedRate,
RateString and SelectedDate properties. The control generates an OnSelectionChange
event to the ASP.NET code behind page thereby enabling the application to
update the maintained booking availability and rate data accordingly (see
the demonstration application CalTest for further details).
Point of Interest
The major part of the control
is the rendering of the calander through a series of html tables. The function
MultiCal is responsible for rendering multiple calendars and calls the function
MonthCal for the rendering of each actual calendar. MonthCal is passed 2
parameters, CalMonth and CalYear, which is used to construct the calendar.
Functions DayRenderStatus and RateRenderStatus generate events OnDayRender
and OnRateRender respectively into the main application in order to secure
the requested information.
After rendering the calendar(s)
the final function called is AddListBox. Each rate textbox is actually a
combobox consisting of a textbox and a listbox triggered by a right click mouse action.
The common listbox and associated javascript code is rendered by the AddListBox
function. Each textbox is constructed as follows:
<TD align=left>
<INPUT class=calendar oncontextmenu="return false;"
onmousedown=MouseBtnDown(arguments[0],this) id=L240606
onkeydown=KeyDown(arguments[0],this)
style="WIDTH: 30px; BACKGROUND-COLOR: #e7e7ff"
maxLength=4 value=250 name=L240606>
</TD>
oncontextmenu disables
the standard right mouse click context dropdown menu. onmousedown and onkeydown
events call the MouseBtnDown and KeyDown javascript functions accordingly.
MouseBtnDown obtains a reference to the common listbox, and loads the variable
selTextbox with a reference to the selected textbox. If the mouse right button
has been clicked it also positions/displays the listbox with the selected
clicked textbox (rate). KeyDown gets the selected key, hides the listbox
and if the key is a carriage return calls the function ValidateTextbox.
function MouseBtnDown(e,textbox){
var listbox=document.getElementById('listbox');
var btnclick;
selTextbox=textbox;
selValue=textbox.value;
if(!e)
var e=window.event;
if(e.which){
btnclick=e.which;
if(btnclick==3)
btnclick=2;
else
if(btnclick==2)
btnclick=4;
}
else
if(e.button)
btnclick=e.button;
if(btnclick==2){
posArray=FindPosition(textbox);
listbox.style.visibility='visible';
listbox.style.position='absolute';
listbox.style.zIndex=200;
listbox.style.left=posArray[0]+28;
listbox.style.top=posArray[1]+5;
}
else
listbox.style.visibility='hidden';
}
On selection of a listbox
entry, function AddToTextbox is called. The entry is added to the textbox,
the listbox hidden and the function ValidateTextbox called.
function AddToTextbox(entry){
var listbox=document.getElementById('listbox');
selTextbox.value=entry.firstChild.nodeValue;
listbox.style.visibility='hidden';
ValidateTextbox(selTextbox);
}
The ValidateTextbox function
tests for a valid textbox entry and if so calls _doPostBack function which
generates a postback event. If the entry is not valid an appropriate alert
message box is displayed.
function ValidateTextbox(textbox){
if(textbox.value){
if(IsNumeric(textbox.value)||(InListbox(textbox.value)))
__doPostBack(postBackEventTarget,textbox.id+textbox.value);
else{
textbox.value=selValue;
alert('The rate entry can only be a number or a listbox entry!');}
}
else{
textbox.value=selValue;
alert('The rate cannot be left empty, please make a entry!');}
}
 |