/*
    ajax.js, (c) fv.cz <devel@fv.cz>
    -- prace s AJAX (Asynchronous JavaScript and XML)
    --
    -- rev.0.6, 21.03.2008, 09:27, smid  :: *ajax_{GET|POST} callback: onLoad, onComplete, onError
    -- rev.0.5, 02.03.2008, 23:39, j3nda :: +callback: onLoad, onComplete, onError
    -- rev.0.4, 17.10.2007, 18:34, j3nda :: *ajax_{GET|POST}
    -- rev.0.3, 17.10.2007, 12:49, j3nda :: *ajax_envelopeFORM()
    -- rev.0.2, 15.10.2007, 16:44, j3nda :: +ajax_{GET|POST}, +ajax_envelope{ID|FORM}, @ajax_replace()
    -- rev.0.1, 31.05.2006, 13:49, j3nda :: revize souboru (via: 'www.jantichy.cz/vyuka/izi228/javascript' && 'ajax.js' <dennis.fridrich@visiontech.cz>)

    TODO: lepsi validade FORMulare ohledne .value hodnoty pro starsi prohlizece, ktere tuto moznost nemaji
    TODO: http://www.quirksmode.org/js/forms.html

    ======
    v pripade, ze se vola ajax_{GET|POST} vcetne funkce na 'callback', je nutne
    zajistit spravne vykonani "naseho" kodu v pripade, ze se pozadavek (ne)povede
    viz:
        http://developer.apple.com/internet/webcontent/xmlhttpreq.html

    napr: 
    function callback_processAjaxResponse() {
    // only if ajax shows "loaded"

        // only if "OK"
        if (ajax.readyState == 4) {
    
            // HTTP status
            if (ajax.status == 200) {
                $('votes').innerHTML = req.responseText;

            } else {
                alert("There was a problem retrieving the XML data:\n" + ajax.statusText);
            }
        }
    
    } 

    zde je tabulka moznych vlastnosti:
    Property  Description
    -------------------------------
    onreadystatechange  Event handler for an event that fires at every state change 
    readyState          Object status integer: 
      0 = uninitialized
      1 = loading
      2 = loaded
      3 = interactive
      4 = complete

    responseText        String version of data returned from server process
    responseXML         DOM-compatible document object of data returned from server process
    status              Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
    statusText          String message accompanying the status code

    ======
*/


// vytvori zakladni instanci pro praci s AJAXem
function ajax_instance() {
    var ajax = false;

    /*@cc_on @*/
    /*@if (@_jscript_version >= 5)
    try {
        ajax = new ActiveXObject('Msxml2.XMLHTTP');

    } catch (e) {
        try {
            ajax = new ActiveXObject('Microsoft.XMLHTTP');
        } catch (E) {
            ajax = false;
        }
    }
    @end @*/
    if (!ajax && typeof XMLHttpRequest != undefined) {
        ajax = new XMLHttpRequest();
    }

    return ajax;
}


// doc: provede pozadavek: GET a vraceny vysledek zobrazi do 'element_id'
// doc: -- element_id          = id elementu v HTML dokumentu
// doc: -- url                 = url adresa pro odeslani pozadavku
// doc: -- err_msg             = text chybove zpravy, pokud se pozadavek nevydari
// doc: -- async               = 0=false|1=true, zda se bude jednat o asynchronni pozadavek [default: true]
// doc: -- callback            = funkce, ktera se zavola pri stavu pozadavku (element_id, ajax, err_msg)
// doc: -- callback            =  {
// doc: -- callback            =    onLoad    (element_id, url)           ~ pred spustenim pozadavku
// doc: -- callback            =    onComplete(element_id, ajax)          ~ po kompletnim pozadavku
// doc: -- callback            =    onError   (element_id, ajax, err_msg) ~ v pripade chyby
// doc: -- callback            =  }
function ajax_GET(element_id, url, err_msg, async, callback) {
    if (!url) {
        document.getElementById(element_id).innerHTML = "";
        return false;
    }

    if (async == undefined) { async=true; }

    var ajax = ajax_instance();
    if (!ajax) { return false; }

    ajax.open('GET', url, async);

    if (callback == undefined) {
        callback=undefined;
        c_onLoad=undefined;
        c_onComp=undefined;
        c_onErr =undefined;

    } else {
        if (callback['onLoad'] != undefined) { c_onLoad=callback['onLoad']; }
        if (callback['onComp'] != undefined) { c_onComp=callback['onComp']; }
        if (callback['onErr']  != undefined) { c_onErr =callback['onErr']; }
    }

    if (c_onLoad == undefined && c_onComp == undefined && c_onErr == undefined && callback != undefined) {
        ajax.onreadystatechange=callback(element_id, ajax, err_msg);

    } else {
        ajax.onreadystatechange = function() {
            if (ajax.readyState == 4) {
                if (ajax.status == 200) {
            
                    r=false;
                    if (c_onComp != undefined) {
                        r=c_onComp(element_id, ajax);
                    }
                    
                    if (!r) {
                        var which_element = document.getElementById(element_id);
                        which_element.innerHTML = ajax.responseText;
                    }

                } else {
                    r=false;
                    if (c_onError != undefined) {
                        c_onError(element_id, ajax, err_msg);
                    }

                    if (!r) {
                        var which_element = document.getElementById(element_id);
  
                        if (!err_msg) { err_msg="ajax: error while GET url data!"; }
                        which_element.innerHTML = err_msg+"<br />\n("+ ajax.status +") "+ ajax.statusText;
                    }
                }

            }
        }
        // END of function()

        if (c_onLoad != undefined) {
            c_onLoad(element_id, url);
        }
    }

    ajax.send(null);
    if (async == false) { return ajax.responseText; }

    return true;
}


// doc: provede pozadavek: POST a vraceny vysledek zobrazi do 'element_id'
// doc: -- element_id = id elementu v HTML dokumentu
// doc: -- url        = url adresa pro odeslani pozadavku
// doc: -- data       = data, ktera se pomoci POSTu odeslou
// doc: -- err_msg    = text chybove zpravy, pokud se pozadavek nevydari
// doc: -- async      = 0=false|1=true, zda se bude jednat o asynchronni pozadavek [default: true]
// doc: -- callback            = funkce, ktera se zavola pri stavu pozadavku (element_id, ajax, err_msg)
// doc: -- callback            =  {
// doc: -- callback            =    onLoad    (element_id, url)           ~ pred spustenim pozadavku
// doc: -- callback            =    onComplete(element_id, ajax)          ~ po kompletnim pozadavku
// doc: -- callback            =    onError   (element_id, ajax, err_msg) ~ v pripade chyby
// doc: -- callback            =  }
function ajax_POST(element_id, url, data, err_msg, async, callback) {
    if (url == undefined) {
        document.getElementById(element_id).innerHTML = "";
        return false;
    }
    
    if (async == undefined) { async=true; }

    var ajax = ajax_instance();
    if (!ajax) { return false; }

    ajax.open('POST', url, async);

    if (callback == undefined) {
        callback=undefined;
        c_onLoad=undefined;
        c_onComp=undefined;
        c_onErr =undefined;

    } else {
        if (callback['onLoad'] != undefined) { c_onLoad=callback['onLoad']; }
        if (callback['onComp'] != undefined) { c_onComp=callback['onComp']; }
        if (callback['onErr']  != undefined) { c_onErr =callback['onErr']; }
    }
                                                                
    if (c_onLoad == undefined && c_onComp == undefined && c_onErr == undefined && callback != undefined) {
        ajax.onreadystatechange=callback(element_id, ajax, err_msg);

    } else {
        ajax.onreadystatechange = function() {
            if (ajax.readyState == 4) {
                if (ajax.status == 200) {
                    r=false;
                    if (c_onComp != undefined) {
                        r=c_onComp(element_id, ajax);
                    }

                    if (!r) {
                        var which_element = document.getElementById(element_id);
                        which_element.innerHTML = ajax.responseText;
                    }

                } else {
                    r=false;
                    if (c_onError != undefined) {
                        c_onError(element_id, ajax, err_msg);
                    }

                    if (!r) {
                        var which_element = document.getElementById(element_id);
  
                        if (!err_msg) { err_msg="ajax: error while POST url data!"; }
                        which_element.innerHTML = err_msg+"<br />\n("+ ajax.status +") "+ ajax.statusText;
                    }
                }

            }
        }
        // END of function()

        if (c_onLoad != undefined) {
            c_onLoad(element_id, url);
        }
    }

    ajax.setRequestHeader("Content-type",   "application/x-www-form-urlencoded");
    ajax.setRequestHeader("Content-length", data.length);
    ajax.setRequestHeader("Connection",     "close");

    ajax.send(data);
    if (async == false) { return ajax.responseText; }

    return true;
}


// doc: vrati obalena data do klasickeho rawurlencode() formatu, aby bylo mozne
// doc: s daty dal pracovat (GET|POST) a zaroven tato data ziska z ID danych
// doc: prvku na strance
// doc: -- element_ids   = (pole|retezec) ID prvku
// doc: -- element_ids   = priklad: id1,id2,id3
// doc: -- element_ids   = priklad: name1=id1,name2=id2,name=3id3
// doc: -- element_ids   = priklad: array(id1, id2, id3)
// doc: -- element_ids   = priklad: array('name1=id1', 'name2=id2', 'name3=id3')
// doc: -- element_ids   = priklad: array(name1 => id1, name2 => id2, name => id3) <<< PROZATIM NEFUNKCNI
// doc: -- concat_string = retezec, ktery oddeluje predana data [default: '&']
function ajax_envelopeID(element_ids, concat_string) {
    var arr = Array();
    var assoc = 0;
    
    if (element_ids   == undefined) { return ''; }
    if (concat_string == undefined || concat_string == '') { concat_string="&"; }

    // element_ids je asociativni pole
    // zatim jej neumim resit, konstrukce je:
    // x=new Array(); x['name1']='text1'; ajax_envelopeID(x);
    if (typeof(element_ids[0]) == "object") {
        return '';

    } else {
        // element_ids neni pole
        if (element_ids.constructor.toString().indexOf("Array") == -1) {
            var tmp=element_ids;
            var tmp_array=tmp.split(",");

            // element_ids ma format pro asociativni pole
            if (element_ids.indexOf('=', 0) >= 0) {
                assoc=1;

                for (var i=0; i<tmp_array.length; i++) {
                    var tmp_line=tmp_array[i].split("=");
                    arr[tmp_line[0]]=tmp_line[1];
                }

            } else {
                arr=tmp_array;
            }

        } else {
        // element_ids je pole
            var tmp_array=element_ids;

            // element_ids ma format pro asociativni pole
            if (element_ids[0].indexOf('=', 0) >= 0) { 
                assoc=true;
                for (var i=0; i<tmp_array.length; i++) {
                    var tmp_line=tmp_array[i].split("=");
                    arr[tmp_line[0]]=tmp_line[1];
                }

            } else {
                arr=element_ids;
            }
        }
    }

    var str='';

    // prochazim asociativni pole
    if (assoc == 1) {
        for (i in arr) {
            str=str + concat_string + i + "="  + escape(encodeURI(document.getElementById(arr[i]).value));
        }

    } else {
    // prochazim pole
        for (var i=0; i<arr.length; i++) {
            str=str + concat_string + escape(encodeURI(document.getElementById(arr[i]).value));
        }
    }
    
    return str;
}


// doc: obali data do klasickeho rawurlencode() formatu, aby bylo mozne
// doc: s daty dal pracovat (GET|POST). prochazi FORMular danych prvku
// doc: -- element_ids = (pole|retezec) ID prvku
// doc: -- element_ids = priklad: id1,id2,id3
// doc: -- element_ids = priklad: name1=id1,name2=id2,name=3id3
// doc: -- element_ids = priklad: array(id1, id2, id3)
// doc: -- element_ids = priklad: array(name1 => id1, name2 => id2, name => id3)

// doc: vrati obalena data do klasickeho rawurlencode() formatu, aby bylo mozne
// doc: s daty dal pracovat (GET|POST) a zaroven tato data ziska z FORMulare
// doc: -- form_name     = nazev formulare, odkud se data ziskaji
// doc: -- element_names = (pole|retezec) nazvu formularovych prvku. pokud je prazdny
// doc: -- element_names = zjisti se vsechny prvky daneho formulare
// doc: -- element_names = priklad: id1,id2,id3
// doc: -- element_names = priklad: array(id1, id2, id3)
// doc: -- concat_string = retezec, ktery oddeluje predana data [default: '&']
function ajax_envelopeFORM(form_name, element_names, concat_string) {
    var str = '';
    var arr = [];

    if (concat_string == undefined || concat_string == '') { concat_string="&"; }
    
    // zjistim pocet prvku ve formulari a jejich hodnotu
    if (element_names == undefined || element_names.length == 0 || element_names == '') {
        tmp=document.forms[form_name];
        str='';
        for (var i=0; i<tmp.length; i++) {
            if (tmp.elements[i].name != '') {
                str=str + concat_string + tmp.elements[i].name + "="  + escape(encodeURI(tmp.elements[i].value));
            }
        }
        return str;

    } else {
    // element_names neni pole
        if (element_names.constructor.toString().indexOf("Array") == -1) {
            arr=element_names.split(",");

        } else {
            arr=element_names;
        }

        tmp=document.forms[form_name]; 
        str='';
        for (var i=0; i<arr.length; i++) {
            if (tmp.elements[arr[i]].name != '') {
                str=str + concat_string + tmp.elements[arr[i]].name + "="  + escape(encodeURI(tmp.elements[arr[i]].value));
            }
        }

        return str;
    }

    return str;
}



// doc: nahradi obsah libovolneho elementu obsahem
// doc: -- element = id elementu na strance, napr: <div id="moje_id">text, text</div>
// doc: -- content = obsah, ktery se pouzije k nahrazeni obsahu elementu
function ajax_replace(element_id, content) {
    if (element_id == undefined || element_id == '') { return false; }
    if (content == undefined) { content=''; }

    document.getElementById(element_id).innerHTML=content;
    return true;
}

