Який найефективніший спосіб сортувати параметри вибору Html за значенням, зберігаючи при цьому вибраний елемент?


81

У мене є jQuery, але я не впевнений, чи є в ньому вбудовані помічники для сортування. Я міг би зробити 2d масиву кожного елемента text, valueі selectedвластивості, але я не думаю , що в JavaScript побудований в Array.sort()працюватиме правильно.


4
Зверніть увагу на себе (так як я повернувся на це питання кілька разів через Google): ось хороше рішення, Ви писали: gist.github.com/1072537
Тревіс

Відповіді:


135

Витягніть параметри у тимчасовий масив, відсортуйте, а потім відновіть список:

var my_options = $("#my_select option");
var selected = $("#my_select").val();

my_options.sort(function(a,b) {
    if (a.text > b.text) return 1;
    if (a.text < b.text) return -1;
    return 0
})

$("#my_select").empty().append( my_options );
$("#my_select").val(selected);

Доречна документація щодо сортування Mozilla (зокрема, порівнянняФункція) та сторінка Алгоритм сортування Вікіпедії .

Якщо ви хочете зробити регістр сортування нечутливим, замініть textнаtext.toLowerCase()

Показана вище функція сортування ілюструє порядок сортування. Точне сортування неанглійських мов може бути складним (див. Алгоритм сортування Unicode ). Використання localeCompare у функції сортування є хорошим рішенням, наприклад:

my_options.sort(function(a,b) {
    return a.text.localeCompare(b.text);
});

1
перегляд цього питання через 3 роки, і цей шлях здається правильним шляхом
travis

8
Зверніть увагу, що це чутливо до регістру - тобто сортуватиме всі речі, які починаються з великих літер, перед речами, які починаються з малих літер. Якщо це небажано, просто додайте символ .toUpperCase()після кожного.text
TJ Ellis

10
Крім того, він не збереже вибрану на даний момент опцію у всіх браузерах як є (Chrome запам'ятав вибране, але Firefox, тобто не, і вибрав останній елемент після читання параметрів). Щоб це виправити, збережіть поточне вибране значення перед сортуванням, а потім знову виберіть його. тобто до чогось іншого, var selected = $("#my_select").val(); а потім після додавання відсортованих опцій, відновіть val, тобто$("#my_select").val(selected);
TJ Ellis

3
круто. слова "ще" можна видалити. функція повернення кінців у будь-якому випадку.
EliSherer

@TJEllis щодо чутливості до регістру, це питання надає ще більше інформації, чому слід використовувати .toUpperCase()проти, .toLowerCase()ігноруючи справи stackoverflow.com/questions/2140627/…
Адріен,

20

Відповідь Тома трохи змінено вище, так що вона насправді змінює вміст поля для вибору для сортування, а не просто повертає відсортовані елементи.

$('#your_select_box').sort_select_box();

Функція jQuery:

$.fn.sort_select_box = function(){
    // Get options from select box
    var my_options = $("#" + this.attr('id') + ' option');
    // sort alphabetically
    my_options.sort(function(a,b) {
        if (a.text > b.text) return 1;
        else if (a.text < b.text) return -1;
        else return 0
    })
   //replace with sorted my_options;
   $(this).empty().append( my_options );

   // clearing any selections
   $("#"+this.attr('id')+" option").attr('selected', false);
}

1
Ця відповідь знаходиться вгорі, але вибрана неправильно
Тиліха

18

Я щойно обгорнув ідею Марка у функцію jquery

$('#your_select_box').sort_select_box();

Функція JQuery:

$.fn.sort_select_box = function(){
    var my_options = $("#" + this.attr('id') + ' option');
    my_options.sort(function(a,b) {
        if (a.text > b.text) return 1;
        else if (a.text < b.text) return -1;
        else return 0
    })
   return my_options;
}

як я можу додати це до моєї поточної події кліку? $ ('# addwire'). клацніть (function () {return! $ ('# варіант вибору дроту: вибрано'). remove (). appendTo ('# wires'). sort_select_box ();}); здається, не працює
mcgrailm

12

Рішення, яке я згадав у своєму коментарі @Juan Perez

$.fn.sortOptions = function(){
    $(this).each(function(){
        var op = $(this).children("option");
        op.sort(function(a, b) {
            return a.text > b.text ? 1 : -1;
        })
        return $(this).empty().append(op);
    });
}

Використання:

$("select").sortOptions();

Це ще можна вдосконалити, але мені не потрібно було більше додавати дзвіночків чи свистків :)


6

Ну, в IE6, схоже, сортується за елементом [0] вкладеного масиву:

function sortSelect(selectToSort) {
    var arrOptions = [];

    for (var i = 0; i < selectToSort.options.length; i++)  {
        arrOptions[i] = [];
        arrOptions[i][0] = selectToSort.options[i].value;
        arrOptions[i][1] = selectToSort.options[i].text;
        arrOptions[i][2] = selectToSort.options[i].selected;
    }

    arrOptions.sort();

    for (var i = 0; i < selectToSort.options.length; i++)  {
        selectToSort.options[i].value = arrOptions[i][0];
        selectToSort.options[i].text = arrOptions[i][1];
        selectToSort.options[i].selected = arrOptions[i][2];
    }
}

Я подивлюсь, чи це працює в інших браузерах ...

Редагувати: це працює і у Firefox, ву-ху!

Однак є простіший спосіб, ніж цей? чи є якийсь метод, вбудований у javascript або jQuery, який сортує виділяє, що мені не вистачає, чи це найкращий спосіб?


8
Зверніть увагу, що ця функція не сортує елементи опцій ; він змінює [значення, текст, виділений] на існуючих елементах таким чином, що вони сортуються (у цьому випадку за значенням). Цього достатньо для більшості програм, але якщо у вас є інші атрибути (CSS, поради щодо інструментів тощо), то цього підходу буде недостатньо.
NVRAM

6

Існує закритий білет jQuery для сорту, який повинен працювати, але просто не був включений в ядро.

jQuery.fn.sort = function() {
  return this.pushStack( [].sort.apply( this, arguments ), []);
};

Посилаючись на ланцюжок груп Google , я думаю, ви просто передаєте функцію, яка використовується для сортування

function sortSelect(selectToSort) {
    jQuery(selectToSort.options).sort(function(a,b){ 
        return a.value > b.value ? 1 : -1; 
    });
}

Сподіваюся, це допоможе!


1
Деякі проблеми з функцією sortSelect: Тут не враховуються рівні можливості. Сортує за значенням, а не за текстом. Об'єкти jQuery не мають властивості з назвою "options". Не має жодного ефекту, оскільки вам потрібно додати параметри до нового елемента виділення.
simon

4

Це краще рішення. Оголосіть JQuery глобальну функцію

$.fn.sortSelect = function() {
    var op = this.children("option");
    op.sort(function(a, b) {
        return a.text > b.text ? 1 : -1;
    })
    return this.empty().append(op);
}

І викликати функцію з коду.

$("#my_select").sortSelect();

1
Я використав для цього варіацію, обернувши внутрішню частину в $ (this) .each (), щоб я міг передати йому селектор для обробки декількох одночасно.
Tom Pietrosanti

1
Крім того, потрібно використовувати $(this)замість простоthis
Tom Pietrosanti

2

Array.sort()за замовчуванням перетворює кожен елемент у рядок та порівнює ці значення. Так ["value", "text", "selected"]сортується як "value, text, selected". Що, мабуть, спрацює нормально, більшу частину часу.

Якщо ви хочете сортувати лише за значенням або інтерпретувати значення як число, тоді ви можете передати функцію порівняння у sort ():

arrOptions.sort(function(a,b) { return new Number(a[0]) - new Number(b[0]); });

1

Пам'ятайте: якщо ви хочете використовувати контекстний селектор, просто об'єднати ідентифікатор не буде працювати

$.fn.sort_select_box = function(){
    var my_options = $("option", $(this));
    my_options.sort(function(a,b) {
        if (a.text > b.text) return 1;
        else if (a.text < b.text) return -1;
        else return 0
    });
    $(this).empty().append(my_options);
}

// Usando:
$("select#ProdutoFornecedorId", $($context)).sort_select_box();

1

Трохи пізно, але для того, що варто, я реалізував більш складну функцію, яку ви можете включити загалом. У ньому є кілька варіантів для різноманітних результатів. Він також може перетворитися на <OPTGROUP>теги на основі їх мітки.

$.fn.sortSelect = function(options){

    const OPTIONS_DEFAULT = {
        recursive:      true,   // Recurse into <optgroup>
        reverse:        false,  // Reverse order
        useValues:      false,  // Use values instead of text for <option> (<optgruop> is always label based)
        blankFirst:     true,   // Force placeholder <option> with empty value first, ignores reverse
    }

    if (typeof options != "object" || null === options) {
        options = OPTIONS_DEFAULT;
    }

    var sortOptions = function($root, $node, options){

        if ($node.length != 1) {
            return false;
        }

        if ($node[0].tagName != "SELECT" && $node[0].tagName != "OPTGROUP") {
            return false;
        }

        if (options.recursive) {
            $node.children('optgroup').each(function(k, v){
                return sortOptions($root, $(v), options);
            });
        }

        var $options        = $node.children('option, optgroup');
        var $optionsSorted  = $options.sort(function(a, b){

            if (options.blankFirst) {
                if (a.tagName == "OPTION" && a.value == "") {
                    return -1;
                }

                if (b.tagName == "OPTION" && b.value == "") {
                    return 1;
                }
            }

            var textA = (a.tagName == "OPTION" ? (options.useValues ? a.value : a.text) : a.label);
            var textB = (b.tagName == "OPTION" ? (options.useValues ? a.value : b.text) : b.label);

            if (textA > textB) {
                return options.reverse ? -1 : 1;
            }

            if (textA < textB) {
                return options.reverse ? 1 : -1;
            }

            return 0;

        });

        $options.remove();
        $optionsSorted.appendTo($node);

        return true;

    };

    var selected = $(this).val();
    var sorted = sortOptions($(this), $(this), {...OPTIONS_DEFAULT, ...options});
    $(this).val(selected);

    return sorted;

};

Потім ви можете викликати sortSelect()функцію на будь-якому <SELECT>тезі або просто на одному, <OPTGROUP>щоб лише відсортувати параметри групи.

Приклад:

$('select').sortSelect();

Зворотне замовлення за допомогою опції "зворотний":

$('select').sortSelect({
    reverse: true
});

Ви можете застосувати це до всіх вибраних автоматично, можливо, лише якщо вони включають важливий клас (наприклад, "js-sort") із цим:

$('select.js-sort').each(function(k, v){
    $(v).sortSelect();
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.