Charl van Niekerk » Blog

Main

Latest

Archives

Powered by Blogger

Two Boxes Select Script

Shit I have no idea what you call this! So I just made up a name "two boxes select". Basically, it's where you have two select boxes and two buttons to click on to move items between these two boxes.

Anyway there are quite a few scripts to do things like this around the web but unfortunately they all seem to suck feature-wise. Here is a script I just found the other day, it's actually something I cooked up months back; unfortunately it makes use of jQuery which sucks still I feel I should rather post it in case somebody can find some use for it. The HTML (5):

<!DOCTYPE HTML>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>Dual Select Boxes Demo</title>
  <link rel="stylesheet" type="text/css" href="select.css">
  <script type="application/javascript" src="jquery.js"></script>
  <script type="application/javascript" src="select.js"></script>
 </head>
 <body>
  <div id="foodselect">
   <select name="food-no" multiple="multiple" ondblclick="moveOption('food-no', 'food-yes')">
    <optgroup label="Fruit">
     <option value="1">Apples</option>
     <option value="2">Bananas</option>
     <option value="3">Oranges</option>
     <option value="4">Pears</option>
    </optgroup>
    <optgroup label="Salads">
     <option value="9">Carrot</option>
     <option value="10">Greek</option>
     <option value="11">Italian</option>
     <option value="12">Potato</option>
    </optgroup>
    <optgroup label="Vegetables">
     <option value="5">Broccoli</option>
     <option value="6">Carrots</option>
     <option value="7">Potatoes</option>
     <option value="8">Spinach</option>
    </optgroup>
    <option value="13">Dutch Cheese</option>
    <option value="14">Fries</option>
    <option value="15">German Sausage</option>
    <option value="16">Lasagna</option>
   </select>
   <button onclick="moveOption('food-yes', 'food-no')">&lt;</button>
   <button onclick="moveOption('food-no', 'food-yes')">&gt;</button>
   <select name="food-yes" multiple="multiple" ondblclick="moveOption('food-yes', 'food-no')"></select>
  </div>
 </body>
</html>

Then, the CSS:

#foodselect {
 margin: 40px auto;
 width: 520px;
}
select {
 float: left;
 margin: 0 5px;
 width: 200px;
 height: 400px;
}
button {
 float: left;
 margin: 180px 5px 0 5px;
}

And finally the JavaScript:

function moveOptionCheck(option, jFrom, jTo) {
 if (option.selected) {
  var jOption = $(option);
  var jFromOptgroup = jOption.parent("optgroup");
  var jToOptgroup;
  if (jFromOptgroup.length > 0) {
   var label = jFromOptgroup.attr("label");
   jToOptgroup = jTo.children("optgroup[label='" + label + "']");
   if (jToOptgroup.length == 0) {
    var found = false;
    var jToOptgroups = jTo.children("optgroup");
    if (jToOptgroups.length > 0) {
     var last;
     jToOptgroups.each(function() {
      if (!found) {
       var jThis = $(this);
       if (jThis.attr("label") > label) {
        jThis.before("<optgroup label='" + label + "'></optgroup>");
        found = true;
       }
      }
      last = jThis;
     });
     if (!found) {
      last.after("<optgroup label='" + label + "'></optgroup>");
     }
    } else if (!found) {
     jTo.prepend("<optgroup label='" + label + "'></optgroup>");
    }
    jToOptgroup = jTo.children("optgroup[label='" + label + "']");
   }
  } else {
   jToOptgroup = jTo;
  }
  var jToOptions = jToOptgroup.children("option");
  var found = false;
  if (jToOptions.length > 0) {
   jToOptions.each(function() {
    if (!found) {
     var jThis = $(this);
     if (jThis.text() > jOption.text()) {
      jThis.before("<option value='" + jOption.val() + "'>" + jOption.text() + "</option>");
      jOption.remove();
      found = true;
     }
    }
   });
  }
  if (!found) {
   jOption.appendTo(jToOptgroup);
  }
  if (jFromOptgroup.children("option").length == 0) {
   jFromOptgroup.remove();
  }
 }
}
function moveOption(fromName, toName) {
 var jFrom = $("select[name='" + fromName + "']");
 var jTo = $("select[name='" + toName + "']");
 jFrom.children("option").each(function(){moveOptionCheck(this, jFrom, jTo);});
 jFrom.children("optgroup").children("option").each(function(){moveOptionCheck(this, jFrom, jTo);});
 jFrom.each(function(){this.selectedIndex = -1;});
 jTo.each(function(){this.selectedIndex = -1;});
}

This was work in progress and I never got time to completely finish this off and document it nicely but I hope it'll at least save somebody some time. It is quite powerful, it handles option groups, it sorts both the option groups and all the items, you can move multiple items in one go, etc.

3 Comments

Comment by Blogger gravyfries on Thursday, May 22, 2008 9:31:00 PM

I have been looking everywhere for this script (that can handle optgroups). unfortunately, I can't get it to work in ie.

works fine in firefox...

Comment by Blogger Corey Coto on Tuesday, June 10, 2008 6:10:00 PM

Found a solution for IE. This has only been tested in IE7 and FF2.


Find the last child of the optgroup (this should be the last option added to the optgroup) and set the text.

Example:
$(optgroup).find('option:last-child').text(value);

Comment by Blogger Charl van Niekerk on Tuesday, June 10, 2008 9:09:00 PM

Thanks for posting the solution corey! :)

Post a Comment

Copyright © 2004-2008 Charl van Niekerk. All articles are released under the Creative Commons Attribution 2.5 South Africa licence, unless where otherwise stated.