// vim: set tabstop=4 shiftwidth=4 foldmethod=marker :
/**
 * XMLHTTP-based remote scripting layer (AJAX).
 */
// {{{ ajax_create_xmlhttp()
function ajax_create_xmlhttp()
{
	var ret = null;
    try { ret = new ActiveXObject('Msxml2.XMLHTTP'); }
    catch (e) {
        try { ret = new ActiveXObject('Microsoft.XMLHTTP'); }
        catch (ee) { ret = null; }
    }
    if (!ret && typeof XMLHttpRequest != 'undefined')
        ret = new XMLHttpRequest();

    return ret;
}
// }}}
// {{{ ajax_query(callbackFunction, url, postObject, asText)
function ajax_query(callbackFunction, url, postObject, asText)
{
    if (brz && !brz.ie && document.domain != location.host) {
        if (window.RemoteScript) {
            // ff bug: can't use XHR when document.domain has been changed
            var rs = new RemoteScript('rs');
            rs.callToServer(url, callbackFunction);
        }
        return;
    }

    // Use Javascript "inner function" to have local variables retain values after outer
    // function has returned. This ensures thread safety.
    // {{{ ajax_bind_callback()
    function ajax_bind_callback() {
        // Must be "complete"
        if (req.readyState == 4) {
            // "HTTP OK"
            if (req.status == 200) {
                if (ajax_callback) {
                    if (asText) { ajax_callback(req.responseText); }
                    else { ajax_callback(req.responseXML); }
                } else { alert('no callback defined'); }
            } else { alert("There was a problem retrieving the xml data:\n" + req.status + ":\t" + req.statusText + "\n" + req.responseText); }
        }
    }
	// }}}

    // hold everything in local variables until inner function is called	
    var ajax_callback = callbackFunction;
    var req = ajax_create_xmlhttp();
    if (!req) { return false; }
    req.onreadystatechange = ajax_bind_callback;
    if (postObject) {
        req.open('POST',url,true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        //alert(ajax_encode_array(postObject));
        req.send(ajax_encode_object(postObject));
    } else {
        req.open('GET',url,true);
        req.send(null);
    }
}
// }}}
// {{{ ajax_logger(page name, log string)
function ajax_logger(page, varString)
{
    var req = ajax_create_xmlhttp();
    if (!req) { return false; }
    req.open('GET', "/logger?page=" + page + varString, true);
    req.send(null);
}
// }}}
// {{{ ajax_encode_array(dataToEncode)
function ajax_encode_array(dataToEncode)
{
    var post_data = '';
    for (var key in dataToEncode) {
        post_data += '&' + escape(key) + '=' + escape(dataToEncode[key]);
    }
    // handle the case where nothing is posted
    if (post_data.length==0) { return ''; }	
    // trim off first &
    return post_data.substring(1);
}
// }}}
/* ajax_encode_object(objObject) - create name->value pair string from an object {{{ */
function ajax_encode_object(objObject)
{
    /* sub(objObject, strPrefix) - recursively encodes an object to name->value pairs {{{ */
    /* "inner function" to avoid all namespace conflicts */
    function sub(objObject, strPrefix)
    {
        var aRet = '';

        /* if prefix is not empty, we need to make it 'prefix.' */
        if(strPrefix) { strPrefix += '.';}

        /* for each part of objObject, if it's an object recurse, otherwise return value */
        for(var strKey in objObject)
            if(typeof(objObject[strKey]) == "object")
                { aRet += sub(objObject[strKey], strPrefix + strKey); }
            else
                { aRet += "&" + escape(strPrefix + strKey) + '=' + escape(objObject[strKey]); }
        return aRet;
    }
    /* }}} */

    var ret = sub(objObject, '');

    // trim initial & from string
	return ret.substring(1,ret.length);
}
/* }}} */
// {{{ ajax_inject_html(tagId,htmlToInject)
/**
 * Non-flickering way of setting innerHTML on an element.
 * @param tag id of an elem (string) or the elem itself
 * @todo optimize by generating offline and using a replace node
 */
function ajax_inject_html(tag, htmlToInject)
{
    //alert('ajax_inject_html:'+tagId);
	var tag_obj = $(tag);
	if (!tag_obj) {
		alert('No such element: '+tag);
		return false;
	}
    var temp_obj = tag_obj.cloneNode(false);
    temp_obj.innerHTML = htmlToInject;
    tag_obj.parentNode.replaceChild(temp_obj,tag_obj);
    return true;
}
// }}}
