Каков наиболее эффективный способ сортировки параметров Html Select по значению, сохраняя при этом текущий выбранный элемент?

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

Примечание для себя (поскольку я возвращался к этому вопросу несколько раз через Google): вот хорошее решение, которое вы написали: gist.github.com/1072537

travis 09.07.2011 00:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
81
1
90 563
10
Перейти к ответу Данный вопрос помечен как решенный

Ответы 10

Ну, в 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, который сортирует, выбирает, что мне не хватает, или это лучший способ?

Обратите внимание, что эта функция не сортирует элементы вариант; он изменяет [значение, текст, выбрано] для существующих элементов таким образом, чтобы они были отсортированы (в данном случае по значению). Этого достаточно для большинства приложений, но если у вас есть другие атрибуты (CSS, подсказки и т. д.), Этого подхода будет недостаточно.

NVRAM 02.12.2009 22:51

Array.sort() по умолчанию преобразует каждый элемент в строку и сравнивает эти значения. Итак, ["value", "text", "selected"] сортируется как "value, text, selected". Что, вероятно, будет работать нормально в большинстве случаев.

Если вы хотите отсортировать только значение или интерпретировать значение как число, вы можете передать функцию сравнения в sort ():

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

Есть закрытый билет 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; 
    });
}

Надеюсь, это поможет!

Некоторые проблемы с функцией sortSelect: при этом не рассматриваются равные варианты. Сортировка по значению, а не по тексту. У объектов jQuery нет свойства с именем «options». Не имеет никакого эффекта, потому что вам нужно добавить параметры к новому элементу выбора.

simon 11.04.2012 11:43
Ответ принят как подходящий

Извлечь параметры во временный массив, отсортировать и перестроить список:

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 (в частности функция compareFunction) и Страница алгоритма сортировки в Википедии являются релевантными.

Если вы хотите сделать сортировку нечувствительной к регистру, замените text на text.toLowerCase()

Показанная выше функция сортировки показывает, как выполнять сортировку. Точная сортировка неанглийских языков может быть сложной (см. алгоритм сортировки юникода). Использование localeCompare в функции сортировки - хорошее решение, например:

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

возвращаясь к этому вопросу 3 года спустя, и этот путь кажется правильным

travis 08.07.2011 21:47

Обратите внимание, что это чувствительно к регистру, то есть все вещи, начинающиеся с прописных букв, будут отсортированы до тех, что начинаются с строчных букв. Если это нежелательно, просто добавляйте .toUpperCase() после каждого .text.

TJ Ellis 02.12.2011 21:49

Кроме того, он не сохранит выбранный в данный момент параметр во всех браузерах как есть (Chrome запомнил, что было выбрано, но firefox и т.е нет, и выбрал последний элемент после того, как параметры были прочитаны). Чтобы исправить это, сохраните текущее выбранное значение перед сортировкой, а затем выберите его повторно. то есть, прежде чем что-либо еще сделать var selected = $("#my_select").val();, а затем после добавления отсортированных параметров восстановить val, то есть $("#my_select").val(selected);

TJ Ellis 02.12.2011 21:52

прохладно. слова else можно удалить. в любом случае возврат заканчивается функцией.

EliSherer 17.03.2014 17:50

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

Adrien Be 26.09.2014 13:28

@TJEllis, вы обсуждаете Natural Sort Algorithm, что на самом деле является очень интересной / сложной частью вопроса (i18n может быть серьезной проблемой). Подробнее об этом читайте на stackoverflow.com/questions/2802341/…, а также на stackoverflow.com/questions/51165/…

Adrien Be 26.09.2014 19:25

@Mark Natural Sort Order довольно "просто" реализован в вашем примере, и для многих он может иметь слишком низкое качество, просто посмотрите, как он сортирует основные латинские символы jsbin.com/daseyutiyuji/1/edit?js,console. Почему бы вместо этого не использовать встроенные в браузеры методы localeCompare() !? см. живую демонстрацию jsbin.com/beboroyifomu/1/edit?js,console, а также обсуждение этой темы stackoverflow.com/questions/51165/…

Adrien Be 29.09.2014 16:10

@Adrien Будьте хорошим комментарием. Вопрос заключался в том, как отсортировать выбранные варианты, и я думаю, что ответ иллюстрирует это. Алгоритм сортировки зависит от того, что сортируется и как это должно быть отсортировано.

Mark 16.10.2014 03:49

также можно сократить обратный вызов сортировки до function(a,b) {return (a.text > b.text)-(a.text<b.text)}

Marat 21.07.2015 10:49

Я использовал это решение вместо jquery, потому что решение jquery не работает в IE11. однако при использовании предложенного решения в IE11 я обнаружил, что диалоговое окно выбора не обновляется автоматически, и решил эту проблему, добавив $("#my_select").focus();.

B5A7 14.12.2017 04:14

Я только что обернул идею Марка в функцию 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'). click (function () {return! $ ('# параметр wireselection: selected'). remove (). appendTo ('# провода'). sort_select_bo‌ x ();}); похоже, не работает

mcgrailm 25.02.2011 23:32

Немного изменен ответ Тома выше, так что он фактически изменяет содержимое поля выбора для сортировки, а не просто возвращает отсортированные элементы.

$('#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);
}

Этот ответ близок к верхнему, но не выбран правильно

thouliha 17.12.2015 18:28

Помните: если вы хотите использовать селектор контекста, просто объедините идентификатор, это не сработает.

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

Это лучшее решение. Объявить глобальную функцию в 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();

Я использовал вариант этого, заключив внутреннюю часть в $ (this) .each (), чтобы я мог передать ему селектор для одновременной обработки нескольких.

Tom Pietrosanti 06.09.2012 23:24

Кроме того, вам нужно использовать $(this) вместо this.

Tom Pietrosanti 06.09.2012 23:24

Решение, которое я упомянул в своем комментарии к @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();

Это все еще можно улучшить, но мне не нужно было добавлять больше наворотов :)

Немного поздно, но, как бы то ни было, я реализовал более сложную функцию, которую вы можете включить в общем виде. У него есть несколько вариантов для разнообразного вывода. Он также может рекурсивно переходить в теги <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();
});

Другие вопросы по теме