// suggest widget functionality for searching
// (c) 2007 Loco (Loohuis Consulting), http://www.loohuis-consulting.nl/
// This work is licensed under a 
// Creative Commons Attribution-Share Alike 3.0 Netherlands License
// see http://www.loohuis-consulting.nl/development/cc-by-sa.php

// server side script
var scriptURL = '/nl/zoeken.php';
var timer;
var delay = 700;
var KEYUP = 38;
var KEYDN = 40;
var hasSuggests= false;
var highlight = -1;
var suggestions;
var acBase;

// set up the action when the HTML has loaded
addEvent(window, 'load', init, false);

// initialize
function init()
{
    var searchtext = document.getElementById('searchtext');
    // assign key handler
    if (searchtext) {
        addEvent(searchtext, 'keydown', keyHandler, false);
        addEvent(searchtext, 'blur', hideSuggest, false);
        // don't let browser interfere
        searchtext.setAttribute("autocomplete","off");
    }
}

//
// event handlers
//

// main keystroke event handler
function keyHandler(e)
{
    e = e || window.event;
    var key = e.keyCode;

    switch(key)
    {
        case KEYUP:
            processUp();
            break;

        case KEYDN:
            processDown();
            break;

        default:
            hideSuggest();
            // clear the current timeout
            clearTimeout(timer);
            // set up a timeout to load suggestions
            timer = setTimeout(getSuggests, delay);
    }
}

// get suggestions from server
function getSuggests()
{
    var searchtext = document.getElementById('searchtext');
    if (searchtext.value.length) { // only if there's content
        var getRequest = 'suggest=' + escape(searchtext.value);
        xmlhttpPost(scriptURL, getRequest, handleResponse);
    }
}

// hide suggest layer
function hideSuggest(e)
{
    var suggest = document.getElementById('suggest');
    suggest.style.display = 'none';
    hasSuggests = false;
    highlight = -1;
}

// load a suggested query
function loadSuggestion()
{
    var suggestForm = document.getElementById('searchform');
    suggestForm.submit();
}

// handle up event
function processUp()
{
    if (hasSuggests) {
        var suggest = document.getElementById('suggest');
        var list = suggest.firstChild;
        opts = list.childNodes;
        if (highlight > 0) {
            opts[highlight].className = '';
            highlight--;
            opts[highlight].className = 'active';
            var searchtext = document.getElementById('searchtext');
            autoComplete(searchtext, suggestions[highlight]);
        }
    }
}

// handle down event
function processDown()
{
    if (hasSuggests) {
        var suggest = document.getElementById('suggest');
        var list = suggest.firstChild;
        opts = list.childNodes;
        if (highlight < opts.length - 1) {
            if (highlight >= 0)
                opts[highlight].className = '';
            highlight++;
            opts[highlight].className = 'active';
            var searchtext = document.getElementById('searchtext');
            autoComplete(searchtext, suggestions[highlight]);
        }
    }
}

// do autocomplete to str in input elm
function autoComplete(elm, str)
{
    var len = acBase.length;
    add = str.substr(len);
    elm.value = acBase + add;
    if (elm.setSelectionRange) {
        elm.setSelectionRange(len, str.length);
    }
    else { // IE
        var oRange = elm.createTextRange();
        oRange.moveStart("character", len);
        oRange.moveEnd("character", add.length);
        oRange.select();
        elm.caretPos = len;
    }
}

//
// AJAX request handling
//

// process a response from the server
function handleResponse(response)
{
    // buffer input for autocompletion
    var searchtext = document.getElementById('searchtext');
    acBase = searchtext.value;

    suggestions = response.split(';');
    // display returned suggestions in suggest list
    if (suggestions.length > 1) {
        var list = document.getElementById('suggest');
        // delete child ul
        while (list.childNodes.length)
            list.removeChild(list.firstChild);
        // create new list
        var ul = document.createElement('ul');
        for (var s in suggestions) {
            if (typeof suggestions[s] != 'function') { // avoid prototype extensions
                var li = document.createElement('li');
                var tn = document.createTextNode(suggestions[s]);
                li.appendChild(tn);
                ul.appendChild(li);
            }
        }
        list.appendChild(ul);
        list.style.display = 'block';
        hasSuggests = true;
    }
    else
        hideSuggest();
    // if at least one suggestion is present, do autocomplete
    if (suggestions[0].length) {
        var searchtext = document.getElementById('searchtext');
        autoComplete(searchtext, suggestions[0]);
    }
}

// after http://www.onlamp.com/pub/a/onlamp/2005/05/19/xmlhttprequest.html
function xmlhttpPost(url, querystring) {
    var xmlHttpReq = false;
    // Mozilla/Safari
    if (window.XMLHttpRequest) {
        xmlHttpReq = new XMLHttpRequest();
    }
    // IE
    else if (window.ActiveXObject) {
        xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlHttpReq.open('POST', url, true);
    xmlHttpReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlHttpReq.onreadystatechange = function() {
        if (xmlHttpReq.readyState == 4) {
            handleResponse(xmlHttpReq.responseText);
        }
    }
    xmlHttpReq.send(querystring);
}

//
// platform independent event utility functions
// http://www.scottandrew.com/weblog/articles/cbs-events
//
function addEvent(obj, evType, fn, useCapture){
    if (obj.addEventListener) {
        obj.addEventListener(evType, fn, useCapture);
        return true;
    } 
    else if (obj.attachEvent) {
        var r = obj.attachEvent("on"+evType, fn);
        return r;
    } 
    else {
        alert("Handler could not be attached");
    }
}

function removeEvent(obj, evType, fn, useCapture){
    if (obj.removeEventListener) {
        obj.removeEventListener(evType, fn, useCapture);
        return true;
    } 
    else if (obj.detachEvent) {
        var r = obj.detachEvent("on"+evType, fn);
        return r;
    } 
    else {
        alert("Handler could not be removed");
    }
}

// http://www.quirksmode.org/js/findpos.html
function findPosX(obj)
{
    var curleft = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curleft += obj.offsetLeft
            obj = obj.offsetParent;
        }
    }
    else if (obj.x)
        curleft += obj.x;
    return curleft;
}

function findPosY(obj)
{
    var curtop = 0;
    if (obj.offsetParent)
    {
        while (obj.offsetParent)
        {
            curtop += obj.offsetTop
            obj = obj.offsetParent;
        }
    }
    else if (obj.y)
        curtop += obj.y;
    return curtop;
}


