function ajaxSelfCall(queryParams, callBackFunction, callBackOnErrorFunction) {
    // construct ajax request URL
    var pagePath = window.location.pathname;
    var pageName = pagePath.substring(pagePath.lastIndexOf('/') + 1);
    var glue = "?";
    if (window.location.href.lastIndexOf("?") != -1) {
    	if (window.location.href.lastIndexOf("?") == window.location.href.length) glue = "";
    	else glue = "&";
    }
    var requestURL = window.location + window.location.search + glue + queryParams;
    // haal de onnodige querystringparams er af
    requestURL = requestURL.replace(window.location.search, ''); 
    /* Set up the request */
    var xmlhttp =  new XMLHttpRequest();

    xmlhttp.open('GET', requestURL, true); // true = asynchronous
    
    /* The callback function */

    xmlhttp.onreadystatechange = function() 
    {
        if (xmlhttp.readyState == 4) 
        {
            if( xmlhttp.status == 200 )
            {
                callBackFunction(xmlhttp.responseText);
            } else {
                if (callBackOnErrorFunction == null) {
                    alert("AJAX Error: "+xmlhttp.status);
                } else {
                    callBackOnErrorFunction(xmlhttp.status);
                }
            }
        }
    }
    
    /* Send the GET request */
    xmlhttp.send(null);
}

function elementType(element) {
    var elementType = element.type;
    if (elementType == null || elementType == '' || elementType == 'undefined') {
        elementType = element.nodeName;
    }
    if (elementType == null || elementType == '' || elementType == 'undefined') {
        alert('unable to determine elementtype; element is shown next!');
        alert(element); 
    }
    return elementType.toLowerCase();
}

function disableElement(element) {
    switch (elementType(element)) {
    case 'select-one':
        element.options.length = 0;
        element.options[0] = new Option("laden...", "");
        break;
    case 'td':
    case 'span':
    case 'p':
        element.innerHTML = 'laden...';
    default:
        element.value = '';
    }
    element.disabled = true;
    return true;
}

function enableElement(element) {
    switch (elementType(element)) {
    case 'td':
    case 'span':
    case 'p':
        // do nothing
    default:
        element.disabled = false;
    }
    return true;
}

function getElementValue(element) {
    switch (elementType(element)) {
    case 'select-one':
        return element.options[element.selectedIndex].value;
    case 'td':
    case 'span':
    case 'p':
        return element.innerHTML;
    default:
        return element.value;
    }
}

function fillDependentElement(childElement, parentElement, actionName) {

    disableElement(childElement);
    var parentValue = getElementValue(parentElement)

    ajaxSelfCall('action='+actionName+'&parentId='+parentValue, fillDependentElementCallback, fillDependentElementCallbackOnError);

    function fillDependentElementCallback(responseText) {
        //alert('child is: ' + childElement.type);
	    switch (elementType(childElement)) {
	    case 'select-one':
	        createOptionsFromText(childElement, responseText);
	        break;
	    case 'checkbox':
	    	if (responseText == '1') {
	        	childElement.checked = true;
	        } else {
	        	childElement.checked = false;
	        }
	        break;
	    case 'td':
	    case 'span':
	    case 'p':
	        childElement.innerHTML = responseText;
	        break;
	    case 'text':
	    	childElement.value = responseText;
	    	break;
	    default:
	        alert('fillDependentElementCallback uses default');
	        dbg(childElement);
	        childElement.value = responseText;
	    }        
        enableElement(childElement);
		if (childElement.onchange != null) {
        	childElement.onchange();
        }
    }
    
    function fillDependentElementCallbackOnError(responseText) {
        childElement.disabled = false;
        alert('error response: ' + responseText);
    }
}

/**
 * optionsText is a text with the format:
 * key1=value1
 * key2=value2
 *
 * This function will add these key-value pairs as options to a select box
 */
function createOptionsFromText( selectObj, optionsText )
{
    var optionCounter = 0;
    var reg = /^([^=]*)=(.*)$/; // regexp which handles key-value pairs
    
    // empty select box first
    selectObj.options.length = 0;
    
    // split text in lines
    var lines = optionsText.split(/[\n\r]|[\n]/);

    for( i=0; i<lines.length; i++ )
    {
        var parsed = reg.exec(lines[i]);
//      alert( lines[i] + "\n" + parsed[1] + "\n" + parsed[2]);
        if( parsed ) // if parsing fails then just do not add options (log, alert?)
        {
            selectObj.options[optionCounter++] = new Option( parsed[2], parsed[1] );
            // if first character is a * then select it
            if( parsed[2].charAt(0) == '*' )
            {
                selectObj.options[optionCounter-1].text = selectObj.options[optionCounter-1].text.substr(1);
                selectObj.selectedIndex = optionCounter-1;
            }
        }
    }
}

function dbg(elem)
{
    var s = "";
    
    if( elem == null ) alert( "NULL" );
    
    for( i in elem )
    {
        s += i + ": " + elem[i] + " | ";
    }
    alert(s);
}



