
/*** (C)Scripterlative.com
   
Info: www.scripterlative.com?selectunique

-Select Unique-

Make a Set of Unique Selections Using Multiple Select Boxes 

* Multiple independent select box groups in the same document.

* Each group can contain any number of select boxes.

Please notify any suspected errors in this text or code, however minor.

These instructions may be removed, but not the above text.

Description
~~~~~~~~~~~
Select Multiple provides a means of making multiple unique selections from a list of options, in places where an order of preference must be stated.

Preparation
~~~~~~~~~~~
The document must contain a set of select boxes, all populated with a single default option, i.e. 'Please Select' or similar. 
Additionally, one of the select boxes (usually the first) must be populated with all the possible options for the group selection.

Installation
~~~~~~~~~~~~
Save this file/text as 'selectunique.js'

In the <head> section of the document insert:

<script type='text/javascript' src='selectunique.js'></script>

Configuration
~~~~~~~~~~~~~
The script is configured by a single call to the function SelectUnique.involve()
The function is passed references to all the select boxes involved in a particular unique selection, in the form of a comma-delimited parameter list.
The first parameter must be the reference to the populated select box.

Example
~~~~~~~
You have a form named 'travel' containing three select boxes named 'choice1', 'choice2' and 'choice3'.

<form name='travel'>
 <select name='choice1'>
  <option value=''>Select first choice travel type</option>
  <option value='air'>Air</option>
  <option value='rail'>Rail</option>
  <option value='road'>Road</option>
  <option value='sea'>Sea</option>
 </select>
 <select name='choice2'>
  <option value=''>Select second choice travel type</option>
 </select> 
 <select name='choice3'>
  <option value=''>Select third choice travel type</option>
 </select> 
</form>

At a point below all the involved select boxes, insert the following:

<script type='text/javascript'>

 SelectUnique.involve(document.forms.travel.choice1, document.forms.travel.choice2, document.forms.travel.choice3);

</script>

That's all there is to it. Repeat for further groups in the same document.

Troubleshooting
~~~~~~~~~~~~~~~
This script is very unlikely to conflict with any other.
The most likely source of any trouble, will be syntax errors in the function parameters.
Ensure all necessary file paths are specified correctly.
Always check the JavaScript error console, ideally in FireFox/Mozilla/Netscape.
The script requires valid HTML: http://validator.w3.org
   
GratuityWare
~~~~~~~~~~~~
This code is free, however if you wish to reward the author, thereby ensuring the continued 
development of such code, you may donate at www.scripterlative.com, stating the URL to which 
the donation applies.
 
** DO NOT EDIT BELOW THIS LINE **/

var SelectUnique=/*28432973637269707465726C61746976652E636F6D*/
{
 data:[], setId:"boxGroup", groupCount:0, 
   
 involve:function()
 {
  var arg=arguments;
  
  var dat = this.data[this.setId+this.groupCount] = {txt:[], val:[], boxes:[]};
  
  for(var i=1, opts=arg[0].options, len=opts.length; i<len; i++)
   { dat.txt[i-1]=opts[i].text; dat.val[i-1]=opts[i].value; }
  
  for(var i=0, len=arg.length; i<len; i++)
  {
   dat.boxes[i]=arg[i];
   this.addToHandler( dat.boxes[i], 'onchange', new Function("SelectUnique.scan('boxGroup"+this.groupCount+"',this)") );
  }
  
  this.groupCount++;
  
 },
 
 selectCheck:function(setName, boxIdx, val)
 {
  var boxes=this.data[setName].boxes;
  
  for(var i=0; i <= boxIdx && boxes[i].options[boxes[i].selectedIndex].text!=val; i++) 
  ;
  
  return i<boxIdx+1;
 },
 
 scan:function(setName, changeBox)
 {
  var set=this.data[setName] ;
  
  for(var i=0; i<set.boxes.length && set.boxes[i]!=changeBox; i++)
  ;
  
  for(var currentBoxData, theBox; i<set.boxes.length-1; i++)
   {
    theBox=set.boxes[i+1];
 
    currentBoxData={idx:theBox.selectedIndex, text:theBox.options[theBox.selectedIndex].text||""}
    
    for(var j=0, k=1; j<set.txt.length; j++)
     if(!this.selectCheck(setName, i, set.txt[j]) )
      theBox.options[k++]=new Option(set.txt[j],set.val[j])
    
    while(theBox.options.length > k)
     theBox.options[theBox.options.length-1]=null;
    
    if(currentBoxData.idx>0) 
    {
     for(var ii=0, len=theBox.options.length; ii<len && theBox.options[ii].text!=currentBoxData.text; ii++)
     ;
     theBox.selectedIndex=(ii!=len) ? ii : 0;     
    }
    else
     theBox.selectedIndex=currentBoxData.idx;     
   }  
 },

 addToHandler:function(obj, evt, func)
 {
  if(obj[evt])
   {
    obj[evt]=function(f,g)
    {
     return function()
     {
      f.apply(this,arguments);
      return g.apply(this,arguments);
     };
    }(func, obj[evt]);
   }
   else
    obj[evt]=func;
 }
 
}

/**End of listing**/