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


// -------------------------------------------------------------------------------------------------
function $$(name, parent, id, clazz, html) {
  var el = document.createElement(name);
  if (id) el.id = id;
  if (clazz) el.className = clazz;
  if (html) el.innerHTML = html;
  if (parent) parent.appendChild(el);
  return el;
}


// -------------------------------------------------------------------------------------------------
/*
 * Because that fucking IE doesn't support changing some attributes after an element has been 
 * added to the DOM, I had to get out of my way and create this retarded method. The worst fucking 
 * browser ever! Boycot it whenever you can!
 */
function $$input(type, parent, id, clazz, value) {
  var el = document.createElement("input");
  el.setAttribute("type", type);
  if (id) el.id = id;
  if (clazz) el.className = clazz;
  if (value) el.value = value;
  if (parent) parent.appendChild(el);
  return el;
}


// -------------------------------------------------------------------------------------------------
function $$$(x) { return x; }


// -------------------------------------------------------------------------------------------------
function $call(method, url, params, cb, doEval) {
  var req = new XMLHttpRequest();
  req.open(method, url);
  if (cb) {
    req.onreadystatechange = function (e) {
      if (req.readyState === 4 && req.status === 200) {
        if (doEval) {
          var res = null;
          try {
            eval("res = " + req.responseText);
          }
          catch (ex) {
            res = { outcome: false, msg: ex };
          }
          cb(res);
        }
        else cb(req);
      }
    };
  };
  if (params) {
    req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    req.setRequestHeader("Content-length", params.length);
    req.setRequestHeader("Connection", "close");
    req.send(params);
  }
  else req.send(null);
}


// -------------------------------------------------------------------------------------------------
function $evtGet(e) {
  if (typeof e == 'undefined') e = window.event;
  if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
  if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
  return e;
}


// -------------------------------------------------------------------------------------------------
function $evtKey(e) {
  e = $evtGet(e);
  return (window.event ? event.keyCode : e.which);
}


// -------------------------------------------------------------------------------------------------
function $evtTgt(e) {
  e = $evtGet(e);
  return e.target || e.srcElement;
}


// -------------------------------------------------------------------------------------------------
function $genSessId(n) {
  var c, res="";
  for (var i=0; i < n; i++) {
    do {
      c = String.fromCharCode(Math.floor(Math.random() * 255));
    } while (c !== encodeURIComponent(c));
    res += c;
  }
  return res;
}


// -------------------------------------------------------------------------------------------------
function $hide() {
  for (var i=0, ni=arguments.length; i < ni; i++) {
    var x = arguments[i];
    (typeof x === "string" ? $(x).style.display = "none" : x.style.display = "none");
  }
}


// -------------------------------------------------------------------------------------------------
function $log(url, evt, killCache, params) {
  if (location.hostname.indexOf("localhost") === -1) {
    var p = "";
    if (params) {
      for (var k in params) p += "&" + k + "=" + params[k];
    }
    p += (killCache ? "&_=" + (new Date()).getTime() : "");  // prevent caching
    $call("GET", url + "/cgi-bin/log.cgi?e=" + evt + p);
  }
}

  
// -------------------------------------------------------------------------------------------------
function $lfold(fn, A, init) {
  var res = init;
  for (var i=0,ni=A.length; i < ni; i++) {
    res = fn(res, A[i]);
  }
  return res;
}


// -------------------------------------------------------------------------------------------------
/*
 * Pass one or more arrays after the 'fn' argument. In the case of 
 * multiple arrays they are anticipated to be of the same size.
 */
function $map(fn) {
  var lstCnt = arguments.length-1;
  var res = [];
  
  if (lstCnt === 1) {  // one extra argument
    if (!(arguments[1] instanceof Array)) {  // and this argument ain't an array
      return fn(arguments[1]);
    }
    
    for (var i=0, l=arguments[1].length; i < l; i++) {  // it is an array
      res[i] = fn(arguments[1][i]);
    }
  }
  else {  // multiple extra arguments
    for (var i=0, l=arguments[1].length; i < l; i++) {
      var lst = [];
      for (var j=1; j <= lstCnt; j++) {
        lst.push(arguments[j][i]);
      }
      res[i] = fn(lst);
    }
  }
  
  return res;
}


// -------------------------------------------------------------------------------------------------
function $removeChildren(el) {
  if (typeof x === "string") el = $(id);
  while (el.hasChildNodes()) el.removeChild(el.childNodes[0] || el.children[0]);
}


// -------------------------------------------------------------------------------------------------
function $setAttr(o,A) {
  for (var a in A) {
    o.setAttribute(a, A[a]);
  }
  return o;
}


// -------------------------------------------------------------------------------------------------
function $show() {
  for (var i=0, ni=arguments.length; i < ni; i++) {
    var x = arguments[i];
    (typeof x === "string" ? $(x).style.display = "block" : x.style.display = "block");
  }
}


// -------------------------------------------------------------------------------------------------
function $trim(s) {
  return s.replace(/^\s+|\s+$/g, "");
}
