// DropDown: This class implements a drop down on a form text box. They are
// able to enter free form text in the text box. But when the box gets focus,
// the drop down lets them select an option from the list to fill in the
// associated text box.
function DropDown(strName, strTextBoxName, arrItems) {
   
   if(typeof strTextBoxName == "undefined" || strTextBoxName == null) {
      this.strTextBoxName = '';
   } else
      this.strTextBoxName = strTextBoxName;
   
   if(typeof strName == "undefined" || strName == null) {
      this.strName = "";
      for(var i = 0; i < 10; i++) {
         this.strName += ""+Math.floor((Math.random()*10))+"";
      }
   } else
      this.strName = strName;
      
   if(typeof arrItems == "undefined" || arrItems == null)
      this.arrItems = new Array();
   else
      this.arrItems = arrItems;
      
   this.objSelectBox = null;
   this.objTextBox = null;
   this.blnVisible = false;
   this.iOrigSelectLeft = 0;
   this.iOrigSelectTop = 0;
   this.iCloseTimerID = -1;
   this.iCloseTime = 1000;
   this.strHighlightColor = "#ffffff";
   this.strHighlightBackgroundColor = "#000000";
};

DropDown.prototype.GetElement = function(strName) {
   if (document.getElementById) {
      return document.getElementById(strName);
   } else if (document.all) {
      return document.all[strName];
   } else if (document.layers) {
      return document.layers[strName];
   } else {
      return null;
   }
};

DropDown.prototype.getRealLeft = function(objElement) {
   if (objElement) {
      iXPos = objElement.offsetLeft;
      objTempElement = objElement.offsetParent;
      while (objTempElement != null) {
         iXPos += objTempElement.offsetLeft;
         objTempElement = objTempElement.offsetParent;
      }
      return iXPos;
   }
}

DropDown.prototype.getRealTop = function(objElement) {
   if (objElement) {
      iYPos = objElement.offsetTop;
      objTempElement = objElement.offsetParent;
      while (objTempElement != null) {
         iYPos += objTempElement.offsetTop;
         objTempElement = objTempElement.offsetParent;
      }
      return iYPos;
   }
}

DropDown.prototype.getRealRight = function(objElement) {
   return getRealLeft(objElement) + objElement.offsetWidth;
};

DropDown.prototype.getRealBottom = function(objElement) {
   return getRealTop(objElement) + objElement.offsetHeight;
};

DropDown.prototype.toggleSelectBox = function(e) {

   // Debuggin
   //alert("This is: "+this.strName);
   //alert("Visibility: "+this.blnVisible+" Style.Visibility: "+objSelectBox.style.visibility);

   if(this.blnVisible)
   {
      this.objSelectBox.style.visibility = "hidden";
      this.blnVisible = false;
      this.ClearCloseTimer();
      return false;
   }
   
   this.ResizeAndPlaceSelectBox();
   
   this.objSelectBox.style.visibility = "visible";
   
   this.blnVisible = true;
   this.StartCloseTimer();
   return false;
};

DropDown.prototype.ResizeAndPlaceSelectBox = function() {

   var SelectBoxWidthAdjustments = new Array();
   SelectBoxWidthAdjustments['Default'] = 0;
   SelectBoxWidthAdjustments['KHTML'] = -4; // For textboxes border. Assume default of 2px left and right, total of 4px.
   SelectBoxWidthAdjustments['Gecko'] = -4; // For textboxes border. Assume default of 2px left and right, total of 4px.
   
   var ItemWidthAdjustments = new Array();
   ItemWidthAdjustments['Default'] = 0;
   ItemWidthAdjustments['KHTML'] = 0;
   ItemWidthAdjustments['WinIE'] = -4;  // Here, IE DOES count the border on the div in offsetWidth, 
   ItemWidthAdjustments['Gecko'] = -14; // Gecko also counts the padding! (2px border, 5px padding assumed)

   var strBrowserName = Global_BrowserSupport.strBrowserName;

   var blnIsMacIE = Global_BrowserSupport.blnIsMacIE;
   var objSelectBox = this.objSelectBox;
   var objTextBox = this.objTextBox;

   // Calculate the Hight, Width, Left, and Top position of the Text Box.
   // Here we subtract 3 from the height, so they slightly overlap, giving us a nice look
   var Height = objTextBox.offsetHeight - 3;
   var Width = objTextBox.offsetWidth;
   var Left = this.getRealLeft(objTextBox);
   var Top = this.getRealTop(objTextBox);

   // For IE5 on the Mac, we need to set the width to 1px in order to get proper calculations
   if ((blnIsMacIE)) objSelectBox.style.width="1px";
   
   // Here we Resize the Select Box depending on wheather the contents are smaller or larger
   // than our text box.
   // debbuggin
   //alert("objSelectBox.offsetWidth: "+objSelectBox.offsetWidth+" Width: "+Width);
   if (objSelectBox.offsetWidth<=Width) { 
      // Our Content is smaller than our text box. So resize the select box to the width
      // of the text box.
      if(typeof SelectBoxWidthAdjustments[strBrowserName] == "undefined") {
         objSelectBox.style.width = (Width + SelectBoxWidthAdjustments['Default']) + "px";
      } else {
         objSelectBox.style.width = (Width + SelectBoxWidthAdjustments[strBrowserName]) + "px";
      }
      // Debuggin
      //alert("Adjusting Width To Text Box: objSelectBox.style.width: "+objSelectBox.style.width);
      
      // Here we resize the inside Items as well.
      for( var i = 0; i < objSelectBox.childNodes.length; i++) {
         if( objSelectBox.childNodes[i].className == "items" ) {
            if(typeof ItemWidthAjustments[strBrowserName] == "undefined") {
               objSelectBox.childNodes[i].style.width = (Width + ItemWidthAdjustments['Default']) + "px";
            } else {
               objSelectBox.childNodes[i].style.width = (Width + ItemWidthAdjustments[strBrowserName]) + "px";
            }
            // Debuggin
            //alert("objSelectBox.childNodes[i].style.width: "+objSelectBox.childNodes[i].style.width);
         }
      }
   } else {
      // Our content is larger than our text box. So we try to have it autoresize.
   
      // IE5 on the Mac doesn't auto size like we want it to. So when we set the width to 1px above, it clamps it almost correctly
      // we just add 4 px to what it does and it looks ok
      if ((!blnIsMacIE)) objSelectBox.style.width = "auto";
      else objSelectBox.style.width = (objSelectBox.offsetWidth + 4) + "px";

      // debuggin
      //alert("Adjusting Width to Content: objSelectBox.style.width: "+objSelectBox.style.width);

      // Here we resize the inside Items as well.
      for( var i = 0; i < objSelectBox.childNodes.length; i++) {
         if( objSelectBox.childNodes[i].className == "items" ) {
            if(typeof ItemWidthAjustments[strBrowserName] == "undefined") {
               objSelectBox.childNodes[i].style.width = (objSelectBox.offsetWidth + ItemWidthAdjustments['Default']) + "px";
            } else {
               objSelectBox.childNodes[i].style.width = (objSelectBox.offsetWidth + ItemWidthAdjustments[strBrowserName]) + "px";
            }
           // Debuggin
           //alert("objSelectBox.childNodes[i].style.width: "+objSelectBox.childNodes[i].style.width);
         }
      }
   }

   // Now we place our Select Box.
   // Debuggin
   //alert("objSelectBox\nLeft: "+getRealLeft(objSelectBox)+"("+objSelectBox.offsetLeft+") Top: "+getRealTop(objSelectBox)+"("+objSelectBox.offsetTop+")");
   if(blnIsMacIE) {
      // For IE5 on the Mac, obj.style.left places the object relative to its original offsetLeft and WITHOUT margins, so we have to compensate
      objSelectBox.style.left = (Left+Width-this.iOrigSelectLeft+(parseInt(document.body.leftMargin))-objSelectBox.offsetWidth)+"px";
   } else {
      objSelectBox.style.left = (Left+Width)-objSelectBox.offsetWidth+"px";
   }

   if(blnIsMacIE) {
      // For IE5 on the Mac, obj.style.left places the object relative to the body WITHOUT margins, so we have to compensate
      objSelectBox.style.top = (Top+Height+(parseInt(document.body.topMargin)-1))+"px" ;
   } else {
      objSelectBox.style.top = (Top+Height)+"px" ;
   }

   // Debuggin
   /*var win = window.open('','Resizing'+this.strName,"width="+400+",height="+400+",top="+0+",left="+0+
                         ",menubar=no,toolbar=no,location=center,scrollbars=yes"+
                         ",resizable=yes,status=no,location=no'");
   win.document.write("ID: "+this.strName+"<br />"+
                      "objTextBox<br />"+
                      "Height: "+Height+" Width: "+Width+"<br />"+
                      "Left: "+Left+" Top: "+Top+"<br />"+
                      "Right(Left+Width): "+(Left+Width)+" Bottom(Top+Height): "+(Top+Height)+"<br />"+
                      "objSelectBox<br />"+
                      "Height: "+objSelectBox.offsetHeight+" Width: "+objSelectBox.offsetWidth+"<br />"+
                      "Left: "+this.getRealLeft(objSelectBox)+"("+objSelectBox.offsetLeft+") Top: "+this.getRealTop(objSelectBox)+"("+objSelectBox.offsetTop+")"+"<br />"+
                      "style.left: "+objSelectBox.style.left+" style.top: "+objSelectBox.style.top+"<br />");
   

   win.document.close();*/
   
   return false;
};

DropDown.prototype.highlight = function(e) {
   var objFiringElement=(e.srcElement? e.srcElement : e.target);
   
   // Debuggin
   /*var win = window.open('','Highlight'+this.strName,"width="+400+",height="+400+",top="+0+",left="+0+
                         ",menubar=no,toolbar=no,location=center,scrollbars=yes"+
                         ",resizable=yes,status=no,location=no'");
   win.document.write("ID: "+objFiringElement.id+"<br />"+" e.currentTarget: "+(typeof e.currentTarget!="undefined"?e.currentTarget.id:typeof e.currentTarget)+"<br />"+
                      "objFiringElement.className: "+(typeof objFiringElement.className!="undefined"?objFiringElement.className:typeof objFiringElement.className)+"<br />"+
                      "objFiringElement.parentNode.className: "+(typeof objFiringElement.parentNode.className!="undefined"?objFiringElement.parentNode.className:typeof objFiringElement.parentNode.className)+"<br />"+
                      "objFiringElement.firstChild.className: "+(typeof objFiringElement.firstChild.className!="undefined"?objFiringElement.firstChild.className:typeof objFiringElement.firstChild.className)+"<br />");
   win.document.close();*/

   if (objFiringElement.className == "DropDownItems" ||
       (objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems")) {
      if(objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems") {
         objFiringElement = objFiringElement.parentNode; // We were called on the child of a drop down item (the text), so move up one node.
      }
      objFiringElement.style.backgroundColor=this.strHighlightBackgroundColor;
      objFiringElement.style.color=this.strHighlightColor;
      e.cancelBubble = true;
      if (e.stopPropagation) e.stopPropagation();
      this.ClearCloseTimer();
   } else {
      dumpProps(objFiringElement,"objFiringElement");
   }

   return true;
};

DropDown.prototype.lowlight = function(e) {
   var objFiringElement=(e.srcElement? e.srcElement : e.target);

   // Debuggin
   /*var win = window.open('','LowLight'+this.strName,"width="+400+",height="+400+",top="+0+",left="+0+
                         ",menubar=no,toolbar=no,location=center,scrollbars=yes"+
                         ",resizable=yes,status=no,location=no'");
   win.document.write("ID: "+objFiringElement.id+"<br />"+" e.currentTarget: "+(typeof e.currentTarget!="undefined"?e.currentTarget.id:typeof e.currentTarget)+"<br />"+
                      "objFiringElement.className: "+(typeof objFiringElement.className!="undefined"?objFiringElement.className:typeof objFiringElement.className)+"<br />"+
                      "objFiringElement.parentNode.className: "+(typeof objFiringElement.parentNode.className!="undefined"?objFiringElement.parentNode.className:typeof objFiringElement.parentNode.className)+"<br />"+
                      "objFiringElement.firstChild.className: "+(typeof objFiringElement.firstChild.className!="undefined"?objFiringElement.firstChild.className:typeof objFiringElement.firstChild.className)+"<br />");
   win.document.close();*/

   if (objFiringElement.className == "DropDownItems" ||
       (objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems")) {
      if(objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems") {
         objFiringElement = objFiringElement.parentNode; // We were called on the child of a drop down item (the text), so move up one node.
      }
      objFiringElement.style.backgroundColor="";
      objFiringElement.style.color="";
      e.cancelBubble = true;
      if (e.stopPropagation) e.stopPropagation();
      if (this.blnVisible) this.StartCloseTimer();
   }

   return true;
};

DropDown.prototype.jumpto = function(e) {
   var objFiringElement=(e.srcElement? e.srcElement : e.target);
   if (objFiringElement.className == "DropDownItems" ||
       (objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems")) {
      if(objFiringElement.parentNode && objFiringElement.parentNode.className == "DropDownItems") {
         objFiringElement = objFiringElement.parentNode; // We were called on the child of a drop down item (the text), so move up one node.
      }
      this.objTextBox.value = objFiringElement.innerHTML;
      objFiringElement.style.backgroundColor="";
      objFiringElement.style.color="";
      this.toggleSelectBox();
      this.objTextBox.focus();
   }
   
   return false;
};

DropDown.prototype.StartCloseTimer = function() {
   this.ClearCloseTimer();
   if(this.iCloseTimerID == -1) {
      this.iCloseTimerID = Global_TimerManager.Start(this.iCloseTime, false, "toggleSelectBox", null, this);
   }
   // Debuggin
   //window.status = this.iCloseTimerID;
};

DropDown.prototype.ClearCloseTimer = function() {
   Global_TimerManager.Stop(this.iCloseTimerID);
   this.iCloseTimerID = -1;
   // Debuggin
   //window.status = this.iCloseTimerID;
};

DropDown.prototype.Init = function() {
   // This sets up the this object in the scope of the function
   // registered as an event handler below. Interesting....
   var DropDownObject = this;
   
   // Must have Basic DHTML Support.
   if (!Global_BrowserSupport.blnHasDHTMLSupport) {
      // Debuggin
      //alert("This browser Doesn't support DHTML.");
      return;
   }
   
   // If W3C DOM Support Available, Use it
   if (Global_BrowserSupport.blnHasW3CDOMSupport){
      // debuggin
      //alert("This browser does support W3C DOM.");
      var objDiv = document.createElement('DIV');
      objDiv.id = this.strName;
      objDiv.className = "DropDownSelectBox";
      for(var i = 0; i < this.arrItems.length; i++) {
         var objItemDiv = document.createElement('DIV');
         objItemDiv.className = "DropDownItems";
         objItemDiv.id = this.strName+"Item"+i;
         objItemDiv.innerHTML = this.arrItems[i];
         objDiv.appendChild(objItemDiv);
      }
      document.body.appendChild(objDiv);
   // Else Use InnerHTML and string construction
   } else {
      // debuggin
      //alert("This browser does not support W3C DOM.");
      var strSelectBox = '';
      strSelectBox = '<div class="DropDownSelectBox" id="'+this.strName+'">';
      for(var i = 0; i < this.arrItems.length; i++) {
         strSelectBox += '<div class="DropDownItems" id="'+this.strName+"Item"+i+'">'+this.arrItems[i]+'</div>';
      }
      strSelectBox += '</div>';
      document.body.innerHTML = document.body.innerHTML + strSelectBox;
      
      // Here we schedule the rest of this function to run a mille-second from
      // now, since most browsers don't like imediately messing with elements
      // created by innerHTML.
      Global_TimerManager.Start(1, false, "InitDelayed", null, this);
      return;
   }
      
   this.InitDelayed();
};

DropDown.prototype.InitDelayed = function() {
   // This sets up the this object in the scope of the function
   // registered as an event handler below. Interesting....
   var DropDownObject = this;

   // debuggin
   //alert("InitDelayed Started");
   
   this.objSelectBox = this.GetElement(this.strName);
   this.objTextBox = this.GetElement(this.strTextBoxName);
   
   if(!this.objSelectBox || !this.objTextBox) {
      // Debuggin
      //alert("objSelectBox: "+this.objSelectBox+" objTextBox: "+this.objTextBox);
      return;
   }
   
   this.AddEvent(this.objTextBox  ,'click'    ,function(e) { DropDownObject.toggleSelectBox((e?e:window.event)); } );
   for( var i = 0; i < this.arrItems.length; i++ ) {
      var objItem = this.GetElement(this.strName+"Item"+i);
      this.AddEvent(objItem,'mouseover',function(e) { DropDownObject.highlight((e?e:window.event)); } );
      this.AddEvent(objItem,'mouseout' ,function(e) { DropDownObject.lowlight((e?e:window.event)); } );
      this.AddEvent(objItem,'click'    ,function(e) { DropDownObject.jumpto((e?e:window.event)); } );
   }
   
   // For IE5 on the Mac, we need to set the width to 1px in order to get proper calculations
   if(Global_BrowserSupport.blnIsMacIE) this.objSelectBox.style.width="1px";
   
   this.iOrigSelectLeft = this.objSelectBox.offsetLeft;
   this.iOrigSelectTop = this.objSelectBox.offsetTop;
   
   // Resize and Place our select box now so scroll bars don't appear.
   this.ResizeAndPlaceSelectBox();
   
};

// This function registers an instance of this class to init
// when the page finishes loading.
DropDown.prototype.Register = function() {
   // This sets up the this object in the scope of the function
   // registered below. Interesting....
   var DropDownObject = this;
   
   // Must have Basic DHTML Support.
   if (!Global_BrowserSupport.blnHasDHTMLSupport) {
      // Debuggin
      //alert("This browser Doesn't support DHTML.");
      return;
   }
   
   this.AddEvent(window,'load',function() { DropDownObject.Init(); } );
}

DropDown.prototype.AddEvent = function(obj, strEventName, objFunction) {
   if (obj.attachEvent) {
      var returnVal = obj.attachEvent("on" + strEventName, objFunction);
      // Debuggin
      //alert("Using attachEvent for on"+strEventName+": "+returnVal);
   } else if(obj.addEventListener && !(Global_BrowserSupport.blnIsKHTML && strEventName == 'click') ) {
      var returnVal = obj.addEventListener(strEventName, objFunction, true);
      // Debuggin
      //alert("Using addEventListener for on"+strEventName+": "+returnVal);
   } else {
      // Debuggin
      //alert("Using Eval for on"+strEventName+"");
      eval(""+
      "if(typeof obj.__queue_on"+strEventName+" == 'undefined') {\n"+
      "   obj.__queue_on"+strEventName+" = new Array();\n"+
      "}\n"+
      "if(typeof obj.on"+strEventName+" == 'function' && \n"+
      "   typeof obj.on"+strEventName+".__chainer == 'undefined') {\n"+
      "   obj.__queue_on"+strEventName+".push(obj.on"+strEventName+");\n"+
      "}\n"+
      "obj.__queue_on"+strEventName+".push(objFunction);\n"+
      "obj.on"+strEventName+" = function (e) {\n"+
      "   var queue = this.__queue_on"+strEventName+";\n"+
      "   if(typeof queue != 'undefined') {\n"+
      "      for( var i = 0; i < queue.length; i++ ) {\n"+
      "         queue[i](e);\n"+
      "      }\n"+
      "   }\n"+
      "};\n"+
      "obj.on"+strEventName+".__chainer = true;");
   }
};