//
// ManagedList.js
//
// JavaScript class for maintaining a Managed List using DOM HTML
// to swap between display and edit elements.
//
// January 2005  -pge
//
// Constructor:
//  ManagedList( baseid, list, firstitem[, blurrproc] )
//   baseid - Name of JavaScript variable declared for this class instance.
//   list - Initial list [{id:id,value:value}].
//   firstitem - Index of selected item.
//   blurrproc - Optional procedure name that takes baseid as argument
//     and called at end of onchange event handler.
//
// Principal methods:
//  embed() - Called to create List Display at desired location in document.
//  setList() - Called to change List Displayed.
//

// Constructor.
function ManagedList
(
  baseid,
  list,
  listv,
  firstitem,
  fieldname,
  nextid,
  previd,
  blurrproc
)
{
  this.baseid = baseid;
  this.list = list;
  this.listv = listv;
  if ( firstitem ) this.selecteditem = firstitem;
  else this.selecteditem = 0;
  this.previousitem = firstitem;
  this.fieldname = fieldname;
  this.nextid = nextid;
  this.previd = previd;
  this.blurrproc = blurrproc;
  this.span = new Object();
  this.hiddenelement = new Object();
  this.displayelement = new Object();
  this.editelement = new Object();
}

// Dummy class instance needed in JS1.1 before methods can be defined.
new ManagedList( "junk",["junk"] );

// Class methods.
ManagedList.prototype.embed = function( el )
{
  this.span = document.createElement( 'span' );
  this.span.id = this.baseid;
  this.span.className = 'ml';
  this.buildList();
  var obj = document.getElementById( el );
  obj.appendChild( this.span );
}
ManagedList.prototype.setSelected = function( item )
{
  this.previousitem = this.selecteditem;
  this.selecteditem = item;
  this.editelement.selectedIndex = item;
  while( this.displayelement.childNodes.length > 0 )
  {
    this.displayelement.removeChild( this.displayelement.firstChild );
  }
  var txt = document.createTextNode( this.list[this.selecteditem] );
  this.displayelement.appendChild( txt );
  if ( this.fieldname )
  {
    if ( this.listv ) this.hiddenelement.value = this.listv[this.selecteditem];
    else this.hiddenelement.value = this.list[this.selecteditem];
  }
}
ManagedList.prototype.setList = function( list, listv, firstitem )
{
  while( this.span.childNodes.length > 0 )
  {
    this.span.removeChild( this.span.firstChild );
  }
  this.list = list;
  if ( listv ) this.listv = listv;
  else this.listv = null;
  this.previousitem = this.selecteditem;
  if ( firstitem ) this.selecteditem = firstitem;
  else this.selecteditem = 0;
  this.buildList();
}
ManagedList.prototype.ml_a_click = function()
{
  if ( this.displayelement.firstChild.nodeType == 3 )
  {
    this.span.replaceChild( this.editelement, this.displayelement );
    this.editelement.focus();
  }
}
ManagedList.prototype.ml_select_blur = function( evt )
{
  evt = ( evt ) ? evt : ( ( window.event ) ? event : null );
  if ( evt )
  {
    var inp = ( evt.target ) ? evt.target :
               ( ( evt.srcElement ) ? evt.srcElement : null );
    if ( inp )
    {
      var obj = eval( inp.id.toString().split( "_" )[2] );
      obj.previousitem = obj.selecteditem;
      obj.selecteditem = obj.editelement.selectedIndex;
      if ( obj.hiddenelement )
      {
        if ( obj.listv ) obj.hiddenelement.value = obj.listv[obj.selecteditem];
        else obj.hiddenelement.value = obj.list[obj.selecteditem];
      }
      var str = obj.editelement.options[obj.editelement.selectedIndex].text;
      var txt = document.createTextNode( str );
      while( obj.displayelement.childNodes.length > 0 )
      {
        obj.displayelement.removeChild( obj.displayelement.firstChild );
      }
      obj.displayelement.appendChild( txt );
      obj.span.replaceChild( obj.displayelement, inp );
      ml_callRemote( inp.id );
     }
  }
}
ManagedList.prototype.ml_text_key = function( evt )
{
  evt = ( evt ) ? evt : ( ( window.event ) ? event : null );
  if ( evt )
  {
    var inp = ( evt.target ) ? evt.target :
               ( ( evt.srcElement ) ? evt.srcElement : null );
    if ( inp )
    {
      var c = ( evt.charCode ) ? evt.charCode :
                 ( ( evt.which ) ? evt.which : evt.keyCode );
      switch( c )
      {
        case ml_cEnter :
          inp.blur();
          return false;
        case ml_cEsc :
          ml_resetOptions( inp.id );
          inp.blur();
          return false;
        case ml_cRightAngleBracket :
          inp.blur();
          ml_editNext( inp.id, false );
          return false;
        case ml_cLeftAngleBracket :
          inp.blur();
          ml_editNext( inp.id, true );
          return false;
        default :
          return true;
      }
    }
  }
  return true;
}
ManagedList.prototype.buildList = function()
{
  var opt;
  var where =
   ( navigator.appName == "Microsoft Internet Explorer" ) ? -1 : null;
  if ( this.fieldname )
  {
    this.hiddenelement = document.createElement( "input" );
    this.hiddenelement.type = "hidden";
    this.hiddenelement.id = "ml_hidden_" + this.fieldname;
    this.hiddenelement.name = this.fieldname;
    if ( this.listv ) this.hiddenelement.value = this.listv[this.selecteditem];
    else this.hiddenelement.value = this.list[this.selecteditem];
    this.span.appendChild( this.hiddenelement );
  }
  this.displayelement = document.createElement( "a" );
  this.displayelement.id = "ml_a_" + this.baseid;
  this.displayelement.className = "ml_display";
  this.displayelement.setAttribute
  ( "href", "javascript:" + this.baseid + ".ml_a_click()" );
  var txt = document.createTextNode( this.list[this.selecteditem] );
  this.displayelement.appendChild( txt );
  this.span.appendChild( this.displayelement );
  this.editelement = document.createElement( "select" );
  this.editelement.id = "ml_select_" + this.baseid;
  this.editelement.name = "ml_select_" + this.baseid;
  this.editelement.className = "ml_edit";
  this.editelement.onblur = this.ml_select_blur;
  this.editelement.onkeypress = this.ml_text_key;
  for ( var i = 0; i < this.list.length; i++ )
  {
    opt = document.createElement( "option" );
    opt.text = this.list[i];
    if ( this.listv ) opt.value = this.listv[i];
    else opt.value = this.list[i];
    this.editelement.add( opt, where );
  }
  this.editelement.selectedIndex = this.selecteditem;
}
ManagedList.prototype.toString = function()
{
  return this.list[this.selecteditem];
}
ManagedList.prototype.valueOf = function()
{
  return this.listv[this.selecteditem];
}
ManagedList.prototype.indexOf = function()
{
  return this.selecteditem;
}

// Global methods.
function ml_resetOptions( el )
{
  var obj = eval( el.toString().split( "_" )[2] );
  if ( obj && obj.editelement )
  {
    obj.editelement.selectedIndex = obj.selecteditem;
  }
}
function ml_editNext( el, prev )
{
  var obj = eval( el.toString().split( "_" )[2] );
  if ( obj )
  {
    var nobj;
    if ( prev ) { if ( obj.previd ) nobj = eval( obj.previd ); }
    else { if ( obj.nextid ) nobj = eval( obj.nextid ); }
    if ( nobj ) { nobj.displayelement.click(); }
  }
}
function ml_callRemote( el )
{
  var obj = eval( el.toString().split( "_" )[2] );
  if ( obj && obj.blurrproc )
  {
    eval( obj.blurrproc + "('" + obj.baseid + "')" );
  }
}

// Keycodes.
var ml_cBackSpace = 8;
var ml_cTab = 9;
var ml_cEnter = 13;
var ml_cEsc = 27;
var ml_cSpace = 32;
var ml_cForwardSlash = 47;
var ml_cColon = 58;
var ml_cSemiColon = 59;
var ml_cLeftAngleBracket = 91;
var ml_cBackSlash = 92;
var ml_cRightAngleBracket = 93;
var ml_cDelete = 127;


