简体   繁体   中英

placing items at the beginning of an array

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.

See http://jsfiddle.net/alnitak/L7ut14ok/

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);

jsfiddle-example

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM