admin管理员组

文章数量:1133929

I'm trying to understand sorting option elements within a select element alphabetically. Ideally, I'd like to have this as a separate function where I can just pass in the select element since it needs to be sorted when the user clicks some buttons.

I've searched high and low for a good way of doing this, but haven't been able to find anything that worked for me.

The option elements should be sorted alphabetically by text, not value.

Is this possible in some way?

I'm trying to understand sorting option elements within a select element alphabetically. Ideally, I'd like to have this as a separate function where I can just pass in the select element since it needs to be sorted when the user clicks some buttons.

I've searched high and low for a good way of doing this, but haven't been able to find anything that worked for me.

The option elements should be sorted alphabetically by text, not value.

Is this possible in some way?

Share Improve this question edited Aug 25, 2017 at 16:48 reformed 4,78012 gold badges66 silver badges93 bronze badges asked Aug 22, 2012 at 12:33 bomortensenbomortensen 3,39610 gold badges57 silver badges77 bronze badges 4
  • So basically you want to give a selector and order all of his children alphabetically by the text they contain ? – pkurek Commented Aug 22, 2012 at 12:37
  • I think you should view this topic: stackoverflow.com/questions/1134976/… – kaz Commented Aug 22, 2012 at 12:37
  • @pkurek: In all it's simplicity, yes :-) kaz: Yeah, I've fooled around with that snippet, but simply can't get it to work :-/ Wondered if there were any other way to do it. – bomortensen Commented Aug 22, 2012 at 12:39
  • @bomortensen: All solutions will be essentially similar. This answer is as easy as it can get. – Felix Kling Commented Aug 22, 2012 at 12:56
Add a comment  | 

11 Answers 11

Reset to default 138

What I'd do is:

  1. Extract the text and value of each <option> into an array of objects;
  2. Sort the array;
  3. Update the <option> elements with the array contents in order.

To do that with jQuery, you could do this:

var options = $('select.whatever option');
var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();
arr.sort(function(o1, o2) { return o1.t > o2.t ? 1 : o1.t < o2.t ? -1 : 0; });
options.each(function(i, o) {
  o.value = arr[i].v;
  $(o).text(arr[i].t);
});

Here is a working jsfiddle.

edit — If you want to sort such that you ignore alphabetic case, you can use the JavaScript .toUpperCase() or .toLowerCase() functions before comparing:

arr.sort(function(o1, o2) {
  var t1 = o1.t.toLowerCase(), t2 = o2.t.toLowerCase();

  return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
});

Accepted answer is not the best in all cases because sometimes you want to perserve classes of options and different arguments (for example data-foo).

My solution is:

var sel = $('#select_id');
var selected = sel.val(); // cache selected value, before reordering
var opts_list = sel.find('option');
opts_list.sort(function(a, b) { return $(a).text() > $(b).text() ? 1 : -1; });
sel.html('').append(opts_list);
sel.val(selected); // set cached selected value

//For ie11 or those who get a blank options, replace html('') empty()

html:

<select id="list">
    <option value="op3">option 3</option>
    <option value="op1">option 1</option>
    <option value="op2">option 2</option>
</select>

jQuery:

var options = $("#list option");                    // Collect options         
options.detach().sort(function(a,b) {               // Detach from select, then Sort
    var at = $(a).text();
    var bt = $(b).text();         
    return (at > bt)?1:((at < bt)?-1:0);            // Tell the sort function how to order
});
options.appendTo("#list");                          // Re-attach to select

I used tracevipin's solution, which worked fantastically. I provide a slightly modified version here for anyone like me who likes to find easily readable code, and compress it after it's understood. I've also used .detach instead of .remove to preserve any bindings on the option DOM elements.

<select id="mSelect" >
    <option value="val1" > DEF </option>
    <option value="val4" > GRT </option>
    <option value="val2" > ABC </option>
    <option value="val3" > OPL </option>
    <option value="val5" > AWS </option>
    <option value="val9" > BTY </option>
</select>

.

$("#mSelect").append($("#mSelect option").remove().sort(function(a, b) {
    var at = $(a).text(), bt = $(b).text();
    return (at > bt)?1:((at < bt)?-1:0);
}));

I know this topic is old but I think my answer can be useful for a lot of people.

Here is jQuery plugin made from Pointy's answer using ES6:

/**
 * Sort values alphabetically in select
 * source: http://stackoverflow.com/questions/12073270/sorting-options-elements-alphabetically-using-jquery
 */
$.fn.extend({
    sortSelect() {
        let options = this.find("option"),
            arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();

        arr.sort((o1, o2) => { // sort select
            let t1 = o1.t.toLowerCase(), 
                t2 = o2.t.toLowerCase();
            return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
        });

        options.each((i, o) => {
            o.value = arr[i].v;
            $(o).text(arr[i].t);
        });
    }
});

Use is very easy

$("select").sortSelect();

Here's my improved version of Pointy's solution:

function sortSelectOptions(selector, skip_first) {
    var options = (skip_first) ? $(selector + ' option:not(:first)') : $(selector + ' option');
    var arr = options.map(function(_, o) { return { t: $(o).text(), v: o.value, s: $(o).prop('selected') }; }).get();
    arr.sort(function(o1, o2) {
      var t1 = o1.t.toLowerCase(), t2 = o2.t.toLowerCase();
      return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
    }); 
    options.each(function(i, o) {
        o.value = arr[i].v;
        $(o).text(arr[i].t);
        if (arr[i].s) {
            $(o).attr('selected', 'selected').prop('selected', true);
        } else {
            $(o).removeAttr('selected');
            $(o).prop('selected', false);
        }
    }); 
}

The function has the skip_first parameter, which is useful when you want to keep the first option on top, e.g. when it's "choose below:".

It also keeps track of the previously selected option.

Example usage:

jQuery(document).ready(function($) {

  sortSelectOptions('#select-id', true);

});

None of the answers worked for me. For some strange reason, when looping through the options, each option returns nothing when text() is called. Instead, I was forced to retrieve the option's label via attr('label')

/**
 * Sort the options of the target select list
 * alphabetically by label. For some reason, when
 * we call detach(), the returned options have no
 * text() and instead we're forced to get the option's
 * label via the 'label' attribute.
 * @param select jQuery selector
 */
function sort_multi_select(select) {
    var options = select.find('option');
    options.detach().sort(function (a, b) {
        var at = $(a).attr('label'), //label, not text()
            bt = $(b).attr('label');
        return at > bt ? 1 : at < bt ? -1 : 0;
    });
    options.appendTo(select);
}

//example
sort_multi_select($('#my_select'));

I combined parts from marxin's and kuxa's excellent answers to create a jQuery custom function that

  1. sorts the options by their text values (case-insensitive),

  2. maintains any already-selected value, and

  3. returns the original jQuery objects against which the function is executed:

    $.fn.extend({
        sortSelect() {
            return this.each(function(){
                let $this = $(this),
                    original_selection = $this.val(),
                    $options = $this.find('option'),
                    arr = $options.map(function(_, o) { return { t: $(o).text(), v: o.value }; }).get();
    
                arr.sort((o1, o2) => {
                    // sort select
                    let t1 = o1.t.toLowerCase(), 
                        t2 = o2.t.toLowerCase();
                    return t1 > t2 ? 1 : t1 < t2 ? -1 : 0;
                });
    
                $options.each((i, o) => {
                    o.value = arr[i].v;
                    $(o).text(arr[i].t);
                });
    
                $this.val(original_selection); 
            })
        }
    });
    

Working example on jsFiddle is available at https://jsfiddle.net/jhfrench/64och25e/.

Yes you can sort the options by its text and append it back to the select box.

 function NASort(a, b) {    
      if (a.innerHTML == 'NA') {
          return 1;   
      }
      else if (b.innerHTML == 'NA') {
          return -1;   
      }       
      return (a.innerHTML > b.innerHTML) ? 1 : -1;
  };

Fiddle: https://jsfiddle.net/vaishali_ravisankar/5zfohf6v/

Malakgeorge answer is nice an can be easily wrapped into a jQuery function:

$.fn.sortSelectByText = function(){
    this.each(function(){
        var selected = $(this).val(); 
        var opts_list = $(this).find('option');
        opts_list.sort(function(a, b) { return $(a).text() > $(b).text() ? 1 : -1; });
        $(this).html('').append(opts_list);
        $(this).val(selected); 
    })
    return this;        
}

The jquery.selectboxes.js plugin has a sort method. You can implement the plugin, or dive into the code to see a way to sort the options.

本文标签: javascriptSorting options elements alphabetically using jQueryStack Overflow