Сортування елементів параметрів за алфавітом за допомогою jQuery


78

Я намагаюся зрозуміти сортування optionелементів всередині selectелемента за алфавітом. В ідеалі, я хотів би мати це як окрему функцію, де я можу просто передати елемент select, оскільки його потрібно сортувати, коли користувач натискає деякі кнопки.

Я шукав високий і низький, щоб знайти хороший спосіб зробити це, але не зміг знайти нічого, що мені підходило.

Елементи параметрів слід сортувати в алфавітному порядку за текстом, а не за значенням.

Це можливо якимось чином?


Отже, в основному ви хочете дати селектору та впорядкувати всіх його дітей за алфавітом за текстом, який вони містять?
pkurek

Я думаю, вам слід переглянути цю тему: stackoverflow.com/questions/1134976/…
каз

@pkurek: У всій простоті, так :-) kaz: Так, я обдурив цей фрагмент, але просто не можу змусити його працювати: - / Цікаво, чи існував якийсь інший спосіб це зробити.
bomortensen

@bomortensen: Усі рішення будуть по суті схожими. Ця відповідь максимально проста.
Фелікс Клінг,

Відповіді:


123

Що б я зробив, це:

  1. Витягніть текст та значення кожного з них <option>у масив об’єктів;
  2. Сортувати масив;
  3. Оновіть <option>елементи з вмістом масиву по порядку.

Щоб зробити це за допомогою jQuery, ви можете зробити наступне:

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

Ось робочий jsfiddle.

редагувати - якщо ви хочете відсортувати так, що ви ігноруєте алфавітний регістр, ви можете використовувати JavaScript .toUpperCase()або .toLowerCase()функції перед порівнянням:

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

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

Це зробило це для мене! Просто довелося зробити всі перевірки> та <у верхній регістр :-) Велике спасибі !!
bomortensen

Ну гаразд, якщо ви хочете ігнорувати алфавітний регістр, тоді так. Радий, що це спрацювало!
Пойнті

так, тому що JS важить великі символи вище, ніж малі при сортуванні .. так здається ;-) Ще раз спасибі, працює як шарм!
bomortensen

6
Дякую за цю відповідь - вирішив мою проблему майже повністю. Мені просто потрібно було збільшити його, щоб врахувати відстеження вибраного варіанту. Для arr options.map я додав "s: $ (o) .attr ('selected')", а потім у options.each просто потрібно було додати: $ (o) .attr ('selected', arr [i] .s); Дякую!
alexleonard

3
Ось змінений код, щоб запам'ятати обраний на даний момент варіант: jsfiddle.net/trELD/700
Jamie Barker

59

Прийнята відповідь є не найкращою у всіх випадках, тому що іноді ви хочете зберегти класи опцій та різні аргументи (наприклад data-foo).

Моє рішення:

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

// Для ie11 або тих, хто отримує порожні параметри, замініть html ('') empty ()


4
Краща відповідь. Це моя справа. Мені потрібно зберегти атрибути даних опцій
Вітор Альмейда

Легка та спрощена відповідь.
UdayKiran Pulipati

3
В останньому рядку ви можете змінити sel.html (''). Append (opts_list) на просто sel.html (opts_list)
jbyrd

1
Слід зазначити, що це не працює, тобто (11): опціони втрачають свої мітки. Найбільш крос-браузерне рішення, яке я знайшов, - це без jquery .
Cethy

Це має бути обрана відповідь! Це набагато простіше, ніж вище, і зберігає будь-які класи або атрибути даних.
Грег Бласс

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);повинно вистачити :)
Фелікс Клінг

Зворотний дзвінок до .sort()має повернути число, яке менше нуля, нуля або більше, щоб відобразити взаємозв'язок впорядкування. Повернення логічного значення насправді не спрацює правильно, я не думаю.
Пойнті

5
Я пішов із вищезазначеним, змінився на: var at = $ (a) .text (). ToLowerCase (), bt = $ (b) .text (). ToLowerCase (); зробити справу сортування незалежною
JayCrossler

27

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

Я використовував розчин трацевіпіну, який діяв фантастично. Тут я надаю трохи змінену версію для всіх, як я, хто любить знаходити легко читабельний код і стискати його після того, як його зрозуміють. Я також використовував .detachзамість того, .removeщоб зберегти будь-які прив'язки до елементів DOM опції.


У мене
спрацювало

Це найкраще рішення IMO і дуже схоже на те, що я збирався опублікувати, оскільки воно зберігає стан елементів (навіть для декількох виділень).
Kris Oye,

Мені також чудово підходить.
Hughsie28,

4
майже ідеально, але Chrome та Firefox показують останній варіант, як вибрано.
Кріштіану Мая,

6

Ось моя вдосконалена версія рішення Pointy :

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

Функція має skip_first параметр, який корисний, коли ви хочете, щоб перший варіант був зверху, наприклад, коли він "вибирає нижче:".

Він також відстежує раніше обраний варіант.

Приклад використання:

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

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

});

6

Я знаю, що ця тема стара, але я думаю, що моя відповідь може бути корисною для багатьох людей.

Ось JQuery плагіна зроблений з загостреного відповіді «s з допомогою 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);
        });
    }
});

Використовувати дуже просто

$("select").sortSelect();

2

Жодна з відповідей у ​​мене не спрацювала. З якоїсь дивної причини під час перегляду параметрів кожен варіант нічого не повертає при text()виклику. Натомість я був змушений отримати ярлик опції через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'));


1

Відповідь Malakgeorge приємна, і її можна легко перегорнути у функцію jQuery:

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

Це хороше рішення, але воно не працює в IE11. Коли я застосував цю функцію до випадаючого списку, текст параметрів порожній. Якщо ви заміните .html ('') на .empty (), це має спрацювати.
Мукеш Кумар

1

Jquery.selectboxes.js плагін має метод сортування. Ви можете застосувати плагін або зануритися в код, щоб побачити спосіб сортування параметрів.


0

Я об’єднав частини чудових відповідей marxin та kuxa, щоб створити спеціальну функцію jQuery

  1. сортує параметри за їх текстовими значеннями (без урахування регістру),

  2. підтримує будь-яке вже вибране значення, і

  3. повертає вихідні об'єкти jQuery, щодо яких виконується функція:

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

Робочий приклад щодо jsFiddle доступний на https://jsfiddle.net/jhfrench/64och25e/ .


Мені подобається, що я міг використати частину часу, яке мене врятувало, покращивши відповіді таким чином, що, мабуть, принесе користь комусь іншому. Переповнення стеку Viva !!!
Jeromy French
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.