I got a select element, with multiple items. I'm supposed to place the values that start with '_' at the beginning of the list, ordered alphabetically. I tried doing it with the unshift() JavaScript method but it didn't work. is there any other way to do this?
html:
<select multiple="multiple">
<option>_c</option>
<option>b</option>
<option>_v</option>
<option>a</option>
</select>
script:
$(document).ready(function() {
var a = [];
$('option').each(function() {
a.push($(this).text());
});
$('option').each(function() {
var v = $(this).text();
var s = v.substring(0,1);
if (s == '_') {
a.unshift($(this).text());
}
});
a.sort();
for (i = 0; i < a.length; i++) {
$('option').eq(i).text(a[i]);
}
});
it outputs the following:
_c
_c
_v
_v
as you can see, it scrambles all values and losts reference to the ones without '_'.
Alphabetically speaking, the underscore already has precedence over other characters, and will be automatically placed in front using a common .sort()
method, so this would give you the correct order:
var a = []; $('option').each(function() { a.push($(this).text()); }); a = a.sort(); for (i = 0; i < a.length; i++) { $('option').eq(i).text(a[i]); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <select multiple="multiple"> <option>_c</option> <option>b</option> <option>_v</option> <option>a</option> </select>
EDIT
As discussed below, it may be better to re-order the elements, not just the values inside them. Also, there's room for improvement on the loops. So, here it goes a fancy way to solve your issue:
OBS: JQuery's .sort()
is not yet officially supported.
var select = $("select"); var opts = select.children("option"); select.append(opts.sort(function(a, b) { return $(a).text() > $(b).text(); }));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <select multiple="multiple"> <option>_c</option> <option>b</option> <option>_v</option> <option>a</option> </select>
Look the example http://jsfiddle.net/68t3x7hy/
var a = [];
$('option').each(function() {
a.push($(this).text());
});
a.sort();
for (i = 0; i < a.length; i++) {
$('option').eq(i).text(a[i]);
}
As @Barmar said, .sort do the work for you!
Based on this plugin from this blog article , and so long as your options are all lower case:
jQuery.fn.mysort = function() {
return this.pushStack( [].sort.apply( this, arguments ), []);
};
NB: although there's already a $.fn.sort
method it's not supposed to be used outside of the library.
$('option').mysort(function(a, b) {
var sa = $(a).text();
var sb = $(b).text();
return (sa < sb) ? -1 : (sa > sb) ? 1 : 0;
}).appendTo('select');
This extracts the option
tags, sorts the elements by their contents, and then simply reappends them to the select
element in the new order.
Using .map()
. As stated before, .sort()
will do everything for your in this case.
var a = $('option').map(function() { return this.outerHTML; }).get().sort(); $('select').html(a.join(','))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <select multiple="multiple"> <option>_c</option> <option>b</option> <option>_v</option> <option>a</option> <option>c</option> <option>_a</option> </select>
I think this is a clean solution:
var $select = $('select');
$select.children().sort(function(a, b) {
return a.innerHTML > b.innerHTML;
}).appendTo($select);
UPDATE
And if you don't want to use $.fn.sort
(because it should be only used internally) you can do the following:
$($select.children().get().sort(function(a, b) {
return a.innerHTML > b.innerHTML;
})).appendTo($select);
For a more compact version of LcSalazar's answer:
var $o = $('option');
var a = $o.map(function() { return $(this).text() }).get().sort();
$o.text(function(n) { return a[n] } );
As with his answer, this has the potentially undesirable behaviour that it leaves the elements in place but shuffles their text values.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.