   // This file contains PRIVATE functions that implement the dynamic GUI in the Multi-value Selector widget.
   // They are not intended for use by anyone else and are subject to change without notice.
   
   //mvsel window support
   var maxEntries = 15;
   var fontSize = 12;
   var fontFamily = ((MS55)?"Trebuchet MS, Arial, Helvetica":"Trebuchet MS");
   var padding = 2;
   
   //select or deselect an item in the list
   function onItemClick(mvselName,itemId)
   {
      //debugger;
      var mvsel = getMvsel(mvselName);
      if (itemId!=null && itemId.length>0)
      {
         if (mvsel.htSelectedItemIds[itemId]==null)
         {
            //add item to selected item list
            mvsel.htSelectedItemIds[itemId] = itemId;
         }
         else
         {
            mvsel.htSelectedItemIds[itemId] = null;
         }
      }
      mvsel.lastChange = updateMvselDisplay(mvsel);   //update the text field
      updateListDisplay(mvselName);             //update the list
   } 
   
   //display or hide window
   function onListActivation(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      if (!mvsel.bItemsVisible)
      {
         showItems(mvselName);
      }
      else
      {
         hideItems(mvselName);
      }
   }
   
   function buildDisplayHTML(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      var html = "";
      if (MS55) html += '<div style="height=100%;overflow-y:auto">';
      else      html += '<div>';
      //html += '<table cellpadding=0 cellspacing=0 style="width:100%; border:0; color:#039; font-family:\''+fontFamily+'\';font-size:'+fontSize+'px">\n';
      html += '<table cellpadding=0 cellspacing=0 style="width:100%; border:0; font-family:\''+fontFamily+'\';font-size:'+fontSize+'px">\n';
      for (var i=0; i<mvsel.itemIds.length; i++)
      {
         var itemId = mvsel.itemIds[i];
         var bSelected = (mvsel.htSelectedItemIds[itemId]!=null);
         var nameTag =((bSelected)?"<b>":"") + toScript(toTag(mvsel.htDisplayNames[itemId])) + ((bSelected)?"</b>":"");
         var parentWin = "opener.";       //mozilla
         if (MS55) parentWin ="parent.";  //ie
         html += '<tr onClick="'+parentWin+'onItemClick(\''+mvselName+'\',\''+itemId+'\');"><td style="cursor:pointer"><nobr>&nbsp;'+nameTag+'</nobr></td></tr>\n';
      }
      html += '</table></div>\n';
      //alert("html = \n"+html);
      
      return html;
   }
   
   //called to create the list window window
   function showItems(mvselName)
   {
      //get the mvsel to populate
      var mvsel = getMvsel(mvselName);
      if (mvsel!=null && mvsel.itemIds!=null && mvsel.itemIds.length>0)
      {
         var itemIds = mvsel.itemsIds;
         
         // build html for popup
         var html=buildDisplayHTML(mvselName);
         
         //compute popup height
         var h = ((mvsel.itemIds.length+1>maxEntries)?maxEntries:mvsel.itemIds.length+1);
         if (MS55)  h = h*(fontSize+5)+padding*2+8;
         else       h = h*(fontSize+7.5)+padding*2+8;
         
         // get length of longest itemDisplayName  
         var w=0;
         for (i=0; i<mvsel.itemIds.length; i++)
         {
            if (mvsel.itemIds[i].length>w) w=mvsel.itemIds[i].length;
         }
         
         //compute width required to display longest text
         var language = iman.getLanguageCode();
         var wFactor = ((language!=null && (language.indexOf("zh")==0 || language.indexOf("ja")==0))?1.3:.55);  
         w = ((w>0)?w:10);
         w = w*fontSize*wFactor+padding*2+2;
         if (mvsel.itemIds.length+1>maxEntries)
         {
            w += 20;    //add width of scrollbar
         }
         
         //compute x,y position to open putdown
         //debugger;
         var pt1 = iman.getScreenPos(mvselName);
         var pt2 = iman.getScreenPos(mvselName+"btn");
         var elWidth = pt2.x-pt1.x-1;
         var elHeight = 21; //el.height;
         var xPos = pt1.x;
         var yPos = pt1.y+elHeight;
         
         //adjust width to be at least as wide as mvsel, but always wide enough to display text
         w = ((w>elWidth)?w:elWidth);
         if (screen && screen.availWidth && w>screen.availWidth)
         {
            //no bigger than the screen.
            w = ((w<screen.availWidth)?w:screen.availWidth);
         }
         
         //display pull-down list
         if (MS55)
         {
            //show the popup window in IE
            mvsel.popBody.innerHTML = html;
            mvsel.popup.show(xPos, yPos, w, h);
         }
         else
         {
            //open a window on other browsers
            var winopts = "dependent,toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=no,width="+(w-8)+",height="+h+",screenX="+xPos+",left="+xPos+",screenY="+yPos+",top="+yPos;
            var win = window.open("webacc?taskId=dev.Empty&merge=fw.Empty",mvselName, winopts);
            mvsel.win = win;
            win.document.write('<html><head></head><body onUnload="opener.focus();">');
            win.document.write(html);
            win.document.writeln('</body></html>');
            win.document.close();
            
            //set window properties 
            setBodyProperties(win.document.body);
         }
         
         //mark selector as visible
         mvsel.bItemsVisible = true;
         
         //switch the button icon
         document.getElementById(mvselName+"btn").src = iman.getModulesPath() + "/dev/images/drop_up.gif";
      }
   }
   
   //called when uparrow clicked
   function hideItems(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      if (mvsel!=null && mvsel.bItemsVisible)
      {
         //hide/close window
         if (MS55) 
         {
            mvsel.popup.hide();
         }
         else
         {
            if (mvsel.win) mvsel.win.close();
         }
         
         //mark selector as invisible
         mvsel.bItemsVisible = false;
         
         //switch the button icon
         document.getElementById(mvselName+"btn").src = iman.getModulesPath() + "/dev/images/drop_down.gif";
         
         //call the specified onChangeCallBack routine
         doCallBack(mvsel);
      }
   }
   
   function doCallBack(mvsel)
   {
      mvselName = mvsel.name;
      if (mvsel.lastValue!=mvsel.lastChange)
      {
         //remember new value
         mvsel.lastValue = mvsel.lastChange;
         
         //call the onChange callback routine to process selection
         var callBack = mvsel.onChangeCallBack;
         if (callBack!=null && callBack.length>0)
         {
            var command = callBack+"('"+toScript(mvselName)+"')";
            try
            {
               eval( command );
            }
            catch(e)
            {
               //specified callback does not exist or failed to execute properly
               alert("mvsel.js:  ERROR--Your callback '"+callBack+"' for mvselector '"+mvselName+
                     "'\neither cannot be found or failed to execute properly."+
                     "\n\nException = "+e);
            }
         }
      }
   }
   
   function mvselReadOnly(mvselName,evt)
   {
      evt = ((evt)?evt:((window.event)?window.event:null));
      if (!evt.keyCode)
      {
         return;
      }
   
      var mvsel = getMvsel(mvselName);
      var keyCode = evt.keyCode;
      //var name = mvsel.name;
      //document.getElementById(name).value = keyCode; 
      if (keyCode>=35 && keyCode<=39)
      {
         //left arrow, right arrow, home, end
         ; //do nothing-- let it happen
      }
      else if (keyCode==46)   //delete key
      {
         //remove selected items from display
         clearSelectedItems(mvselName);
      }
      else
      {
         //any other key -- cancel event
          iman.cancelEvent(evt);         //hide the window
      }
   }
   
   function mvselKeyDown(mvselName,evt)
   {
      evt = ((evt)?evt:((window.event)?window.event:null));
      if (!evt.keyCode)
      {
         return;
      }
   
      var mvsel = getMvsel(mvselName);
      var keyCode = evt.keyCode;
      if (keyCode==13 || keyCode==32)
      {
         //carriage return or space
         onListActivation(mvselName);  //click on the list
      }
      else
      {
         //any key but enter or space
         hideItems(mvselName);         //hide the window
      }
      iman.cancelEvent(evt);
   }
   
   function clearSelectedItems(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      mvsel.htSelectedItemIds = new Array(); //clear selected items array
      mvsel.lastChange = "";
      updateMvselDisplay(mvsel);
      doCallBack(mvsel);
   }
   
   //redisplay the contents of the list after an item click
   function updateListDisplay(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      var html = buildDisplayHTML(mvselName);   //get new HTML
      if (MS55)
      {
         //ie
         mvsel.popBody.innerHTML = html;
      }
      else
      {
         //mozilla
         mvsel.win.document.write('<html><head></head><body onUnload="opener.focus();">');
         mvsel.win.document.write(html);
         mvsel.win.document.writeln('</body></html>');
         mvsel.win.document.close();
         
         //set window properties 
         setBodyProperties(mvsel.win.document.body);
      }
   }
   
   //return a string Array() of the selected item ids   
   function getSelectedItems(mvselName)
   {
      var mvsel = getMvsel(mvselName);
      var selectedItems = Array();
      if (mvsel!=null)
      {
         var htSelectedItems = mvsel.htSelectedItemIds;
         for (i in htSelectedItems)
         {
            if (htSelectedItems[i]!=null)
            {
               selectedItems[selectedItems.length] = htSelectedItems[i];
            }
         }
      }
      return selectedItems;
   }
  
   //----------- utility routines ------------------
   function getMvsel(mvselName)
   {
      return window.mvsels[mvselName];
   }
   
   function setBodyProperties(body)
   {
      body.style.padding = padding;
      body.style.cursor = "default";
      body.style.backgroundColor = "#FFFFFF";
      //body.style.border = "1 solid gray";
      body.style.border = "1 solid black";
      
   }
   