Event.KEY_SPACE = 32;
Event.KEY_PGUP = 33;
Event.KEY_PGDOWN = 34;
Event.KEY_END = 35;
Event.KEY_HOME = 36;

// ListBoxClass: emulate list box, with stylized options
var ListBoxClass = Class.create();
ListBoxClass.prototype = {
  initialize: function(listboxid,multiple) {
    this.listboxid = listboxid;
    this.multiple = multiple;
    this.options = new Array();
    this.labels = new Array();
    this.selected = new Array();
    this.last = -1;
    this.focused = -1;

    this.onselect = null;

    new Insertion.Bottom(this.listboxid,"<table cellpadding='0' cellspacing='0'><tbody></tbody></table>");
    new Insertion.Bottom(this.listboxid,"<input type='hidden' id='" + this.listboxid + "_hidden' name='" + this.listboxid + "_hidden'>");

    this.table = $(this.listboxid).getElementsByTagName('table')[0];
    this.table.onclick = this.changeValue.bindAsEventListener(this);
  },

  onSelection: function(sel) {
    (this.onselect || Prototype.emptyFunction).apply(sel, arguments)
  },

  addOption: function(text,value,selected) {
    if(selected)
      this.selected.push(this.options.length);
    this.options.push(value);
    this.labels.push(text);
    new Insertion.Bottom(this.table.childNodes[0],"<tr><td UNSELECTABLE='ON'>" + text + "</td></tr>");
  },

  reset: function() {
    while(this.options.length > 0)
      this.options.pop();
    while(this.selected.length > 0)
      this.selected.pop();
    while(this.labels.length > 0)
      this.labels.pop();
    this.last = -1;
    var _rows = this.table.getElementsByTagName('tr');
    for(var i=_rows.length-1;i>=0;i--)
    {
      Element.remove(_rows[i]);
    }
    $(this.listboxid + '_hidden').value = '';
  },

  resetLast: function() {
    var _rows = this.table.getElementsByTagName('tr');
    for(var i=_rows.length-1;i>=0;i--)
        Element.removeClassName(_rows[i],"last");
  },

  searchInitial: function(keyc) {
    var schar = String.fromCharCode(keyc);
    var _rows = this.table.getElementsByTagName('tr');
    var _rowslen = _rows.length;
    for(var i=0;i<_rowslen;i++)
    {
        labl = new String(this.labels[i]);
        if(labl.indexOf(schar) == 0)
        {
            this.scrollTo(i);
            this.moveFocus(i, this.focused, true);
            break;
        }
    }
  },

  setValue: function(current) {
    var _rows = this.table.getElementsByTagName('tr');
    var _rowslen = _rows.length;
    for(var i=0;i<_rowslen;i++)
    {
        if(i == current)
        {
            Element.addClassName(_rows[i],"last");
            Element.addClassName(_rows[i],"selected");
            val = this.options[i];
            $(this.listboxid + '_hidden').value = encodeURIComponent(val);
            this.onSelection(this.listboxid);
        }
        else
        {
            Element.removeClassName(_rows[i],"last");
            Element.removeClassName(_rows[i],"selected");
        }
    }
  },

  moveFocus: function(current, old, sc, st) {
    var _rows = this.table.getElementsByTagName('tr');
    var _rowslen = _rows.length;
    if(current >= 0 && current < _rowslen)
        for(var i=0;i<_rowslen;i++)
        {
          if(i == old)
            Element.removeClassName(_rows[old],"last");
          if(i == current)
          {
            Element.addClassName(_rows[current],"last");
            this.focused = current;
            if(!sc)
                this.scrollControl(current);
            if(st)
                this.scrollTo(current);
          }
        }
  },

  scrollTo: function(current) {
    var _rows = this.table.getElementsByTagName('tr');
    off = Element.getDimensions(this.listboxid);
    elheight = new Number();
    for(var i=0;i<current;i++)
    {
        dim = Element.getDimensions(_rows[i]);
        h = new Number(dim.height);
        elheight += h;
    }
    document.getElementById(this.listboxid).scrollTop = elheight;
  },

  scrollControl: function(current) {
    var _rows = this.table.getElementsByTagName('tr');
    off = Element.getDimensions(this.listboxid);
    elheight = new Number();
    for(var i=0;i<=current;i++)
    {
        dim = Element.getDimensions(_rows[i]);
        h = new Number(dim.height);
        elheight += h;
    }
    topline = new Number(document.getElementById(this.listboxid).scrollTop + h);
    bottomline = new Number(topline + off.height - h);
    if(elheight > bottomline)
        document.getElementById(this.listboxid).scrollTop += h;
    if(elheight < topline)
        document.getElementById(this.listboxid).scrollTop -= h;
  },

  changeValue: function(evnt) {
    var elem = Event.element(evnt);
    var currtr = elem.parentNode;
    while(currtr.tagName != 'TR')
      currtr = currtr.parentNode;
    var pos = -1;
    var _rows = this.table.getElementsByTagName('tr');
    var _rowslen = _rows.length;
    for(var i=0;i<_rowslen;i++)
    {
      if(_rows[i] == currtr)
      {
        pos = i;
        break;
      }
    }
    for(var i=0;i<_rowslen;i++)
      Element.removeClassName(_rows[i],"last");

    if(pos >= 0)
    {
      var formElem = null;
      var form = currtr;
      while(form != undefined && form != null)
      {
          if(form.tagName == 'FORM')
          {
            formElem = Form.getElements(form);
            break;
          }
          form = form.parentNode;
      }
      if(formElem != null)
        for (var j = 0; j < formElem.length; j++)
          formElem[j].blur();
    }

    var newselected = new Array();
    var done = false;
    if(this.multiple)
    {
      if(evnt.ctrlKey)
      {
        if(! this.selected.include(pos))
          done = true;
      }
      else if(evnt.shiftKey)
      {
        if(pos < this.last)
        {
          for(var i=pos+1;i<this.last;i++)
          {
            if(! this.selected.include(i))
              newselected.push(i);
          }
        }
        else if(pos > this.last)
        {
          for(var i=pos-1;i>this.last;i--)
          {
            if(! this.selected.include(i))
              newselected.push(i);
          }
        }
        done = true;
      }
    }
    if(! done)
    {
      while(this.selected.length > 0)
        this.selected.pop();

      var selected = document.getElementsByClassName('selected', $(this.listboxid));
      len = selected.length;
      for(var i=0;i<len;i++)
        Element.removeClassName(selected[i],"selected");
    }
    newselected.push(pos);

    len = newselected.length;
    for(var i=0;i<len;i++)
    {
      rowidx = newselected[i];
      if(rowidx >= 0 && rowidx < _rowslen)
      {
        Element.addClassName(_rows[rowidx],"selected");
        document.getElementById(this.listboxid.substring(0, this.listboxid.indexOf('_')) + '_focusctrl').focus();
        this.focused = rowidx;
      }
    }
    this.selected = this.selected.concat(newselected);

    if(pos != this.last)
    {
      if(this.last >= 0 && this.last < _rowslen)
      {
        Element.removeClassName(_rows[this.last],"last");
      }
      this.last = pos;
      Element.addClassName(currtr,"last");
    }

    var value = new Array();
    len = this.selected.length;
    for(var i=0;i<len;i++)
    {
      value.push(this.options[this.selected[i]]);
    }
    $(this.listboxid + '_hidden').value = encodeURIComponent(value);

    if(! this.multiple)
        this.onSelection(this.listboxid);
  },

  handleKeyPress: function(evnt) {
    if(document.all && document.getElementById)
        keycode = evnt.keyCode;
    else
        keycode = evnt.which;

    if( (keycode > 64 && keycode < 91) )
        this.searchInitial(keycode);

    switch(keycode) {
        case Event.KEY_HOME:
        case Event.KEY_END:
            cur = (keycode == Event.KEY_HOME ? 0 : this.options.length-1);
            this.moveFocus(cur, this.focused, false, true);
            break;
        case Event.KEY_UP:
        case Event.KEY_DOWN:
        case Event.KEY_PGUP:
        case Event.KEY_PGDOWN:
            cur = (keycode == Event.KEY_UP ? this.focused-1 : (keycode == Event.KEY_DOWN ? this.focused+1 :
                (keycode == Event.KEY_PGUP ? this.focused-10 : this.focused+10)));
            st = ( (keycode == Event.KEY_PGUP || keycode == Event.KEY_PGDOWN) ? true : false);
            this.moveFocus(cur, this.focused, false, st);
            break;
        case Event.KEY_RETURN:
        case Event.KEY_SPACE:
            this.setValue(this.focused);
            break;
        case Event.KEY_TAB:
            this.resetLast();
            return;
            break;
    }
    if(document.all && document.getElementById)
        evnt.returnValue = false;
    else
    {
        evnt.preventDefault();
        return false;
    }
  }
};
