<!--
/* 
-------------------------------------------------------------------------------------------------
rhi.js

Author: mdeangelis

Description
-----------
Scripts for the RHI project.

Modification History: (LIFO)
---------------------------
May 21, 2009 - mdeangelis - Want to be able to intercept the "Go" button click - in the generateCustomSelects,
                            detect presence of handleGoButtonClick, if there, call it
Mar 26, 2009 - mdeangelis - Fix for 17171 - per request of business team, added multi-select for procurers (admin xmlfilelist)
Mar 07, 2009 - mdeangelis - Fix for 17093 - intercept case when user switches report from geo summary
                            to a report that expects only one selected geographic area
Dec 03, 2008 - mdeangelis - for geo summary, provide way for pseudo-dropdown of geographic area
                            to automatically scroll to the first selected country or region
Oct 20, 2008 - mdeangelis - integrate new methods and multi-select geographic area drop-down
Sep 19, 2008 - mdeangelis - integrate new funding sources drop-down
Jun 06, 2008 - mdeangelis - created
------------------------------------------------------------------------------------------------ 
*/
  
// rhi namespace
// ==============
function RHI()
{  
   //-------------------------------------------------------------------------
   // style control for custom drop-downs
   //-------------------------------------------------------------------------
   
   // an sb1 color for fonts
   var DROP_DOWN_FONT_COLOR = 'black'; // default
   var DROP_DOWN_SELECTED_COLOR = '#335EA8'; // default

   var SHIFT_PRESSED = false;
   var CTRL_PRESSED  = false;
   //var altPressed = false; // move window not needed
   
   // remember settings before usurping / restore after done
   var FUNC_MOUSEDOWN = null;
   var FUNC_MOUSEUP   = null;
   
   var COMN_SELECTED_ATTR = "selected";
   var COMN_SELECTED      = "yes";
   var COMN_NOT_SELECTED  = "no";
   
   //-------------------------------------------------------------------------
   // For the funding sources refinement panel
   //-------------------------------------------------------------------------   
   var NUM_FUNDING_SOURCES = -1;
   var FS_CHECKBOX_ELT_ID  = "fsCheckbox";
   var FS_OPT_PREFIX  = "fsOpt";
   var FS_SELECT_ID = "selectedDonors";

   //-------------------------------------------------------------------------
   // For the methods refinement panel
   //-------------------------------------------------------------------------
   var NUM_METHODS = -1;
   var MTD_CHECKBOX_ELT_ID  = "mtdCheckbox";
   var MTD_OPT_PREFIX  = "mtdOpt";
   var MTD_SELECT_ID = "selectedMethods";

   //-------------------------------------------------------------------------
   // For the multi-geographic area refinement panel
   //------------------------------------------------------------------------- 
   var NUM_GEOGRAPHIC_AREAS = -1;
   var GEO_OPT_PREFIX  = "geoOpt";
   var GEO_SELECT_ID = "selectedGeographicAreas";
   // geographic areas doesn't have a checkbox for select/deselect all

   //-------------------------------------------------------------------------
   // For the procurers / admin refinement panel - added Mar 26, 2009 - 17171
   //-------------------------------------------------------------------------   
   var NUM_PROCURERS = -1;
   var PROC_CHECKBOX_ELT_ID  = "procCheckbox";
   var PROC_OPT_PREFIX  = "procOpt";
   var PROC_SELECT_ID = "selectedProcurers";

   //-------------------------------------------------------------------------
   // FUNCTIONS BEGIN HERE
   //-------------------------------------------------------------------------

   // Utility functions
   this.report_error = function (msg)
   {
      alert("RHI ERROR: " + msg + " - please contact JSI support");
   } // report_error
   
   this.failed_to_detect = function (elt)
   {
      rhi.report_error("Failed to detect element : " + elt);
   } // failed_to_detect

   this.onCheckBoxClick = function( objSelectId, objCheckBoxId ) 
   {
      var strFunc = "onCheckBoxClick";
   
      if ( ! document.getElementById ) { return; }
   
      var objSelect = document.getElementById(objSelectId);
      if ( !objSelect ) { rhi.failed_to_detect(strFunc+"[objSelect]"); return; }
   
      var objCheckBox = document.getElementById(objCheckBoxId);
      if ( !objCheckBox ) { rhi.failed_to_detect(strFunc+"[objCheckBox]"); return; }
   
      var doCheck = false;
   
      if ( objCheckBox.checked == true ) 
      {
         doCheck = true;
      }
   
      // select/de-select all options in the select list based on checkbox
      for ( var x = 0; x < objSelect.length; x++) 
      { 
      var eltOption = objSelect.options[x];
      if ( !eltOption ) { rhi.failed_to_detect(strFunc+"[eltOption]"); return; }
      eltOption.selected = doCheck;
      }
   } // onCheckBoxClick

   // User has changed what is selected in list ...
   this.onSelectChange = function( objSelectId, objCheckBoxId ) 
   {
      var strFunc = "onSelectChange";
      
      if ( ! document.getElementById ) { return; }
      
      var objSelect = document.getElementById(objSelectId);
      if ( !objSelect ) { rhi.failed_to_detect(strFunc+"[objSelect]"); return; }
      
      var objCheckBox = document.getElementById(objCheckBoxId);
      if ( !objCheckBox ) { rhi.failed_to_detect(strFunc+"[objCheckBox]"); return; }
      
      var allChecked = true;
      
      // as soon as we find a non-selected option, the checbox becomes unchecked
      
      for ( var x = 0; x < objSelect.length; x++) 
      { 
         var eltOption = objSelect.options[x];
         if ( !eltOption ) { rhi.failed_to_detect(strFunc+"[eltOption]"); return; }
         
         if ( ! eltOption.selected )
         {
            allChecked = false;
         }
      }
      objCheckBox.checked = allChecked; 
   }  // onSelectChange

   // User has changed what is selected in list ...
   this.showOptionSelected = function( elt ) 
   {
      var strFunc = "showOptionSelected";
   
      if ( !elt ) { rhi.failed_to_detect(strFunc+"[elt]"); return; }
   
      elt.className = "sb1NavBarOptionSelected";
   } // showOptionSelected

   // Year-based report, user changed start month, make sure at least 1 year exists in range ...
   this.adjustEndYear = function( ) 
   {
      var strFunc = "adjustEndYear";
      
      if ( ! document.getElementById ) { return; }
      
      var objStartMonth   = document.getElementById("startMonth");
      var objStartYear    = document.getElementById("startYear");
      var objEndYear      = document.getElementById("endYear");

      if ( ! objStartMonth )  { rhi.failed_to_detect(strFunc+"[objStartMonth]"); return; }
      if ( ! objStartYear )   { rhi.failed_to_detect(strFunc+"[objStartYear]"); return; }
      if ( ! objEndYear )     { rhi.failed_to_detect(strFunc+"[objEndYear]"); return; }
      
      if ( objEndYear[objEndYear.selectedIndex].value <= objStartYear[objStartYear.selectedIndex].value )
      {
         if ( objEndYear[objEndYear.selectedIndex].value == objStartYear[objStartYear.selectedIndex].value )
         {
            var m = objStartMonth[objStartMonth.selectedIndex].value;
            if ( m == 0 ) { return; } // same year and January start ...
         }
         var adj = objStartYear.selectedIndex + 1;
         if ( adj == objStartYear.length ) { adj = adj - 1; }
         objEndYear[objEndYear.selectedIndex].selected = false;
         objEndYear[adj].selected = true;
      }
   } // adjustEndYear

   // Year-based report, user changed end month, make sure at least 1 year exists in range ...
   this.adjustStartYear = function( ) 
   { 
      var strFunc = "adjustStartYear";
      
      if ( ! document.getElementById ) { return; }
      
      var objStartMonth   = document.getElementById("startMonth");
      var objStartYear    = document.getElementById("startYear");
      var objEndYear      = document.getElementById("endYear");

      if ( ! objStartMonth )  { rhi.failed_to_detect(strFunc+"[objStartMonth]"); return; }
      if ( ! objStartYear )   { rhi.failed_to_detect(strFunc+"[objStartYear]"); return; }
      if ( ! objEndYear )     { rhi.failed_to_detect(strFunc+"[objEndYear]"); return; }
      
      if ( objEndYear[objEndYear.selectedIndex].value <= objStartYear[objStartYear.selectedIndex].value )
      {
         if ( objEndYear[objEndYear.selectedIndex].value == objStartYear[objStartYear.selectedIndex].value )
         {
            var m = objStartMonth[objStartMonth.selectedIndex].value;
            if ( m == 0 ) { return; } // same year and January start ...
         }
         var adj = objEndYear.selectedIndex - 1;
         if ( adj < 0 ) { adj = 0; }
         objStartYear[objStartYear.selectedIndex].selected = false;
         objStartYear[adj].selected = true;
      }
   }  // adjustStartYear

   // Year-based report, user changed start month, recalc the end month to post ...
   this.recalcEndMonth = function( ) 
   {
      var strFunc = "recalcEndMonth";
      
      if ( ! document.getElementById ) { return; }
      
      var objStartMonth   = document.getElementById("startMonth");
      var objEndMonth     = document.getElementById("endMonth");
      var objEndMonthName = document.getElementById("endMonthName");
      var objStartYear    = document.getElementById("startYear");
      var objEndYear      = document.getElementById("endYear");
      
      if ( ! objStartMonth )  { rhi.failed_to_detect(strFunc+"[objStartMonth]"); return; }
      if ( ! objEndMonth )    { rhi.failed_to_detect(strFunc+"[objEndMonth]"); return; }
      if ( ! objEndMonthName ){ rhi.failed_to_detect(strFunc+"[objEndMonthName]"); return; }
      if ( ! objStartYear )   { rhi.failed_to_detect(strFunc+"[objStartYear]"); return; }
      if ( ! objEndYear )     { rhi.failed_to_detect(strFunc+"[objEndYear]"); return; }
      
      objEndMonth.value = "0";
      objEndMonthName.innerHTML = "undefined";
      
      for ( var x = 0; x < objStartMonth.length; x++) 
      { 
         var eltOption = objStartMonth.options[x];
         if ( !eltOption ) { rhi.failed_to_detect(strFunc+"[eltOption]"); return; }
         
         if ( eltOption.selected )
         {
            var m = x - 1;
            if ( m < 0 ) { m = 11; }
            
            var endMonth     = objStartMonth[m].value;
            var endMonthName = objStartMonth[m].innerHTML;
            
            objEndMonth.value         = endMonth;
            objEndMonthName.innerHTML = endMonthName;
            
            // ok to be same year when it's January thru December, but otherwise, if we started with same years,
            // then nudge the end year up, so we have at least 1 full year
            this.adjustEndYear();
            return;
         }
      }            
   } // recalcEndMonth

   // The following is necessary because IE sizes the drop-down when width
   // attribute set using 98%, but Firefox does not; Firefox sizes correctly
   // when width set to 250, but Explorer does not ...
   this.adjustGeoDropdown = function( browserDetector ) 
   {
      if ( browserDetector && document.getElementById )
      {
         var theSelect  = document.getElementById("selectedGeographicAreas");
         var theBrowser = browserDetector.browser;
         
         if (theBrowser && theSelect)
         {
            theBrowser = theBrowser.toUpperCase();
            if ( theBrowser == 'EXPLORER' )
            {
               theSelect.style.width = "98%";
            }
            else // including FIREFOX
            {
               theSelect.style.width = "250px";
            }
         }
      }
   } // adjustGeoDropdown

   //---------------------------------------------------------------------------
   // Oct 20, 2008 - mdeangelis - common refinement panel / multi-selects
   //---------------------------------------------------------------------------

   //---------------------------------------------------------------------------
   // Dec 03, 2008 - mdeangelis - for geo summary, provide way for pseudo-dropdown 
   // of geographic area to auto-scroll to the first selected country or region
   //---------------------------------------------------------------------------
	this.autoScrollToFirstSelected = function(divID)
	{
		var theDiv = document.getElementById(divID);
		if ( theDiv && theDiv.getElementsByTagName )
		{
			var children = theDiv.getElementsByTagName('SPAN');
			if ( children )
			{
				var scrollAmt    = -1;
				var lineHeightPx = 14; // amount to scroll per line item in the "drop-down"

				for ( var i = 0; i < children.length; i++ )
				{
					var selected = children[i].getAttribute("selected");
					if ( selected && selected == "yes" )
					{
						scrollAmt = i * lineHeightPx;
						theDiv.scrollTop = scrollAmt;
						break;
					}
				}
			}
		}
	} // autoScrollToFirstSelected

   //---------------------------------------------------------------------------
   // common refinement panel initialization
   //---------------------------------------------------------------------------
   // initial rendering of options as selected or not
   this.initRefinePanelFontColor = function(fontColor)
   {
      DROP_DOWN_FONT_COLOR = fontColor;
   } // initRefinePanelFontColor

   // sets mouse down/up handlers when we're over the funding source drop-down
   this.initMouseHandlers = function()
   {
      if (parseInt(navigator.appVersion) > 3) 
      {
         FUNC_MOUSEDOWN = document.onmousedown;
         FUNC_MOUSEUP = document.onmouseup;
   
         document.onmousedown = this.mouseDown;
         document.onmouseup = this.clearSelections;
   
         if (navigator.appName == "Netscape") 
         {
            document.captureEvents(Event.MOUSEDOWN);
            document.captureEvents(Event.MOUSEUP);
         }
      }
   } // initMouseHandlers

   // restores mouse down/up handlers to original settings when we've left the funding source drop-down
   this.restoreMouseDown = function()
   {
      if (parseInt(navigator.appVersion) > 3) 
      {
         document.onmousedown = FUNC_MOUSEDOWN;
         document.onmouseup = FUNC_MOUSEUP;
      }
   } // restoreMouseDown

   // mousedown event handler - record whether we've used CTRL or SHIFT keys
   this.mouseDown = function(e) 
   {
      if (parseInt(navigator.appVersion) > 3)
      {
         var evt = (navigator.appName == "Netscape" ? e : window.event);
         
         SHIFT_PRESSED = evt.shiftKey;
         CTRL_PRESSED  = evt.ctrlKey;
         //evt.altKey; // not needed
      }
      
      return true;
   } // mouseDown

   // for a given multi-select element, render its visual state as selected or not
   this.renderOptionSelectedState = function(opt)
   {
      var selectState = opt.getAttribute(COMN_SELECTED_ATTR);
   
      if ( COMN_SELECTED == selectState )
      {
         opt.parentNode.style.backgroundColor = DROP_DOWN_SELECTED_COLOR;
         opt.style.color = "white";
      }
      else
      {
         opt.parentNode.style.backgroundColor = "white";
         opt.style.color = DROP_DOWN_FONT_COLOR;
      }
   } // renderOptionSelectedState

   // in case user selects text inadvertently, we clear and selection to keep experience like a <select>
   this.clearSelections = function() 
   {
      if (document.selection)
      {
         document.selection.empty();
      }
      else if (window.getSelection)
      {
         window.getSelection().removeAllRanges();
      }
   } // clearSelections
   
	//---------------------------------------------------------------------------
	// Mar 26, 2009 - mdeangelis - 17171 - add for support of admin procurer multi-select
	//---------------------------------------------------------------------------
   // abstracted way to detect if the current form has multi-selects in it
   this.formSupportsMultiWidget = function(theForm)
   {
		if ( document.getElementById('bottomGoButton') ) { return true; }

		var action = theForm.action;

		if ( action.indexOf("/admin/xmlfiles") >= 0 )
		{
			return true;
		}

		return false;
	}
	//---------------------------------------------------------------------------

   // when form is submitted, call this function to append the needed <select> element
   this.generateComnMultiSelect = function(theForm, nSelectElements, idSelectElement, optPrefix)
   {
      var strFunc = "generateComnMultiSelect";
      
      //------------------------------------------------------------------------
      // We need to avoid the case where the Go button appears without the funding source
      // dropdown; namely, on the index/home page.  We don't want to post a form element
      // for selected funding sources in that case.  So, detect the case where there is
      // a second Go button (who's id is "bottomGoButton") so we know we're on a true 
      // refinement panel where donor selections are made
      //------------------------------------------------------------------------
      
		// Mar 26, 2009 - mdeangelis - 17171 - for admin procurer dropdown, abstract way widget detected
      //if ( ! document.getElementById('bottomGoButton') ) { return; }
		if ( ! this.formSupportsMultiWidget(theForm) ) { return; }
      
      if ( ! theForm )  { rhi.failed_to_detect(strFunc+"[theForm]"); return; }
      if ( ! nSelectElements ) { rhi.failed_to_detect(strFunc+"[nSelectElements]"); return; }
      if ( ! idSelectElement ) { rhi.failed_to_detect(strFunc+"[idSelectElement]"); return; }
      if ( ! optPrefix ) { rhi.failed_to_detect(strFunc+"[optPrefix]"); return; }
      
      // We're on a true refinement panel with donor/funding source drop-down
      
      var eltHiddenDiv = document.createElement("DIV");
      eltHiddenDiv.style.visibility = "hidden";
      
      //------------------------------------------------------------------------
      // Oct 17, 2008 - mdeangelis - avoid shifting report table area when many (32) 
      // funding sources, create the div so it burps into the form way out of the way
      //------------------------------------------------------------------------
      eltHiddenDiv.style.position = "absolute";
      eltHiddenDiv.style.top = "999px";
      eltHiddenDiv.style.left = "0px";
      //------------------------------------------------------------------------
      
      var eltSelect;
      var eltOption;
   
      // Create new hidden element to turn OFF update skip-once
   
      // We have to test for IE, because IE6 didn't work unless handled this way
      if ( navigator.appName.match(/Internet Explorer/) ) 
      {
         eltSelect = document.createElement("<SELECT MULTIPLE>");
      } 
      else 
      {
         eltSelect = document.createElement("SELECT");
         eltSelect.multiple = true;
      }
   
      eltSelect.id = idSelectElement;
      eltSelect.name = eltSelect.id;
   
      theForm.appendChild(eltSelect); // add select to form
   
      for (i = 1; i <= nSelectElements; i++)
      {
         var opt = document.getElementById(optPrefix+i.toString());

		 // Oct 21, 2008 - mdeangelis - optimization / only pass selected options
         if (opt && COMN_SELECTED == opt.getAttribute(COMN_SELECTED_ATTR) )
         {
            eltOption = document.createElement('OPTION');
            eltOption.innerHTML = opt.innerHTML;
            eltOption.value = opt.getAttribute('value');
            eltOption.selected = true;
            eltSelect.appendChild(eltOption); // add option to select
         }
      }  
      
      eltHiddenDiv.appendChild(eltSelect); // add select to hidden div
      theForm.appendChild(eltHiddenDiv); // add hidden div to form
      
      return; // we're a simple button
   } // generateComnMultiSelect

   // called once on load and after options are clicked to visually depict options as selected or not
   this.renderComnSelectionState = function(nSelectElements, optPrefix, chkBoxEltId)
   {
      var strFunc = "renderComnSelectionState";

      if ( ! nSelectElements ) { rhi.failed_to_detect(strFunc+"[nSelectElements]"); return; }
      if ( ! optPrefix ) { rhi.failed_to_detect(strFunc+"[optPrefix]"); return; }
      // some multi-selects don't have parallel checkbox (e.g. geo multi-select)
      
      // update selections
      for (i = 1; i <= nSelectElements; i++)
      {
         var elt = document.getElementById(optPrefix+i.toString());
         if (elt)
         {
            this.renderOptionSelectedState(elt);
         }
      }

      // count how many selected after handling
      var cntSelected = 0;
      for (i = 1; i <= nSelectElements; i++)
      {
         var elt = document.getElementById(optPrefix+i.toString());
         
         if (elt)
         {
            if ( COMN_SELECTED == elt.getAttribute(COMN_SELECTED_ATTR) )
            {
               cntSelected++;
            } 
         }
      }

      // if we have a partner checkbox (select all/deselect all)
      if ( chkBoxEltId )
      {
         var chk = document.getElementById(chkBoxEltId);
         
         if (! chk)
         {
            this.failed_to_detect(strFunc+" "+chkBoxEltId);
            return;
         }
         
         // update checkbox state
         if ( nSelectElements == cntSelected )
         {
            chk.checked = true;
         }
         else
         {
            chk.checked = false;
         }
      }
   } // renderComnSelectionState
   
   // handler when multi-select checkbox (select all / deselect all) is clicked
   this.handleComnClickChkOptions = function(idCheckBox, nSelectElements, optPrefix)
   {
      var strFunc = "handleComnClickChkOptions";
      
      if ( ! idCheckBox ) { rhi.failed_to_detect(strFunc+"[idCheckBox]"); return; }
      if ( ! nSelectElements ) { rhi.failed_to_detect(strFunc+"[nSelectElements]"); return; }
      if ( ! optPrefix ) { rhi.failed_to_detect(strFunc+"[optPrefix]"); return; }
 
      var selectState;
      var elt = document.getElementById(idCheckBox);
   
      if ( ! elt ) { rhi.failed_to_detect(strFunc+"[elt]"); return; }
      
      if (elt)
      {
         if (elt.checked)
         {
            selectState = COMN_SELECTED;   
         }
         else
         {
            selectState = COMN_NOT_SELECTED;
         }
      }
   
      for (i = 1; i <= nSelectElements; i++)
      {
         var opt = document.getElementById(optPrefix+i.toString());
         if (opt)
         {
            opt.setAttribute(COMN_SELECTED_ATTR, selectState);
         }
      }
   
      this.renderComnSelectionState(nSelectElements, optPrefix, idCheckBox);
   } // handleComnClickChkOptions

   // handler for when option on custom multi-select drop-down is clicked
   this.handleComnOptionClicked = function(opt, nSelectElements, optPrefix, idCheckBox)
   {
      var strFunc = "handleComnOptionClicked";
      
      if ( ! opt ) { rhi.failed_to_detect(strFunc+"[opt]"); return; }
      if ( ! nSelectElements ) { rhi.failed_to_detect(strFunc+"[nSelectElements]"); return; }
      if ( ! optPrefix ) { rhi.failed_to_detect(strFunc+"[optPrefix]"); return; }
      // multi-select might not have a checkbox for select/deselect all
      
      this.clearSelections(); // this required for partially selected text - we're only simulating an <option> tag
   
      var minSelected   = nSelectElements + 1;
      var maxSelected   = 0;
      var cntSelected   = 0; // convenience
      var thisOptIdx    = 0;
      var selectState   = "undefined";
   
      // get min/max selected
      for (i = 1; i <= nSelectElements; i++)
      {
         var elt = document.getElementById(optPrefix+i.toString());
   
         if (elt)
         {
            if (elt.id == opt.id) { thisOptIdx = i; } // mark which option we are
   
            if ( COMN_SELECTED == elt.getAttribute(COMN_SELECTED_ATTR) )
            {
               cntSelected++;
               if (i < minSelected) { minSelected = i; }
               if (i > maxSelected) { maxSelected = i; }
            } 
         }
      }
   
      if (SHIFT_PRESSED)
      {
         if (0 == cntSelected)
         {
            // this one the first to select
            opt.setAttribute(COMN_SELECTED_ATTR, COMN_SELECTED);   
         }
         else if ( thisOptIdx > minSelected && thisOptIdx < maxSelected )
         {
            // clear all and then mark selected from max down to this one
   
            // clear selected state for all  
            for (i = 1; i <= nSelectElements; i++)
            {
               var elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  elt.setAttribute(COMN_SELECTED_ATTR, COMN_NOT_SELECTED);
               }
            }
   
            for ( i = maxSelected; i >= thisOptIdx; i-- )
            {
               elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  elt.setAttribute(COMN_SELECTED_ATTR, COMN_SELECTED);
               }
            }
         }
         else if ( thisOptIdx <= minSelected )
         {
            // start at selected option and keep going until a break - once a break, deselect
            selectState = COMN_SELECTED;
            for ( i = thisOptIdx; i <= minSelected; i++ )
            {
               elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  elt.setAttribute(COMN_SELECTED_ATTR, selectState);
               }
            }
            
            for ( i = (minSelected + 1); i <= nSelectElements; i++ )
            {
               elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  if ( COMN_NOT_SELECTED == elt.getAttribute(COMN_SELECTED_ATTR) )
                  {
                     selectState = COMN_NOT_SELECTED;
                  }
                  elt.setAttribute(COMN_SELECTED_ATTR, selectState);
               }
            }
         }
         else if ( thisOptIdx >= maxSelected )
         {
            // start at selected option and keep going until a break - once a break, deselect
            selectState = COMN_SELECTED;
            for ( i = thisOptIdx; i >= maxSelected; i-- )
            {
               elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  elt.setAttribute(COMN_SELECTED_ATTR, selectState);
               }
            }
            
            for ( i = (maxSelected - 1); i >= 1; i-- )
            {
               elt = document.getElementById(optPrefix+i.toString());
               if (elt)
               {
                  if ( COMN_NOT_SELECTED == elt.getAttribute(COMN_SELECTED_ATTR) )
                  {
                     selectState = COMN_NOT_SELECTED;
                  }
                  elt.setAttribute(COMN_SELECTED_ATTR, selectState);
               }
            }
         }   
         // select between range
      }
      else if (CTRL_PRESSED)
      {
         // leave other options selected, toggle this one
         var newState = ( COMN_SELECTED == opt.getAttribute(COMN_SELECTED_ATTR) ) ? COMN_NOT_SELECTED : COMN_SELECTED;
         opt.setAttribute(COMN_SELECTED_ATTR, newState);  // if we clicked on unselected item, now selected
      }
      else
      {
         // clear selected state for all  
         for (i = 1; i <= nSelectElements; i++)
         {
            var elt = document.getElementById(optPrefix+i.toString());
            if (elt)
            {
               elt.setAttribute(COMN_SELECTED_ATTR, COMN_NOT_SELECTED);
            }
         }
         //----------------------------------------------------------------------------
         // if we clicked out of the selection range just set to selected, otherwise
         // if we are the only one selected, toggle; otherwise, if we clicked on
         // a selected item in a selected range, leave only the clicked item selected
         //---------------------------------------------------------------------------
         if ( 0 == cntSelected )
         {
            opt.setAttribute(COMN_SELECTED_ATTR, COMN_SELECTED); // turn on  
         }
         if ( 1 == cntSelected && thisOptIdx == minSelected )
         {
            opt.setAttribute(COMN_SELECTED_ATTR, COMN_NOT_SELECTED); // toggle off 
         }
         else  
         {
            // clicked on an option other than what was selected before
            opt.setAttribute(COMN_SELECTED_ATTR, COMN_SELECTED); // leave 
         }		
      }
   
      // update selections
      this.renderComnSelectionState(nSelectElements, optPrefix, idCheckBox);
   } // handleComnOptionClicked

   // handler when multi-select dropdown's checkbox (select all) is clicked
   this.handleComnClickChkOptions = function(idCheckBox, nSelectElements, optPrefix)
   {
      var strFunc = "handleComnClickChkOptions";
      
      if ( ! idCheckBox ) { rhi.failed_to_detect(strFunc+"[idCheckBox]"); return; }
      if ( ! nSelectElements ) { rhi.failed_to_detect(strFunc+"[nSelectElements]"); return; }
      if ( ! optPrefix ) { rhi.failed_to_detect(strFunc+"[optPrefix]"); return; }
      
      var selectState;
      var elt = document.getElementById(idCheckBox);
      
      if ( ! elt ) { rhi.failed_to_detect(strFunc+"[elt]"); return; }
   
      if (elt)
      {
         if (elt.checked)
         {
            selectState = COMN_SELECTED;
         }
         else
         {
            selectState = COMN_NOT_SELECTED;
         }
      }
   
      for (i = 1; i <= nSelectElements; i++)
      {
         var opt = document.getElementById(optPrefix+i.toString());
         if (opt)
         {
            opt.setAttribute(COMN_SELECTED_ATTR, selectState);
         }
      }
   
      // update selections
      this.renderComnSelectionState(nSelectElements, optPrefix, idCheckBox);
   } // handleComnClickChkOptions

   // put here: calls to generate hidden selects when form submitted
   this.generateCustomSelects = function(theForm)
   {
		//-----------------------------------------------------------------------
		// May 21, 2009 - mdeangelis
		//
		// @@TODO - refactor the event so that this happens as a consequence of
		// handling the go button click - its inverted at the moment ...
		//
		// Want to be able to intercept the "Go" button click - in the generateCustomSelects,
      // detect presence of handleGoButtonClick, if there, call it
		//-----------------------------------------------------------------------
		if ( window.handleGoButtonClick )
		{
				handleGoButtonClick();
		}
		//-----------------------------------------------------------------------

      if ( NUM_FUNDING_SOURCES > 0 )
      {
         this.generateFSSelect(theForm);
      }
      
      if ( NUM_METHODS > 0 )
      {     
         this.generateMTDSelect(theForm);
      }
      
      if ( NUM_GEOGRAPHIC_AREAS > 0 )
      {
          this.generateGEOSelect(theForm);
      }

		//-----------------------------------------------------------------------
		// Mar 26, 2009 - mdeangelis - 17171 - add new multi-select for procurers
		//-----------------------------------------------------------------------	
		if ( NUM_PROCURERS > 0 )
      {
          this.generateProcurerSelect(theForm);
      }
		//-----------------------------------------------------------------------

		//-----------------------------------------------------------------------
		// Mar 07, 2009 - mdeangelis - Fix for 17093 - ADD SECTION
		//-----------------------------------------------------------------------
		var action = theForm.action;

		if ( action.indexOf("geosummary") > 0 )
		{
			// we're on the geographic summary report page
			var rptTypeSelect = document.getElementById("rptType");
			var idx = rptTypeSelect.selectedIndex;

			if ( idx >= 0 )
			{
				// just making sure there are selections

				//----------------------------------------------------------------------------
				// we're currently on the geographic summary report, but user is changing
				// which report they want to see to either shipment summary, value summary or
				// quantity summary ... in that case, detect if more than one geographc area
				// is selected and if so, ajust the multi-select to subtract all selections
				// except the first 
				//----------------------------------------------------------------------------
				if ( rptTypeSelect[idx].value && ( "3" > rptTypeSelect[idx].value ) )
				{
					// selected report expects 1 geo area: ship summary, value summary, qty summary

					var eltSelectMultiGeo = document.getElementById(GEO_SELECT_ID);
					var foundFirst = false;
					for (var i = 0; i < eltSelectMultiGeo.length; i++)
					{
						if (eltSelectMultiGeo[i].selected)
						{
							if (foundFirst)
							{
								eltSelectMultiGeo[i].selected = false; // only take first
							}
							foundFirst = true;
						}
					}
				}
			}
		}
		//-----------------------------------------------------------------------
   }

   //---------------------------------------------------------------------------
   // BEGIN: new funding source horizontal scrolling drop-down
   //---------------------------------------------------------------------------
   
   // initial rendering of options as selected or not
   this.initRefinePanelFundingSources = function(nFundingSources)
   {
      NUM_FUNDING_SOURCES = nFundingSources;
      this.renderComnSelectionState(NUM_FUNDING_SOURCES, FS_OPT_PREFIX, FS_CHECKBOX_ELT_ID);
   } // initRefinePanelFundingSources

   // handler when funding sources checkbox (select all) is clicked
   this.handleFSClickChkOptions = function()
   {
      this.handleComnClickChkOptions(FS_CHECKBOX_ELT_ID, NUM_FUNDING_SOURCES, FS_OPT_PREFIX);
   } // handleFSClickChkOptions

   // handler for when option on custom funding source multi-select drop-down is clicked
   this.handleFSOptionClicked = function(opt)
   {
      this.handleComnOptionClicked(opt, NUM_FUNDING_SOURCES, FS_OPT_PREFIX, FS_CHECKBOX_ELT_ID);
   } // handleFSOptionClicked
   
   // when form is submitted, call this function to append the needed <select> element
   this.generateFSSelect = function(theForm)
   {
      this.generateComnMultiSelect(theForm, NUM_FUNDING_SOURCES, FS_SELECT_ID, FS_OPT_PREFIX);
   } // generateFSSelect

   //---------------------------------------------------------------------------
   // END: new funding source horizontal scrolling drop-down
   //---------------------------------------------------------------------------

   //---------------------------------------------------------------------------
   // BEGIN: new method horizontal scrolling drop-down
   //---------------------------------------------------------------------------
   
   // initial rendering of options as selected or not
   this.initRefinePanelMethods = function(nMethods)
   {
      NUM_METHODS = nMethods;
      this.renderComnSelectionState(NUM_METHODS, MTD_OPT_PREFIX, MTD_CHECKBOX_ELT_ID);
   } // initRefinePanelMethods

   // handler when method checkbox (select all) is clicked
   this.handleMTDClickChkOptions = function()
   {
      this.handleComnClickChkOptions(MTD_CHECKBOX_ELT_ID, NUM_METHODS, MTD_OPT_PREFIX);
   } // handleMTDClickChkOptions

   // handler for when option on custom method multi-select drop-down is clicked
   this.handleMTDOptionClicked = function(opt)
   {
      this.handleComnOptionClicked(opt, NUM_METHODS, MTD_OPT_PREFIX, MTD_CHECKBOX_ELT_ID);
   } // handleMTDOptionClicked
   
   // when form is submitted, call this function to append the needed <select> element
   this.generateMTDSelect = function(theForm)
   {
      this.generateComnMultiSelect(theForm, NUM_METHODS, MTD_SELECT_ID, MTD_OPT_PREFIX);
   } // generateMTDSelect

   //---------------------------------------------------------------------------
   // END: new method horizontal scrolling drop-down
   //---------------------------------------------------------------------------

   //---------------------------------------------------------------------------
   // BEGIN: new geo area horizontal scrolling drop-down
   //---------------------------------------------------------------------------
   
   // initial rendering of options as selected or not
   this.initRefinePanelGeoAreas = function(nGeoAreas)
   {
      NUM_GEOGRAPHIC_AREAS = nGeoAreas;
      this.renderComnSelectionState(NUM_GEOGRAPHIC_AREAS, GEO_OPT_PREFIX, null);
   } // initRefinePanelGeoAreas

   // handler for when option on custom geographic areas multi-select drop-down is clicked
   this.handleGEOOptionClicked = function(opt)
   {
      this.handleComnOptionClicked(opt, NUM_GEOGRAPHIC_AREAS, GEO_OPT_PREFIX, null);
   } // handleGEOOptionClicked
   
   // when form is submitted, call this function to append the needed <select> element
   this.generateGEOSelect = function(theForm)
   {
      this.generateComnMultiSelect(theForm, NUM_GEOGRAPHIC_AREAS, GEO_SELECT_ID, GEO_OPT_PREFIX);
   } // generateGEOSelect

   //---------------------------------------------------------------------------
   // END: new geographic areas horizontal scrolling drop-down
   //---------------------------------------------------------------------------

	//---------------------------------------------------------------------------
   // BEGIN: new procurer horizontal scrolling drop-down - added Mar 26, 2009 - 17171
   //---------------------------------------------------------------------------
   
   // initial rendering of options as selected or not
   this.initRefinePanelProcurers = function(nProcurers)
   {
      NUM_PROCURERS = nProcurers;
      this.renderComnSelectionState(NUM_PROCURERS, PROC_OPT_PREFIX, PROC_CHECKBOX_ELT_ID);
   } // initRefinePanelProcurers

   // handler when procurers checkbox (select all) is clicked
   this.handleProcurerClickChkOptions = function()
   {
      this.handleComnClickChkOptions(PROC_CHECKBOX_ELT_ID, NUM_PROCURERS, PROC_OPT_PREFIX);
   } // handleProcurerClickChkOptions

   // handler for when option on custom procurers multi-select drop-down is clicked
   this.handleProcurerOptionClicked = function(opt)
   {
      this.handleComnOptionClicked(opt, NUM_PROCURERS, PROC_OPT_PREFIX, PROC_CHECKBOX_ELT_ID);
   } // handleProcurerOptionClicked
   
   // when form is submitted, call this function to append the needed <select> element
   this.generateProcurerSelect = function(theForm)
   {
      this.generateComnMultiSelect(theForm, NUM_PROCURERS, PROC_SELECT_ID, PROC_OPT_PREFIX);
   } // generateProcurerSelect

   //---------------------------------------------------------------------------
   // END: new procurer horizontal scrolling drop-down
   //---------------------------------------------------------------------------

} // rhi namespace

//------------------------------------------------------------------------------
// Oct 20, 2008 - mdeangelis - tighten up browser feature support
// We only support browsers that support getElementById feature

var rhi = null;

if ( document.getElementById )
{
   rhi = new RHI();
}
else
{
   alert("Sorry, your browser is not supported - this application\n"+
         "requires the support of getElementById");
}
//------------------------------------------------------------------------------

// The following is courtesy of: http://www.quirksmode.org/js/detect.html
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();

//alert("The browser you are using is: " + BrowserDetect.browser);
//-->