Elem.prototype.ensureClassIncludes=function(classname, include) {
    var classes, newclasses;

    if (this.className!="") {
        classes=this.className.split(" ");
        newclasses="";
    } else {
        classes=new Array();
        newclasses="";
    }
    
    for (var i=0; i<classes.length; i++) {
        if (classes[i]!=classname) newclasses+=classes[i]+" ";
    }
    
    if (include) newclasses+=classname+" ";
    this.className=newclasses.substr(0,newclasses.length-1);
}

Elem.prototype.getBounds=function() {
    var left=0;
    var top=0;
    var width=this.offsetWidth;
    var height=this.offsetHeight;
    
    var ele=this;
    
    if (ele.offsetParent) {
        do {
            left+=ele.offsetLeft;
            top+=ele.offsetTop;
        } while (ele=ele.offsetParent);
    }
    return { x: left, y: top, width: width, height: height };
}

/**
 * 
 */
Elem.prototype.getEffectiveStyle=function(pseudo) {
    if (window.getComputedStyle) {
        return window.getComputedStyle(this, pseudo);
    } else {
        return this.currentStyle;
    }
}

Elem.prototype.getPosition=function(obj) {
    var curleft = curtop = 0;
    
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    return { x: curleft, y: curtop };
}

/**
 * Returns the textual content of the element.
 */
Elem.prototype.getInnerText=function() {
    if (this.textContent) {
        return this.textContent;
    } else {
        return this.text; // IE Bug possible
    }
}

Elem.prototype.animateStyle=function(newstyle) {
  
}

Elem.prototype.classIncludes=function(clazz) {
  //TODO: implement properly to allow multiple classes
  return this.className==clazz;
}

Elem.prototype.setVisible=function(visible) {
  if (visible) {
    this.style.display='block';
  } else {
    this.style.display='none';
  }
}


function Elem() {

}

/**
 * Adds a function to an object.
 * @param obj - the object to add the function to
 * @param name - the name the function will have once added
 * @param fn - the function to add
 */
Elem.addFunction=function(obj, name, fn) {
  if (typeof obj[name]=="undefined") obj[name]=fn;
}

/**
 * Gets an element by id, and adds Elem's extra functions to it
 */
Elem.getById=function(id) {
  var element;

  if (document.getElementById) {
    element=document.getElementById(id);
  } else {
    alert("getElementById not present");
  }
  
  if (element!=null) {
    Elem.processElement(element);
  }
  
  return element;
}

/**
 * Gets elements by tag, and adds Elem's extra functions to them.
 */
Elem.getByTag=function(tag) {
  var elements=document.getElementsByTagName(tag);

  for (var e in elements) {
    if (typeof elements[e]=="object") {
      Elem.processElement(elements[e]);
    }
  }
  
  return elements;
}

/**
 * Gets elements by class, and adds Elem's extra functions to them.
 */
Elem.getByClass=function(clazz) {
  var tagmatch=document.getElementsByTagName("*");
  var elements=new Array();

  for (var i=0; i<tagmatch.length; i++) {
    var element=tagmatch[i]; 
    Elem.addFunction(element, "classIncludes", Elem.prototype.classIncludes);
    if (element.classIncludes(clazz)) {
      Elem.processElement(element);
      elements.push(element);
    }  
  }
  
  return elements;
}

/**
 * Gets elements by class, and adds Elem's extra functions to them.
 */
Elem.getByTagAndClass=function(tag, clazz) {
  var tagmatch=document.getElementsByTagName(tag);
  var elements=new Array();

  for (var i=0; i<tagmatch.length; i++) {
    var element=tagmatch[i]; 
    Elem.addFunction(element, "classIncludes", Elem.prototype.classIncludes);
    if (element.classIncludes(clazz)) {
      Elem.processElement(element);
      elements.push(element);
    }  
  }
  
  return elements;
}

/**
 * Adds the extra methods provided by Elem.
 */
Elem.processElement=function(element) {
  Elem.addFunction(element, "ensureClassIncludes", Elem.prototype.ensureClassIncludes);
  Elem.addFunction(element, "findPos", Elem.prototype.findPos);
  Elem.addFunction(element, "getBounds", Elem.prototype.getBounds);
  Elem.addFunction(element, "getInnerText", Elem.prototype.getInnerText);
  Elem.addFunction(element, "classIncludes", Elem.prototype.classIncludes);
  Elem.addFunction(element, "getEffectiveStyle", Elem.prototype.getEffectiveStyle);
  Elem.addFunction(element, "setVisible", Elem.prototype.setVisible);
}

