
/**
 * getElementsByClassName(ClassName,tagName,parentElement)
 *
 * Returns an array of elements under the given parent with the given tag and
 * class names.
 *
 * @param string ClassName name of class to get elements containing
 * @param string tagName name of HTML tag with class in it (i.e. 'div')
 * @param mixed parentElement HTML element containing elements with desired 
 *              class names (i.e. document)
 * @return array elements found with ClassName contained in class attribute
 *               (may be an empty array)
 */
function getElementsByClassName(ClassName,tagName,parentElement){
  var elements = new Array();
  var d = parentElement ? parentElement : document;
  var allElements;

  if(tagName)
    allElements = d.all && d.all.tags(tagName) || d.getElementsByTagName && d.getElementsByTagName(tagName);
  else 
    allElements = d.all || d.getElementsByTagName("*");
  
  for(var i = 0,len = allElements.length; i < len; i++)
    if(isClass(allElements[i], ClassName))
      elements[elements.length] = allElements[i];
  
  return elements;
}

/**
 * isClass(element, name)
 *
 * Returns true if the class given in name exists in the given elements
 * className property, returns false otherwise.
 *
 * @param mixed element is an HTML element with a className attribute
 * @param string name the name of the class to check element for
 * @return boolean true if name is found in element's class, false otherwise
 */
function isClass(element, name) {
  var is = false;
  
  if(element.className) {
    var classes = element.className.split(' ');
    for(var i = 0; i < classes.length; i++) {
      if(classes[i] == name) {
        is = true;
        break;
      }
    }
  }
  
  return is;
}

/**
 * addClass(element, name)
 *
 * Adds the given class name to the class(es) already in the elements className
 * property. Returns the full class name with the new one added (does not alter
 * the element).
 *
 * @param mixed element is an HTML element w/ a className attribute
 * @param string name is the class name to add to the element
 * @return string the new className with the new class added
 */
function addClass(element, name) {
  var className = element.className;
  if(className == null || className == '')
    className = name;
  else
    className += ' ' + name;
  return className;
}

/**
 * removeClass(element, name)
 *
 * Removes the given class name from the given element's class(es). Does not
 * alter the element but returns the full className without the removed name.
 * Returns the elements original className if name was not found.
 *
 * @param mixed element is an HTML element w/ a className attribute
 * @param string name is the class name to remove from the element
 * @param string the new class name without the given name
 */
function removeClass(element, name) {
  var className = '';
  
  //alert("removing '" + name + "' from '" + element.className + "'");
  
  var classes = element.className.split(' ');
  for(var i = 0; i < classes.length; i++) {
    if(classes[i] != name)
      className += classes[i] + ' ';
  }
  // strip trailing space
  className = className.substring(0, className.length - 1);
  
  //alert("result '" + className + "'");
  
  return className;
}

/**
 * getClasses(element)
 *
 * Returns an array of class names contained in the className property of the
 * given HTML element.
 *
 * @param mixed element is an HTML element w/ a className attribute
 * @return array of class names (may be empty)
 */
function getClasses(element) { return element.className.split(' '); }

/**
 * setQuery(str, key, value)
 *
 * Adds the given key/value pair to the given query string or overwrites the
 * value of the given key with the passed value if it exists. If str is null
 * then it pulls the current query string. Returns a new query string with the
 * the given key/value set.
 *
 * @param string key the name of the key to set
 * @param string value the value to set the key to
 * @param string str a query string to set the key/value in
 * @return string new query string w/ the key/value set
 */
function setQuery(key, value, str) {
  str = str ? str : location.search;
  var query = parseQuery(str);
  query[key] = value;
  return buildQuery(query);
}

/**
 * getQueryFromString(str)
 *
 * Returns the query string portion of a url in a String object (str)
 *
 * @param String str
 * @return string query string portion of string st
 */
function getQueryFromString(str) {
  var query = false;
  var parts = str.split('?');
  if(parts[1])
    query = parts[1];
  return query;
}

/**
 * getQuery(url)
 *
 * Returns the query string portion of a url
 *
 * @param Location url
 * @return string query string portion of url
 */
function getQuery(url) {
  return unescape(url.search);
}

/**
 * getLocation(url)
 *
 * Returns the portion of a url before the query string
 *
 * @param Location url
 * @return string url up to the query seperator
 */
function getLocation(url) {
  return url.protocol + '//' + url.hostname + url.pathname;
}

/**
 * parseQuery(str)
 *
 * Parses the given query string into an associative array of key/value pairs.
 * If no query string is given then it pulls the current query string.
 *
 * @param string str query string to parse
 * @return array key/value pairs from query string
 */
function parseQuery(str) {
  var query = null;
  var args = new Array();
  str ? str = str : str = location.search;
  str.charAt(0) == '?' ? query = str.substring(1) : query = str;
  if(query) {
    var fields = query.split('&');
    for(var f = 0; f < fields.length; f++) {
      var field = fields[f].split('=');
      args[unescape(field[0].replace(/\+/g, ' '))] = unescape(field[1].replace(/\+/g, ' '));
    }
  }
  return args;
}

function getQueryValue(str, key) {
  query = parseQuery(str);
  return query[key];
}

/**
 * buildQuery(args)
 *
 * Builds a query string from an associative array of key/value pairs. Order
 * is based on whatever order the array is in.
 *
 * @param array args key/value pairs to build query string from.
 * @return string query string created from key/value pairs
 */
function buildQuery(args) {
  var str = '';  
  for(var i in args)
    str += escape(i.replace(/\s/g, '+')) + '=' + escape(args[i].replace(/\s/g, '+')) + '&';
  // strip trailing ampersand
  str = str.substring(0, str.length - 1);
  return str;
}
