/* combobox.js */
 // Usage:
 //  jvhead_addstmt("<script language='JavaScript' src='/jslib/combobox.js' type='text/javascript'></script>");
 //  jvhead_addstmt("<script language='JavaScript' src='/jslib/wddx/wddx.js' type='text/javascript'></script>");
 //
 // Function summary:
 //    combobox_dosubmit
 //    selectUnselectMatchingOptions
 //    selectMatchingOptions
 //    selectOnlyMatchingOptions
 //    unSelectMatchingOptions
 //    sortSelect
 //      after sort, you may wish to reattach ids since they are dropped during sorting...
 //       reapplyids: function(so) {
 //        for (var i=0; i<so.options.length; i++) {
 //          so.options[i].id = so.options[i].value;
 //        }
 //       },
 //    unselectAllOptions
 //    selectAllOptions
 //    moveSelectedOptions
 //    moveOneOptions
 //    addToSelectOptions (see sortSelect note above if sort is true here)
 //    deleSelectedOptions
 //    deleOptions
 //    copySelectedOptions
 //    moveAllOptions
 //    copyAllOptions
 //    swapOptions
 //    moveOptionUp
 //    moveOptionDown
 // ===================================================================
 // Author: Matt Kruse <matt@mattkruse.com>
 // WWW: http://www.mattkruse.com/
 // Extensions by: Frank Koenen <fkoenen@virtualmonet.com>
 //
 // NOTICE: You may use this code for any purpose, commercial or
 // private, without any further permission from the author. You may
 // remove this notice from your final code if you wish, however it is
 // appreciated by the author if at least my web site address is kept.
 //
 // You may *NOT* re-distribute this code in any way except through its
 // use. That means, you can include it in your product, or your web
 // site, or any other form where the code is actually being used. You
 // may not put the plain javascript up on your site for download or
 // include it in your javascript libraries for download. Instead,
 // please just point to my URL to ensure the most up-to-date versions
 // of the files. Thanks.
 // ===================================================================

 // -------------------------------------------------------------------
 //  Use this function on submits to gather selection items into wddx/array
 //  Call this function with two or three arguments: 
 //   1 :== the name of the hidden variable to store the wddx value into.
 //   2 :== the name of the multi-select widget that contains the values.
 //   3 :== only if selected in the list. [default=false]
 //  Also: make sure wddx/wddx.js is included!
 // -------------------------------------------------------------------
function combobox_dosubmit(hidden,selectObj,selected) {

 if ( ! arguments[2] ) selected=false;

 if ( hidden && selectObj ) {
  var myarr = new Array();
  var count=0;
  for ( var i=0;i<selectObj.length;i++ ) {
   if ( ( selected && selectObj[i].selected ) || ! selected ) {
    myarr[count++]= new combobox_wddxobject(selectObj[i].value,selectObj[i].text);
   }
  }

  var MySer = new WddxSerializer();
  hidden.value=MySer.serialize(myarr);
 
  return(true);
 }

}
function combobox_wddxobject(value,text) { this.value=value; this.text=text; }

 // -------------------------------------------------------------------
 // selectUnselectMatchingOptions(select_object,regex,select/unselect,true/false)
 //  This is a general function used by the select functions below, to
 //  avoid code duplication
 // -------------------------------------------------------------------
 function selectUnselectMatchingOptions(obj,regex,which,only) {
         if (window.RegExp) {
                 if (which == "select") {
                         var selected1=true;
                         var selected2=false;
                         }
                 else if (which == "unselect") {
                         var selected1=false;
                         var selected2=true;
                         }
                 else {
                         return;
                         }
                 var re = new RegExp(regex);
                 for (var i=0; i<obj.options.length; i++) {
                         if (re.test(obj.options[i].text)) {
                                 obj.options[i].selected = selected1;
                                 }
                         else {
                                 if (only == true) {
                                         obj.options[i].selected = selected2;
                                         }
                                 }
                         }
                 }
         }
                 
 // -------------------------------------------------------------------
 // selectMatchingOptions(select_object,regex)
 //  This function selects all options that match the regular expression
 //  passed in. Currently-selected options will not be changed.
 // -------------------------------------------------------------------
 function selectMatchingOptions(obj,regex) {
         selectUnselectMatchingOptions(obj,regex,"select",false);
         }
 // -------------------------------------------------------------------
 // selectOnlyMatchingOptions(select_object,regex)
 //  This function selects all options that match the regular expression
 //  passed in. Selected options that don't match will be un-selected.
 // -------------------------------------------------------------------
 function selectOnlyMatchingOptions(obj,regex) {
         selectUnselectMatchingOptions(obj,regex,"select",true);
         }
 // -------------------------------------------------------------------
 // unSelectMatchingOptions(select_object,regex)
 //  This function Unselects all options that match the regular expression
 //  passed in. 
 // -------------------------------------------------------------------
 function unSelectMatchingOptions(obj,regex) {
         selectUnselectMatchingOptions(obj,regex,"unselect",false);
         }
         
 // -------------------------------------------------------------------
 // sortSelect(select_object)
 //   Pass this function a SELECT object and the options will be sorted
 //   by their text (display) values
 // -------------------------------------------------------------------
 function sortSelect(obj) {
         var o = new Array();
         for (var i=0; i<obj.options.length; i++) {
           o[o.length] = new Option( obj.options[i].text, obj.options[i].value, obj.options[i].defaultSelected, obj.options[i].selected) ;
         }

         o = o.sort( 
                 function(a,b) { 
                   if ((a.text+"") < (b.text+"")) { return -1; }
                   if ((a.text+"") > (b.text+"")) { return 1; }
                   return 0;
                 } 
             );

         if ( ! o ) return;
         for (var i=0; i<o.length; i++) {
           obj.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
         }
 }

 // -------------------------------------------------------------------
 // unselectAllOptions(select_object)
 //  This function takes a select box and un-selects all options (in a 
 //  multiple select object).
 // -------------------------------------------------------------------
 function unselectAllOptions(obj) {
         for (var i=0; i<obj.options.length; i++) {
                 obj.options[i].selected = false;
                 }
         }
         
 // -------------------------------------------------------------------
 // selectAllOptions(select_object)
 //  This function takes a select box and selects all options (in a 
 //  multiple select object). This is used when passing values between
 //  two select boxes. Select all options in the right box before 
 //  submitting the form so the values will be sent to the server.
 // -------------------------------------------------------------------
 function selectAllOptions(obj) {
         for (var i=0; i<obj.options.length; i++) {
                 obj.options[i].selected = true;
                 }
         }
         
 // -------------------------------------------------------------------
 // moveSelectedOptions(select_object,select_object[,autosort(true/false)[,regex]])
 //  This function moves options between select boxes. Works best with
 //  multi-select boxes to create the common Windows control effect.
 //  Passes all selected values from the first object to the second
 //  object and re-sorts each box.
 //  If a third argument of 'false' is passed, then the lists are not
 //  sorted after the move.
 //  If a fourth string argument is passed, this will function as a
 //  Regular Expression to match against the TEXT or the options. If 
 //  the text of an option matches the pattern, it will NOT be moved.
 //  It will be treated as an unmoveable option.
 //  You can also put this into the <SELECT> object as follows:
 //    onDblClick="moveSelectedOptions(this,this.form.target)
 //  This way, when the user double-clicks on a value in one box, it
 //  will be transferred to the other (in browsers that support the 
 //  onDblClick() event handler).
 //  this function returns the number of items moved.
 // -------------------------------------------------------------------
 function moveSelectedOptions(from,to) {

         var c=0;

         // Unselect matching options, if required
         if (arguments.length>3) {
             var regex = arguments[3];
             if (regex != "") {
               unSelectMatchingOptions(from,regex);
           }
         }

         // Move them over
         for (var i=0; i<from.options.length; i++) {
           var o = from.options[i];
           if (o.selected) {
             to.options[to.options.length] = new Option( o.text, o.value, false, false);
             c++;
           }
         }

         if ( c > 0 ) {
           // Delete them from original
           for (var i=(from.options.length-1); i>=0; i--) {
               var o = from.options[i];
               if (o.selected) {
                 from.options[i] = null;
             }
           }
           
           if ((arguments.length<3) || (arguments[2]==true)) {
              sortSelect(from);
              sortSelect(to);
           }
           
           from.selectedIndex = -1;
           to.selectedIndex = -1;
         }

         return c;
  }

 // -------------------------------------------------------------------
 // move one item from an option box, to another, given index.
 // -------------------------------------------------------------------
 function moveOneOptions(from,to,index) {
   addToSelectOptions(to,from.options[index].value,from.options[index].text,false);
   from.options[index] = null;
 }

 // -------------------------------------------------------------------
 // addToSelectOptions(select_object,value,text[,autosort(true/false)],[cleanvalues(true/false)])
 //  This function adds items from an options select box.
 // -------------------------------------------------------------------
 function addToSelectOptions(to,value,text,autosort,cleanvalues) {

    if ( typeof(cleanvalues) == 'undefined' ) cleanvalues=true;
    if ( typeof(autosort) == 'undefined' )    autosort=false;

    if ( cleanvalues ) {
     if ( value ) value=value.replace(/ +$/g,'');
     if ( text ) text=text.replace(/ +$/g,'');
     if ( ! text ) text=value;
     if ( text == '' || value == '' ) return;
    }

    // Add
    to.options[to.options.length] = new Option( text, value, false, false);

    if (autosort==true) sortSelect(to);

    to.selectedIndex = -1;

  }

 // -------------------------------------------------------------------
 // deleSelectedOptions(select_object)
 //  This function removes selected items from an options select box. Works best with
 //  onDblClick() event handler.
 //  this function returns the number of items deleted.
 // -------------------------------------------------------------------
 function deleSelectedOptions(from) {

         var c=0;
         // Delete them if they are selected.
         var ll=from.options.length;
         for (var i=(ll-1); i>=0; i--) {
                 var o = from.options[i];
                 if (o.selected) {
                    from.options[i] = null;
                    c++;
                 }
         }
         if ( c > 0 ) from.selectedIndex = -1;
         return c;
  }

 // -------------------------------------------------------------------
 // deleOptions(select_object)
 //  This function removes items from an options select box.
 // -------------------------------------------------------------------
 function deleOptions(from) {

         // Delete them
         var ll=from.options.length;
         for (var i=(ll-1); i>=0; i--) {
           var o = from.options[i];
           from.options[i] = null;
         }
         from.selectedIndex = -1;
  }

 // -------------------------------------------------------------------
 // copySelectedOptions(select_object,select_object[,autosort(true/false)])
 //  This function copies options between select boxes instead of 
 //  moving items. Duplicates in the target list are not allowed.
 // -------------------------------------------------------------------
 function copySelectedOptions(from,to) {
         var options = new Object();
         for (var i=0; i<to.options.length; i++) {
                 options[to.options[i].text] = true;
                 }
         for (var i=0; i<from.options.length; i++) {
                 var o = from.options[i];
                 if (o.selected) {
                         if (options[o.text] == null || options[o.text] == "undefined") {
                                 to.options[to.options.length] = new Option( o.text, o.value, false, false);
                                 }
                         }
                 }
         if ((arguments.length<3) || (arguments[2]==true)) {
                 sortSelect(to);
                 }
         from.selectedIndex = -1;
         to.selectedIndex = -1;
         }

 // -------------------------------------------------------------------
 // moveAllOptions(select_object,select_object[,autosort(true/false)[,regex]])
 //  Move all options from one select box to another.
 // -------------------------------------------------------------------
 function moveAllOptions(from,to) {
         selectAllOptions(from);
         if (arguments.length==2) {
                 moveSelectedOptions(from,to);
                 }
         else if (arguments.length==3) {
                 moveSelectedOptions(from,to,arguments[2]);
                 }
         else if (arguments.length==4) {
                 moveSelectedOptions(from,to,arguments[2],arguments[3]);
                 }
         }

 // -------------------------------------------------------------------
 // copyAllOptions(select_object,select_object[,autosort(true/false)])
 //  Copy all options from one select box to another, instead of
 //  removing items. Duplicates in the target list are not allowed.
 // -------------------------------------------------------------------
 function copyAllOptions(from,to) {
         selectAllOptions(from);
         if (arguments.length==2) {
                 copySelectedOptions(from,to);
                 }
         else if (arguments.length==3) {
                 copySelectedOptions(from,to,arguments[2]);
                 }
         }

 // -------------------------------------------------------------------
 // swapOptions(select_object,option1,option2,[array_of_attributes_to_preserve])
 //  Swap positions of two options in a select list
 // Example: swapOptions(selectorobject,1,2,['Xcustom','style']);
 // -------------------------------------------------------------------
 function swapOptions(obj,i,j,preserveattributes) {
         var o = obj.options;
         var i_selected = o[i].selected;
         var j_selected = o[j].selected;

         if ( preserveattributes ) {
          var obji=new Object();
          var objj=new Object();
          for(var n=0;n<preserveattributes.length;n++){
           obji[preserveattributes[n]]=o[i].getAttribute(preserveattributes[n]);
           objj[preserveattributes[n]]=o[j].getAttribute(preserveattributes[n]);
          }
         }

         var temp = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
         var temp2= new Option(o[j].text, o[j].value, o[j].defaultSelected, o[j].selected);
         o[i] = temp2;
         o[j] = temp;
         o[i].selected = j_selected;
         o[j].selected = i_selected;

         if ( preserveattributes ) {
          for(var n=0;n<preserveattributes.length;n++){
           o[i].setAttribute(preserveattributes[n],objj[preserveattributes[n]]);
           o[j].setAttribute(preserveattributes[n],obji[preserveattributes[n]]);
          }
         }
 }
         
 // -------------------------------------------------------------------
 // moveOptionUp(select_object,[array_of_attributes_to_preserve])
 //  Move *selected* option in a select list up one
 // Example: moveOptionUp(selectorobject,['Xcustom','style']);
 // -------------------------------------------------------------------
 function moveOptionUp(obj,preserveattributes) {
         // If > 1 option selected, do nothing
         var selectedCount=0;
         for (i=0; i<obj.options.length; i++) {
                 if (obj.options[i].selected) {
                         selectedCount++;
                         }
                 }
         if (selectedCount > 1) {
                 return;
                 }
         // If this is the first item in the list, do nothing
         var i = obj.selectedIndex;
         if (i == 0) {
                 return;
                 }
         swapOptions(obj,i,i-1,preserveattributes);
         obj.options[i-1].selected = true;
         }

 // -------------------------------------------------------------------
 // moveOptionDown(select_object,[array_of_attributes_to_preserve])
 //  Move *selected* option in a select list down one
 // Example: moveOptionDown(selectorobject,['Xcustom','style']);
 // -------------------------------------------------------------------
 function moveOptionDown(obj,preserveattributes) {
         // If > 1 option selected, do nothing
         var selectedCount=0;
         for (i=0; i<obj.options.length; i++) {
                 if (obj.options[i].selected) {
                         selectedCount++;
                         }
                 }
         if (selectedCount > 1) {
                 return;
                 }
         // If this is the last item in the list, do nothing
         var i = obj.selectedIndex;
         if (i == (obj.options.length-1)) {
                 return;
                 }
         swapOptions(obj,i,i+1,preserveattributes);
         obj.options[i+1].selected = true;
         }
