1

I have 2 listboxes and when a button is pressed I need to move an option from one to another.

I did this:

HTML

<table border="1" cellpadding="5">
    <tr>
        <td> Un-Selected <br />
            <select multiple="multiple" id="selectBoxOne" size="5" class="selectListBox">
                <option value="0" id="multiple0">Option 0</option>
                <option value="1" id="multiple1">Option 1</option>
                <option value="2" id="multiple2">Option 2</option>
                <option value="3" id="multiple3">Option 3</option>
                <option value="4" id="multiple4">Option 4</option>
                <option value="5" id="multiple5">Option 5</option>
            </select>
            <br />
            <input type="checkbox" id="selectAllFirst" />Select All or Ctrl+Click
        </td>
        <td>
            <div onclick="move('left');">
                << </div>
                    <div onclick="move('right');"> >></div>
        </td>
        <td> Selected <br />
            <select name="policyCode" multiple="multiple" id="selectBoxSecond" size="5" class="selectListBox"></select>
            <br />
            <input type="checkbox" id="selectAllSecond" />Select All or Ctrl+Click
        </td>
    </tr>
</table>

javascript:

// Declare elements

var selectOptions = Array();
selectOptions[0] = "Option 0";
selectOptions[1] = "Option 1";
selectOptions[2] = "Option 2";
selectOptions[3] = "Option 3";
selectOptions[4] = "Option 4";
selectOptions[5] = "Option 5";

// function to move an element from a box to the other
function move(sens)
{               
    if (sens == "right")
    {
        var selObj = document.getElementById('selectBoxOne');    
        var chkAll = document.getElementById("selectAllFirst")
        var destination = document.getElementById("selectBoxSecond");
    }
    else
    {
        var selObj = document.getElementById('selectBoxSecond');    
        var chkAll = document.getElementById("selectAllSecond")
        var destination = document.getElementById("selectBoxOne");
    }
    var selectedArray = new Array();        
    var i;
    var count = 0;
    if (chkAll.checked == 1)
    {
        for (i = 0; i<selectOptions.length; i++)
        {
            selectedArray[i] = i;
        }
    }
    else
    {            
        for (i=0; i<selObj.options.length; i++) {
            if (selObj.options[i].selected) {
                selectedArray[count] = selObj.options[i].value;
            count++;
            }
        }            
    }
    
    for (i = 0; i < selectedArray.length; i++)
    {
        var optionTag = document.createElement("option");
        id = selectedArray[i];
        optionTag.innerHTML = selectOptions[id];
        optionTag.value = id;
        optionTag.id = "multiple"+id;
        destination.appendChild(optionTag);
        var rmv = document.getElementById("multiple"+id);
        rmv.parentNode.removeChild(rmv);
    }
}

Now: The script works great from moving from left box to the right box. But when I try the other way around it kind of crashes. No error returned but I know for sure is the removal part (if I comment it it works fine... except that it generates duplicates since there is no removal of the moved option).

To be more specific, this 2 lines: var rmv = document.getElementById("multiple"+id); rmv.parentNode.removeChild(rmv);

Since there is no error returned, I don't know how to fix this.

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
zozo
  • 8,230
  • 19
  • 79
  • 134
  • Q: Have you tried putting your "remove" in a second loop: don't remove anything until you've finished adding, first? – paulsm4 Aug 08 '11 at 06:46

2 Answers2

6

That's a very long winded way of doing things! :-)

You can move an option from one select to another simply by assigning it as a child of the other select, e.g.

function move(sens) {

  var i, sourceSel, targetSel; 

  if (sens == 'right') {
    sourceSel = document.getElementById('selectBoxOne'); 
    targetSel = document.getElementById('selectBoxSecond');
  } else {
    sourceSel = document.getElementById('selectBoxSecond'); 
    targetSel = document.getElementById('selectBoxOne');
  }

  i = sourceSel.options.length;
  while (i--) {
    if (sourceSel.options[i].selected) {
      targetSel.appendChild(sourceSel.options[i]);
    }
  }
}

will move all the selected options from one to the other. Note that the while loop goes backwards because the options collection is a live NodeList, so as you remove options is shortens the collection. If you go forwards through it you need to update the index and length as you go (so going backward is simpler).

You may want to include some kind of ordering or sorting (e.g. by value or text).

I guess if the selectAll checkbox is checked you'll just move them all, or (preferably) you could use a click listener to select/deselect all the appropriate optoins when it's clicked independent of the move function.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • I have done my implementation using your sample code but when i try to save my changes the page does a postback and i get the following exception: "Invalid postback or callback argument. Event validation is enabled using ''". How can i work around that?. – StackTrace Apr 08 '22 at 08:22
  • @StackTrace—post a question. – RobG Apr 08 '22 at 12:40
  • @RobB I have already posted it here https://stackoverflow.com/questions/71783620/invalid-postback-or-callback-argument-event-validation-is-enabled-using-pages-e – StackTrace Apr 11 '22 at 05:28
  • @StackTrace—different problem. Get a .NET expert. – RobG Apr 11 '22 at 11:25
1

An id has to be unique, or it won't work properly. As you add the new option before removing the original, you get two options with the same id, and you won't find the original option when you want to remove it.

Just swap these three lines around, so that you remove the option before adding the new one. From this:

destination.appendChild(optionTag);
var rmv = document.getElementById("multiple"+id);
rmv.parentNode.removeChild(rmv);

to this:

var rmv = document.getElementById("multiple"+id);
rmv.parentNode.removeChild(rmv);
destination.appendChild(optionTag);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005