////////////////////////////////////////////////////////////////////////////////
//
//                              DropMenu.js
//
//  Description: 
//    this file contains a constructor for versatile dropMenus
//
//  Compatibility:
//    Do not assign anything to the following labels
//        afDocOnclicks
//        afDocOnmouseups
//        docOnclickIndex
//        docOnmouseupIndex
//        DropMenu
//  
//    Also, do not directly assign anything to the events document.onclick and
//    document.onmouseup.  Instead, use the following lines to add a function
//    to these events:
//        var myIndex = docOnclickIndex++;
//        afDocOnclicks[myIndex] = {dofunc: function() {/*stuff to do*/}};
//                            OR
//        var myIndex = docOnmouseupIndex++;
//        afDocOnmouseups[myIndex] = {dofunc: function() {/*stuff to do */}};
//
//    This will add your function to a list of functions executed onclick and
//    onmouseup.  To remove it from the list, use:
//        delete(afDocOnclicks[myIndex]);
//                            OR
//        delete(afDocOnmouseups[myIndex]);
//
////////////////////////////////////////////////////////////////////////////////




function DropMenu() {
  this.state = 0;   //state affects behavior for each event
  this.docOnclickIndex = docOnclickIndex++;
  this.docOnmouseupIndex = docOnmouseupIndex++;
  this.options = [];
  this.hidden = new Element('div', {'class': 'hiddenOptions'});
  this.container = $(arguments[1]);
  this.currOption = null;
  this.currIndex;
  
  //dropdown menu events
  this.expand = function() {
    this.container.className = "open";
  };
  this.contract = function() {
    this.container.className = "closed";
  };
  
  this.put = function() {
    this.container.update(this.currOption);
    this.container.appendChild(this.hidden);
  };
  
  this.onchange = function(i) {};
  
  this.setCurrOption = function(index) {
    if(index == this.currIndex) {
      this.options[index].className = "firstOption";
      /*no change; do nothing*/
      }
    else { 
      removeChildren(this.container);
      for(i=0; i<this.options.length; i++) {
        if(i!=index) {
          this.hidden.appendChild(this.options[i]);
        }

      }
      this.options[this.currIndex].className = "option";
      this.currOption = this.options[index];
      this.options[index].className = "firstOption"
      this.currIndex = index;      
      this.put();
      this.onchange(this.options[this.currIndex].readAttribute('value'));
    }
  };
  
  this.idToIndex = function(id) {
    for(var i=0; i<this.options.length; i++) {
      if(this.options[i].getAttribute('value') == id)
        return i;
    }
    return -1;
  }
  
  this.onclick = function(i) {
    switch(this.state) {
      case 0:
        break;
      case 1:
        break;
      case 2:
        break;
      case 3:
        this.state = 0;
        this.contract();
        this.setCurrOption(i);
        break;
    }
  };
  
  this.onmousedown = function(i) {
    switch(this.state) {
      case 0:
        this.t = setTimeout(this.armTimeout(this, 2), 200);
        this.options[this.currIndex].className = "firstOptionHighlight";
        this.state = 1;
        this.expand();
        break;
      case 1:
        break;
      case 2:
        break;
      case 3:
        break;
    }
  };
  
  this.onmouseup = function(i) {
    switch(this.state) {
      case 0:
        break;
      case 1:
        clearTimeout(this.t);
        this.state = -1;
        break;
      case 2:
        this.state = 0;
        this.contract();
        this.setCurrOption(i);
        break;
      case 3:
        break;
    }
  };
  
  this.onmouseover = function() {
    switch(this.state) {
      case 0:
        break;
      case 1:
        break;
      case 2:
        break;
      case 3:
        break;
    }
  };
  
  this.onmouseout = function() {
    switch(this.state) {
      case 0:
        break;
      case 1:
        break;
      case 2:
        break;
      case 3:
        break;
    }
  };
  
  this.optionmouseover = function(i) {
    switch(this.state) {
      case 0:
        break;
      case 1:
        if(i == this.currIndex)
          this.options[i].className = "firstOptionHighlight";
        else
          this.options[i].className = "optionHighlight";
        break;
      case 2:
        if(i == this.currIndex)
          this.options[i].className = "firstOptionHighlight";
        else
          this.options[i].className = "optionHighlight";     
        break;
      case 3:
        if(i == this.currIndex)
          this.options[i].className = "firstOptionHighlight";
        else
          this.options[i].className = "optionHighlight";
        break;
    }
  };
  
  this.optionmouseout = function(i) {
     switch(this.state) {
      case 0:
        break;
      case 1:
        if(i == this.currIndex)
          this.options[i].className = "firstOption";
        else
          this.options[i].className = "option";
        break;
      case 2:
        if(i == this.currIndex)
          this.options[i].className = "firstOption";
        else
          this.options[i].className = "option"; 
        break;
      case 3:
        if(i == this.currIndex)
          this.options[i].className = "firstOption";
        else
          this.options[i].className = "option";  
        break;
    }
  };
  
  this.externalclick = function() {
    switch(this.state) {
      case 0:
        break;
      case 1:
        break;
      case 2:
        break;
      case -1:
        this.state = 3;
        break;
      case 3:
        this.state = 0;
        this.contract();
        break;
    }
  };
  
  this.externalmouseup = function() {
    switch(this.state) {
      case 0:
        break;
      case 1:
        clearTimeout(this.t);
        this.state = 0;
        this.contract();
        break;
      case 2:
        this.state = 0;
        this.contract();
        break;
      case 3:
        break;
    }
  }
  
  //arming functions.  Ugly, but necessary to keep "this" and "i" in the scope of functions assigned to HTML elements's events
  this.armTimeout = function(o) {
    return function() {o.state=2;};
  };
  this.armOnclick = function (o, i) {
    return function() {o.onclick(i);};
  };
  this.armOnmousedown = function (o,i) {
    return function() {o.onmousedown(i);};
  };
  this.armOnmouseup = function (o,i) {
    return function() {o.onmouseup(i);};
  };
  this.armOptionmouseover = function(o,i) {
    return function() {o.optionmouseover(i);};
  };
  this.armOptionmouseout = function(o,i) {
    return function() {o.optionmouseout(i);};
  };
  this.armOnmouseover = function(o) {
    return function() {o.onmouseover();};
  };
  this.armOnmouseout = function(o) {
    return function () {o.onmouseout();};
  };
  this.armExternalclick = function(o) {
    return function() {o.externalclick();};
  };
  this.armExternalmouseup = function(o) {
    return function() {o.externalmouseup();};
  };
  
  //create the HTML objects for each optoin.  Set first option as currently selected
  //put others in hidden div.  Assign DropMenu events to options's events
  this.updateOptions = function(optionList) { 
    
    //clear everything first
    removeChildren(this.hidden);
    removeChildren(this.container);
    this.options = [];
    this.currOption = null;
    //then add new stuf

    for(var i=0; i<optionList.length; i++) {
      var text;
      if(typeof optionList[i] === 'string') {
        optionList[i] = {'name':optionList[i], 'id':optionList[i]};
      }
      if(i == 0)
        this.options.push(new Element('div', { 'class': 'firstOption', 'value': optionList[i].id}));
      else
        this.options.push(new Element('div', { 'class': 'option', 'value': optionList[i].id}));
      
      /*optionHeight = new Element('div', {'class':'optionHeight'});
      this.options[i].appendChild(optionHeight);*/
      
      text = new Element('div', {'class': 'optionText'});
      text.update(optionList[i].name);
      this.options[i].appendChild(text);
      
      /*clear = new Element('div', {'class':'clearBoth'});
      clear.style.border = "solid 1px blue";
      this.options[i].appendChild(clear);*/
      
      this.options[i].onclick = this.armOnclick(this, i);
      this.options[i].onmousedown = this.armOnmousedown(this, i);
      this.options[i].onmouseup = this.armOnmouseup(this, i);
      this.options[i].onmouseover = this.armOptionmouseover(this, i);
      this.options[i].onmouseout = this.armOptionmouseout(this,i);
      if(i==0) {
        this.currOption = this.options[i];
        this.currIndex = i;
      }
      if(i>0)
        this.hidden.appendChild(this.options[i]);
    }
    this.put();
  }
      
  this.updateOptions(arguments[0]);
  this.container.onmouseover = this.armOnmouseover(this);
  this.container.onmouseout = this.armOnmouseout(this);
  //disable text selection in MSIE
  this.container.onselectstart= function() {return false;};
  //disable text selection in firefox
  this.container.onmousedown= function(e) {return false;};
  this.container.onclick = function() {return true;};
  //add dropmenu bahaviors for document events
  afDocOnclicks[this.docOnclickIndex] = {dofunc: this.armExternalclick(this)};
  afDocOnmouseups[this.docOnmouseupIndex] = {dofunc: this.armExternalmouseup(this)};
  this.container.style.cursor = "pointer";
  
  this.unlink = function() {
    delete(afDocOnclicks[this.docOnclickIndex]);
    delete(afDocOnmouseups[this.docOnmouseupIndex]);
  }

}

function removeChildren(htmlElement) {
  htmlElement.update();
}
