Array.prototype.each = function(fn) {
  var index, value;
  for (index=0; index<this.length; index++) {
    fn(this[index], index);
  }
}

String.prototype.trim  = function() { return this.replace(/^\s+|\s+$/g, ''); };

String.prototype.queryParams = function() {
    var pairs = this.match(/^\??(.*)$/)[1].split('&');
    var params = {};
    pairs.each(function(value, index) {
      var pair = value.split('=');
      params[pair[0]] = pair[1];
    });
    return params;
}

String.prototype.camelize = function() {
  var oStringList = this.split('-');
  if (oStringList.length == 1) return oStringList[0];
    
  var camelizedString = this.indexOf('-') == 0
    ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 
    : oStringList[0];
    
  for (var i = 1, len = oStringList.length; i < len; i++) {
    var s = oStringList[i];
    camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
  }
  
  return camelizedString;
}

function addEvent(obj, evType, fn, useCapture) {
  if (obj.addEventListener) {
    obj.addEventListener(evType, fn, useCapture);
    return true;
  }
  
  evType = 'on' + evType;
  
  if (obj.attachEvent) {
    return obj.attachEvent(evType, fn);
  }
  if (obj[evType]) {
    var oldfn = obj[evType];
    obj[evType] = function() { oldfn(); fn(); }
  }
  else {
    obj[evType] = fn;
  }
}

function removeEvent(obj, evType, fn, useCapture) {
  if (obj.removeEventListener) {
    obj.removeEventListener(evType, fn, useCapture);
    return true;
  }
  if (obj.detachEvent) {
    obj.detachEvent('on' + evType, fn);
  }
}

function MyPosition() {
  switch (arguments.length) {
  case 0:
    this.x = this.y = 0;
    break;
  case 1:
    this.x = arguments[0].x;
    this.y = arguments[0].y;
    break;
  default:
    this.x = arguments[0];
    this.y = arguments[1];
  }
  
  this.toString = function() { return "[" + this.x + "," + this.y + "]"; }
}

function getPos(e) {
  var mX, mY;
  if (e.pageX && e.pageY) {
    mX = e.pageX;
    mY = e.pageY;
  }
  else if (e.clientX && e.clientY) {
    mX = e.clientX;
    mY = e.clientY;
    if (document.all) {
      mX += document.body.scrollLeft;
      mY += document.body.scrollTop;
    }
  }
  return new MyPosition(mX, mY);
}

function addClassName(el, name) {
  if (hasClassName(el, name)) return;
  el.className += " " + name;
}

function hasClassName(el, name) {

  var i, list;

  // Return true if the given element currently has the given class
  // name.

  list = el.className.split(" ");
  for (i = 0; i < list.length; i++)
    if (list[i] == name)
      return true;

  return false;
}

function removeClassName(el, name) {

  var i, curList, newList;

  if (el.className == null)
    return;

  // Remove the given class name from the element's className property.

  newList = new Array();
  curList = el.className.split(" ");
  for (i = 0; i < curList.length; i++)
    if (curList[i] != name)
      newList.push(curList[i]);
  el.className = newList.join(" ");
}

function getElementStyle(element, style) {
  element = $(element);
  var value = element.style[style.camelize()];
  if (!value) {
    if (document.defaultView && document.defaultView.getComputedStyle) {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css.getPropertyValue(style) : null;
    } else if (element.currentStyle) {
      value = element.currentStyle[style.camelize()];
    }
  }

  if (window.opera && ('|left|top|right|bottom'.indexOf(style) > -1))
    if (getElementStyle(element, 'position') == 'static') value = 'auto';

  return value == 'auto' ? null : value;
}

function setElementStyle(element, style) {
  element = $(element);
  for (name in style) 
    element.style[name.camelize()] = style[name];
}

function getElementPos(el) {
  var valueT = 0, valueL = 0;
  do {
    valueT += el.offsetTop  || 0;
    valueL += el.offsetLeft || 0;
    el = el.offsetParent;
  } while (el);
  return new MyPosition(valueL, valueT);
}

// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Position.cumulativeOffset for
// KHTML/WebKit only.
if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
  function getElementPos(el) {
    var valueT = 0, valueL = 0;
    do {
      valueT += el.offsetTop  || 0;
      valueL += el.offsetLeft || 0;
      if (el.offsetParent == document.body)
        if (getElementStyle(element, 'position') == 'absolute') break;
        
      el = el.offsetParent;
    } while (el);
    
    return { x:valueL, y:valueT, toString: function() { return "[" + valueL + "," + valueT + "]"; } };
  }
}

function matchNodeDesc(node, toElTag, toElClass, toElID) {
  var s;
  if ( (s = toElTag.toString().trim().toLowerCase()  ) != "") { if (node.tagName.toLowerCase() != s) return false; }
  if ( (s = toElClass.toString().trim().toLowerCase()) != "") { if (!hasClassName(node,s)) return false; }
  if ( (s = toElID.toString().trim().toLowerCase())    != "") { if (node.id.toLowerCase() != s) return false; }
  return true;
}

function ascendDOM(fromEl, toElTag, toElClass, toElID) {
  var el = fromEl;
  while (el) {
    if (matchNodeDesc(el, toElTag, toElClass, toElID)) { return el; }
    if (el.tagName.toLowerCase() == "body") { return false; }
    el = el.parentNode;
  }
  return false;
}

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

/*
function $$(selector) {
  return document.getElementsBySelector(selector);
}
*/

// -------------- Cookie functions

function setCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}

function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}

function deleteCookie(name, path, domain) {
  if (getCookie(name)) {
    document.cookie = name + "=" +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
}

function fixDate(date) {
  var base = new Date(0);
  var skew = base.getTime();
  if (skew > 0)
    date.setTime(date.getTime() - skew);
}

function eventInfo(e) {
  e = window.event || e;
  if (!e) return;
  
  e.element = e.target || e.sourceElement;
  
  e.pointerX = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
  e.pointerY = e.pageY || (e.clientY + (document.documentElement.scrollTop  || document.body.scrollTop));
  
  e.stop = function() {
    if (e.preventDefault) { 
      e.preventDefault(); 
      e.stopPropagation(); 
    } else {
      e.returnValue = false;
      e.cancelBubble = true;
    }
  };

  // find the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  e.findElement = function(tagName) {
    var element = e.element;
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  };
  
  return e;
}

Function.prototype.bind = function(object) {
	var __method = this;
	return function() {
		return __method.apply(object, arguments);
	}
}

Function.prototype.bindAsEventListener = function(object) {
var __method = this;
	return function(event) {
		__method.call(object, event || window.event);
	}
}


