I like this component, but I feel it needs to sort the dual listbox contents as items shift between the two, so I'm including a patched version of the JavaScript:
function SortList(listname) { var $r = $(listname + ' option'); $r.sort(function(a, b) { // return (a.value < b.value) ? -1 : (a.value > b.value) ? 1 : 0; // if you do not have value attribute for option use the text value. Replace the above line of code with the one below. return (a.text < b.text) ? -1 : (a.text > b.text) ? 1 : 0; }); $($r).remove(); $(listname).append($($r)); } function triggerTransferClick(sourceListBox, targetListBox, hidenListBox, isLeft2right, nothingToMoveMessage) { var selectedOpts = $('#' + $(sourceListBox).attr('id') + ' option:selected'); if (selectedOpts.length == 0) { alert(nothingToMoveMessage); } else { $(targetListBox).append($(selectedOpts).clone()); $('#' + $(sourceListBox).attr('id') + ' option:selected').each(function() { var value = $(this).val(); $('#' + $(hidenListBox).attr('id') + ' option').each(function() { if ($(this).val() == value) { if (isLeft2right) $(this).attr('selected', 'selected'); else $(this).removeAttr('selected'); } }); }); $(selectedOpts).remove(); if ($('.filter').val() != '' && $('#' + $(sourceListBox).attr('id') + ' option:visible').length == 0) { $('.filter').val(''); if (isLeft2right) { doFilter($(sourceListBox), ''); //SortList($(sourceListBox)); } else { doFilter($(targetListBox), ''); //SortList($(targetListBox)); } } SortList('#" + ListBoxId1 + "'); SortList('#" + ListBoxId2 + "'); } } function doFilter(listBox, filterText) { var count = 0; $('#' + listBox.attr('id') + ' option').each(function () { if ($(this).text().search(new RegExp(filterText, 'i')) < 0) { $(this).hide(); } else { $(this).show(); count++; } }); $('#' + listBox.attr('id') + ' option:visible').first().attr('selected', 'selected'); return count; } $(document).ready(function() { var nothingToMoveMessage = '"+NothingToMoveMessage+"'; var listBox1 = $('#" + ListBoxId1 + "'); var listBox1Id = $('#" + ListBoxId1 + "').attr('id'); var listBox2 = $('#" + ListBoxId2 + "'); var listBox2Id = $('#" + ListBoxId2 + "').attr('id'); var listBox3 = $('#"+ListBoxId1+"_"+ListBoxId2+"'); var listBox3Id = $('#"+ListBoxId1+"_"+ListBoxId2+"').attr('id'); var arrow = {left: 37, up: 38, right: 39, down: 40 }; $(listBox2).hide(); $('#' + listBox1Id + ' option:selected').remove(); $(listBox3).append($('#' + listBox2Id + ' option:selected').clone()); $('#' + listBox3Id + ' option').each(function() { if ($(this).attr('selected') == 'selected') $(this).removeAttr('selected'); else $(this).hide(); }); $(listBox3).attr('style', $(listBox1).attr('style')).addClass($(listBox1).attr('class')); $('.filter').keyup(function () { var filterText = $(this).val(); var count = doFilter($(this).parent().find('select:visible'), filterText); $('#filter-count').text(count); }); $('.btnRight').click(function (e) { triggerTransferClick(listBox1, listBox3, listBox2, true, nothingToMoveMessage); e.preventDefault(); }); $(document).on('dblclick', '#' + listBox1Id + ' option', function(e) { triggerTransferClick(listBox1, listBox3, listBox2, true, nothingToMoveMessage); e.preventDefault(); }); $('.btnAllRight').click(function (e) { $('#' + listBox1Id + ' option').attr('selected', 'selected'); triggerTransferClick(listBox1, listBox3, listBox2, true, nothingToMoveMessage); e.preventDefault(); }); $('.btnLeft').click(function (e) { triggerTransferClick(listBox3, listBox1, listBox2, false, nothingToMoveMessage); e.preventDefault(); }); $(document).on('dblclick', '#' + listBox3Id + ' option', function(e) { triggerTransferClick(listBox3, listBox1, listBox2, false, nothingToMoveMessage); e.preventDefault(); }); $('.btnAllLeft').click(function (e) { $('#' + listBox3Id + ' option').attr('selected', 'selected'); triggerTransferClick(listBox3, listBox1, listBox2, false, nothingToMoveMessage); e.preventDefault(); }); $(listBox1).keydown(function (e) { var keyCode = e.keyCode || e.which; if (keyCode == arrow.right) triggerTransferClick(listBox1, listBox3, listBox2, true, nothingToMoveMessage); }); $(listBox3).keydown(function (e) { var keyCode = e.keyCode || e.which; if (keyCode == arrow.left) triggerTransferClick(listBox3, listBox1, listBox2, false, nothingToMoveMessage); }); });
Thank you very much James. I just uploaded a new version of the component with your contribution.