// JBo 20081229: added compatibility for IE < 5
var TEXT_NODE = 3;
if (!Array.prototype.push)
    Array.prototype.push = function() {
        var thisLength = this.length;
        for(var i=0, argLen=arguments.length; i<argLen; i++)
            this[thisLength+i] = arguments[i];
        return this.length;
    };


var currentSearchText = "";
var editBox           = null;
var suggestionList    = null;

var haveInitialized = false;
var haveAjax = false;

function searchBindTo(element)
{
    if (!haveAjax) return true;

    editBox = element;
    // JBo 20081229: Added IE detection
    if (editBox.attachEvent)
    {
        editBox.attachEvent('onkeyup',    onSearchKeyUp);
        editBox.attachEvent('onkeypress', onSearchKeyPress);
        editBox.attachEvent('onblur',     onCompleteTest);
        editBox.attachEvent('onclick',    function(){editBox.select()});
    }
    else
    {
        editBox.setAttribute('onkeyup',      "javascript:return onSearchKeyUp(event, this);");
        editBox.setAttribute('onkeypress',   "javascript:return onSearchKeyPress(event, this);");
        editBox.setAttribute('onblur',       "javascript:return onCompleteTest(event, this);");
        editBox.setAttribute('onclick',      "javascript:this.select();");
    }
    //editBox.focus();
    editBox.select();
    if (suggestionList == null)
        suggestionList = document.getElementById("locationResults");
    if (suggestionList == null)
    {
        suggestionList = document.createElement("SELECT");
        suggestionList.setAttribute("id",       "locationResults");
        suggestionList.setAttribute("multiple", "multiple");
        if (suggestionList.attachEvent)
        {
            suggestionList.attachEvent("onchange",   onResultsEvent);
            suggestionList.attachEvent("onkeypress", onResultsEvent);
        }
        else
        {
            suggestionList.setAttribute("onchange",   "javascript:return onResultsEvent(event, this);");
            suggestionList.setAttribute("onkeypress", "javascript:return onResultsEvent(event, this);");
        }
        document.body.appendChild(suggestionList);
    }
    else
    {
        removeAllChilds(suggestionList);
    }
    suggestionList.style.display = "none";
    suggestionList.style.position = "absolute";
    return true;
}

function searchUnbind()
{
    if (editBox.detachEvent)
    {
        editBox.detachEvent('onkeyup',    onSearchKeyUp);
        editBox.detachEvent('onkeypress', onSearchKeyPress);
    }
    else
    {
        editBox.setAttribute('onkeyup',    "");
        editBox.setAttribute('onkeypress', "");
    }
    editBox = null;
    return true;
}

function onSearchKeyUp(event, element)
{
    if (!event) event = window.event;
    if (event.keyCode == 40 || event.keyCode == 63233 || event.keyCode == 27 || event.keyCode == 13)
        return shiftFocusToSuggestionList();

    if ((editBox) && (editBox.value) && (editBox.value.length > 2) && !editBox.readonly && (currentSearchText != editBox.value))
    {
        currentSearchText = editBox.value;
        onXMLComplete = processSearchResults;
        loadXMLDoc("lookup.php?name=" + escape(currentSearchText));
    }
    else
    {
        if (suggestionList.style.display != "none")
            suggestionList.style.display  = "none";
    }
    return true;
}

function onSearchKeyPress(event, element)
{
    if (!event) event = window.event;
    if (event.keyCode == 9) // tab key
    {
        if (suggestionList.style.display == "none") // no suggestion list showing, allow for normal processing
            return true;
    }
    if (event.keyCode == 9 || event.keyCode == 13 || event.keyCode == 40 || event.keyCode == 63233) // tab, enter or down arrow or safari down arrow
    {
        // JBo 20081229: isolated this into a function
        return shiftFocusToSuggestionList();
    }
    else if (event.keyCode == 27) // esc key
    {
        suggestionList.style.display = "none";
        removeAllChilds(suggestionList);
        return false;
    }
    else if (event.keyCode == 0) // a readable character has been typed
    {
        var hidden = document.getElementById(editBox.getAttribute("name") + "ID");
        if (hidden != null)
        {
            editBox.parentNode.removeChild(hidden);
            // JBo 20081217: updated these IDs might not always exist
            if (document.getElementById("kgco2ID") != null)
            {
                document.getElementById("distanceID").setAttribute("value", "0");
                document.getElementById("kgco2ID").setAttribute("value",    "0");
                document.getElementById("offsetID").setAttribute("value",   "0.00");
            }
            updateForm();
        }
    }
    
    return true;
}

// JBo 20081229: create this function
function shiftFocusToSuggestionList()
{
    if ((suggestionList.style.display == "none") && (editBox.value.length > 2) && !editBox.readonly) //(suggestionList.childNodes.length > 0))
    {
        showSuggestionList();
    }
    if (suggestionList.style.display != "none")
    {
        suggestionList.focus();
        if (suggestionList.childNodes.length > 0)
        {
            suggestionList.firstChild.selected = true;
            editBox.value = getElementText(suggestionList.firstChild);
        }
    }
    return true;
}

function onResultsEvent(event, element)
{
    if (!event) event = window.event;
    var selectedIndex = -1;
    if (suggestionList.childNodes.length > 0)
    {
        selectedIndex = 0;
        while (selectedIndex < suggestionList.childNodes.length && !suggestionList.childNodes[selectedIndex].selected)
            selectedIndex++;
    }

    if ((selectedIndex >= 0) && (selectedIndex < suggestionList.childNodes.length) && !editBox.readonly)
        editBox.value = getElementText(suggestionList.childNodes[selectedIndex]);

    if (((selectedIndex >= 0) && (selectedIndex < suggestionList.childNodes.length)) &&
        ( ((event.type == "keypress") && ((event.keyCode == 13) || (event.keyCode == 9))) ||
           (event.type == "click")
        )
        
       )
    {
        var value = suggestionList.childNodes[selectedIndex].getAttribute("value");
        editBox.parentNode.appendChild(createHiddenId(value));
        editBox.focus();
        suggestionList.style.display = "none";
        removeAllChilds(suggestionList);
        tryCalculate();
        updateForm();
        return false;
    }
    else if ((event.type == "keypress") && (event.keyCode == 27))
    {
        editBox.focus();
        suggestionList.style.display = "none";
        removeAllChilds(suggestionList);
        updateForm();
        return false;
    }

    return true;
}

function processSearchResults(xml)
{
    // Prepare the target element to hold the XML search results
    removeAllChilds(suggestionList);

    // Fetch all locations and fit them in the <select> element
    var locations = xml.documentElement.getElementsByTagName("location");
    if (locations.length > 0)
    {
        for(var i=0; i<locations.length; i++)
        {
            var option = document.createElement("OPTION");
            var text = locations[i].firstChild.nodeValue;
            // If the search text is in the text, emphesize it
            var iFind = text.toLowerCase().indexOf(currentSearchText.toLowerCase()); // regardless of the case
            if (iFind >= 0)
            {
                var lastFound = 0;
                while (iFind >= 0)
                {
                    if (iFind > lastFound) // the text in front of the 'currentSearchText'
                        option.appendChild( document.createTextNode( text.substring(lastFound, iFind) ) );
                    var emph = document.createElement("SPAN");
                    emph.setAttribute("class", "searchword");
                    emph.appendChild( document.createTextNode(text.substring(iFind, iFind+currentSearchText.length)) );
                    option.appendChild(emph);
                    lastFound = iFind + currentSearchText.length;
                    iFind = text.toLowerCase().indexOf(currentSearchText.toLowerCase(), lastFound); // regardless of the case
                }
                if (lastFound < text.length) // the text behind the 'currentSearchText'
                    option.appendChild( document.createTextNode( text.substring(lastFound) ) );
            }
            else
                option.appendChild( document.createTextNode(text) );
            option.setAttribute('value',   locations[i].getAttribute('value'));
            if (option.attachEvent)
                option.attachEvent('onclick', onResultsEvent);
            else
                option.setAttribute('onclick', "javascript:return onResultsEvent(event, this);");
            suggestionList.appendChild(option);
        }
        showSuggestionList();
    }
    else if (locations.length == 0)
    {
        var option = document.createElement("OPTION");
        var emph   = document.createElement("I");
        emph.appendChild(document.createTextNode("no matches."));
        option.appendChild(emph);
        suggestionList.appendChild(option);
        //showSuggestionList();
    }
}

function showSuggestionList()
{
    if (suggestionList.childNodes.length > 0)
    {
        offsets = getOffsets(editBox);
        suggestionList.style.left = offsets[0] + "px";
        suggestionList.style.top  = offsets[1] + editBox.offsetHeight + "px";
        suggestionList.style.display = "";
    }
}

function onCompleteTest(event, element)
{
    if (!event) event = window.event;
    if (!element) element = (editBox) ? editBox : this;
    if (!element || !element.name) return true;
    if (document.getElementById(element.name+"ID") == null)
    {
        if (suggestionList.childNodes.length > 0)
        {
            /*var txt = getElementText(suggestionList.firstChild);
            if ((suggestionList.childNodes.length == 1) && (txt != "no matches."))
            {
                element.value = txt;
                element.parentNode.appendChild(createHiddenId(suggestionList.firstChild.value));
            }
            else if (suggestionList.childNodes.length > 1)*/
            {
                showSuggestionList();
                suggestionList.focus();
                //suggestionList.firstChild.selected = true;
            }
        }
    }
    if (document.getElementById(element.name+"ID") != null)
    {
        tryCalculate();
    }
    else
    {
        element.value = "";
    }
    return true;
}

function tryCalculate(event, element)
{
    var city1      = document.getElementById("cityname1ID");
    var city2      = document.getElementById("cityname2ID");
    var journey    = document.getElementById("journeyID");
    var passengers = document.getElementById("passengersID");

    if (city1 != null && city2 != null)
    {
        var params = [];
        //params.push("cityname1=");
        //params.push("cityname2=");
        params.push("action=Confirm");
        params.push(city1.name      + "=" + city1.value);
        params.push(city2.name      + "=" + city2.value);
        params.push(journey.name    + "=" + getElementText(journey.options[journey.selectedIndex]));
        params.push(passengers.name + "=" + passengers.value);
        params.push("method=xml");

        onXMLComplete = parseFormPost;
        loadXMLDoc("calculator1.php?"+ params.join("&"));
    }
}

function parseFormPost(xml)
{
    if (!xml) return;
    var doc = xml.documentElement;
// JBo, 20081210: removed, since there is a basket-item preview instead of this
/* 
    document.getElementById("distanceID").value = getElementText(doc.getElementsByTagName("distance")[0]);
    document.getElementById("kgco2ID").value    = getElementText(doc.getElementsByTagName("kgco2")[0]);
    document.getElementById("offsetID").value   = getElementText(doc.getElementsByTagName("offset")[0]);
*/
    updateForm();

    var basketItems = xml.getElementsByTagName("table");
    if (basketItems.length > 0)
    {
        var item = basketItems[0];
        var table = document.getElementById("basket");
        if (table==null)
        {
            table = document.createElement("TABLE");
            table.setAttribute("id", "basket");
            //document.getElementById("boxtext").appendChild(table);
            document.forms[0].appendChild(table);
        }
        table.setAttribute("class", item.getAttribute("class"));
        removeAllChilds(table);
        copyXmlToHtml(item, table);
    }

// JBo, 20081215: added
// JBo, 20081217: updated to prevent multiple INPUTs appearing
    var hidden = document.getElementById("kgco2ID");
    if (hidden == null)
    {
        hidden = document.createElement("INPUT");
        hidden.setAttribute("name",  "kgco2");
        hidden.setAttribute("id",    "kgco2ID");
        hidden.setAttribute("type",  "hidden");
        document.forms[0].appendChild(hidden);
    }
    hidden.value = getElementText(doc.getElementsByTagName("kgco2")[0]);

    hidden = document.getElementById("offsetID");
    if (hidden == null)
    {
        hidden = document.createElement("INPUT");
        hidden.setAttribute("name",  "offset");
        hidden.setAttribute("id",    "offsetID");
        hidden.setAttribute("type",  "hidden");
        document.forms[0].appendChild(hidden);
    }
    hidden.value = getElementText(doc.getElementsByTagName("offset")[0]);
}

// JBo, 20081215: added
function copyXmlToHtml(xml, html)
{
    for (var elem=0; elem<xml.childNodes.length; elem++)
    {
        if (xml.childNodes[elem].nodeType == 1) //xml element
        {
            var child = document.createElement(xml.childNodes[elem].nodeName);
            for (var attr=0; attr<xml.childNodes[elem].attributes.length; attr++)
            {
                var at = xml.childNodes[elem].attributes[attr];
                child.setAttribute(at.name, at.value);
            }
            html.appendChild(child);
            copyXmlToHtml(xml.childNodes[elem], child);
        }
        else if (xml.childNodes[elem].nodeType == TEXT_NODE) //text element
        {
            child = document.createTextNode( xml.childNodes[elem].nodeValue );
            html.appendChild(child);
        }
        else if(xml.childNodes[elem].nodeType == 4) //CDATA element
        {
            var data = xml.childNodes[elem].nodeValue;
            if (data.substr(0, 1) == "&" && data.substr(-1, 1) == ";") // EntityReference
            {
                child = document.createElement("SPAN");
                child.innerHTML = data;
                html.appendChild(child);
            }
        }
    }
}

function createHiddenId(value)
{
    var hidden = document.createElement("INPUT");
    hidden.setAttribute("value", value); 
    hidden.setAttribute("name",  editBox.getAttribute("name") + "ID");
    hidden.setAttribute("id",    editBox.getAttribute("name") + "ID");
    hidden.setAttribute("type",  "hidden");
    return hidden;
}

function getElementText(elem)
{
    var res = "";
    for (var i=0; i<elem.childNodes.length; i++)
    {
        var child = elem.childNodes[i];
        res += (child.nodeType == TEXT_NODE) ? child.nodeValue : getElementText(child) ;
    }
    return res;
}

// JBo, 20081215: added
function initialize()
{
    createXmlHttp();
    haveAjax = (xmlhttp != null);

    var inputs = document.getElementsByTagName("INPUT");
    for (var i=0; i<inputs.length; i++)
    {
        if (inputs[i].getAttribute("name").substr(0, 8) == "cityname")
            if (inputs[i].getAttribute('autocomplete') != "off")
                inputs[i].setAttribute('autocomplete', "off");
    }

    haveInitialized = true;
}

function updateForm()
{
// JBo, 20081215: added
    if (!haveInitialized) initialize();

    var btnCalculate = document.getElementById("actionCalculateID");
    var btnAdd       = document.getElementById("actionAddID");
    var haveAirports = (document.getElementById("cityname1ID") != null) && (document.getElementById("cityname2ID") != null);
    var parentNode   = btnCalculate.parentNode;
// JBo, 20081215: added
    if (haveAjax && btnCalculate.style.display != 'none')
    {
        btnCalculate.style.display = 'none';
        var btnClear = document.getElementById("actionClearID")
    if (btnClear)
        btnClear.style.display = 'none';
    }
    if (haveAirports && (btnAdd == null))
    {   // only the 'Calculate' button is present
        document.forms[0].setAttribute('action', document.baseURI);
        btnCalculate.setAttribute('value', 'Re-Calculate');
// JBo, 20081210: removed, since there is a basket-item preview instead of this
/* 
        var br = document.createElement("BR");
        btnAdd = document.createElement("INPUT");
        btnAdd.setAttribute('value', "Add to Basket");
        btnAdd.setAttribute('id',    "actionAddID");
        btnAdd.setAttribute('name',  "action");
        btnAdd.setAttribute('type',  "submit");
        parentNode.insertBefore(br, btnCalculate);
        parentNode.insertBefore(btnAdd, br); // make sure the 'Add to Basket' comes first
*/
    }
    else if (!haveAirports && (btnAdd != null))
    {   // both the 'Add to Basket' and 'Re-Calculate' buttons are present
        document.forms[0].setAttribute('action', "flightdistance.php");
        btnCalculate.setAttribute('value', 'Calculate');
// JBo, 20081210: removed, since there is a basket-item preview instead of this
/* 
        parentNode.removeChild(btnAdd);
        parentNode.removeChild(parentNode.getElementsByTagName("BR")[0]);
*/
    }
// JBo, 20081210: removed, since there is a basket-item preview instead of this
/* 
    var dsply = (btnCalculate.value == "Calculate") ? "none" : "" ;
    document.getElementById("distance").style.display  = dsply;
    document.getElementById("emissions").style.display = dsply;
    document.getElementById("payment").style.display   = dsply;
*/
}

function removeAllChilds(element)
{
    while (element.childNodes.length > 0)
        element.removeChild(element.firstChild);
}

function getOffsets(element)
{
    var offsetLeft = 0;
    var offsetTop  = 0;
    if (element.offsetParent)
    {
        do
        {
            offsetLeft += element.offsetLeft;
            offsetTop  += element.offsetTop;
        }
        while (element = element.offsetParent);
    }
    return [offsetLeft, offsetTop];
}

function debug(msg)
{
    var trace = document.getElementById("trace");
    if (trace)
    {
        trace.appendChild( document.createTextNode(msg) );
        trace.appendChild( document.createElement("BR") );
    }
}

function fadeout(elem, waitforTime, fadeTime)
{
    setTimeout("startFading('" + elem.id + "', " + fadeTime + ")", waitforTime*1000);
}

function startFading(id, fadeTime)
{
    opacity(id, 100, 0, fadeTime*1000);
}

// Following functions taken from:
// http://brainerror.net/scripts/javascript/blendtrans/
function opacity(id, opacStart, opacEnd, millisec) {
    //speed for each frame
    var speed = Math.round(millisec / 100);
    var timer = 0;

    //determine the direction for the blending, if start and end are the same nothing happens
    if(opacStart > opacEnd) {
        for(i = opacStart; i >= opacEnd; i--) {
            setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed));
            timer++;
        }
    } else if(opacStart < opacEnd) {
        for(i = opacStart; i <= opacEnd; i++)
        {
            setTimeout("changeOpac(" + i + ",'" + id + "')",(timer * speed));
            timer++;
        }
    }
}

//change the opacity for different browsers
function changeOpac(opacity, id) {
    var object = document.getElementById(id).style;
    object.opacity = (opacity / 100);
    object.MozOpacity = (opacity / 100);
    object.KhtmlOpacity = (opacity / 100);
    object.filter = "alpha(opacity=" + opacity + ")";
} 

