﻿//Consts
var WEEK_COUNT = 6;
var DAYS_ON_WEEK = 7;

/****************************************
*               RCCalendarStyle
*****************************************/

/// <summary>
/// Richer Components - Calendar Day Class
/// </summmary>
function RCCalendarStyle()
{
    this.Day = null;
    this.DayHover = null;
    this.DayOtherMonth = null;
    this.DaySelected = null;
    this.DayHeader = null;
    this.Calendar = null;
    this.Previous = null;
    this.Next = null;
    this.Title = null;
    this.Picker = null;
    this.Close = null;
    this.PreviousYear = null;
    this.NextYear = null;
    this.NextYearPressed = null;
    this.NextYearOver = null;
    this.NextPressed = null;
    this.NextOver = null;
    this.DropDownList = null;
    this.PreviousOver = null;
    this.PreviousPressed = null;
    this.PreviousYearOver = null;
    this.PreviousYearPressed = null;
    this.MultiMonthContainer = null;
    this.MonthTitle = null;
    this.TodaysDateButton = null;
} // RCCalendarStyle

/****************************************
*               RCCalendar
*****************************************/

/// <summary>
/// Richer Components - Calendar Class
/// </summmary>
function RCCalendar( calendarId )
{
    this.ID = calendarId;
    this.AutoPostBack = false;
    this.ReadOnly = false;
    this.DayNames = new Array();
    this.AbbreviatedDayNames = new Array();
    this.MonthNames = new Array();
    this.AbbreviatedMonthNames = new Array();
    this.FirstDayOfWeek = RCFirstDayOfWeek.Default;
    this.DayNameFormat = RCNameFormat.Short;
    this.MonthNameFormat = RCNameFormat.Full;
    this.Style = new RCCalendarStyle();
    this.AllowMultipleSelection = false;
    this.Behavior = RCBehavior.Picker;
    this.PopupControlAnchorID = null;
    this.Picker = new RCDatePicker(this);
    this._popupVisible = false;
    this.PopupButtonImage = null;
    this.MonthRowCount = 1;
    this.MonthColumnCount = 1;
    this.PopupPosition = RCPopupPosition.Right;
    this._windowSize = { width: 0, height: 0 };
    this.MainContainerElement = null;
    
    //Dates
    this._selectedDates = new RCKeyValueCollection();
    this._visibleCalendarDays = new RCKeyValueCollection();
    this.SelectedDate = null;
    this.VisibleDate = new Date();
    this.TodaysDate = new Date();
    
    //Captions
    this.TodayCaption = 'Today';
    this.ClearCaption = 'Clear';
    
    //AJAX Effects
    this.SwapMonthEffect = RCSwapMonthEffect.None;
    this.SwapMonthSpeed = 10;
    this._ajaxEffectObj = null;
    this.PopupSpeed = 10;
    this.PopupEffect = RCPopupEffect.None;
    this.PopupOrientation = RCOrientation.Vertical;
    this._effectOnProgress = false;
    this._tempTimer = null;
    this._isIncrementingMonth = false;
    this._hideOnNextMouseUp = true;
    this._mouseUpHandler = null;
    
    //event handlers
    this._eventHandlers = new RCKeyValueCollection();
} // RCCalendar

/// <summary>
/// Adds a new handler to the handler list
/// </summmary>
RCCalendar.prototype._AddHandler = function( eventId, newHandler )
{
    var list = null;
    
    if ( newHandler != null )
    {
        list = this._eventHandlers.Get( eventId );
        
        if ( list == null )
        {
            list = new RCKeyValueCollection();
            this._eventHandlers.Add( eventId, list );
        }
        
        list.Add( newHandler, newHandler );
    }
} // _AddHandler

/// <summary>
/// Removes the given handler from the handler list
/// </summmary>
RCCalendar.prototype._RemoveHandler = function( eventId, handler )
{
    var list = null;
    
    if ( handler != null )
    {
        list = this._eventHandlers.Get( eventId );
        
        if ( list != null )
            list.Remove( handler );
    }
} // _RemoveHandler

/// <summary>
/// Fire the given event
/// </summmary>
RCCalendar.prototype._FireEvent = function( eventId, args )
{
    var list = this._eventHandlers.Get( eventId );
    var handler = null;
    
    for (var i = 0; list != null && i < list.GetSize(); i++)
    {
        handler = list.GetValueAt( i );
        
        handler.apply(this, args);
    }
} // _FireEvent

/// <summary>
/// Removes the given handler from the Visible Date changed event
/// </summmary>
RCCalendar.prototype.RemoveHandler_OnVisibleDateChanged = function( handler )
{
    this._RemoveHandler( RCCalendarEvents.OnVisibleDateChanged, handler );
} // RemoveHandler_OnVisibleDateChanged

/// <summary>
/// Adds a new handler for the Visible Date changed event
/// </summmary>
RCCalendar.prototype.AddHandler_OnVisibleDateChanged = function( newHandler )
{
    this._AddHandler( RCCalendarEvents.OnVisibleDateChanged, newHandler );
} // AddHandler_OnVisibleDateChanged

/// <summary>
/// Removes the given handler from the remove selected date changed event
/// </summmary>
RCCalendar.prototype.RemoveHandler_OnRemoveSelectedDate = function( handler )
{
    this._RemoveHandler( RCCalendarEvents.OnRemoveSelectedDate, handler );
} // RemoveHandler_OnRemoveSelectedDate

/// <summary>
/// Adds a new handler to the Remove selected date event
/// </summmary>
RCCalendar.prototype.AddHandler_OnRemoveSelectedDate = function( newHandler )
{
    this._AddHandler( RCCalendarEvents.OnRemoveSelectedDate, newHandler );
} // AddHandler_OnRemoveSelectedDate

/// <summary>
/// Adds a new handler to the selected date changed event
/// </summmary>
RCCalendar.prototype.AddHandler_OnSelectedDateChaged = function( newHandler )
{
    this._AddHandler( RCCalendarEvents.OnSelectedDateChanged, newHandler );
} // AddHandler_OnSelectedDateChaged

/// <summary>
/// Removes the given handler from the selected date changed event
/// </summmary>
RCCalendar.prototype.RemoveHandler_OnSelectedDateChaged = function( handler )
{
    this._RemoveHandler( RCCalendarEvents.OnSelectedDateChanged, handler );
} // RemoveHandler_OnSelectedDateChaged

/// <summary>
/// Saves the current state of the control to the hidden fields
/// for post back validation
/// </summmary>
RCCalendar.prototype._Save = function()
{
    this._SaveVisibleDate();
    this._SaveSelectedDate();
    this._SaveSelectedDates();
} // _Save

/// <summary>
/// Saves the current selected dates of the control to the hidden fields
/// for post back validation
/// </summmary>
RCCalendar.prototype._SaveSelectedDates = function()
{
    var hiddenSelectedDates = null;
    var calendarDay = null;
    
    hiddenSelectedDates = $( this.ID + '_SelectedDateList' );
    hiddenSelectedDates.value = '';
    
    for (var i = 0; i < this._selectedDates.GetSize(); i++)
    {
        calendarDay = this._selectedDates.GetValueAt(i);
        
        if ( calendarDay == null )
            continue;
    
        if ( i > 0 )
            hiddenSelectedDates.value += ',';
            
        hiddenSelectedDates.value += calendarDay.Date.toCustomString();
    }
} // _SaveSelectedDates

/// <summary>
/// Saves the current selected date of the control to the hidden fields
/// for post back validation
/// </summmary>
RCCalendar.prototype._SaveSelectedDate = function()
{
    var hiddenSelectedDate = null;
    
    hiddenSelectedDate = $( this.ID + '_SelectedDate' );
    
    if ( this.SelectedDate != null )
        hiddenSelectedDate.value = this.SelectedDate.toCustomString();
    else
        hiddenSelectedDate.value = '';
} // _SaveSelectedDate

/// <summary>
/// Saves the current visible date of the control to the hidden fields
/// for post back validation
/// </summmary>
RCCalendar.prototype._SaveVisibleDate = function()
{
    var hiddenVisibleDate = null;
    
    hiddenVisibleDate = $( this.ID + '_VisibleDate' );
    hiddenVisibleDate.value = this.VisibleDate.toCustomString();
} // _SaveVisibleDate

/// <summary>
/// Initializes the Calendar object
/// </summmary>
RCCalendar.prototype.Init = function()
{
    var handler = null;
    var calendarContainer = null;
    var form = null;
    
    if ( this.VisibleDate == null )
        this.VisibleDate = this.TodaysDate.clone();
        
    if ( this.Behavior == RCBehavior.Picker ||
         this.Behavior == RCBehavior.LitePicker ||
         this.Behavior == RCBehavior.PickerAndCalendarPopUp )
    {
        //if ( this.SelectedDate == null )
        //    this.SelectedDate = this.TodaysDate.clone();
        
        /*
        //Add the calendar popup container to the main document body instead
        //of having it into the same container of the main container
        calendarContainer = this._GetCalendarContainer();
        form = $( RC_FormID );
        calendarContainer.parentNode.removeChild( calendarContainer );
        form.appendChild( calendarContainer );
        */
        
        handler = new Function('event', 'Window_OnResize(' + this.ID + ', event)');
        //Attach the window resize event
        AttachEventHandler(window, 'resize', handler);
        
        //Get initial window size
        this._windowSize.width = document.Screen.Width();
        this._windowSize.height = document.Screen.Height();
    
        this.Picker.Init();
    }
} // Init

/// <summary>
/// Raises a post back to the server
/// </summmary>
RCCalendar.prototype.PostBack = function()
{
} // PostBack

/// <summary>
/// Clear the Date
/// </summmary>
RCCalendar.prototype.ClearDate = function()
{
    this._SelectDate( null, true );
    this.Hide();
} // ClearDate

/// <summary>
/// Go To Todays Date
/// </summmary>
RCCalendar.prototype.GoToTodaysDate = function()
{
    if ( this.ReadOnly ) 
        this.SetVisibleDate( this.TodaysDate );
    else
        this._SelectDate( this.TodaysDate, true );
    
    this.Hide();
} // GoToTodaysDate

/// <summary>
/// Get the main calendar HTML object container
/// </summmary>
RCCalendar.prototype._GetCalendarContainer = function()
{
    return $( this.ID + '_CalendarContainer' );
} // _GetCalendarContainer

/// <summary>
/// Get the main HTML object container of the calendar
/// </summmary>
RCCalendar.prototype._GetContainer = function()
{
    if ( this.MainContainerElement == null )
        this.MainContainerElement = $( this.ID + '_Container' );
        
    return this.MainContainerElement;
} // _GetContainer

/// <summary>
/// Returns the day table container
/// </summmary>
RCCalendar.prototype._GetDaysTableContainer = function()
{
    return $( this.ID + '_DaysTable' );
} // _GetDaysTableContainer

/// <summary>
/// Returns the calendar title container
/// </summmary>
RCCalendar.prototype._GetCalendarTitleContainer = function()
{
    return $( this.ID + '_CalendarTitle' );
} // _GetCalendarTitleContainer

/// <summary>
/// Returns true if the calendar is a multimonth instance and false if not
/// </summmary>
RCCalendar.prototype._IsMultiMonth = function()
{
    var multiMonth = false;
    
    multiMonth = ( this.MonthRowCount != 1 || this.MonthColumnCount != 1 );
    
    return multiMonth;
} // _IsMultiMonth

/// <summary>
/// Sets the calendar visible date
/// </summmary>
RCCalendar.prototype.SetVisibleDate = function( dateObject, forceToShow )
{
    var tempFunction = null;
    var fireEvent = false;
    var thisRef = this;
    var doProcess = false;
    
    //Exit function if the given date object is null
    if ( dateObject == null )
        return;
    
    //Check if must exit the process or not
    if ( this.Behavior == RCBehavior.PickerAndCalendarPopUp && 
         ! this._popupVisible )
    {
        doProcess = false;
    }
    //If the calendar is a picker instance
    else if ( this.Behavior == RCBehavior.Picker )
    {
        doProcess = false;
    }
    //If the calendar is a multi month instance
    else if ( this._IsMultiMonth() )
    {
        var start = this.VisibleDate.clone();
        var end = start.clone();

        start.setDate( 1 );
        start.setMinTime();
        
        end.setMonth( end.getMonth() + (this.MonthRowCount * this.MonthColumnCount) - 1 );
        end.setDate( $DaysInMonth( end.getMonth(), end.getFullYear() ) );
        end.setMaxTime();
        
        //Check for the date range
        if ( dateObject < start || dateObject > end )
            doProcess = true;
    }
    //if other than a picker or multi calendar instance
    else
    {
        if ( forceToShow || 
             this.VisibleDate.getMonth() != dateObject.getMonth() ||
             this.VisibleDate.getFullYear() != dateObject.getFullYear() )
        {
            doProcess = true;
        }
    }
         
    //Check if must execute the process or not
    if ( doProcess )
    {
        fireEvent = ! this.VisibleDate.equals( dateObject );
    
        //update this instance visible date
        this.VisibleDate = dateObject.clone();
        
        if ( fireEvent )
        {
            //Fire Event
            this._FireEvent(RCCalendarEvents.OnVisibleDateChanged, [this, dateObject.clone()]);
            
            //Save state
            this._SaveVisibleDate();
        }

        if ( ! this._effectOnProgress )
        {
            //Show the new visible date to the user
            if ( this._IsMultiMonth() )
                this._SetVisibleDateMultiMonth( dateObject.clone() );
            else
                this._SetVisibleDate( dateObject.clone() );
        }
        else
        {
            //make sure is showing the visible date (a delay can take place here
            //so we run this function to make sure the selected visible date is
            //showing to the user)
            
            //Create the function that checks for the correct visible date
            tempFunction = function()
                {      
                    window.clearTimeout( thisRef._tempTimer );
                                  
                    if ( thisRef._effectOnProgress )
                        thisRef._tempTimer = window.setTimeout( tempFunction, 100 );
                    else
                        thisRef.SetVisibleDate( thisRef.VisibleDate, true );
                };
            
            tempFunction();
        }
    }
} // SetVisibleDate

/// <summary>
/// Sets the calendar visible date
/// </summmary>
RCCalendar.prototype._SetVisibleDate = function( dateObject )
{
    var newCalendar = null;
    var oldCalendar = null;
    var daysTable = null;
    var daysTableContainer = null;
    var calendarTitleContainer = null;
    var ajaxEffect = null;
    var tempFunction = null;
    var thisRef = this;
    
    //get the calendar title container
    calendarTitleContainer = this._GetCalendarTitleContainer();
    
    this._effectOnProgress = true;
        
    //Get the day tables container
    daysTableContainer = this._GetDaysTableContainer();
    //Get the old calendar container
    oldCalendar = daysTableContainer.childNodes[0];
    //Create the new calendar container
    newCalendar = document.createElement( 'div' );
    
    //get the days table object
    daysTable = this._BuildDaysTable( dateObject );
    
    //set the HTML content
    newCalendar.innerHTML = daysTable.ToHTML(); 
    
    //save height and width
    daysTableContainer.style.width = GetWidth( oldCalendar ) + 'px';
    daysTableContainer.style.height = GetHeight( oldCalendar ) + 'px';
    newCalendar.style.width = GetWidth( oldCalendar ) + 'px';
    newCalendar.style.height = GetHeight( oldCalendar ) + 'px';
    
    //Update positions
    newCalendar.style.position = 'absolute';
    oldCalendar.style.position = 'absolute';
    
    //update id's
    newCalendar.id = this.ID + '_NewCalendar';
    oldCalendar.id = this.ID + '_OldCalendar';
    
    //sort elements
    daysTableContainer.removeChild( oldCalendar );
    daysTableContainer.appendChild( newCalendar );
    daysTableContainer.appendChild( oldCalendar );
    
    daysTableContainer.style.position = 'relative';
    daysTableContainer.style.overflow = 'hidden';

    //do the ajax stuff
    switch ( this.SwapMonthEffect )
    {
        case RCSwapMonthEffect.None:
            newCalendar.style.visibility = 'visible';
            daysTableContainer.removeChild( oldCalendar );
            this.RefreshVisibleContent();
            this._effectOnProgress = false;
            break;
            
        case RCSwapMonthEffect.Slide:
            ajaxEffect = new RCSlide2
                ( 
                    oldCalendar.id, 
                    this.SwapMonthSpeed,
                    (
                        ( ! this._isIncrementingMonth ) ?
                            GetWidth(oldCalendar) + GetLeft(oldCalendar) :
                            GetLeft(oldCalendar) - GetWidth(oldCalendar)
                    )
                );
                
            ajaxEffect.Vertically = false;
            
            ajaxEffect.onSlideFinished = function() 
                                        {
                                            daysTableContainer.removeChild( oldCalendar );
                                            newCalendar.style.left = '0px'; 
                                            thisRef._effectOnProgress = false;
                                        };
            ajaxEffect.onSlideLooped = function()
                                        {
                                            oldCalendar.style.width = GetWidth(newCalendar) + 'px';
                                            
                                            if ( ! thisRef._isIncrementingMonth )
                                                newCalendar.style.left = GetLeft(oldCalendar) - GetWidth(newCalendar) + 'px';
                                            else
                                                newCalendar.style.left = GetWidth(newCalendar) + GetLeft(oldCalendar) + 'px';
                                        };
            ajaxEffect.onSlideStart = function()
                                        {
                                            //get the calendar days
                                            var listObjs = oldCalendar.getElementsByTagName( 'td' );
                                            
                                            for (var i = 0; i < listObjs.length; i++)
                                            {
                                                //Change the id to delete any conflicts with the new
                                                //calendar days objects
                                                listObjs[i].id += '_old';
                                            }
                                            
                                            thisRef.RefreshVisibleContent();
                                        };
            ajaxEffect.ExecuteHide();
            break;
    
        default:
            alert( 'Invalid swap month effect \'' + this.SwapMonthEffect + '\'' );
            break;
    }
    
    //Set the new calendar title
    calendarTitleContainer.innerHTML = 
        this._GetMonthName( this.VisibleDate.getMonth() ) + ', ' + 
        this.VisibleDate.getFullYear();
} // _SetVisibleDate

/// <summary>
/// Sets the multi month calendar visible date
/// </summmary>
RCCalendar.prototype._SetVisibleDateMultiMonth = function( dateObject )
{
    var newCalendar = null;
    var oldCalendar = null;
    var calendars = null;
    var divContainer = null;
    var calendarTitleContainer = null;
    var ajaxEffect = null;
    var tempFunction = null;
    var thisRef = this;
    
    //get the calendar title container
    calendarTitleContainer = this._GetCalendarTitleContainer();
    
    this._effectOnProgress = true;
        
    //Get the day tables container
    divContainer = $( this.ID + '_MultiMonthContainer' );
    //Get the old calendars container
    oldCalendar = divContainer.childNodes[0];
    //Create the new calendars container
    newCalendar = document.createElement( 'div' );
    
    //get the calendars
    calendars = this._BuildMultiMonth( dateObject );
    
    //set the HTML content
    newCalendar.innerHTML = calendars.ToHTML(); 
    
    //save height and width
    divContainer.style.width = GetWidth( oldCalendar ) + 'px';
    divContainer.style.height = GetHeight( oldCalendar ) + 'px';
    newCalendar.style.width = GetWidth( oldCalendar ) + 'px';
    newCalendar.style.height = GetHeight( oldCalendar ) + 'px';
    
    //update positions
    newCalendar.style.position = 'absolute';
    oldCalendar.style.position = 'absolute';
    
    //update id's
    newCalendar.id = this.ID + '_NewCalendar';
    oldCalendar.id = this.ID + '_OldCalendar';
    
    //sort elements
    divContainer.removeChild( oldCalendar );
    divContainer.appendChild( newCalendar );
    divContainer.appendChild( oldCalendar );
    
    divContainer.style.position = 'relative';
    divContainer.style.overflow = 'hidden';

    //do the ajax stuff
    switch ( this.SwapMonthEffect )
    {
        case RCSwapMonthEffect.None:
            newCalendar.style.visibility = 'visible';
            divContainer.removeChild( oldCalendar );
            this.RefreshVisibleContent();
            this._effectOnProgress = false;
            break;
            
        case RCSwapMonthEffect.Slide:
            ajaxEffect = new RCSlide2
                (
                    oldCalendar.id, 
                    this.SwapMonthSpeed,
                    (
                        ( ! this._isIncrementingMonth ) ?
                            GetWidth(oldCalendar) + GetLeft(oldCalendar) :
                            GetLeft(oldCalendar) - GetWidth(oldCalendar)
                    )
                );
                
            ajaxEffect.Vertically = false;
            
            ajaxEffect.onSlideFinished = function() 
                                        {
                                            divContainer.removeChild( oldCalendar );
                                            newCalendar.style.left = '0px'; 
                                            thisRef._effectOnProgress = false;
                                        };
            ajaxEffect.onSlideLooped = function()
                                        {
                                            oldCalendar.style.width = GetWidth(newCalendar) + 'px';
                                            
                                            if ( ! thisRef._isIncrementingMonth )
                                                newCalendar.style.left = GetLeft(oldCalendar) - GetWidth(newCalendar) + 'px';
                                            else
                                                newCalendar.style.left = GetWidth(newCalendar) + GetLeft(oldCalendar) + 'px';
                                        };
            ajaxEffect.onSlideStart = function()
                                        {
                                            thisRef.RefreshVisibleContent();
                                        };
            ajaxEffect.ExecuteHide();
            break;
    
        default:
            alert( 'Invalid swap month effect \'' + this.SwapMonthEffect + '\'' );
            break;
    }
    
    //Set the new calendar title
    calendarTitleContainer.innerHTML = 
        this._GetMonthName( this.VisibleDate.getMonth() ) + ' ' + this.VisibleDate.getFullYear() + ' To ' +
        this._GetMonthName( dateObject.getMonth() ) + ' ' + dateObject.getFullYear();
} // _SetVisibleDateMultiMonth

/// <summary>
/// Go to the next year
/// </summmary>
RCCalendar.prototype.NextYear = function()
{
    var visibleDate = null;

    visibleDate = this.VisibleDate.clone();
    visibleDate.setFullYear( visibleDate.getFullYear() + 1 );
    
    this._isIncrementingMonth = true;
    this.SetVisibleDate( visibleDate );
} // NextYear

/// <summary>
/// Go to the previous year
/// </summmary>
RCCalendar.prototype.PreviousYear = function()
{
    var visibleDate = null;
    
    visibleDate = this.VisibleDate.clone();
    visibleDate.setFullYear( visibleDate.getFullYear() - 1 );
    
    this._isIncrementingMonth = false;
    this.SetVisibleDate( visibleDate );
} // PreviousYear

/// <summary>
/// Go to the previous month
/// </summmary>
RCCalendar.prototype.PreviousMonth = function()
{
    var visibleDate = null;
    
    //Set the new visible date
    visibleDate = this.VisibleDate.clone();
    
    if ( this._IsMultiMonth() )
        visibleDate.setMonth( visibleDate.getMonth() - (this.MonthRowCount * this.MonthColumnCount)  );
    else
        visibleDate.setMonth( visibleDate.getMonth() - 1 );
    
    this._isIncrementingMonth = false;
    this.SetVisibleDate( visibleDate );
} // PreviousMonth

/// <summary>
/// Go to the next month
/// </summmary>
RCCalendar.prototype.NextMonth = function()
{
    var visibleDate = null;
    
    //Set the new visible date
    visibleDate = this.VisibleDate.clone();
    
    if ( this._IsMultiMonth() )
        visibleDate.setMonth( visibleDate.getMonth() + (this.MonthRowCount * this.MonthColumnCount)  );
    else
        visibleDate.setMonth( visibleDate.getMonth() + 1 );
    
    this._isIncrementingMonth = true;
    this.SetVisibleDate( visibleDate );
} // NextMonth

/// <summary>
/// Build and returns the calendar header
/// </summmary>
RCCalendar.prototype._BuildHeader = function( visibleDate )
{
    var table = null;
    var row = null;
    var cell = null;
    var titleSpan = null;
    
    //create the table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    table.Style.Add('width', '100%');
    
    //add the title row
    row = new RCHTMLObject( 'tr' );
    table.AddControl( row );
    
    //Add the date title cell
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.Attributes.Add('class', this.Style.Title);
    titleSpan = new RCHTMLObject( 'span' );
    titleSpan.Attributes.Add('id', this.ID + '_CalendarTitle');
    cell.AddControl( titleSpan );
    titleSpan.AddControl( this._GetMonthName( visibleDate.getMonth() ) );
    titleSpan.AddControl( ', ' );
    titleSpan.AddControl( visibleDate.getFullYear() );
    
    if ( this.Behavior == RCBehavior.CalendarPopUp ||
         this.Behavior == RCBehavior.LitePicker ||
         this.Behavior == RCBehavior.PickerAndCalendarPopUp )
    {
        //Add the close button cell
        cell = new RCHTMLObject( 'td' );
        row.AddControl( cell );
        cell.Attributes.Add('class', this.Style.Close);
        cell.Attributes.Add('onclick', this.ID + '.Hide()');
        cell.AddControl( '&nbsp;' );
    }
    
    return table;
} // _BuildHeader

/// <summary>
/// Build and returns the calendar header for the multi month calendar
/// </summmary>
RCCalendar.prototype._BuildHeaderMultiMonth = function( visibleDateStart, visibleDateEnd )
{
    var table = null;
    var row = null;
    var cell = null;
    var titleSpan = null;
    
    //create the table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    table.Style.Add('width', '100%');
    
    //add the title row
    row = new RCHTMLObject( 'tr' );
    table.AddControl( row );
    
    //Add the date title cell
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.Attributes.Add('class', this.Style.Title);
    titleSpan = new RCHTMLObject( 'span' );
    titleSpan.Attributes.Add('id', this.ID + '_CalendarTitle');
    cell.AddControl( titleSpan );
    
    titleSpan.AddControl( this._GetMonthName( visibleDateStart.getMonth() ) );
    titleSpan.AddControl( ' ' );
    titleSpan.AddControl( visibleDateStart.getFullYear() );
    titleSpan.AddControl( ' To ' );
    titleSpan.AddControl( this._GetMonthName( visibleDateEnd.getMonth() ) );
    titleSpan.AddControl( ' ' );
    titleSpan.AddControl( visibleDateEnd.getFullYear() );
    
    if ( this.Behavior == RCBehavior.CalendarPopUp ||
         this.Behavior == RCBehavior.LitePicker ||
         this.Behavior == RCBehavior.PickerAndCalendarPopUp )
    {
        //Add the close button cell
        cell = new RCHTMLObject( 'td' );
        row.AddControl( cell );
        cell.Attributes.Add('class', this.Style.Close);
        cell.Attributes.Add('onclick', this.ID + '.Hide()');
        cell.AddControl( '&nbsp;' );
    }
    
    return table;
} // _BuildHeaderMultiMonth

/// <summary>
/// Build and returns the calendar navigation
/// </summmary>
RCCalendar.prototype._BuildNavigation = function()
{
    var MAX_DROPDOWNITEMS = 10;
    var table = null;
    var row = null;
    var cell = null;
    var nextYearButton = null;
    var nextMonthButton = null;
    var previousMonthButton = null;
    var previousYearButton = null;
    var thisRef = this;
    
    //create the table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    table.Style.Add('width', '100%');
    
    //add the navigation row
    row = new RCHTMLObject( 'tr' );
    table.AddControl( row );
    
    //Add the previous year button cell    
    cell = new RCDropDownButton( this, this.ID + '_NavigationPreviousYear', 'td', 
                                 this.Style.PreviousYear, this.Style.PreviousYearOver,
                                 this.Style.PreviousYearPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.PreviousYear()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                key,
                thisRef.VisibleDate.getMonth(),
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef._isIncrementingMonth = false;
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
        cell.Items.Add( this.VisibleDate.getFullYear() - i, this.VisibleDate.getFullYear() - i );
        
    previousYearButton = cell;
    
    //Add the previous button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationPrevious', 'td', 
                                 this.Style.Previous, this.Style.PreviousOver,
                                 this.Style.PreviousPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.PreviousMonth()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                thisRef.VisibleDate.getFullYear(),
                key,
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef._isIncrementingMonth = false;
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 0; i < this.MonthNames.length; i++)
    {
        cell.Items.Add( i, this._GetMonthName(i) );
       
        if ( this.VisibleDate.getMonth() == i )
            cell.SelectedItemIndex = i;
    }
    previousMonthButton = cell;
    
    //Add the date title cell
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildTodaysLink() );
    if ( ! this.ReadOnly )
    {
        cell.AddControl( '&nbsp;' );
        cell.AddControl( this._BuildClearLink() );
    }
    cell.Attributes.Add( 'class', this.Style.TodaysDateButton );    
    
    //Add the next button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationNext', 'td', 
                                 this.Style.Next, this.Style.NextOver,
                                 this.Style.NextPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.NextMonth()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                thisRef.VisibleDate.getFullYear(),
                key,
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef._isIncrementingMonth = true;
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 0; i < this.MonthNames.length; i++)
    {
        cell.Items.Add( i, this._GetMonthName(i) );
       
        if ( this.VisibleDate.getMonth() == i )
            cell.SelectedItemIndex = i;
    }
    nextMonthButton = cell;    
    
    //Add the next year button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationNextYear', 'td', 
                                 this.Style.NextYear, this.Style.NextYearOver,
                                 this.Style.NextYearPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.NextYear()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                key,
                thisRef.VisibleDate.getMonth(),
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef._isIncrementingMonth = true;
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
        cell.Items.Add( this.VisibleDate.getFullYear() + i, this.VisibleDate.getFullYear() + i );
        
    nextYearButton = cell;    
    
    //Set the event handler for the navigation menu
    this.AddHandler_OnVisibleDateChanged( 
        function(calendar, dateObj)
        {
            nextMonthButton.SelectedItemIndex = dateObj.getMonth();
            previousMonthButton.SelectedItemIndex = dateObj.getMonth();
            
            //If the year has changed
            if ( nextYearButton.Items.GetValueAt( 0 ) != thisRef.VisibleDate.getFullYear() - 1 )
            {
                previousYearButton.Items.Clear();
                nextYearButton.Items.Clear();
                
                for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
                    previousYearButton.Items.Add( thisRef.VisibleDate.getFullYear() - i, thisRef.VisibleDate.getFullYear() - i );
                
                for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
                    nextYearButton.Items.Add( thisRef.VisibleDate.getFullYear() + i, thisRef.VisibleDate.getFullYear() + i );
            }
        }
    );
    
    return table;
} // _BuildNavigation

/// <summary>
/// Build and returns the calendar navigation for the multimonth calendar
/// </summmary>
RCCalendar.prototype._BuildNavigationMultiMonth = function()
{
    var MAX_DROPDOWNITEMS = 10;
    var table = null;
    var row = null;
    var cell = null;
    var nextYearButton = null;
    var nextMonthButton = null;
    var previousMonthButton = null;
    var previousYearButton = null;
    var thisRef = this;
    
    //create the table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    table.Style.Add('width', '100%');
    
    //add the navigation row
    row = new RCHTMLObject( 'tr' );
    table.AddControl( row );
    
    //Add the previous year button cell    
    cell = new RCDropDownButton( this, this.ID + '_NavigationPreviousYear', 'td', 
                                 this.Style.PreviousYear, this.Style.PreviousYearOver,
                                 this.Style.PreviousYearPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.PreviousYear()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                key,
                thisRef.VisibleDate.getMonth(),
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
        cell.Items.Add( this.VisibleDate.getFullYear() - i, this.VisibleDate.getFullYear() - i );
        
    previousYearButton = cell;
    
    //Add the previous button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationPrevious', 'td', 
                                 this.Style.Previous, this.Style.PreviousOver,
                                 this.Style.PreviousPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.PreviousMonth()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                thisRef.VisibleDate.getFullYear(),
                key,
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 0; i < this.MonthNames.length; i++)
    {
        cell.Items.Add( i, this._GetMonthName(i) );
       
        if ( this.VisibleDate.getMonth() == i )
            cell.SelectedItemIndex = i;
    }
    previousMonthButton = cell;
    
    //Add the date title cell
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildTodaysLink() );
    if ( ! this.ReadOnly )
    {
        cell.AddControl( '&nbsp;' );
        cell.AddControl( this._BuildClearLink() );
    }
    cell.Attributes.Add( 'class', this.Style.TodaysDateButton );
    
    //Add the next button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationNext', 'td', 
                                 this.Style.Next, this.Style.NextOver,
                                 this.Style.NextPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.NextMonth()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                thisRef.VisibleDate.getFullYear(),
                key,
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 0; i < this.MonthNames.length; i++)
    {
        cell.Items.Add( i, this._GetMonthName(i) );
       
        if ( this.VisibleDate.getMonth() == i )
            cell.SelectedItemIndex = i;
    }
    nextMonthButton = cell;    
    
    //Add the next year button cell
    cell = new RCDropDownButton( this, this.ID + '_NavigationNextYear', 'td', 
                                 this.Style.NextYear, this.Style.NextYearOver,
                                 this.Style.NextYearPressed, this.Style.DropDownList );
    row.AddControl( cell );
    cell.Attributes.Add('onclick', this.ID + '.NextYear()');
    cell.AddControl( '&nbsp;' );
    
    cell.OnItemSelected = 
        function (sender, key)
        {
            var dateObj = new Date(
                key,
                thisRef.VisibleDate.getMonth(),
                thisRef.VisibleDate.getDate(),
                thisRef.VisibleDate.getHours(),
                thisRef.VisibleDate.getMinutes(),
                thisRef.VisibleDate.getSeconds(),
                thisRef.VisibleDate.getMilliseconds()
            );
            thisRef.SetVisibleDate( dateObj );
        };
    
    for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
        cell.Items.Add( this.VisibleDate.getFullYear() + i, this.VisibleDate.getFullYear() + i );
        
    nextYearButton = cell;    
    
    //Set the event handler for the navigation menu
    this.AddHandler_OnVisibleDateChanged( 
        function(calendar, dateObj)
        {
            nextMonthButton.SelectedItemIndex = dateObj.getMonth();
            previousMonthButton.SelectedItemIndex = dateObj.getMonth();
            
            //If the year has changed
            if ( nextYearButton.Items.GetValueAt( 0 ) != thisRef.VisibleDate.getFullYear() - 1 )
            {
                previousYearButton.Items.Clear();
                nextYearButton.Items.Clear();
                
                for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
                    previousYearButton.Items.Add( thisRef.VisibleDate.getFullYear() - i, thisRef.VisibleDate.getFullYear() - i );
                
                for (var i = 1; i <= MAX_DROPDOWNITEMS; i++)
                    nextYearButton.Items.Add( thisRef.VisibleDate.getFullYear() + i, thisRef.VisibleDate.getFullYear() + i );
            }
        }
    );
    
    return table;
} // _BuildNavigationMultiMonth

/// <summary>
/// Builds the today link button
/// </summmary>
RCCalendar.prototype._BuildTodaysLink = function()
{
    var control = null;
    
    control = new RCHTMLObject( 'a' );
    control.AddControl( this.TodayCaption );
    control.Attributes.Add( 'href', 'javascript:void(0);' );
    control.Attributes.Add( 'onclick', this.ID + '.GoToTodaysDate()' );
    
    return control;
} // _BuildTodaysLink

/// <summary>
/// Builds the clear link button
/// </summmary>
RCCalendar.prototype._BuildClearLink = function()
{
    var control = null;
    
    control = new RCHTMLObject( 'a' );
    control.AddControl( this.ClearCaption );
    control.Attributes.Add( 'href', 'javascript:void(0);' );
    control.Attributes.Add( 'onclick', this.ID + '.ClearDate()' );
    
    return control;
} // _BuildClearLink

/// <summary>
/// Returns the month name
/// </summmary>
RCCalendar.prototype._GetMonthName = function( monthIndex )
{
    var monthName = null;
    
    switch ( this.MonthNameFormat )
    {
        case RCNameFormat.Short:
            monthName = this.AbbreviatedMonthNames[monthIndex];
            break;
            
        case RCNameFormat.Full:
            monthName = this.MonthNames[monthIndex];
            break;
            
        case RCNameFormat.FirstTwoLetters:
            monthName = this.MonthNames[monthIndex].substring(0, 2);
            break;
            
        case RCNameFormat.FirstLetter:
            monthName = this.MonthNames[monthIndex].substring(0, 1);
            break;
              
        default:
            alert( 'Invalid Month Name Format: \'' + this.MonthNameFormat + '\'' );
            break;
    }
    
    return monthName;
} // _GetMonthName

/// <summary>
/// Build and returns the calendar day header.
/// (A row with 7 cells representing all the 7 days of the week)
/// </summmary>
RCCalendar.prototype._BuildDayHeader = function()
{
    var tempDay = null;
    var row = null;
    var cell = null;
    
    if ( this.DayNameFormat != RCNameFormat.None )
    {
        //add a new row for the header
        row = new RCHTMLObject( 'tr' );
        row.Attributes.Add( 'class', this.Style.DayHeader );
        
        //Set initial day name index
        tempDay = this.FirstDayOfWeek;
        
        //Add the calendar header
        for (var day = 0; day < DAYS_ON_WEEK; day++)
        {
            //add a new cell for the day name
            //cell = row.AddCell();
            cell = new RCHTMLObject( 'td' );
            row.AddControl( cell );
            
            switch ( this.DayNameFormat )
            {
                case RCNameFormat.Short:
                    cell.AddControl( this.AbbreviatedDayNames[tempDay] );
                    break;
                    
                case RCNameFormat.Full:
                    cell.AddControl( this.DayNames[tempDay] );
                    break;
                    
                case RCNameFormat.FirstTwoLetters:
                    cell.AddControl( this.DayNames[tempDay].substring(0, 2) );
                    break;
                    
                case RCNameFormat.FirstLetter:
                    cell.AddControl( this.DayNames[tempDay].substring(0, 1) );
                    break;
                      
                default:
                    alert( 'Invalid Day Name Format: \'' + this.DayNameFormat + '\'' );
                    break;
            }
            
            //get the day name index
            tempDay++;
            if ( tempDay > DAYS_ON_WEEK - 1 )
                tempDay = 0;
        }
    }
    
    return row;
} // _BuildDayHeader

/// <summary>
/// Build and appends to the given parent table
/// all the day rows of the calendar for the given
/// visible date
/// </summmary>
RCCalendar.prototype._BuildDaysRows = function( parentTable, visibleDate, dontShowOtherMonthDays )
{
    var row = null;
    var calendarDay = null;
    var currentDate = null;
    var daysToBacktrack = null;
    var isOtherMonthDay = null;
    var dayVisible = true;
    
    //Calculate dates for the process
    currentDate = visibleDate.clone();
    currentDate.setFullYear
    (
        visibleDate.getFullYear(), 
        visibleDate.getMonth(), 
        1
    );
    daysToBacktrack = currentDate.getDay() - this.FirstDayOfWeek;
    currentDate.setFullYear
    (
        currentDate.getFullYear(), 
        currentDate.getMonth(), 
        currentDate.getDate() - daysToBacktrack
    );
    
    //Add the calendar days
    for (var week = 0; week < WEEK_COUNT; week++)
    {
        //add a new row for the week
        row = new RCHTMLObject( 'tr' );
        parentTable.AddControl( row );
        
        for (var day = 0; day < DAYS_ON_WEEK; day++)
        {
            if ( dontShowOtherMonthDays )
            {
                isOtherMonthDay = ( currentDate.getMonth() != visibleDate.getMonth() );
                dayVisible = ! isOtherMonthDay;
            }
        
            //Create a new calendar day object
            calendarDay = new RCCalendarDay( this, new Date( currentDate.clone() ), false, dayVisible );
            
            if ( ! dontShowOtherMonthDays || (dontShowOtherMonthDays && ! isOtherMonthDay) )
            {
                //Update selection status
                
                if ( this.SelectedDate != null && calendarDay.Date.equals(this.SelectedDate) )
                    calendarDay.Selected = true;
                else if ( this._selectedDates.ContainsKey( calendarDay.Date.getUniqueId() ) )
                    calendarDay.Selected = true;
                
                if ( dayVisible )
                {
                    //Update the list of visible calendar days
                    this._visibleCalendarDays.Add( calendarDay.Date.getUniqueId(), calendarDay );
                }
            }
            
            //add the calendar day cell to the row
            row.AddControl( calendarDay );
            
            //Advance to the next day
            currentDate.setDate( currentDate.getDate() + 1 );
        }
    }
} // _BuildDaysRows

/// <summary>
/// Build and returns the day table object
/// </summmary>
RCCalendar.prototype._BuildDaysTable = function( visibleDate, dontShowOtherMonthDays, addMonthTitle )
{
    var div = null;
    var table = null;
    var row = null;
    var cell = null;
    
    //create the main table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    
    if ( addMonthTitle )
    {
        row = new RCHTMLObject( 'tr' );
        table.AddControl( row );
        
        cell = new RCHTMLObject( 'td' );
        //colspan = 7 because there are 7 cells (7 days of week)
        cell.Attributes.Add( 'colspan', 7 );
        cell.Attributes.Add( 'class', this.Style.MonthTitle );
        row.AddControl( cell );
        
        cell.AddControl( this._GetMonthName(visibleDate.getMonth()) + ' ' + visibleDate.getFullYear() );
    }
    
    //Add the calendar days header
    table.AddControl( this._BuildDayHeader() );
    
    //Append the day rows to the calendar table
    this._BuildDaysRows( table, visibleDate, dontShowOtherMonthDays );
    
    //Create the wrap div
    div = new RCHTMLObject( 'div' );
    div.AddControl( table );
    div.Style.Add('overflow', 'hidden');
    
    return div;
} // _BuildDaysTable

/// <summary>
/// Render the calendar behavior type 'RCBehavior.Calendar'
/// </summmary>
RCCalendar.prototype._RenderCalendar = function( mainContainer, visibleDate )
{
    var html = null;
    var calendar = null;
    var table = null;
    var row = null;
    var cell = null;
    var divDaysTableContainer = null;
    
    //create the main table
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add('cellspacing', 0);
    table.Attributes.Add('cellpadding', 0);
    
    //create the calendar main container
    calendar = new RCHTMLObject( 'table' );
    calendar.Attributes.Add( 'class', this.Style.Calendar );
    calendar.Attributes.Add( 'cellspacing', 0 );
    calendar.Attributes.Add( 'cellpadding', 0 );
    
    //Add the calendar header title
    row = new RCHTMLObject( 'tr' );
    calendar.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildHeader(visibleDate) );
    
    //Add the calendar navigation
    row = new RCHTMLObject( 'tr' );
    calendar.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildNavigation() );
    
    //Add the container of the calendar days table
    divDaysTableContainer = new RCHTMLObject( 'div' ); 
    divDaysTableContainer.AddControl( this._BuildDaysTable(visibleDate) );
    divDaysTableContainer.Attributes.Add('id', this.ID + '_DaysTable');
    
    row = new RCHTMLObject( 'tr' );
    calendar.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( divDaysTableContainer );
    
    //Add the table to the calendar main container
    row = new RCHTMLObject( 'tr' );
    calendar.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( table );
    
    //Render the control to the container
    mainContainer.innerHTML = calendar.ToHTML();
} // _RenderCalendar

/// <summary>
/// Render the calendar behavior type 'RCBehavior.PickerAndCalendarPopUp'
/// </summmary>
RCCalendar.prototype._RenderPickerAndCalendarPopUp = function( mainContainer, visibleDate )
{
    var image = null;
    var container = null;
    var pickerContainer = null;
    var table = null;
    var row = null;
    var col = null;
    
    container = this._GetContainer();
    
    //Get the image element
    image = this._CreateImagePopup();    
    this.PopupControlAnchorID = image.Attributes.Get( 'id' );
    
    //Create the AJAX Effect object
    this._InitPopUpAJAXEffect( mainContainer );
    
    if ( this._IsMultiMonth() )
    {
        //render the multi month calendar
        this._RenderMultiMonthCalendar( mainContainer, visibleDate );
    }
    else
    {
        //Render the calendar
        this._RenderCalendar( mainContainer, visibleDate );
    }
    
    table = new RCHTMLObject( 'table' );
    table.Attributes.Add( 'cellspacing', 0 );
    table.Attributes.Add( 'cellpadding', 0 );
    
    row = new RCHTMLObject( 'tr' );
    table.AddControl( row );
    
    col = new RCHTMLObject( 'td' );
    row.AddControl( col );
    col.AddControl( this.Picker );
    
    col = new RCHTMLObject( 'td' );
    row.AddControl( col );
    col.AddControl( '&nbsp;' );
    
    col = new RCHTMLObject( 'td' );
    row.AddControl( col );
    col.AddControl( image );
    
    pickerContainer = document.createElement( 'div' );
    pickerContainer.innerHTML = table.ToHTML();
    container.appendChild( pickerContainer );
    
    this.Picker.ShowDate();
} // _RenderPickerAndCalendarPopUp

/// <summary>
/// Render the calendar behavior type 'RCBehavior.LitePicker'
/// </summmary>
RCCalendar.prototype._RenderLitePicker = function( mainContainer, visibleDate )
{
    var container = null;
    var pickerContainer = null;
    
    container = this._GetContainer();
    
    //Create the AJAX Effect object
    this._InitPopUpAJAXEffect( mainContainer );
    
    if ( this._IsMultiMonth() )
    {
        //render the multi month calendar
        this._RenderMultiMonthCalendar( mainContainer, visibleDate );
    }
    else
    {
        //Render the calendar
        this._RenderCalendar( mainContainer, visibleDate );
    }
    
    pickerContainer = document.createElement( 'div' );
    pickerContainer.innerHTML = this.Picker.ToHTML();
    container.appendChild( pickerContainer );
    
    this.Picker.ShowDate();
} // _RenderLitePicker

/// <summary>
/// Render the calendar behavior type 'RCBehavior.CalendarPopUp'
/// </summmary>
RCCalendar.prototype._RenderCalendarPopUp = function( mainContainer, visibleDate )
{
    var image = null;
    var imageElement = null;
    var container = null;
    
    container = this._GetContainer();
    
    //Get the image element
    image = this._CreateImagePopup();    
    this.PopupControlAnchorID = image.Attributes.Get( 'id' );
    
    //Create the AJAX Effect object
    this._InitPopUpAJAXEffect( mainContainer );
    //Render the calendar
    this._RenderCalendar( mainContainer, visibleDate );
    
    //Append elements
    imageElement = document.createElement( 'div' );
    imageElement.innerHTML = image.ToHTML();
    container.appendChild( imageElement );
} // _RenderCalendarPopUp

/// <summary>
/// Builds and returns a multi month object
/// </summmary>
RCCalendar.prototype._BuildMultiMonth = function( currentDate )
{
    var table = null;
    var row = null;
    var cell = null;
    var divContainer = null;
    
    divContainer = new RCHTMLObject( 'div' );
    divContainer.Attributes.Add( 'id', this.ID + '_MultiMonthContainer' );
    divContainer.Style.Add( 'background-color', 'white' );
    
    table = new RCHTMLObject( 'table' );
    divContainer.AddControl( table );
    table.Attributes.Add( 'cellpadding', 5 );
    table.Attributes.Add( 'cellspacing', 5 );
    
    for (var rowCount = 0; rowCount < this.MonthRowCount; rowCount++)
    {
        row = new RCHTMLObject( 'tr' );
        table.AddControl( row );
    
        for (var columnCount = 0; columnCount < this.MonthColumnCount; columnCount++)
        {
            cell = new RCHTMLObject( 'td' );
            row.AddControl( cell );
            
            cell.AddControl( this._BuildDaysTable( currentDate, true, true ) );
            
            //Update the current date to the next month
            currentDate.setMonth( currentDate.getMonth() + 1 );
        }
    }
    
    //Fix to the last month of the builded calendars
    currentDate.setMonth( currentDate.getMonth() - 1 );
            
    return divContainer;
} // _BuildMultiMonth

/// <summary>
/// Render the multi month calendar popup behavior
/// </summmary>
RCCalendar.prototype._RenderMultiMonthCalendarPopUp = function( mainContainer, visibleDate )
{
    var image = null;
    var imageElement = null;
    var container = null;
    
    container = this._GetContainer();
    currentDate = this.VisibleDate.clone();
    
    //Get the image element
    image = this._CreateImagePopup();
    this.PopupControlAnchorID = image.Attributes.Get( 'id' );
    
    //Create the AJAX Effect object
    this._InitPopUpAJAXEffect( mainContainer );
    
    //render the multi month calendar
    this._RenderMultiMonthCalendar( mainContainer, visibleDate );
    
    //Append elements
    imageElement = document.createElement( 'div' );
    imageElement.innerHTML = image.ToHTML();
    container.appendChild( imageElement );
} // _RenderMultiMonthCalendarPopUp


/// <summary>
/// Render the multi month calendar
/// </summmary>
RCCalendar.prototype._RenderMultiMonthCalendar = function( mainContainer, visibleDate )
{
    var container = null;
    var calendars = null;
    var row = null;
    var cell = null;
    var currentDate = null;
    var mainTable = null;
    
    container = this._GetContainer();
    currentDate = visibleDate.clone();
    
    mainTable = new RCHTMLObject( 'table' );
    mainTable.Attributes.Add( 'cellpadding', 0 );
    mainTable.Attributes.Add( 'cellspacing', 0 );
    mainTable.Attributes.Add( 'class', this.Style.MultiMonthContainer );
    
    //build the calendars
    calendars = this._BuildMultiMonth( currentDate );
    
    //Add the calendar header title
    row = new RCHTMLObject( 'tr' );
    mainTable.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildHeaderMultiMonth( this.VisibleDate, currentDate ) );
    
    //Add the navigation menu
    row = new RCHTMLObject( 'tr' );
    mainTable.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( this._BuildNavigationMultiMonth() );
    
    //Add the calendars
    row = new RCHTMLObject( 'tr' );
    mainTable.AddControl( row );
    cell = new RCHTMLObject( 'td' );
    row.AddControl( cell );
    cell.AddControl( calendars );

    mainContainer.innerHTML = mainTable.ToHTML();
} // _RenderMultiMonthCalendar

/// <summary>
/// Creates and returns the image popup element
/// </summmary>
RCCalendar.prototype._CreateImagePopup = function()
{
    var img = null;
    
    img = new RCHTMLObject( 'img' );
    img.Attributes.Add( 'id', this.ID + '_CalendarImagePopup' );
    img.Attributes.Add( 'title', 'Click to show the calendar' );
    img.Attributes.Add( 'alt', 'Click to show the calendar' );
    img.Attributes.Add( 'src', this.PopupButtonImage );
    img.Attributes.Add( 'onclick', this.ID + '.Show()' );
    img.Style.Add( 'cursor', 'pointer' );
    
    return img;
} // _CreateImagePopup

/// <summary>
/// Initializes the ajax effect object for this calendar instance
/// </summmary>
RCCalendar.prototype._InitPopUpAJAXEffect = function( container )
{
    //Init the container propeties
    container.style.display = 'block';
    container.style.visibility = 'hidden';
    container.style.position = 'absolute';
    container.style.zIndex = '100';
    container.style.overflow = 'hidden';
        
    if ( this._ajaxEffectObj == null )
    {
        switch ( this.PopupEffect )
        {
            case RCPopupEffect.Slide:
                this._ajaxEffectObj = new RCSlide( container.id, this.PopupSpeed );
                break;
                
            case RCPopupEffect.Fade:
                this._ajaxEffectObj = new RCFade( container.id, this.PopupSpeed );
                break;
                
            case RCPopupEffect.None:
                this._ajaxEffectObj = new RCFade( container.id, 100 );
                break;
                
            case RCPopupEffect.ElasticOut:
                this._ajaxEffectObj = new RCMotion( container.id );
                this._ajaxEffectObj.MotionType = RCMotionType.ElasticOut;
                this._ajaxEffectObj.Duration = this.PopupSpeed;
                break;
                
            case RCPopupEffect.BounceOut:
                this._ajaxEffectObj = new RCMotion( container.id );
                this._ajaxEffectObj.MotionType = RCMotionType.BounceOut;
                this._ajaxEffectObj.Duration = this.PopupSpeed;
                break;
                
            case RCPopupEffect.BackOut:
                this._ajaxEffectObj = new RCMotion( container.id );
                this._ajaxEffectObj.MotionType = RCMotionType.BackOut;
                this._ajaxEffectObj.Duration = this.PopupSpeed;
                break;
        
            default:
                alert('Invalid Popup Effect \'' + this.PopupEffect + '\'');
                break;
        }
    }
    
    if ( this._mouseUpHandler == null )
    {
        this._mouseUpHandler = new Function('event', 'Document_OnMouseUpHandler(' + this.ID + ', event)');
        //Attach the document mouse up event
        AttachEventHandler(document, 'mouseup', this._mouseUpHandler);
    }
} // _InitPopUpAJAXEffect

/// <summary>
/// Shows the calendar to the user
/// </summmary>
RCCalendar.prototype.Show = function()
{
    var position = null;
    var container = null;
    var controlAnchor = null;
    
    if ( ! this._popupVisible && 
         ( this.Behavior == RCBehavior.CalendarPopUp || 
           this.Behavior == RCBehavior.PickerAndCalendarPopUp ||
           this.Behavior == RCBehavior.LitePicker ||
           this._IsMultiMonth() ) )
    {
        //Update state
        this._popupVisible = true;
        
        //get the container
        container = this._GetCalendarContainer();
        //get the anchor control
        controlAnchor = $( this.PopupControlAnchorID );
        //get the position
        //position = $Pos( this.PopupControlAnchorID );
        position = $PosTillFirstAbsoluteParentFound( this.PopupControlAnchorID );
        
        //Set the popup display position
        switch ( this.PopupPosition )
        {
            case RCPopupPosition.Left:
                //set left
                position[0] -= GetWidth(container);
                break;
                
            case RCPopupPosition.LeftMiddle:
                //set left
                position[0] -= GetWidth(container);
                //set top
                position[1] -= ( GetHeight(container) / 2 );
                break;
                
            case RCPopupPosition.Right:
                //set left
                position[0] += GetWidth(controlAnchor);
                break;
                
            case RCPopupPosition.RightMiddle:
                //set left
                position[0] += GetWidth(controlAnchor);
                //set top
                position[1] -= ( GetHeight(container) / 2 );
                break;
                
            case RCPopupPosition.BottomLeft:
                //set top
                position[1] += GetHeight(controlAnchor);
                break;
                
            case RCPopupPosition.BottomRight:
                //set top
                position[1] += GetHeight(controlAnchor);
                //set left
                position[0] += GetWidth(controlAnchor) - GetWidth(container);
                break;
                
            case RCPopupPosition.BottomMiddle:
                //set top
                position[1] += GetHeight(controlAnchor);
                //set left
                position[0] += ( ( GetWidth(controlAnchor) - GetWidth(container) ) / 2 );
                break;
                
            case RCPopupPosition.TopLeft:
                //set top
                position[1] -= GetHeight(container);
                break;
                
            case RCPopupPosition.TopRight:
                //set top
                position[1] -= GetHeight(container);
                //set left
                position[0] += GetWidth(controlAnchor) - GetWidth(container);
                break;
                
            case RCPopupPosition.TopMiddle:
                //set top
                position[1] -= GetHeight(container);
                //set left
                position[0] += ( ( GetWidth(controlAnchor) - GetWidth(container) ) / 2 );
                break;
            
            default:
                alert( 'Invalid popup display position' );
                break;
        }
        
        switch ( this.PopupEffect )
        {
            case RCPopupEffect.Slide:
                this._ajaxEffectObj.Vertically = ( this.PopupOrientation == RCOrientation.Vertical );
                container.style.left = position[0] + 'px';
                container.style.top = position[1] + 'px';
                break;
                
            case RCPopupEffect.Fade:
            case RCPopupEffect.None:
                container.style.top = position[1] + 'px';
                container.style.left = position[0] + 'px';
                this._ajaxEffectObj.SetInitialOpacity( 0 );
                break;
                
            case RCPopupEffect.ElasticOut:
            case RCPopupEffect.BounceOut:
            case RCPopupEffect.BackOut:
                this._ajaxEffectObj.StartPosition = -500;
                if ( this.PopupOrientation == RCOrientation.Vertical )
                {
                    this._ajaxEffectObj.StyleProperty = 'top';
                    this._ajaxEffectObj.SetFinish( position[1] );
                    container.style.left = position[0] + 'px';
                }
                else
                {
                    container.style.top = position[1] + 'px';
                    this._ajaxEffectObj.StyleProperty = 'left';
                    this._ajaxEffectObj.SetFinish( position[0] );
                }
                break;
        
            default:
                alert('Invalid Popup Effect \'' + this.PopupEffect + '\'');
                break;
        }
        
        //Execute the ajax effect
        this._ajaxEffectObj.ExecuteShow();
        
        //Set visible date
        if ( this.SelectedDate != null )
            this.SetVisibleDate( this.SelectedDate );
    }
} // Show

/// <summary>
/// Hide the calendar from the user
/// </summmary>
RCCalendar.prototype.Hide = function()
{
    if ( this._popupVisible && 
         ( this.Behavior == RCBehavior.CalendarPopUp ||
           this.Behavior == RCBehavior.LitePicker ||
           this.Behavior == RCBehavior.PickerAndCalendarPopUp || 
           this._IsMultiMonth() ) )
    {
        this._ajaxEffectObj.ExecuteHide();
        this._popupVisible = false;
    }
} // Hide

/// <summary>
/// Render the date picker control
/// </summmary>
RCCalendar.prototype._RenderPicker = function( mainContainer, visibleDate )
{
    //Render the control to the container
    mainContainer.innerHTML = this.Picker.ToHTML();
    this.Picker.ShowDate();
} // _RenderPicker

/// <summary>
/// Render the calendar control
/// </summmary>
RCCalendar.prototype._Render = function( container, calendarBehavior, visibleDate )
{
    //Clear visible calendar dates
    this._visibleCalendarDays.Clear();
    
    switch ( calendarBehavior )
    {
        case RCBehavior.Calendar:
            if ( this._IsMultiMonth() )
                this._RenderMultiMonthCalendar( container, visibleDate );
            else
                this._RenderCalendar( container, visibleDate );
            break;
            
        case RCBehavior.CalendarPopUp:
            if ( this._IsMultiMonth() )
                this._RenderMultiMonthCalendarPopUp( container, visibleDate );
            else
                this._RenderCalendarPopUp( container, visibleDate );
            break;
            
        case RCBehavior.Picker:
            this._RenderPicker( container, visibleDate );
            break;
            
        case RCBehavior.PickerAndCalendarPopUp: 
            this._RenderPickerAndCalendarPopUp( container, visibleDate );
            break;
            
        case RCBehavior.LitePicker: 
            this._RenderLitePicker( container, visibleDate );
            break;
    
        default:
            alert('Invalid RichDatePicker Behavior \'' + calendarBehavior + '\'');
            break;
    }
} // _Render

/// <summary>
/// Render the calendar control
/// </summmary>
RCCalendar.prototype.Render = function()
{
    var container = null;
    var calendarContainer = null;
    
    if ( this.IsVisible )
    {
        //get the main container
        container = this._GetContainer();
        
        calendarContainer = $( this.ID + '_CalendarContainer' );
        
        //Render
        this._Render( calendarContainer, this.Behavior, this.VisibleDate );
        
        //Refresh visual content
        this.RefreshVisibleContent();
    }
} // Render

/// <summary>
/// Shows the control to the user
/// </summmary>
RCCalendar.prototype.ShowControl = function()
{
    if ( ! this.IsVisible )
    {
        this.IsVisible = true;
        this.Render();
    }
} // ShowControl

/// <summary>
/// Hides the control from the user
/// </summmary>
RCCalendar.prototype.HideControl = function()
{
    var container = null;

    if ( this.IsVisible )
    {
        //get the main container
        container = this._GetContainer();
        
        if ( container.hasChildNodes() )
            while ( container.childNodes.length > 0 )
                container.removeChild( container.firstChild );
                
        this.IsVisible = false;
    }
} // HideControl

//Show and HIde functions here-----------------------------------------------------------------------------------------------------

/// <summary>
/// Adds the given array of date objects to 
/// this calendar instance selected dates list
/// </summmary>
RCCalendar.prototype.AddSelectedDateRange = function( dateArray )
{
    for (var i = 0; i < dateArray.length; i++)
        this._SelectDate( dateArray[i], false );
} // AddSelectedDateRange

/// <summary>
/// Checks if the given date is selected or not
/// </summmary>
RCCalendar.prototype.IsDateSelected = function( dateObject )
{
    return this._selectedDates.ContainsKey( dateObject.getUniqueId() );
} // IsDateSelected

/// <summary>
/// Add a new date to the selected dates collection
/// of the calendar object
/// </summmary>
RCCalendar.prototype._SelectDate = function( dateObject, raiseEvent )
{
    var calendarDay = null;
    var tempDateObject = null;
    
    //Update dates
    this.SetVisibleDate( dateObject );
    this.SelectedDate = dateObject;
    
    this._SaveSelectedDate();
    
    if ( this.Behavior == RCBehavior.Picker )
    {
        this.Picker.ShowDate();
    }
    else
    {
        if ( this.Behavior == RCBehavior.PickerAndCalendarPopUp ||
             this.Behavior == RCBehavior.LitePicker )
        {
            this.Picker.ShowDate();
        }
        
        if ( dateObject != null )
        {
            //get the calendar day
            calendarDay = this.GetCalendarDay( dateObject.getUniqueId() );
            
            //check for the calendar day to exists
            if ( calendarDay == null )
                calendarDay = new RCCalendarDay( this, dateObject, false );
            
            if ( ! this.AllowMultipleSelection )
            {
                //Clear any selection
                this._selectedDates.Clear();
                
                //Unselect all the other selected dates
                this._visibleCalendarDays.PerformCallOnValueObject('Unselect');
            }
                
            //add it to the list if not selected already
            if ( ! this._selectedDates.ContainsKey( calendarDay.Date.getUniqueId() ) )
                this._selectedDates.Add( calendarDay.Date.getUniqueId(), calendarDay );
            
            //Update calendar day object status
            calendarDay.Select();
        }
        else
        {
            //Clear any selection
            this._selectedDates.Clear();
            
            //Unselect all the other selected dates
            this._visibleCalendarDays.PerformCallOnValueObject('Unselect');
        }
        
        this._SaveSelectedDates();
    }
    
    if ( dateObject != null )
        tempDateObject = dateObject.clone();
    else
        tempDateObject = null;
    
    if ( raiseEvent ) 
    {
        //Call event
        this._FireEvent( RCCalendarEvents.OnSelectedDateChanged, [this, tempDateObject] );
    }
    
    if ( this.AutoPostBack )
    {
        //Postback to the server
        this.PostBack();
    }
} // _SelectDate

/// <summary>
/// Add a new date to the selected dates collection
/// of the calendar object
/// </summmary>
RCCalendar.prototype.SelectDate = function( dateObject )
{
    this._SelectDate( dateObject, false );
} // SelectDate

/// <summary>
/// Removes the given date from this calendar instance
/// selected dates collection
/// </summmary>
RCCalendar.prototype.UnselectDate = function( dateObject )
{
    var calendarDay = null;
    
    //get the calendar day
    calendarDay = this._selectedDates.Get( dateObject.getUniqueId() );
    
    //check for the calendar day to exists
    if ( calendarDay != null )
    {
        //remove it from the list
        this._selectedDates.Remove( calendarDay.Date.getUniqueId() );
        
        this._SaveSelectedDates();
        
        //Update calendar day object status
        calendarDay.Unselect();
        
        //Call event
        this._FireEvent( RCCalendarEvents.OnRemoveSelectedDate, [this, calendarDay.Date.clone()] );
    }
} // UnselectDate

/// <summary>
/// Check the selection status for the given date
/// </summmary>
RCCalendar.prototype.OnClick_SelectDate = function( time )
{
    var date = null;
    
    //Get the date object
    date = new Date( time );
    
    if ( this.Behavior == RCBehavior.CalendarPopUp ||
         this.Behavior == RCBehavior.LitePicker ||
         this.Behavior == RCBehavior.PickerAndCalendarPopUp )
    {
        if ( ! this.IsDateSelected( date ) )
            this._SelectDate( date, true );
            
        this.Hide();
    }
    else
    {     
        //check selection status
        if ( ! this.IsDateSelected( date ) )
            this._SelectDate( date, true );
        else
        {
            this.SelectedDate = null;
            this.UnselectDate( date );
        }
    }
} // OnClick_SelectDate

/// <summary>
/// Refresh the visual content of the calendar
/// </summmary>
RCCalendar.prototype.RefreshVisibleContent = function()
{
    //Refresh style on visible calendar days
    this._visibleCalendarDays.PerformCallOnValueObject('UpdateStyle');
} // RefreshVisibleContent

/// <summary>
/// Returns the calendar day object
/// </summmary>
RCCalendar.prototype.GetCalendarDay = function( dateId )
{
    return this._visibleCalendarDays.Get( dateId );
} // GetCalendarDay

/****************************************
*               RCCalendarDay
*****************************************/

/// <summary>
/// Richer Components - Calendar Day Class
/// </summmary>
function RCCalendarDay( calendar, date, selected, visible )
{
    this.Calendar = calendar;
    this.Date = date;
    this.Selected = selected;
    this.Visible = ( visible ) ? true : false;
} // RCCalendar

/// <summary>
/// Update 
/// </summmary>
RCCalendarDay.prototype.UpdateStyle = function( mouseOver )
{
    var appliedStyle = null;
    var dayControl = null;
    var visibleDate = null;
    var id = null;
    
    //get the id
    id = this.Calendar.ID + '_' + this.Date.getUniqueId();
    
    //Get the visible date
    visibleDate = this.Calendar.VisibleDate;
    //get the day control
    dayControl = $( id );
    
    //if this date belongs to the same month
    if ( this.Selected )
        appliedStyle = this.Calendar.Style.DaySelected;
    else if ( mouseOver )
        appliedStyle = this.Calendar.Style.DayHover;
    else if ( this.Date.sameMonthAndYear( visibleDate ) || this.Calendar._IsMultiMonth() )
        appliedStyle = this.Calendar.Style.Day;
    else
        appliedStyle = this.Calendar.Style.DayOtherMonth;
    
    //Set the style to the control
    if ( dayControl != null )
        dayControl.className = appliedStyle;
        
    return appliedStyle;
} // UpdateStyle

/// <summary>
/// Select this calendar day on the calendar
/// </summmary>
RCCalendarDay.prototype.Select = function()
{
    if ( ! this.Selected )
    {
        this.Selected = true;
        this.UpdateStyle();
    }
} // Select

/// <summary>
/// Unselect this calendar day on the calendar
/// </summmary>
RCCalendarDay.prototype.Unselect = function()
{
    if ( this.Selected )
    {
        this.Selected = false;
        this.UpdateStyle();
    }
} // Unselect

/// <summary>
/// Occurs when the mouse is over this instance of day
/// </summmary>
RCCalendarDay.prototype.OnMouseOver = function()
{
    this.UpdateStyle( true );
} // OnMouseOver

/// <summary>
/// Occurs when the mouse is out of this instance of day
/// </summmary>
RCCalendarDay.prototype.OnMouseOut = function()
{
    this.UpdateStyle();
} // OnMouseOut

/// <summary>
/// Returns the HTML markup for this instance
/// </summmary>
RCCalendarDay.prototype.ToHTML = function()
{
    var control = null;
    var visibleDate = null;
    var dateId = null;
    var id = null;
    
    //get the id
    dateId = this.Date.getUniqueId();
    id = this.Calendar.ID + '_' + dateId;
    
    //Get the visible date
    visibleDate = this.Calendar.VisibleDate;
    
    control = new RCHTMLObject( 'td' );
    control.Attributes.Add( 'class', this.UpdateStyle() );
    
    if ( this.Visible )
    {
        control.AddControl( this.Date.getDate() );
        control.Attributes.Add( 'id', id );
        control.Attributes.Add
        ( 
            'onmouseover', 
            this.Calendar.ID + '.GetCalendarDay(' + dateId + ').OnMouseOver();'
        );
        control.Attributes.Add
        ( 
            'onmouseout', 
            this.Calendar.ID + '.GetCalendarDay(' + dateId + ').OnMouseOut();'
        );
        if ( ! this.Calendar.ReadOnly )
        {
            control.Attributes.Add
            ( 
                'onclick', 
                this.Calendar.ID + '.OnClick_SelectDate(' + this.Date.valueOf() + ')' 
            );
        }
    }
    else
    {
        control.AddControl( '&nbsp;' );
    }
    
    return control.ToHTML();
} // ToHTML

/****************************************
*               Global Functions
*****************************************/

/// <summary>
/// Handles the mouse up event over the whole document
/// </summmary>
function Document_OnMouseUpHandler( calendar, event )
{
    var target = null;
    var hide = false;
    var container = null;
    var controlAnchor = null;
    
    if ( calendar._hideOnNextMouseUp )
    {
        if ( calendar._popupVisible && 
             ( calendar.Behavior == RCBehavior.CalendarPopUp ||
               calendar.Behavior == RCBehavior.LitePicker ||
               calendar.Behavior == RCBehavior.PickerAndCalendarPopUp ||
               calendar._IsMultiMonth() ) )
        {   
            //Get the container
            container = calendar._GetCalendarContainer();
            //get the control anchor
            controlAnchor = $( calendar.PopupControlAnchorID );
        
            //Check for the event
            if( ! event )
                event = window.event;
                
            //Get the target element
            target = event.target ? event.target : event.srcElement;
            
            //Check if should hide the popup or not
            if ( target != container )
            {
                if ( target == null )
                {
                    hide = true;
                }
                else if ( controlAnchor != null && controlAnchor == target )
                {
                    hide = false;
                }
                else if ( container.contains )
                {
                    hide = ! container.contains(target);
                }
                else
                {
                    while ( target.parentNode ) 
                    {
                        target = target.parentNode; 
                        if ( target == container )
                            break;
                    }
                    hide = (target != container);
                }
            }
            
            //Hide the control
            if ( hide )
                calendar.Hide();
        }
    }
    else
    {
        calendar._hideOnNextMouseUp = true;
    }
} // Document_OnMouseUpHandler

/// <summary>
/// Handles the window resize event
/// </summmary>
function Window_OnResize( calendar, event )
{
    var newWidth = document.Screen.Width();
    var newHeight = document.Screen.Height();
    
    if ( calendar != null &&
         ( calendar._windowSize.width != newWidth || 
           calendar._windowSize.height != newHeight ) )
    {
        calendar._windowSize.width = newWidth;
        calendar._windowSize.height = newHeight;
        
        calendar.Hide();
    }
} // Window_OnResize