在保留当前选定项目的同时,按值对Html Select选项进行排序的最有效方法是什么?


80

我有jQuery,但不确定是否有内置的排序助手。我可以为每个项目的textvalueselected属性创建一个2D数组,但是我认为内置的javascript不能Array.sort()正常工作。


4
自我注意(因为我已经通过Google多次回到这个问题):这是您写的一个很好的解决方案:gist.github.com/1072537
travis

Answers:


134

将选项提取到一个临时数组中,进行排序,然后重建列表:

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)和Wikipedia的“排序算法”页面相关。

如果要使排序不区分大小写,请替换texttext.toLowerCase()

上面显示的排序功能说明了如何进行排序。准确地对非英语语言进行排序可能很复杂(请参阅Unicode排序规则算法)。在sort函数中使用localeCompare是一个很好的解决方案,例如:

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

1
3年后重新审视这个问题,这条路线似乎是正确的路
travis

8
请注意,这是区分大小写的-也就是说,它将以小写字母开头的所有内容排序为大写字母开头的所有内容。如果不希望这样,只需.toUpperCase()在每个之后添加一个.text
TJ Ellis

10
而且,它不会按原样在所有浏览器中保留当前选择的选项(Chrome记住了选择的内容,但是firefox和ie没有选择,并在读取选项后选择了最后一个元素)。要解决此问题,请在排序之前保存当前选择的值,然后重新选择它。即,在执行其他任何操作之前 var selected = $("#my_select").val(); ,然后在添加了已排序的选项之后,请恢复val,即$("#my_select").val(selected);
TJ Ellis

3
凉。可以删除“其他”字词。无论如何,返回端函数。
EliSherer 2014年

关于区分大小写@TJEllis,这个问题提供了更多的信息为什么要使用.toUpperCase()VS.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
该答案接近顶部,但选择不正确
thouliha 2015年

18

我刚刚将Mark的想法包装在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('#wires')。sort_select_box();}); 似乎不起作用
mcgrailm 2011年

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
注意,此功能不对选项元素进行排序;它更改现有元素上的[value,text,selected],以便对它们进行排序(在这种情况下,按值排序)。这对于大多数应用程序已经足够,但是如果您具有其他属性(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”的属性。没有任何效果,因为您必须将选项附加到新的select元素上。
simon'4

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 2012年

1
另外,您需要使用$(this)的不仅仅是this
汤姆·皮耶特罗桑蒂

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

切记:如果要使用上下文选择器,则仅连接ID将不起作用

$.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();
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.