Basically, you need to pull the <option>
s out of the target <select>
, add the option to that array, sort it by hand, and then replace the target <select>
s <option>
s with the sorted list. jQuery doesn't help that much with this sort of thing but the low level DOM version isn't terribly difficult, something like this:
exc = $('#geo_country_exclude')[0]
inc = $('#geo_country_include')[0]
by_option_value = (a, b) ->
return +1 if(a.value > b.value)
return -1 if(a.value < b.value)
return 0
mv = (from, to) ->
# to.options looks like an array and smells like an array but
# it isn't an array so we employ the standard arrayification trick.
opts = [].slice.call(to.options)
# Move the <option>
opts.push(from.options[from.selectedIndex])
from.remove(from.selectedIndex)
# Sort and replace.
to.remove(0) for i in [ 0 ... to.options.length ]
to.add(opt) for opt in opts.sort(by_option_value)
$('#add' ).click (event) -> mv(exc, inc)
$('#remove').click (event) -> mv(inc, exc)
You might need to tweak the by_option_value
comparison function and you might want to adjust the selected items in the <select>
s after the move but you can sort that you easily enough.
Demo: http://jsfiddle.net/ambiguous/qRw3K/
If you need to deal with multi-selects then a minor modification to mv
will do the trick:
mv = (from, to) ->
opts = [].slice.call(to.options)
while from.selectedIndex >= 0
opts.push(from.options[from.selectedIndex])
from.remove(from.selectedIndex)
to.remove(0) for i in [ 0 ... to.options.length ]
to.add(opt) for opt in opts.sort(by_option_value)
You just need to wrap the opts.push
and from.remove
in a little while
loop.
Demo: http://jsfiddle.net/ambiguous/qRw3K/1/