使用jQuery按字母顺序对选项元素进行排序


78

我正在尝试按字母顺序理解option元素内的排序元素select。理想情况下,我想将此作为一个单独的函数,在这里我可以只传递select元素,因为当用户单击某些按钮时需要对它进行排序。

我在高低处寻找了实现此目标的一种好方法,但是找不到任何对我有用的方法。

选项元素应按文本而不是值按字母顺序排序。

这有可能吗?


所以,基本上,您想提供一个选择器,并按其包含的文字按字母顺序对所有孩子进行排序?
pkurek,2012年

我想你应该查看此主题:stackoverflow.com/questions/1134976/...
KAZ

@pkurek:简而言之,是的:-) kaz:是的,我骗了那个片段,但根本无法使它起作用:-/想知道是否还有其他方法可以做到这一点。
bomortensen

@bomortensen:所有解决方案本质上都是相似的。这个答案很简单。
菲利克斯·克林

Answers:


122

我要做的是:

  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

好的,如果您要忽略字母大小写,那就可以。很高兴它有效!
Pointy 2012年

是的,因为在排序时JS的大小写字符比小写的字符大..看来;-)再次感谢您,它的工作原理很吸引人!
bomortensen 2012年

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
最佳答案。这是我的情况。我需要保持期权数据的属性
Vitor Almeida

简单而简化的答案。
UdayKiran Pulipati 2014年

3
在最后一行,您可以将sel.html('')。append(opts_list)更改为sel.html(opts_list)
jbyrd

1
应该注意的是,它在ie(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()时应返回小于零,零或更大的数字,以反映顺序关系。我不认为返回布尔值实际上是行不通的。
Pointy 2012年

5
我使用上面的方法,更改为:var at = $(a).text()。toLowerCase(),bt = $(b).text()。toLowerCase(); 使排序情况下独立
JayCrossler

26

的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

我使用了tracevipin的解决方案,效果很好。我在这里为喜欢我的人提供了稍微修改的版本,他们喜欢找到易于阅读的代码,并理解对其进行压缩。我还使用了.detach而不是.remove保留选项DOM元素上的任何绑定。


为我完美工作
JulioPopócatl2015年

这是IMO的最佳解决方案,并且与我要发布的内容非常相似,因为它保留了元素的状态(即使是多个选择)。
克里斯·奥耶

也为我完美地工作。
Hughsie17年

3
几乎完美,但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);

});

4

我知道这个话题很老,但是我认为我的回答对很多人有用。

这是Pointy使用ES6的答案制成的jQuery插件:

/**
 * 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;        
}


0

我结合了marxinkuxa的出色答案中的部分,以创建一个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 Stack溢出!!!
法国耶罗米(Jeromy French)
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.