var isInitialised = false;
//var isSearchDirtyEnoughForPostback;
//var blockAutoScroll = false;
//var isNavigatingCalendar = true;
//var tblMainTables;
var numberOfDaysVisibleOnCalendar;
var pricingTablesNeedRateRefresh = false;

var ddlMonth;
var ddlDayOfMonth;
var ddlNights;
var ddlAdults;
var ddlChildren;
var ddlConcessions;
var isAccomm;


window.onload = makeDoubleDelegate(window.onload, initialisation);


function initialisation() {
    if (initialiseGoogleMaps) initialiseGoogleMaps();
    //if (!(document.getElementById("ControlId_ddlMonth") && document.getElementById(document.getElementById("ControlId_ddlMonth").value))) return;

    try {
        /*
        ddlMonth = document.getElementById(document.getElementById("ControlId_ddlMonth").value);
        ddlDayOfMonth = document.getElementById(document.getElementById("ControlId_ddlDayOfMonth").value);
        ddlNights = document.getElementById(document.getElementById("ControlId_ddlNights").value);
        ddlAdults = document.getElementById(document.getElementById("ControlId_ddlAdults").value);
        ddlChildren = document.getElementById(document.getElementById("ControlId_ddlChildren").value);
        ddlConcessions = document.getElementById(document.getElementById("ControlId_ddlConcessions").value);
        radAccommodation = document.getElementById(document.getElementById("ControlId_radAccommodation").value);
        */
        /*
        var displayStartDate = document.getElementById('displayStartDate');
        if (displayStartDate == null || displayStartDate == '') isNavigatingCalendar = true;
        else isNavigatingCalendar = false;
        */
        var element = document.getElementById('BookNowButtonData');
        if (element) element.value = "";

        element = document.getElementById('numberOfDaysVisibleOnCalendar');
        if (element) numberOfDaysVisibleOnCalendar = parseInt(element.value, 10);
 
        
        var tables = document.getElementsByTagName('table');
        var lst = new Array();
        var tblMainCount = 0;
        for (var i = 0; i < tables.length; i++) {
            if (tables[i].id.indexOf('tblMain') >= 0) {
                lst[tblMainCount++] = tables[i];
            }
        }
        tblMainTables = lst;

        document.body.onunload = function() { hideWaitingCursor(); };
        window.onunload = function() { hideWaitingCursor(); };

        window.onscroll = function() { setWaitingDivLocations(); setCalendarPopupVisible(false); }
        window.onresize = function() { setWaitingDivLocations(); setCalendarPopupVisible(false); }

        /*
        if (isSearchDirtyEnoughForPostback) {
            disablePricingTables();
        } else {
            processPricingTablesWithWaiting();
        }*/

        var waitingDivs = document.createElement('div');
        waitingDivs.id = 'waitingDivs';
        waitingDivs.style.cssText = 'display:none; position:absolute;left:0px;top:0px;width:100%;height:100%;float:none;';

            var waitingBackground = document.createElement('div');
            waitingBackground.id = 'waitingBackground';
            waitingBackground.style.cssText = 'position:absolute;left:0px;top:0px;width:100%;height:100%;float:none;';
            waitingBackground.className = 'pob_busy_indicator_background';
            waitingDivs.appendChild(waitingBackground);

            var waitingAnimation = document.createElement('img');
            waitingAnimation.id = 'waitingAnimation';
            waitingAnimation.src = '../branding/default/images/ajax-loader.gif';
            waitingAnimation.style.cssText = 'display:block;  position:absolute; float:left';
            waitingAnimation.className = 'pob_busy_indicator_animation';
            waitingDivs.appendChild(waitingAnimation);


        document.body.appendChild(waitingDivs);
        
        isInitialised = true;
    }
    finally {
    
    }
};

function getFirstPriceCellIndex(row) {
    return 1;
    /*if(isAccomm()) return 3;
    else return 2;*/
}

/*
function disablePricingTables() {

    if (pricingTablesNeedRateRefresh) {
        return; 
    }
    
    pricingTablesNeedRateRefresh = true;
    
    for (var i = 0; i < tblMainTables.length; i++) {

        var spanContainer = tblMainTables[i].parentNode;

        var e = tblMainTables[i];
        var rleft   = e.offsetLeft;
        var rtop    = e.offsetTop;
        var rwidth  = e.offsetWidth;
        var rheight = e.offsetHeight;

        var headerIndex = getHeaderRowIndex(e);
        if(headerIndex != 0){
            var customHeaderHeight = e.rows[0].offsetHeight;
            rheight = rheight - customHeaderHeight;
            rtop = rtop + customHeaderHeight; 
        }
        
        var div = document.createElement('div');
        div.className       = 'pob_calendar_strip_disabling_mask';
        div.style.position  = "absolute";

        div.style.left   = rleft + 'px';
        div.style.top    = rtop + 'px';
        div.style.width  = rwidth + 'px';
        div.style.height = rheight + 'px';
        
        var text = document.createElement('label');
        text.style.position = "absolute";
        text.className = 'pob_calendar_strip_disabling_mask_text';
        text.innerHTML = 'The prices displayed are no longer valid as you have changed the search criteria.<BR />Please <a href="#" onclick="return btnSearch();">click here</a> to update prices.';

        spanContainer.insertBefore(text, tblMainTables[i]);
        text.style.top  = (rtop  + ((rheight - text.clientHeight) / 2)) + 'px';
        text.style.left = (rleft + ((rwidth  - text.clientWidth ) / 2)) + 'px';

        spanContainer.insertBefore(div, tblMainTables[i]);
    }
}
*/

/*
function mouseMoved(e) {
    if (!e) {
        if (window.event) {
            //Internet Explorer
            e = window.event;
        } else {
            //total failure, we have no way of referencing the event
            return;
        }       
    }           
    if (typeof (e.pageX) == 'number') {
        //most browsers
        currentMouseX = e.pageX;
        currentMouseY = e.pageY;
    } else if (typeof (e.clientX) == 'number') {
        //Internet Explorer and older browsers
        //other browsers provide this, but follow the pageX/Y branch
        currentMouseX = e.clientX;
        currentMouseY = e.clientY;
    } else {
        //total failure, we have no way of obtaining the mouse coordinates
        return;
    }

    if (currentPopup != null && currentPopup.style.display != "none") {
        currentPopup.style.left = (currentMouseX - currentPopup.parentElement.clientLeft) + 'px';
    }
}*/

function performPostback() {
    
    var form = document.getElementById('V3_FORM');
    if (form == null && document.forms.length >= 1) { form = document.forms[0]; }

    if (form != null) {
        form.submit();
        showWaitingCursor();
    }
}

function showWaitingCursor() {
    var div = document.getElementById('waitingDivs');
    if(div) div.style.display = "";

    setWaitingDivLocations();
    //window.onscroll = setWaitingDivLocations;
    //window.onresize = setWaitingDivLocations;

}

function hideWaitingCursor() {
    try { document.getElementById('waitingDivs').style.display = "none"; }
    catch (e) { }
}


function setWaitingDivLocations() {

    var scrollTop = document.body.scrollTop;

    if (scrollTop == 0) {
        if (window.pageYOffset) { scrollTop = window.pageYOffset; }
        else                    { scrollTop = (document.body.parentElement) ? document.body.parentElement.scrollTop : 0; }
    }

    var div = document.getElementById('waitingDivs');
    if (div) {
        div.style.top = scrollTop + 'px';
    }
    /* div = document.getElementById('waitingAnimation');
    
    //div.style.top = scrollTop + 'px';
    
    var viewport = getViewportDimensions();
    div.style.width  = (viewport.width  == 0) ? 50 : parseInt(viewport.width , 10) + 'px';
    div.style.height = (viewport.height == 0) ? 50 : parseInt(viewport.height, 10) + 'px';
    
    //var left = (viewport.width == 0) ? 50 : parseInt((viewport.width - elem.offsetWidth) / 2, 10);
    //var top = (viewport.height == 0) ? 50 : parseInt((viewport.height - elem.offsetHeight) / 2, 10);
    */
    
    var image = document.getElementById('waitingAnimation');
    centerElement(image);
}


function btnSearch() {

    isNavigatingCalendar = false; //this will now allow postback's when the booking date isn't found.

    if (validateSearchForm()) {
        document.getElementById("displayStartDate").value = ""; //reset the display, the user has clicked the search button
        document.getElementById("BookNowButtonData").value = ""; //reset any booking details form, the user has clicked the search button
        performPostback();
    }
    return false;

}

function validateSearchForm() {
    var hasNoChildrenField    = (ddlChildren == undefined || ddlChildren == null);
    var hasNoConcessionsField = (ddlConcessions == undefined || ddlConcessions == null);

    if (ddlAdults.selectedIndex == 0 && (hasNoChildrenField || ddlChildren.selectedIndex == 0) && (hasNoConcessionsField || ddlConcessions.selectedIndex == 0)) {
        alert('Please select number of people');
        return false;
    }

    var dayOfMonth = parseInt(ddlDayOfMonth.options[ddlDayOfMonth.selectedIndex].value, 10);
    var monthText = ddlMonth.options[ddlMonth.selectedIndex].value;
    var strDate = dayOfMonth + " " + ARR_STRINGS['short_month'][parseInt(monthText.substr(5, 2), 10) - 1] + " " + monthText.substr(0, 4);

    var currentDATE = new Date();
    currentDATE.setHours(0, 0, 0, 0);

    if (Date.parse(strDate) < currentDATE) {
        alert("Please select a date in the future");
        return false;
    }
    
    return true;
}

function storeBookButtonInformation(sender, buttonParams) {
    
    //var isAccom = isAccomm();
    //var ddlMonth = getSearchControl("ddlMonth");
    //var ddlDayOfMonth = getSearchControl("ddlDayOfMonth");
    /*
    var ddl = getSearchControl("ddlNights");
    var numOfNights = parseInt(ddl.options[ddl.selectedIndex].value, 10);  //getSearchControl("ddlNights").selectedIndex + 1;
    
    ddl = getSearchControl("ddlAdults");
    var numOfAdults= parseInt(ddl.options[ddl.selectedIndex].value, 10);
    
    ddl = getSearchControl("ddlChildren");
    var numOfChildren = parseInt(ddl.options[ddl.selectedIndex].value, 10);
    if (!isAccom) { numOfNights = 1; }                        
    */var bookingDate = ddlMonth.options[ddlMonth.selectedIndex].value.substr(0, 8) + ddlDayOfMonth.options[ddlDayOfMonth.selectedIndex].value;
    /*
    document.getElementById('BookNowButtonData').value = buttonParams + '|' + bookingDate + '|' + numOfNights + '|' + numOfAdults + '|' + numOfChildren + '|' + isAccom;
    */
    document.getElementById('BookNowButtonData').value = buttonParams + '|' + bookingDate;
    setTimeout(showWaitingCursor, 300);
    //performPostback();
}

function scollButtonClicked(scrollDelta, newDate) {
    isNavigatingCalendar = true;

    if (tblMainTables == null || tblMainTables.length == 0) {
        return;
    }

    var delta = scrollDelta;
    while (delta != 0) {
        if (canScrollRow(tblMainTables[0].rows[getHeaderRowIndex(tblMainTables[0])], delta) == true) { //if scroll header row is successful
            scrollDelta = delta;
            break;
        }
        if (scrollDelta > 0) {
            delta--;
        } else {
            delta++;
        }
    }

    if (delta == 0) {
        if (newDate != '') {
            document.getElementById('displayStartDate').value = newDate;
            performPostback();
        }
    }
    else {
        processPricingTablesWithWaiting(scrollDelta); // == true && newDate != '') {
    }
    return false; 
}

function setBookingDate(dateString) {
    setBookingDateWithoutProcessingTables(dateString);
    processPricingTablesWithWaiting();
}

function setBookingDateUsingOffset(offset) {

    var year  = parseInt(ddlMonth.options[ddlMonth.selectedIndex].value.substr(0, 4), 10);
    var month = parseInt(ddlMonth.options[ddlMonth.selectedIndex].value.substr(5, 2), 10) - 1; //Javascript is ZERO based for months
    var day   = ddlDayOfMonth.options[ddlDayOfMonth.selectedIndex].value;

    var d = new Date();
    d.setFullYear(year, month, day);
    d.setDate(d.getDate() + offset);

    //don't try and set it to earlier than today!
    if (d < new Date()) d = new Date();


    //setBookingDate(formatDate(d, 'yyyy MM dd'));
    setBookingDateWithoutProcessingTables(formatDate(d, 'yyyy MM dd'));
    processPricingTables(offset);
    
}

function setBookingDateWithoutProcessingTables(dateString) {
    isNavigatingCalendar = false;
    blockAutoScroll = false;

    //year = parseInt(dateString.substr(0, 4), 10);
    //month = parseInt(dateString.substr(5, 2), 10);
    //day = parseInt(dateString.substr(8, 2), 10);

    var seekingText = dateString.substr(0, 7); //year.toString() + ' ' + (month > 9 ? month.toString() : '0' + month.toString());
    
    if (ddlMonth.options[ddlMonth.selectedIndex] != seekingText) {
        for (var i = 0; i < ddlMonth.options.length; i++) {
            if (ddlMonth.options[i].value.substring(0, 7) == seekingText) {
                ddlMonth.selectedIndex = i;
                break;
            }
        }
        setDaysOfMonth();
    }
    var day = dateString.substr(8, 2);
    for (var i = 0; i < ddlDayOfMonth.options.length; i++) {
        if (ddlDayOfMonth.options[i].value == day) {
            ddlDayOfMonth.selectedIndex = i;
            break;
        }
    }
    
    //ddlNights.selectedIndex = numOfNights - 1;
}


function processPricingTablesWithWaiting() {

    var scrollDelta = 0;

    if (arguments.length == 1) {// && arguments[0] == "scrollTables") {
        scrollDelta = parseInt(arguments[0], 10);
        blockAutoScroll = true;
    }

    if (isSearchDirtyEnoughForPostback == true) { //if search box is dirty, don't do any highlighting at all on the page
        performPostback();
        return;
        //return;
    }

    if (tblMainTables != null) {
        if (tblMainTables.length > 3) { showWaitingCursor(); }
        setTimeout("processPricingTables(" + scrollDelta + ");", 200);
    }
    
    return false;
}

function processPricingTables(scrollDelta) {

    if (tblMainTables == undefined) {
        return;
    }
    
    var doPostback = false;

    try {

        var dayOfMonth = ddlDayOfMonth.options[ddlDayOfMonth.selectedIndex].value;
        if(dayOfMonth < 10) dayOfMonth = '0' + dayOfMonth; //pad left with 0 if single digit
        
        var seekingText = ddlMonth.options[ddlMonth.selectedIndex].value.substring(0, 8)
                          + dayOfMonth;

        var performScroll = false;
        
        var numOfCells= ddlNights.selectedIndex + 1;
        if (numOfCells > numberOfDaysVisibleOnCalendar) {
            numOfCells = numberOfDaysVisibleOnCalendar;
        }
        
        for (var i = 0; i < tblMainTables.length; i++) {
            if (processTable(tblMainTables[i], seekingText, numOfCells, scrollDelta)) {
                doPostback = true;  //needs a postback
            }
        }

        blockAutoScroll = false;
    }
    finally {
        if (doPostback == true) {
            if (!isNavigatingCalendar) {
                performPostback();
                return false;
            }
        }
        hideWaitingCursor();
    }
    return false;
}

function findNearestCell(row, startIndex, direction, limit, styleToLookFor) {
    for (var i = startIndex; i != limit; i += direction) {
        if (row.cells[i].style.display != styleToLookFor) {
            return i; //move to the previous index
        }
    }
    return -1;
}

function canScrollRow(row, scrollDelta) {
    var cellCount = row.cells.length;                           //
    var indexOfFirstPriceCell = 3;   //- row.cells[0].colSpan;       //'logo'      colspan = 1 ~~ (3 - 1) = 2 index of first header cell
    var indexOfLastPriceCell = cellCount - 3;                   //'prod desc' colspan = 2 ~~ (2 - 1) = 1 index of first price cell
    if (scrollDelta < 0) { //scroll backwards in time
        scrollDelta = -scrollDelta; //make number positive
        doHide = false;

        if (row.cells[indexOfFirstPriceCell].style.display == "") {
            return false; //cannot scroll to the left
        }
        ci = findNearestCell(row, indexOfFirstPriceCell, 1, indexOfLastPriceCell, "none");
        if (ci - scrollDelta < indexOfFirstPriceCell) {
            return false;
        }
    }
    else {
        doHide = true;

        if (row.cells[indexOfLastPriceCell].style.display == "") {
            return false; //cannot scroll to the right
        }
        ci = findNearestCell(row, indexOfLastPriceCell, -1, indexOfFirstPriceCell, "none");
        if (ci + scrollDelta > indexOfLastPriceCell) {
            return false;
        }
    }

    return true;
}

function scrollRow(row, scrollDelta) {
    var cellCount = row.cells.length;                           //
    var indexOfFirstPriceCell = getFirstPriceCellIndex(row);  //- row.cells[0].colSpan;       //'logo'      colspan = 1 ~~ (3 - 1) = 2 index of first header cell
    var indexOfLastPriceCell = cellCount - 3;                   //'prod desc' colspan = 2 ~~ (2 - 1) = 1 index of first price cell
                                                                //---------------------------- 
    var successful = false;                                     //|1 logo |2 << < |3 M |4 T |5 W  |
                                                                //----------------------------
    var ci;                                                     //|1product desc  |2 $ |3 $ |4 $  |
    var doHide;                                                 //----------------------------
    var styleTo;

    if (scrollDelta < 0) { //scroll backwards in time
        scrollDelta = -scrollDelta; //make number positive
        doHide = false;

        if (row.cells[indexOfFirstPriceCell].style.display == "") {
            return false;//cannot scroll to the left
        }
        ci = findNearestCell(row, indexOfFirstPriceCell, 1, indexOfLastPriceCell, "none");
        if (ci - scrollDelta < indexOfFirstPriceCell) {
            return false;
        }
    }
    else {
        doHide = true;

        if (row.cells[indexOfLastPriceCell].style.display == "") {
            return false; //cannot scroll to the right
        }
        ci = findNearestCell(row, indexOfLastPriceCell, -1, indexOfFirstPriceCell, "none");
        if (ci + scrollDelta > indexOfLastPriceCell) {
            return false;
        }

    }

    //process cells on left
    styleTo = (doHide ? "none" : "");
    ci = findNearestCell(row, indexOfFirstPriceCell, 1, indexOfLastPriceCell, "none");

    if (ci != -1) {

        for (var i = 0; i < scrollDelta; i++) {
            if (doHide) {
                row.cells[ci + i ].style.display = styleTo;
            }
            else {
                row.cells[ci - i - 1].style.display = styleTo;
            }
            
        }

        successful = true;
    }

    if (!successful) {
        return false;
    }
    else {
        successful = false;
    }

    doHide = !doHide;
    //process cells on the right
    styleTo = (doHide ? "none" : "");
    ci = findNearestCell(row, indexOfLastPriceCell, -1, indexOfFirstPriceCell, "none");

    if (ci != -1) {

        for (var i = 0; i < scrollDelta; i++) {
            if (doHide) {
                row.cells[ci - i].style.display = styleTo;
            }
            else {
                row.cells[ci + i + 1].style.display = styleTo;
            }
        }
        successful = true; // we are finished here
    }

    return successful;

}

function getHeaderRowIndex(table){
    var headerRowIndex = 1;
    
    for (var i = 0; i < table.rows.length; i++) {
        if (table.rows[i].attributes["isDateHeaderRow"]) {
            headerRowIndex = i;
            break;
        }
    }
    
    return headerRowIndex;
}

function processTable(table, seekingText, newNumOfNights, scrollDelta) {
    var rows = table.rows;
    var numRows = rows.length;
    var returnValue = false;
    var headerRowIndex = getHeaderRowIndex(table);
    
    if (scrollDelta != 0) {
        if (scrollRow(rows[headerRowIndex], scrollDelta) == false) { //scroll dates header row
            scrollDelta = 0;
            if (blockAutoScroll) {
                return true;
            }
        }
    }

    for (var i = headerRowIndex + 1; i < numRows; i++) { //start at row index 2, skipping the custom header row, and the dates header row
        if (rows[i].cells.length > 3) { //3 is a magic number!

            resetRow(rows[i]);
            setBookNowButtonEnabled(rows[i], false);
            
            if (scrollDelta != 0) {
                if (!scrollRow(rows[i], scrollDelta)) { //if not successful
                    returnValue = true; //return we need a postback
                }
            }

            if (performRowMerge(rows[headerRowIndex], rows[i], seekingText, newNumOfNights)) {
                returnValue = true; //needs a postback
            }
        }
    }
    return returnValue;
}

function resetRow(row) {

    for (var i = getFirstPriceCellIndex(row); i < row.cells.length - 2; i++) { //length-1 becase we don't want to process the last cell (book now button cell)
        
        if (row.cells[i].attributes["previousValue"] != null) {

            var mergedCell = row.cells[i];
            var previousValue = row.cells[i].attributes["previousValue"].value;
                                
            mergedCell.removeAttribute('previousValue');
            var mergedCellCount = mergedCell.colSpan;
            mergedCell.colSpan = 1;
            mergedCell.innerHTML = previousValue;

            for (var k = 1; k < mergedCellCount; k++) {
                row.cells[i + k].style.display = "";
                //row.cells[i + k].className = "pob_calendar_strip_price_cell";
            }
        }

        if (row.cells[i].innerHTML.indexOf('-', 0) >= 0) {
            row.cells[i].className = "pob_calendar_strip_noprice_cell grid_price_cells";
            row.cells[i].firstChild.className = "pob_calendar_strip_noprice_text";
        }
        else {
            row.cells[i].className = "pob_calendar_strip_price_cell grid_price_cells";
            row.cells[i].firstChild.className = "pob_calendar_strip_price_text";
        }
    }
}

function setBookNowButtonEnabled(row, enabled) {
    var span = row.cells[row.cells.length - 1].firstChild;
    var btn = span.firstChild;
    if (span.innerHTML.indexOf(">Book<") != -1) {
        if (enabled == true ) {
            span.style.display = "";
        }
        else if(enabled == false ) {
            span.style.display = "none";
        }
    }
}

function highlightBookingPeriod(row, startIndex, count) {
    var aCellHasPrice = false;
    var aCellIsInvisible = false;
    var invisibleIndex = 0;


    if (!blockAutoScroll
         && !isNavigatingCalendar
         && row.cells[startIndex].style.display == "none") //if first cell is hidden, then we need to scroll to this cell
    {
        for (var i = startIndex; i < row.cells.length - 2; i++) {
            if (row.cells[i].style.display != "none") {
                blockAutoScroll = true; //stop any possible infinite loop
                processPricingTables(startIndex - i);
                return false;
            }
        }
        for (var i = startIndex; i >= 2; i--) {
            if (row.cells[i].style.display != "none") {
                blockAutoScroll = true; //stop any possible infinite loop
                processPricingTables(startIndex - i);
                return false;
            }
        }
        return false;
    }
    
    for (var i = startIndex; i < (startIndex + count); i++) {
        
        if (i >= row.cells.length - 1) {
            return false;
        }
        
        var e = row.cells[i].firstChild;
        while (e && e.nodeName.toUpperCase() != 'SPAN') e = e.firstChild;
        
        if (e.innerHTML.indexOf('-', 0) >= 0) { //if the text '-' is found, dont merge
            row.cells[i].className = "pob_calendar_strip_highlight_cell grid_price_cells";
            row.cells[i].firstChild.className = "pob_calendar_strip_highlight_text";
            if (count == 1) { aCellHasPrice = false; }
        } else{
            row.cells[i].className = "pob_calendar_strip_highlight_cell grid_price_cells";
            aCellHasPrice = true;
        }

        if (row.cells[i].style.display == "none"
            && !aCellIsInvisible) {
            invisibleIndex = i; 
            aCellIsInvisible = true;
        }
    }

    if (aCellIsInvisible && !blockAutoScroll && !isNavigatingCalendar) {
        blockAutoScroll=true; //stop any possible infinite loop
        processPricingTables(count - (invisibleIndex - startIndex));
        return false;
    }
    
    if (aCellHasPrice && !aCellIsInvisible) {
        return true;
    } else {
        return false;
    }
}

function performRowMerge(headerRow, row, seekingText, numOfCellsToMerge) {

    if (isSearchDirtyEnoughForPostback == true) { //if search box is dirty, don't do any highlighting at all on the page
        return;
    }

    numOfCellsToMerge = parseInt(numOfCellsToMerge, 10);
    
    var numCells = row.cells.length - 1; //dont count the last cell which contains the 'book now' button
    
    if (!isAccomm) {
        numOfCellsToMerge = 1; //if it's not accommodation we're looking at, then highlight only one cell by default
    }
    
    var mergingCell;
    var bookingPeriodIsAvailable;
    var shouldPerformMerge;

    for (var i = getFirstPriceCellIndex(row); i < numCells; i++) {
        //var data = headerRow.cells[i].innerHTML.toLowerCase();
        var attribute = headerRow.cells[i].attributes['date'];

        //if attribute is not found, then the automation is suppose to be disabled, so no need for postback.
        if (attribute == null) { return false; }
        
        if(attribute != null 
            && attribute.value == seekingText) {
            
            shouldPerformMerge = highlightBookingPeriod(row, i, numOfCellsToMerge);
            
            if (shouldPerformMerge
                && (i < (row.cells.length - numOfCellsToMerge))) { //merge cells

                mergingCell = row.cells[i];
                bookingPeriodIsAvailable = mergingCell.attributes["TotalBookingCost"] != null;

                mergingCell.setAttribute("previousValue", mergingCell.innerHTML);

                for (var k = parseInt(numOfCellsToMerge, 10) - 1; k > 0; k--) {
                    row.cells[i + k].style.display = "none";    
                }
                mergingCell.colSpan = numOfCellsToMerge;

                if (bookingPeriodIsAvailable) { // "$0,000 in Total"
                    mergingCell.innerHTML = "<span class=\"pob_calendar_strip_total_booking_cost_text\">" +
                                                mergingCell.attributes["TotalBookingCost"].value +
                                            "</span>";
                    mergingCell.className = "pob_calendar_strip_total_booking_cost_cell grid_price_cells";
                    setBookNowButtonEnabled(row, true);
                } else if (shouldPerformMerge) { // "Unavailable"
                    mergingCell.innerHTML = "<span class=\"pob_calendar_strip_highlight_unavailable_text\">Unavailable</span>";
                    mergingCell.className = "pob_calendar_strip_highlight_unavailable_cell grid_price_cells";
                }
                
                return false; //does not need a post back
                
            }

            if (parseInt(numOfCellsToMerge, 10) + i >= numCells)
                return true; //needs a postback due to dates are outside of table
            else
                return false;
        }
    }
    
    return true; //never found the right spot in the table, so we need to do postback.
                 //UNLESS the date was never on the table due to navigation controls being used without setting the booking date
}

function postbackIfProductAvailable(cell, isPriceCell, storeBookNowButtonDataMethod, postbackFunction) { //HERE!

    var date = cell.attributes["date"].value;
    var isAvailable = false;
    
    setBookingDate(date);
    
    if (isPriceCell == true) { //cell is a Price cell, so check this product is available
        bookingPeriodIsAvailable = (cell.attributes["TotalBookingCost"] != null);
        if (bookingPeriodIsAvailable) {
            //storeBookNowButtonDataMethod();
            isAvailable = true;
        }
    }
    else { //cell is a Date cell, so find any product which is available
        var startCellIndex = 0;
        var attribute;
        
        for (var i = 0; i < tblMainTables.length;  i++) {
            for (var j = getHeaderRowIndex(tblMainTables[i]) + 1; j < tblMainTables[i].rows.length; j++) {
                for (var k = startCellIndex; k < tblMainTables[i].rows[j].cells.length; k++) {
                    attribute = tblMainTables[i].rows[j].cells[k].attributes["date"];
                    if (attribute != null && attribute.value == date) {
                        if(startCellIndex == 0 && k > 0) startCellIndex = k - 1; //speed up searches, don't start search from start of each row
                        if (tblMainTables[i].rows[j].cells[k].attributes["TotalBookingCost"] != null) {
                            if(storeBookNowButtonDataMethod) storeBookNowButtonDataMethod();
                            isAvailable = true; //yes, a product is available
                        }
                        break;
                    }
                }
            }
        }
    }

    if (isAvailable) {
        postbackFunction();
        setTimeout(showWaitingCursor, 300);
    }     
    return isAvailable;
}

/************************** Search Control javascripts ***********************************/


function setCalendarPopupVisible(value) {
    var div = document.getElementById('CALENDAR_POPUP');
    var modalBG = document.getElementById('modalBackground');
    if (div != null && modalBG != null) {

        div.style.display = "none";
        modalBG.style.display = "none";

        if (value == true) {
            div.style.display = "";
            modalBG.style.display = "";
        }
        else {
            hidePopup();
        }
    }
}

function calendarDateSelected(calendarIndex, date, millisecondsDate) {
    var value = new Date(millisecondsDate);
    if(value) {
        setBookingDateWithoutProcessingTables(formatDate(value, 'yyyy MM dd'));
        isSearchDirtyEnoughForPostback = true;
        //disablePricingTables();
    }
    hidePopup();
    //setCalendarPopupVisible(false);
}

function updateCurrentDateOnCalendar() {
    var calendar = document.getElementById('calendarControl');
    if (calendar == null) { return; }

    //var ddlMonth = getSearchControl("ddlMonth");
    var dayOfMonth = parseInt(ddlDayOfMonth.options[ddlDayOfMonth.selectedIndex].value, 10);
    var monthText = ddlMonth.options[ddlMonth.selectedIndex].value;

    var strDate = dayOfMonth + " " + ARR_STRINGS['short_month'][parseInt(monthText.substr(5, 2), 10) - 1] + " " + monthText.substr(0, 4);

    var currentDATE = new Date();
    currentDATE.setHours(0, 0, 0, 0);

    if (Date.parse(strDate) >= currentDATE) {
        A_CALENDARS[0].TC2D(Date.parse(strDate)); //just a little hack
        //calendar.value = strDate; // WHY DOESN'T THIS WORK?
    }
}

function ddlDayOfMonthChanged(sender) {
    if (sender.selectedIndex == -1) {
        sender.selectedIndex = 0;
    }
    updateCurrentDateOnCalendar();

    //searchDDLChanged(sender)
}

function ddlMonthChanged(sender, optionalDayControlId) {
    setDaysOfMonth();
    updateCurrentDateOnCalendar();
    
    //searchDDLChanged(sender)
}

function setDaysOfMonth(ddlDayOfMonthOptional, ddlMonthOptional) {
    var ddlM = ddlMonth, ddlD = ddlDayOfMonth;
    
    if (!ddlMonth && ddlMonthOptional) {
        ddlM = document.getElementById(ddlMonthOptional);
    }
    if (!ddlDayOfMonth && ddlDayOfMonthOptional) {
        ddlD = document.getElementById(ddlDayOfMonthOptional);
    }
    var firstDayOfMonth,
        lastDayOfMonth = parseInt(ddlM.value.substr(8, 2), 10),
        selectedDay = parseInt(ddlD.value, 10); //remeber the selected day

    if (isFinite(lastDayOfMonth)) {

        firstDayOfMonth = (ddlM.value.length < 13 ? 1 : parseInt(ddlM.value.substring(11, 13), 10));
        if (!isFinite(firstDayOfMonth)) firstDayOfMonth = 1;

        ddlD.options.length = 0; //clear the options
        //re-add one option for each day
        for (var i = firstDayOfMonth; i <= lastDayOfMonth; i++) {
            var text = i.toString();
            if (i < 10) { text = '0' + i; }
            ddlD.options[ddlD.options.length] = new Option(i, text);
            if (i == selectedDay) ddlD.selectedIndex = ddlD.options.length - 1;
        }

        if (selectedDay < firstDayOfMonth) {
            ddlD.selectedIndex = 0;
        } else if (selectedDay > lastDayOfMonth) {
            ddlD.selectedIndex = ddlD.options.length - 1;
        }
    }
}

function categoryChanged(inputId, newValue) {
    //if (isSearchDirtyEnoughForPostback = true; ) {
    var input = document.getElementById(inputId);
    if (input && input.value != newValue) {
        input.value = newValue;
        btnSearch();
    }
    //}
}

function setDDLOptions(ddl, min, max) {

    var currentSelectedIndex = ddl.selectedIndex;
    ddl.options.length = 0; //clear list

    for (var i = min; i <= max; i++) {
        ddl.options.add(new Option(i, i));
    }

    if (currentSelectedIndex < ddl.options.length) {
        ddl.selectedIndex = currentSelectedIndex;
    } else {
        ddl.selectedIndex = ddl.options.length - 1;
    }
}



function searchDDLChanged(sender) {
    isSearchDirtyEnoughForPostback = true;
    blockAutoScroll = true;
    if (!pricingTablesNeedRateRefresh && tblMainTables != undefined) {
        processPricingTables(0);
        disablePricingTables();
    }
}

/**** GRID WITH TICK BOX JAVA SCRIPT FUNCTIONS ****/
function initialiseTable(tableId) {
    var table = document.getElementById(tableId);
    if (!table) return;
    
    for (var i = 0; i < table.rows.length; i++) {

        if (table.rows[i].cells.length <= 5 || table.rows[i].attributes["isDateHeaderRow"]) 
            continue;
        
        initialiseRow(table.rows[i]);
    }
}
function initialiseRow(row) {
    tickboxCheckChangeINTERNAL(row); 
    
    var input;
    for (var i = 1; i < row.cells.length - 2; i++) {
        input = getInputControl(row.cells[i]);
        if (input) setCellCssStyles(input);
    }
}

function getInputControl(cell) {
    if(cell)
        for (var i = 0; i < cell.childNodes.length; i++) {
            if (cell.childNodes[i].tagName && cell.childNodes[i].tagName.toUpperCase() == 'INPUT') return cell.childNodes[i];
        }
}

function invertCheckBox(e, cell) {

    var box = getInputControl(cell);
    if (!box) return; //if no input control

    if (e) var event = e;
    else if (window.event) var event = window.event;

    if (event.stopPropagation) e.stopPropagation();
    else if (event.cancelBubble != undefined) window.event.cancelBubble = true;
    
    var target = event.target || event.srcElement;
    if (target.tagName.toUpperCase() != 'INPUT') {
        if (box.type.toUpperCase() == 'CHECKBOX')
            box.checked = !box.checked; //invert check box
        else if (box.checked == false)
            box.checked = true; //check radio button
        else
            return; //don't need to change anything, return now.
        tickboxCheckChange(box);
    }
}

var previousRadio = new Object();
function setCellCssStyles(inputBox) {
    if (inputBox.type.toUpperCase() == 'RADIO') {
        var key = inputBox.name;
        if (previousRadio[key] && previousRadio[key].checked == false)
            RemoveCssStyle(previousRadio[key].parentNode, 'pob_calendar_strip_highlight_cell')
        if (inputBox.checked == true)
            previousRadio[key] = inputBox;
    }
    
    if (inputBox.checked == true) AddCssStyle(inputBox.parentNode, 'pob_calendar_strip_highlight_cell')
    else if (inputBox.checked == false) RemoveCssStyle(inputBox.parentNode, 'pob_calendar_strip_highlight_cell');
}

var currentDelayTimer = new Object();
function tickboxCheckChange(inputBox) {
    var cell = inputBox.parentNode; if (!cell) return;
    var row = cell.parentNode;if (!row) return;
    var timerKey = row.id;

    setCellCssStyles(inputBox);

    if (currentDelayTimer[timerKey]) clearTimeout(currentDelayTimer[timerKey]);  //if row has a timer, clear it
    if (isAccomm) {
        InformUserOfRateRefreshRequired(row);
        currentDelayTimer[timerKey] = setTimeout(function() { tickboxCheckChangeINTERNAL(row); }, 500); //set new timer
    } else {
        currentDelayTimer[timerKey] = setTimeout(function() { tickboxCheckChangeINTERNAL(row); }, 1); //set new timer
    }
}

function getConsecutiveBlockRange(row) {

    var firstIndex = -1, unselectedIndex = -1, lastIndex = 0;
    var checkBox, thereIsNoCheckBoxes = true;

    for (var i = 1; i < row.cells.length - 2; i++) {
        if (!row.cells[i].attributes["date"]) continue;
        checkBox = getInputControl(row.cells[i]);
        if (checkBox) { //checkbox exists
            thereIsNoCheckBoxes = false;
            if (checkBox.checked) {
                if (firstIndex == -1) firstIndex = i;
                lastIndex = i;
                continue;
            }
        }
        if (firstIndex != -1 && unselectedIndex == -1) { //we already have a ticked box, so now there is a break in the block
            unselectedIndex = i;
        }
    }

    if (firstIndex == -1) { //no boxes were ticked
        if (thereIsNoCheckBoxes)
            return { first: 0, last: 0, count: 0, noBoxes: true };
        else
            return { first: 0, last: 0, count: 0, noBoxesTicked: true };
    }
    else if (unselectedIndex == -1 || unselectedIndex > lastIndex)
    //else there was no unselected boxes after the first ticked,
    //or the unselected was the cell after the last found ticked box
        return { first: firstIndex, last: lastIndex, count: (lastIndex - firstIndex) + 1, consecutiveBlocks: true, commencementDate: row.cells[firstIndex].attributes["date"].value };
    else //there was no consecutive block
        return { first: 0, last: 0, count: 0, consecutiveBlocks: false, commencementDate: row.cells[firstIndex].attributes["date"].value };
}

function tickboxCheckChangeINTERNAL(row) {

    var range = getConsecutiveBlockRange(row);

    if (isInitialised) {
        if (range.commencementDate) setBookingDateWithoutProcessingTables(range.commencementDate);
        if (range.count > 0 && isAccomm) ddlNights.selectedIndex = range.count - 1;
    }
    
    if (range.consecutiveBlocks == true) { //there was no boxes ticked
        if (pricingTablesNeedRateRefresh)
            InformUserOfRateRefreshRequired(row, range);
        else if (row.cells[range.first].attributes["TotalBookingCost" + range.count.toString()])
            InformUserOfTotalPrice(row, row.cells[range.first].attributes["TotalBookingCost" + range.count.toString()].value, range.commencementDate);
        else if (ddlNights && parseInt(ddlNights.value, 10) > (row.cells.length - 3) && row.cells[range.first].attributes["TotalBookingCost" + ddlNights.value]) {
            InformUserOfTotalPrice(row, row.cells[range.first].attributes["TotalBookingCost" + ddlNights.value].value, range.commencementDate);
        }
        else if (row.cells[range.first].attributes["NotAvailable" + range.count.toString()])
            InformUserOfUnavailableStay(row);
        else if (row.attributes["MinStay"] && parseInt(row.attributes["MinStay"].value, 10) > range.count)
            InformUserOfInvalidDuration(row, parseInt(row.attributes["MinStay"].value, 10));
        else
            InformUserOfRateRefreshRequired(row, range);
    }
    else if (range.consecutiveBlocks == false) 
                                    InformUserOfNonConsecutiveBlock(row);
    else if (range.noBoxesTicked)   InformUserOfNoTickedBoxes(row);
    else if (range.noBoxes)         removeBookNowButton(row, false);
}

function InformUserOfTotalPrice(row, priceText, date) {
    var ref = GetOutputCells(row);
    if (!ref) return;

    ref.TotalCell.innerHTML = priceText;
    AddCssStyle(ref.BookingLink, 'book_now_button');
    RemoveCssStyle(ref.BookingLink, 'refresh_rates_button');


    var buttonParams = ref.BookingLink.attributes["BookNowButtonParams"];

    if (buttonParams && buttonParams.value) {
        var settarget = null;
        if (ref.BookingLink.attributes["settarget"] && ref.BookingLink.attributes["settarget"].value) {
            settarget = ref.BookingLink.attributes["settarget"].value;
        }
        ref.BookingLink.onclick = function() { setBookingInformation(buttonParams.value, date, settarget); };
                                  
        SetVisible(ref.BookingLink, true);
    }
}
function InformUserOfRateRefreshRequired(row, range) {
    var ref = GetOutputCells(row);
    if (!ref) return;
    if (range) {
        var total = 0.00;
        for (var i = range.first; i <= range.last; i++) {
            total += parseFloat(row.cells[i].attributes["price"].value, 10);
        }
        if (total == 0) return;
        ref.TotalCell.innerHTML = 'Estimated cost is $' + total.toString();
    }
    else {
        ref.TotalCell.innerHTML = '';
    }
    RemoveCssStyle(ref.BookingLink, 'book_now_button');
    AddCssStyle(ref.BookingLink, 'refresh_rates_button');

    ref.BookingLink.onclick = function() { setTimeout(showWaitingCursor, 300); };
    SetVisible(ref.BookingLink, true);
}

function InformUserOfUnavailableStay(row) {
    var ref = GetOutputCells(row);
    if (!ref) return;

    ref.TotalCell.innerHTML = 'This period is not available.';
    SetVisible(ref.BookingLink, false);
}
function InformUserOfInvalidDuration(row, minStay) {
    var ref = GetOutputCells(row);
    if (!ref) return;

    ref.TotalCell.innerHTML = 'Minimum ' + minStay.toString() + ' nights';
    SetVisible(ref.BookingLink, false);
}
function InformUserOfNoTickedBoxes(row) {
    var ref = GetOutputCells(row);
    if (!ref) return;

    SetVisible(ref.BookingLink, false);
    ref.TotalCell.innerHTML = 'Please select dates'; 
}
function InformUserOfNonConsecutiveBlock(row) {
    var ref = GetOutputCells(row);
    if (!ref) return;

    SetVisible(ref.BookingLink, false);
    ref.TotalCell.innerHTML = 'Please select consecutive dates';
}







function GetOutputCells(row) {
    var totalCell, bookingCell, bookingLink; //totalDiv

    totalCell = GetTotalPriceCell(row);
    if (!totalCell) return;
    
    bookingCell = GetBookingCell(row);
    if (!bookingCell || !bookingCell.childNodes || bookingCell.childNodes.length == 0) return false;

    for (var i = 0; i < bookingCell.childNodes.length; i++) {
        if (bookingCell.childNodes[i].tagName.toUpperCase() == 'A') {
            bookingLink = bookingCell.childNodes[i];
            break;
        }
    }

    if (totalCell && bookingCell && bookingLink) {
        return { BookingCell: bookingCell,
                 TotalCell: totalCell,
                 BookingLink: bookingLink  };
    }
    else return;
}

function DisableBookNowButton(row) {
    var ref = GetOutputCells(row);
    if (!ref) return;
    ref.BookingLink.visible = false;
}

function GetBookingCell(row) { if (row) return row.cells[row.cells.length - 1]; }
function GetTotalPriceCell(row) { if (row) return row.cells[row.cells.length - 2]; }


//USE THIS FUNCTION WHEN USING TICK BOXES (OVERRIDES THE METHOD DEFINED EARLIER IN THE JAVASCRIPT)
function setBookNowButtonEnabled(row, enabled) {return;}
function processPricingTables(scrollDelta) { return; }
function searchDDLChanged(sender) { disablePricingTables(); }
function disablePricingTables() {

    if (pricingTablesNeedRateRefresh) {
        return;
    }
    pricingTablesNeedRateRefresh = true;
    var wasInitialised = isInitialised;
    isInitialised = false; //we set this to false so that the tickboxCheckChange knows this isn't a user activated checkchange
    
    for (var i = 0; i < tblMainTables.length; i++) {
        for (var j = 0; j < tblMainTables[i].rows.length; j++) {
            if (tblMainTables[i].rows[j].cells.length > 4) //all pricing rows have this attribute on the row
                tickboxCheckChangeINTERNAL(tblMainTables[i].rows[j]);
        }
    }
    isInitialised = wasInitialised;
}


function ScrollCalendar(offset) {

    var hiddenInput = document.getElementById('firstCellDate');
    var currentStartDate = hiddenInput.value;

    var year = parseInt(currentStartDate.substr(0, 4), 10);
    var month = parseInt(currentStartDate.substr(5, 2), 10) - 1; //Javascript is ZERO based for months
    var day = parseInt(currentStartDate.substr(8,2), 10);

    var d = new Date();
    d.setFullYear(year, month, day);
    d.setDate(d.getDate() + offset);

    //don't try and set it to earlier than today!
    //if (d < new Date()) d = new Date();
    
    hiddenInput.value = formatDate(d, 'yyyy MM dd');

    setBookingDateUsingOffset(offset);
    //setBookingDateWithoutProcessingTables(hiddenInput.value);
    performPostback();
}


function removeBookNowButton(row) { //no tickboxes == no book now button
    var ref = GetOutputCells(row);
    if (ref) ref.BookingCell.removeChild(ref.BookingLink);
}

function setBookingInformation(buttonParams, date, optionalSetTarget) {

    if (optionalSetTarget) {
        var v3_form = document.getElementById('V3_FORM');
        var oldTarget = v3_form.target;
        v3_form.target = optionalSetTarget;
        setTimeout(function() { v3_form.target = oldTarget; document.getElementById('BookNowButtonData').value = ''; }, 1000);
    }

    if (optionalSetTarget != '_blank') {
        setTimeout(showWaitingCursor, 300);
    }
    
    document.getElementById('BookNowButtonData').value = buttonParams + '|' + date;
}

