/*

This file contains javascript wrappers for common html elements
which allows for easy element specific manipulation.

It is based on the prototype javascript library

Each element in this library can exist in one of two states.  Either it
represents an object actually in the document, or it represents an object
that doesn't yet exist in the document.  The second case is indended for 
creating an element in memory prior to writing it to the document.




*/

//----------------------------------------------------------------------
// This is the base object that handles the basic operations common
// to all HTML elements
//----------------------------------------------------------------------
function element_base(){
  this.element_name  = null;
  this.element_attrs = null;
  this.my_element = null;
  
  //
  //Connects this element up to an existing select element
  //
  this.bind = function(element){
    this.my_element = document.getElementById(element);
  }
  //
  //Creates an element as a child to the given element
  //
  this.createAt = function(elem){
    var targetElem = this.normalizeElem(elem);
    this.my_element = new Element(this.element_name,this.element_attrs);
    targetElem.my_element.insert(this.my_element);
    this.addContent();    
  }
  //
  //Creates an element after (as a sibling of) the given element
  //
  this.createAfter = function(elem){
    var targetElem = this.normalizeElem(elem);
    this.my_element = new Element(this.element_name,this.element_attrs);
    targetElem.my_element.insert({after:this.my_element});
    this.addContent();    
  }
  //
  //This method should be overridden by subclasses.  After an element is created, this 
  //method is called to fill out any content.  The overriden method should depend on 
  //this.my_element being initialized with the element to initialize
  //
  this.addContent = function(){}
  
  this.setFocus = function(){
    my_element.focus();  
  }
  
  //
  //an element being passed in could be one of several types.
  //it could be an element_base derived type, or it could be
  //the id of an element.  This method takes the various types
  //and converts it to a element_base related object
  //
  this.normalizeElem = function(elem){
    //alert(typeof elem);
    if ( typeof elem == "object") {
       return elem;
    } else {
       //assume it's an id
       var new_elem = new element_base();
       new_elem.bind(elem);
       return new_elem;  
    }
    
  }
  
  this.escapeHTML = function (str) {                                       
    return str.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/"/g,'&quot;');
  }
  

}
//----------------------------------------------------------------------
// checkbox
//----------------------------------------------------------------------
function Checkbox(){

  this.check = function(){
    this.my_element.checked = true;
  }
  this.uncheck = function(){
    this.my_element.checked = false;
  }
  this.toggle = function(){
  }
  this.isChecked = function(){
    return this.my_element.checked;
  }

}
Checkbox.prototype = new element_base;

//----------------------------------------------------------------------
// text element
//----------------------------------------------------------------------
function Text(){
  this.element_name = "input";
  this.element_attrs = {"type":"text"}; 
  this.value = null;  //value can be stored here temporarily until the 
                      //element is actually created
  
  this.getValue = function(){return this.my_element.value;};
  this.setValue = function(v){
    if (this.my_element!=null){
       this.my_element.value = v;
    } else {
       this.value = v;  
    } 
  }
  this.addContent = function(){
      this.setValue(this.value);
  }
}
Text.prototype = new element_base;
//----------------------------------------------------------------------
// Select element
//----------------------------------------------------------------------
function Select(){
  this.element_name = "select";
  var optiongroups
  
  this.addOption = function(text,value){
    this.my_element.insert("<option value='"+value+"'>"+this.escapeHTML(text)+"</option>");
  }
  this.addOptionGroup = function(text){
    this.my_element.insert("<optgroup label='"+text+"'/>");
  }
  this.addOptionToGroup = function(text,value,groupname){
    var optgroups = this.my_element.select("optgroup");
    var found = false;
    for (var i=0; i<optgroups.length; i++){
        if (optgroups[i].label==groupname){
           var opt = document.createElement("option");
           opt.value = value;
           opt.appendChild(document.createTextNode(text));
           optgroups[i].appendChild(opt);
           found = true;
        }
    }
    if (!found) return false;
    return true;
  }
  this.getSelectedText  = function(){
    return  this.my_element.options[this.my_element.selectedIndex].text;  //returns the text that the user sees
  };
  this.getSelectedValue = function(){
    return this.my_element.options[this.my_element.selectedIndex].value; //returns the value attribute
  };
  this.scrollToTop = function(){
    this.my_element.selectedIndex=0;
  }
  this.selectByName  = function(name){
    for (var i=0; i<this.my_element.options.length; i++){
        if (this.my_element.options[i].text == name){
           this.my_element.selectedIndex = i;
        }
    }  
  }
  this.selectByValue  = function(value){
    for (var i=0; i<this.my_element.options.length; i++){
        if (this.my_element.options[i].value == value){
           this.my_element.selectedIndex = i;
        }
    }  
  }
  this.sort = function(){
    var o = new Array();
  
    if (this.my_element.options==null) { return; }
  
    for (var i=0; i<this.my_element.options.length; i++) {
        o[o.length] = new Option( this.my_element.options[i].text, this.my_element.options[i].value, 
        this.my_element.options[i].defaultSelected,        
        this.my_element.options[i].selected) ;
    }
    if (o.length==0) { return; }
    o = o.sort( function(a,b) { 
                  if ((a.text.toLowerCase()+"") < (b.text.toLowerCase()+"")) { return -1; }
                  if ((a.text.toLowerCase()+"") > (b.text.toLowerCase()+"")) { return 1; }
                  return 0;
                  } 
               );
  
    for (var i=0; i<o.length; i++) {
        this.my_element.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
    }

  }
  
  
  // Gets the number of selectable items in the list (option groups 
  // are visible in the list but are not selectable and so are 
  // not counted.
  this.count = function(){
    return this.my_element.length;
  }
}
Select.prototype = new element_base;

function OptionGroup(){

}



//----------------------------------------------------------------------
// table element
//----------------------------------------------------------------------
function Table(){
  this.element_name = "table";
  this.deleteContents = function(){
    if (this.my_element==null){
       alert("Table.deleteContents is not implemented for the case where the Table object is not bound to an actual table element");  
       return;
    }
    var elementarray = this.my_element.down('tbody').childElements();
    for (var i=0; i<elementarray.length; i++){
        elementarray[i].remove();
    }
  }
}
Table.prototype = new element_base;
//----------------------------------------------------------------------
// div element
//----------------------------------------------------------------------
function Div(){
  this.element_name = "div";
  this.setHTML = function(html){
    this.my_element.innerHTML = html;
  }
  this.appendHTML = function(html){
    this.my_element.innerHTML = this.my_element.innerHTML+html;
  }

}
Div.prototype = new element_base;


//----------------------------------------------------------------------
// RadioButtonGroup
// radio buttons cannot be handled in the same way as other 
// controls because a radio button is not a single control.
//----------------------------------------------------------------------
function RadioButtonGroup(){
  var rblist = null;

  this.bind = function(group_name){
    rblist = document.getElementsByName(group_name);
  }
  this.getSelectedValue = function(){
    for (var i=0; i<rblist.length; i++){
        if (rblist[i].checked){
           return rblist[i].value;
        }
    }    
    return null;
  }
  this.getSelectedText = function(){
    for (var i=0; i<rblist.length; i++){
        if (rblist[i].checked){
           return rblist[i].nextSibling.wholeText;
        }
    }
    return null;
  }
  this.setSelected = function(value){
    alert('Radio.setSelected not implemented');
  }

}