function $(id) { 
    return document.getElementById(id); 
}

debug_elem = null;

function create_request() {
    var ret = null;
    if (window.XMLHttpRequest) {
        ret = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
            ret = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                ret = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {}
        }
    }
    return ret;
}

function parse_json(txt) {
    return eval('(' + txt + ')')
}

function getraw(url, finish, err) {
    var request = create_request();
    if (request) {
       request.open("GET", url);
       request.onreadystatechange = function() {
           if(request.readyState == 4) {
               var ok = false;
               try {
                   ok = request.status == 200 && !request.error;
               } catch (e) { }
               if (ok) {
                   var txt = request.responseText;
                   if (debug_elem) {
                       setelemtext(debug_elem, txt);
                   }
                   finish(request)
                   
               } else {
                   if (err)
                       err(request)
               }
           }
       }
       request.send("");
    } 
    return request;
}

function getjson(url, finish, err) {
    getraw(url, function(obj) { finish(parse_json(obj.responseText)) }, err);
}

function getxml(url, finish, err) {
    getraw(url, function(obj) { finish(obj.responseXML) }, err);
}

function newelem(t, clas, txt) { 
    var ret = document.createElement(t);
    if (clas)
        ret.className = clas;

    if (txt) 
        ret.appendChild(document.createTextNode(txt))

    return ret;
}

function clearelem(p) {
    var cc = p.firstChild;
    var oc;
    while (cc) {
        oc = cc;
        cc = cc.nextSibling;
        p.removeChild(oc);
    }
}

function clearafter(cc) {
    if (!cc)
        return;
    var p = cc.parentNode;
    var oc;
    while (cc) {
        oc = cc;
        cc = cc.nextSibling;
        p.removeChild(oc);
    }
}

function addtext(elem, txt) {
    elem.appendChild(document.createTextNode(txt));
}

function addbr(elem) {
    elem.appendChild(newelem('br'));
}

function addtextclas(elem, clas, txt) {
    elem.appendChild(newelem('span', clas, txt));
}

function setelemtext(e, txt) {
    var tt = e.firstChild;
    if (tt) {
        tt.data = txt;
    } else {
        addtext(e, txt);
    }
}


function addcell(row, clas, txt) {
    var td = newelem('td', clas, txt);
    row.appendChild(td);
    return td;
}

function addcelle(row, clas, e) {
    var td = newelem('td', clas);
    td.appendChild(e);
    row.appendChild(td);
    return td;
}

function init_debug() {
    var debug_div = $('debug');
    if (debug_div) {
        var expander = newelem('span', 'debugexpander', 'Debug >>');
        //global
        debug_elem = newelem('pre');
        debug_elem.style.display = 'none';
        
        expander.onclick = function() {
            if (debug_elem.style.display != 'none') {
                debug_elem.style.display = 'none';
                setelemtext(expander, 'Debug >>');
            } else {
                debug_elem.style.display = 'block';
                setelemtext(expander, 'Debug <<');
            }
        }
        debug_div.appendChild(expander);
        debug_div.appendChild(debug_elem);
    }
}

function foreach(arr, f) {
    var l = arr.length;
    for (var i = 0; i < l; i++) {
        var v = f(arr[i], i);
        if (v != null)
            return v;
    }
}

Array.prototype.each = function(f) {
    return foreach(this, f);
}

Array.prototype.append = function(v) {
    this[this.length] = v;
}
