
var dom = {

  elById : function(id) {
    return (typeof id != "string") ? id : (document["getElementById"] ? document.getElementById(id) : false );
  },
  
  elsByTag : function(t, p) {
    var p = p ? dom.elById(p) : document;
    return p["getElementsByTagName"] ? p.getElementsByTagName(t) : [];
  },
  
  elByTag : function(t, p) {
    var els = dom.elsByTag(t, p);
    return els.length ? els[0] : 0;
  },
  
  elsByClass : function(c, p, t) {
    var els = t ? dom.elsByTag(t, p) : dom.elsByTag("*", p);
    var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
    var r = [];
    for (var i = 0, i_max = els.length; i < i_max; i++) {
      if (els[i].className && els[i].className.match(re)) {
        r[r.length] = els[i];
      }
    }
    return r;
  },
  
  elByClass : function(c, p, t) {
    var els = dom.elsByClass(c, p, t);
    return els.length ? els[0] : 0;
  },
  
  hasClass : function(el, c) {
    var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
    return (el.className && el.className.match(re)) ? 1 : 0;
  },

  addClass : function(el, c) {
    if (!dom.hasClass(el, c)) {
      el.className += el.className ? " " + c : c;
    }
  },

  elsByAttr : function(a_name, a, p) {
    var els = dom.elsByTag("*", p);
    var esc_a = a.replace(/([\.])/g, '\\$1');
    var re = new RegExp("(^|\\s)" + esc_a + "(\\s|$)");
    var r = [];
    var cur_a;
    for (var i = 0, i_max = els.length; i < i_max; i++) {
      if ((cur_a = els[i].getAttribute(a_name)) && cur_a.match(re)) {
        r[r.length] = els[i];
      }
    }
    return r;
  },

  elByAttr : function(a_name, a, p) {
    var els = dom.elsByAttr(t, p);
    return els.length ? els[0] : 0;
  },
  
  elsByPath : function(path, p) {
    var p = p ? dom.elById(p) : document;
    var parts = path.split(" ");
    var part = parts.shift();
    var rest = parts.join(" ");
    var m;
    var r = [];
    var sub_r;
    var els = [];
    if (m = part.match(/^[\.](.*)$/)) {/* .foo */
      var els = dom.elsByClass(m[1], p);
    }
    else if (m = part.match(/^[\#](.*)$/)) {/* #foo */
      var els = [dom.elById(m[1])];
    }
    else if (m = part.match(/^([^\.]+)\.(.*)$/)) {/* foo.bar */
      var els = dom.elsByClass(m[2], p, m[1]);
    }
    else {/* foo */
      var els = dom.elsByTag(part, p);
    }
    if (rest) {
      for (var i = 0, i_max = els.length; i < i_max; i++) {
        r.append(dom.elsByPath(rest, els[i]));
      }
    }
    else {
      r = els;
    }
    return r;
  },
  
  elByPath : function(path, p) {
    var els = dom.elsByPath(path, p);
    return els.length ? els[0] : 0;
  },
  
  attrVal : function(el, a_name) {
  	return(el && el["getAttribute"]) ? el.getAttribute(a_name) : false;
  },
  
  setEl : function(id, val) {
    dom.elById(id).innerHTML = val;
  },

  toggleEl : function(id) {
    var el = dom.elById(id);
    el.style.display = (el.style.display == "none") ? "" : "none";
    window.focus();
  },
  
  getId : function(el) {
    var el = dom.elById(el);
    if (!el) return 0;
    if (el.id) return el.id;
    if (!el.dom_id) {
      var pos = 0;
      if (p = el.parentNode) {
        var cn = p.childNodes;
        while (cn[pos] != el) {
          pos++;
        }
      }
      el.dom_id = p ? dom.getId(p) + '.' + pos : pos;
    }
    return el.dom_id;
  },
  
  event_registry : {'count' : 0},
  
  addEvent : function(el, e_type, fnc) {
    var el = dom.elById(el);
    if (!el) return 0;
    /* unset old listener */
    dom.removeEvent(el, e_type, fnc);
    /* dom_id */
    var dom_id = dom.getId(el);
    if (!dom.event_registry.dom_id) {
      dom.event_registry.dom_id = {};
    }
    /* register */
    var fnc_key = escape(e_type + fnc);
    var added = false;
    dom.event_registry.dom_id.fnc_key = [el, e_type];
    /* add handler */
    if (el.addEventListener) el.addEventListener(e_type, fnc, false);
    else if (el.attachEvent) el.attachEvent('on' + e_type, fnc);
    else {
      var cur_fnc = el['on' + e_type];
      el['on' + e_type] = (typeof old_fnc == 'function') ? function() { cur_fnc(); fnc();} : fnc;
    }
  },
  
  removeEvent : function(el, e_type, fnc) {
    var el = dom.elById(el);
    if (!el) return 0;
    var dom_id = dom.getId(el);
    var fnc_key = escape(e_type + fnc);
    if (!dom.event_registry.dom_id) return 1;
    if (!dom.event_registry.dom_id.fnc_key) return 1;
    var old_el = dom.event_registry.dom_id.fnc_key[0];
    try {
      el.removeEventListener(e_type, fnc, false);
      old_el.removeEventListener(e_type, fnc, false);
    } catch (e) {};
    try {
      el.detachEvent('on' + e_type, fnc); 
      old_el.detachEvent('on' + e_type, fnc); 
    } catch (e) {};
    try {
      el['on' + e_type] = null;
      old_el['on' + e_type] = null;
    } catch (e) {};
    if (dom.event_registry.dom_id.fnc_key[0].dom_id != dom_id) { /* replaced */
      dom.event_registry.dom_id.fnc_key[0] = null;
    }
    dom.event_registry.dom_id.fnc_key = null;
  },
  
  cancelEvent : function(e) {
    if (e.preventDefault) {
      e.preventDefault();
      e.stopPropagation();
    }
    else {
      e.cancelBubble = true;
      e.returnValue = false;
    }
  }
  
};
