// Copyright Daniel Hillis 2006
// University of Wisconsin-Eau Claire
// McIntyre Library

///////////////////////////////////////////////////////////////
//                     Function.changeThis()                 //
///////////////////////////////////////////////////////////////


Function.prototype.changeThis = function(newThis) {
  var method = this;
  return function() {return method.call(newThis);}
  }


///////////////////////////////////////////////////////////////
//           browserCompatibleAddEventListener()             //
///////////////////////////////////////////////////////////////

function browserCompatibleAddEventListener(element, event, userFunc, phase, newThis) {
  // Set default values for phase
  phase = (phase == null) ? false : phase;

  var func = userFunc;
  if (newThis) 
    func = userFunc.changeThis(newThis);

  if (event != "valuechange")
    return _addEventListner(element, event, func, phase);
  
  // now we know that event="valueChange"  Ths is an event that I'm adding.  The 
  // ideas is that the event fires whenever the value in an element changes
  switch (element.tagName) {
    case "INPUT":
      switch (element.type) {
        case "text":
          return _addEventListner(element, "keyup", func, phase);
        case "radio":
          return _addEventListner(element, "click", func, phase);
        case "checkbox":
          return _addEventListner(element, "click", func, phase);
        case "password":
          return _addEventListner(element, "keyup", func, phase);
        default:
          return _addEventListner(element, "click", func, phase);
        }
    case "SELECT":
      return _addEventListner(element, "change", func, phase);
    case "TEXTAREA":
      return _addEventListner(element, "keyup", func, phase);
    default:
      return _addEventListner(element, "click", func, phase);
    }

  }

function _addEventListner(element, event, func, phase) {
    if (element.addEventListener) {
    element.addEventListener(event, func, phase);
    }
  else if (element.attachEvent) {
    element.attachEvent("on"+event, func);
    }
  else {
    alert("your browser doesn't support attaching event handlers");
    }
  }


///////////////////////////////////////////////////////////////
//                     $E() notation                         //
///////////////////////////////////////////////////////////////

var _elementCache = new Object();
function $E(id) {
  if (_elementCache[id])
    return _elementCache[id];

  var element = document.getElementById(id);
  if (!element) {
    alert("Element with ID: " + id + " cannot be found");
    return false;
    }
  
  switch (element.tagName) {
    case "INPUT":
      switch (element.type) {
        case "text":
          return _elementCache[id] = new InputText(id);
        case "button":
          return _elementCache[id] = new InputButton(id);
        case "radio":
          return _elementCache[id] = new InputRadioArray(id);
        case "checkbox":
          return _elementCache[id] = new InputCheckbox(id);
        default:
          return _elementCache[id] = new Element(id);
        }
      break;
    
    case "SELECT":
      if (element.multiple)
        return _elementCache[id] = new InputMultipleSelect(id);
      else
        return _elementCache[id] = new InputSelect(id);

    case "TEXTAREA":
      return _elementCache[id] = new InputTextArea(id);

    default:
      return _elementCache[id] = new Element(id);
    }
  }

///////////////////////////////////////////////////////////////
//                     Element                               //
///////////////////////////////////////////////////////////////
function Element (id) {
  this.id = id;
  if (id) 
    this.element = document.getElementById(id);

  if ( id && !this.element)
    alert("Element with ID: " + id + " cannot be found");
  }

Element.prototype.addEventListener = function(event, func, phase, newThis) {
  // set default value for newThis
  newThis = (newThis == null) ? this : newThis;

  browserCompatibleAddEventListener(this.element, event, func, phase, newThis);
  }

///////////////////////////////////////////////////////////////
//                     InputText                             //
///////////////////////////////////////////////////////////////

function InputText (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputText.prototype = new Element;

InputText.prototype.getValue = function() {
  return this.element.value;
  }

///////////////////////////////////////////////////////////////
//                     InputSelect                           //
///////////////////////////////////////////////////////////////

function InputSelect (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputSelect.prototype = new Element;

InputSelect.prototype.getValue = function() {
  return this.element.value;
  }

InputSelect.prototype.populateOptionsFromArray = function(aOptions) {
  for (i=this.element.options.length; i>=0; i--)
    this.element.options[i] = null;
  for (i=0; i<aOptions.length; i++) {
    this.element.options[this.element.options.length] = new Option(aOptions[i][1], aOptions[i][0]);
    }
  }
///////////////////////////////////////////////////////////////
//                     InputMultipleSelect                   //
///////////////////////////////////////////////////////////////

function InputMultipleSelect (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputMultipleSelect.prototype = new Element;

InputMultipleSelect.prototype.getValue = function() {
  var returnArray = new Array();
  for (var i=0; i<this.element.options.length; i++) {
    if (this.element.options[i].selected)
      returnArray.push(this.element.options[i].value);
    }
  return returnArray;
  }

InputMultipleSelect.prototype.getOptionValues = function() {
  var returnArray = new Array();
  for (var i=0; i<this.element.options.length; i++) {
    returnArray.push(this.element.options[i].value);
    }
  return returnArray;
  }

InputMultipleSelect.prototype.populateOptionsFromArray = function(aOptions) {
  for (i=this.element.options.length; i>=0; i--)
    this.element.options[i] = null;
  for (i=0; i<aOptions.length; i++) {
    this.element.options[this.element.options.length] = new Option(aOptions[i][1], aOptions[i][0]);
    }
  }
///////////////////////////////////////////////////////////////
//                     InputButton                           //
///////////////////////////////////////////////////////////////

function InputButton (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputButton.prototype = new Element;

InputButton.prototype.getValue = function() {
  return this.element.value;
  }

///////////////////////////////////////////////////////////////
//                     InputCheckbox                         //
///////////////////////////////////////////////////////////////

function InputCheckbox (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputCheckbox.prototype = new Element;

InputCheckbox.prototype.getValue = function() {
  return this.element.value;
  }

///////////////////////////////////////////////////////////////
//                     InputRadioArray                       //
///////////////////////////////////////////////////////////////

function InputRadioArray (id) {
  // inherit from Element
  Element.call(this, id);

  this.elements = document.getElementsByName(this.element.name);
  }
// not necessary
//InputRadioArray.prototype = new Element;

InputRadioArray.prototype.getValue = function() {
  for (i=0;i<this.elements.length;i++) {
    if (this.elements[i].checked) {
      return(this.elements[i].value);
      }
    }
  return null;
  }

InputRadioArray.prototype.addEventListener = function(event, func, phase, newThis) {
  // set default value for newThis
  newThis = (newThis == null) ? this : newThis;

  for (i=0;i<this.elements.length;i++) {
    browserCompatibleAddEventListener(this.elements[i], event, func, phase, newThis);
    }
  
  }


///////////////////////////////////////////////////////////////
//                     InputTextArea                         //
///////////////////////////////////////////////////////////////

function InputTextArea (id) {
  // inherit from Element
  Element.call(this, id);

  }
InputTextArea.prototype = new Element;

InputTextArea.prototype.getValue = function() {
  return this.element.value;
  }