Сортування елементів параметрів за алфавітом за допомогою 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.