// returns one or more elements by id (or the element itself if passed an element)
function $() {
  var results = [], e;
  for (var i = 0; i < arguments.length; i++) {
    e = arguments[i];
    if (typeof e == 'string')
      e = document.getElementById(e);
    results.push(e);
  }
  return results.length < 2 ? results[0] : results;
}

// hide an element
function hide() {
  var e = null;
  
  for (var i = 0; i < arguments.length; i++) {
    e = $(arguments[i]);
    if (e) {
      e.style.visibility = 'hidden';
      e.style.display = 'none';
      if (e.onhide) e.onhide();
    }
  }
  
  return e;
}

// show an element
function show() {
  var e = null;
  
  for (var i = 0; i < arguments.length; i++) {
    e = $(arguments[i]);
    if (e) {
      e.style.visibility = 'visible';
      e.style.display = '';
      if (e.onshow) e.onshow();
    }
  }
  
  return e;
}

// return whether a given element is visible
function visible(e) {
  e = $(e);
  return e ? e.style.display != 'none' : false;
}

// toggle an element's visibility
function toggle() {
  for (var i = 0; i < arguments.length; i++) {
    var e = $(arguments[i]);
    visible(e) ? hide(e) : show(e);
  }
}

// ensure that a function is called within the scope of the given element
function bind(elem, func) {
  return function() { func.call(elem); };
};

// appends an <option> to a <select>
function addOption(select, name, value) {
  var op = document.createElement('option');
  op.value = value;
  op.innerHTML = name;
  select.appendChild(op);
};

// add event listener to an object
Listener = {
  add: function(obj, method, func) {
    if (obj && method && func) {
      if (!obj.listeners) obj.listeners = {};
      if (!obj.listeners[method]) {
        obj.listeners[method] = [];
        if (obj[method]) obj.listeners[method].push(obj[method]);
        obj[method] = bind(obj, Listener.listen(method));
      }
      obj.listeners[method].push(func);
    }
  },
  
  listen: function(method) {
    return function() {
      for (var i = 0; i < this.listeners[method].length; i++) {
        if (typeof this.listeners[method][i] == 'function')
          this.listeners[method][i].call(this);
        else
          eval(this.listeners[method][i]);
      }
    };
  }
};

/**
 * Adds the given style class to the given element, ensuring that it does not already exist.
 * @param elem the element to classify.
 * @param className the style class to be added.
 */
function add_class(elem, className) {
  if (elem) {
    if (!elem.className || elem.className.length == 0)
      elem.className = className;
    else if (!elem.className.match('(^' + className + '$)|(^' + className + ' )|( ' + className + '$)|( ' + className + ' )'))
      elem.className += ' ' + className;
  }
}

/**
 * Removes the given style class from the given element.
 * @param elem the element to declassify.
 * @param className the style class to be removed.
 */
function remove_class(elem, className) {
  if (elem && elem.className) {
    elem.className = elem.className.replace(new RegExp('^' + className + '()()$'), '$2')
                                   .replace(new RegExp('^' + className + '( )()'), '$2')
                                   .replace(new RegExp('( )' + className + '( )'), '$2')
                                   .replace(new RegExp('( )' + className + '()$'), '$2');
  }
}

/***** Form temporary default input data *****/
function setup_temporaries() {
  var temporaries = document.getElementsByTagName('input');
  for (var i = 0; i < temporaries.length; i++) {
    if (!temporaries[i]._tset && (temporaries[i].type == 'text' || temporaries[i].type == 'password'))
      inputTemporarySetup(temporaries[i]);
  }
  
  temporaries = document.getElementsByTagName('textarea');
  for (var i = 0; i < temporaries.length; i++) {
    if (!temporaries[i]._tset)
      inputTemporarySetup(temporaries[i]);
  }
}

function inputTemporarySetup(elem) {
  elem = $(elem);
  if (elem) {
    var text = elem.getAttribute("temporary") || elem.temporary;

    if (text && !text.match(/^\s*$/)) {
      elem.use_temporary_class = (elem.className && elem.className.match(/temporary/)) ? true : false;
      elem.prev_onfocus = elem.onfocus;
      elem.prev_onblur = elem.onblur;
      elem.temporary = text;
      elem._tset = true;
      
      // if the input is a password field, we want the temporary text to be visible.
      // this means we need to create a temporary input with value equal to the temporary,
      // and switch between the password and the text field.  setting password.type = 'text'
      // does not work in Internet Explorer (read-only property).
      if (elem.type == 'password') {
        var p_input = document.createElement('input');
        p_input._tset = true;
        p_input.elem = elem;
        p_input.value = text;
        p_input.type = 'text';
        p_input.className = elem.className;
        p_input.onfocus = passTemporaryFocus;
        if (elem.id) p_input.id = elem.id + '_t';
        p_input.style.width = elem.style.width;
        p_input.style.display = elem.style.display;
        p_input.style.visibility = elem.style.visibility;
        
        hide(elem);
        elem.p_input = p_input;
        elem.onhide = passTemporaryHide;
        elem.onshow = passTemporaryShow;
        elem.onblur = passTemporaryBlur;
        remove_class(elem, 'temporary');
        elem.parentNode.insertBefore(p_input, elem);
      } else {
        if (!elem.value) elem.value = text;
        else if (elem.use_temporary_class && elem.value != text) remove_class(elem, 'temporary');
        
        elem.onfocus = textTemporaryFocus;
        elem.onblur = textTemporaryBlur;
      }
    }
    
    var onEnter = elem.getAttribute("onenter") || elem.getAttribute("onEnter") || elem.onenter || elem.onEnter;
    if (onEnter) Event.observe(elem, 'keypress', onEnterFunction(elem, onEnter));
  }
}

function textTemporaryFocus() {
  if (this.temporary && this.value == this.temporary) {
    this.value = '';
    if (this.use_temporary_class && this.className)
      remove_class(this, 'temporary');
  }
  
  if (this.prev_onfocus) return this.prev_onfocus();
}

function textTemporaryBlur() {
  if (this.temporary && (this.value == "" || this.value == this.temporary)) {
    if (this.use_temporary_class) add_class(this, 'temporary');
    this.value = this.temporary;
  }
  
  if (this.prev_onblur) return this.prev_onblur();
}

function passTemporaryFocus() {
  this.style.display = 'none';
  this.style.visibility = 'hidden';
  this.elem.style.display = '';
  this.elem.style.visibility = 'visible';
  this.elem.focus();
  this.elem.select();
  
  if (this.elem.prev_onfocus) return this.elem.prev_onfocus();
}

function passTemporaryBlur() {
  passTemporaryShow.call(this);
  if (this.prev_onblur) return this.prev_onblur();
}

function passTemporaryHide() {
  this.p_input.style.display = 'none';
  this.p_input.style.visibility = 'hidden';
}

function passTemporaryShow() {
  if (this.value == '' || this.value == this.temporary) {
    this.value = '';
    this.style.display = 'none';
    this.style.visibility = 'hidden';
    this.p_input.style.display = '';
    this.p_input.style.visibility = 'visible';
  }
}

function onEnterFunction(elem, onEnter) {
  elem.onEnter = onEnter;
  return function(e) {
    e = window.event || e;
    if (e.keyCode == 13) {
      if (typeof onEnter == 'function')
        return this.onEnter();
      else
        return eval(this.onEnter);
    }
  }.bind(elem);
}

Listener.add(window, 'onload', setup_temporaries);

