Sortieren von Optionselementen alphabetisch mit jQuery


78

Ich versuche, das Sortieren von optionElementen innerhalb eines selectElements alphabetisch zu verstehen . Idealerweise möchte ich dies als separate Funktion haben, bei der ich das Auswahlelement einfach übergeben kann, da es sortiert werden muss, wenn der Benutzer auf einige Schaltflächen klickt.

Ich habe hoch und niedrig nach einem guten Weg gesucht, aber ich konnte nichts finden, was für mich funktioniert hat.

Die Optionselemente sollten alphabetisch nach Text und nicht nach Wert sortiert sein.

Ist das irgendwie möglich?


Sie möchten also im Grunde einen Selektor geben und alle seine Kinder alphabetisch nach dem darin enthaltenen Text sortieren?
pkurek

Ich denke, Sie sollten dieses Thema anzeigen
kaz

@pkurek: In aller Einfachheit, ja :-) kaz: Ja, ich habe mit diesem Snippet herumgespielt, kann es aber einfach nicht zum Laufen bringen: - / Ich habe mich gefragt, ob es einen anderen Weg gibt, es zu tun.
Bomortensen

@bomortensen: Alle Lösungen werden im Wesentlichen ähnlich sein. Diese Antwort ist so einfach wie möglich.
Felix Kling

Antworten:


122

Was ich tun würde ist:

  1. Extrahieren Sie den Text und den Wert jedes <option>Objekts in ein Array von Objekten.
  2. Sortieren Sie das Array.
  3. Aktualisieren Sie die <option>Elemente mit dem Array-Inhalt der Reihe nach.

Um dies mit jQuery zu tun, können Sie Folgendes tun:

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

Hier ist eine funktionierende jsfiddle.

Bearbeiten - Wenn Sie so sortieren möchten, dass Sie die alphabetische Groß- und Kleinschreibung ignorieren, können Sie vor dem Vergleich JavaScript .toUpperCase()oder .toLowerCase()Funktionen verwenden:

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

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

Das hat es für mich getan! Musste nur alle> und <Checks in Großbuchstaben machen :-) Vielen Dank !!
Bomortensen

Ah OK richtig, wenn Sie den alphabetischen Fall ignorieren möchten, dann ja. Ich bin froh, dass es funktioniert hat!
Pointy

ja, weil JS beim Sortieren Großbuchstaben höher wiegt als Kleinbuchstaben .. so scheint es ;-) Nochmals vielen Dank, funktioniert wie ein Zauber!
Bomortensen

6
Vielen Dank für diese Antwort - mein Problem fast vollständig gelöst. Ich musste es nur erweitern, um die Verfolgung der ausgewählten Option zu berücksichtigen. Für die arr options.map habe ich "s: $ (o) .attr ('selected')" hinzugefügt und dann in options.each nur Folgendes hinzugefügt: $ (o) .attr ('selected', arr [i] .s); Vielen Dank!
Alexanderle

3
Hier ist der geänderte Code, um sich an die aktuell ausgewählte Option zu erinnern: jsfiddle.net/trELD/700
Jamie Barker

59

Die akzeptierte Antwort ist nicht in allen Fällen die beste, da Sie manchmal Klassen von Optionen und verschiedene Argumente (z. B. data-foo) beibehalten möchten.

Meine Lösung ist:

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

// Für ie11 oder diejenigen, die leere Optionen erhalten, ersetzen Sie html ('') empty ()


4
Beste Antwort. Das ist mein Fall. Ich muss Optionsdaten attrs behalten
Vitor Almeida

Einfache und vereinfachte Antwort.
UdayKiran Pulipati

3
In der letzten Zeile können Sie sel.html (''). Append (opts_list) in einfach sel.html (opts_list)
ändern

1
Es sollte beachtet werden, dass es in (11) nicht funktioniert: Die Optionen verlieren ihre Beschriftung. Die browserübergreifendste Lösung, die ich gefunden habe, ist eine jquery-freie .
Cethy

Dies sollte die ausgewählte Antwort sein! Dies ist viel einfacher als oben und behält alle Klassen oder Datenattribute bei.
Greg Blass

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

2
$("#mSelect").append($options);sollte ausreichen :)
Felix Kling

Der Rückruf an .sort()sollte eine Zahl zurückgeben, die kleiner als Null, Null oder größer ist, um die Ordnungsbeziehung widerzuspiegeln. Die Rückgabe eines Booleschen Werts funktioniert meiner Meinung nach nicht richtig.
Pointy

5
Ich ging mit dem oben Gesagten um und änderte mich zu: var at = $ (a) .text (). ToLowerCase (), bt = $ (b) .text (). ToLowerCase (); um den Sortierfall unabhängig zu machen
JayCrossler

26

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

Ich habe Tracevipins Lösung verwendet, die fantastisch funktioniert hat. Ich biete hier eine leicht modifizierte Version für alle wie mich an, die leicht lesbaren Code finden und komprimieren möchten, nachdem er verstanden wurde. Ich habe auch verwendet, .detachanstatt .removeBindungen für die Option DOM-Elemente beizubehalten.


Arbeitete perfekt für mich
Julio Popócatl

Dies ist die beste IMO-Lösung und sehr ähnlich zu dem, was ich veröffentlichen wollte, da der Status der Elemente erhalten bleibt (auch bei Mehrfachauswahl).
Kris Oye

Funktioniert auch bei mir perfekt.
Hughsie28

3
fast perfekt, aber Chrome und Firefox zeigen die letzte Option als ausgewählt an.
Cristiano Maia

6

Hier ist meine verbesserte Version von Pointys Lösung :

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

Die Funktion verfügt über den skip_firstParameter, der nützlich ist, wenn Sie die erste Option oben behalten möchten, z. B. wenn Sie "unten wählen:".

Außerdem wird die zuvor ausgewählte Option verfolgt.

Anwendungsbeispiel:

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

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

});

4

Ich weiß, dass dieses Thema alt ist, aber ich denke, meine Antwort kann für viele Menschen nützlich sein.

Hier ist das jQuery-Plugin, das aus Pointys Antwort mit ES6 erstellt wurde:

/**
 * 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);
        });
    }
});

Die Bedienung ist sehr einfach

$("select").sortSelect();

2

Keine der Antworten hat bei mir funktioniert. Aus irgendeinem seltsamen Grund gibt jede Option beim Durchlaufen der Optionen nichts zurück, wenn sie text()aufgerufen wird. Stattdessen musste ich das Etikett der Option über abrufenattr('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'));


1

Die Antwort von Malakgeorge ist nett und kann leicht in eine jQuery-Funktion eingebunden werden:

$.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;        
}


0

Ich habe Teile aus den hervorragenden Antworten von Marxin und Kuxa kombiniert , um eine benutzerdefinierte jQuery-Funktion zu erstellen, die

  1. sortiert die Optionen nach ihren Textwerten (ohne Berücksichtigung der Groß- und Kleinschreibung),

  2. behält jeden bereits ausgewählten Wert bei, und

  3. Gibt die ursprünglichen jQuery-Objekte zurück, für die die Funktion ausgeführt wird:

    $.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); 
            })
        }
    });
    

Ein Arbeitsbeispiel für jsFiddle finden Sie unter https://jsfiddle.net/jhfrench/64och25e/ .


Ich finde es toll, dass ich einen Teil der Zeit nutzen konnte, die mir diese Frage / Antwort erspart hat, indem ich die Antworten auf eine Weise verbessert habe, die hoffentlich jemand anderem zugute kommt. Viva Stack Overflow !!!
Jeromy French
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.