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?

bomortensen
quelle
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;
});
Spitze
quelle
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 ()

Marxin
quelle
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);
}));
Diode
quelle
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.

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

});
Victor BV
quelle
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();
Kuxa
quelle
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'));
rmirabelle
quelle
1

Ja, Sie können die Optionen nach ihrem Text sortieren und wieder an das Auswahlfeld anhängen.

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

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

Shali Ravi
quelle
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;        
}
Dr. Fred
quelle
1

Das Plugin jquery.selectboxes.js verfügt über eine Sortiermethode . Sie können das Plugin implementieren oder in den Code eintauchen, um eine Möglichkeit zum Sortieren der Optionen zu finden.

Sam Tyson
quelle
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/ .

Jeromy Französisch
quelle
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