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

时间:2008-09-05 14:05:35

标签: javascript jquery arrays sorting html-select

我有jQuery,但我不确定它是否有任何内置的排序助手。我可以为每个项目的textvalueselected属性制作一个二维数组,但我不认为内置Array.sort()的javascript可以正常工作。

11 个答案:

答案 0 :(得分:128)

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

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's sort documentation(特别是compareFunction)和Wikipedia's Sorting Algorithm page是相关的。

如果您想使排序不区分大小写,请将text替换为text.toLowerCase()

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

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

答案 1 :(得分:19)

稍微修改了汤姆的答案,以便它实际修改要排序的选择框的内容,而不是仅返回已排序的元素。

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

答案 2 :(得分:17)

我刚刚在jquery函数中包含了Mark的想法

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

答案 3 :(得分: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();

这仍然可以改进,但我不需要添加任何铃声或口哨声:))

答案 4 :(得分:6)

a closed jQuery ticket对于一种应该有效的排序,但只是未包含在核心中。

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

a Google Groups thread引用,我想你只是传入一个用于排序的函数,就像这样

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

希望它有所帮助!

答案 5 :(得分:5)

好吧,在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中的方法可以选择我缺少的选项,或者这是最好的方法吗?

答案 6 :(得分: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();

答案 7 :(得分:2)

Array.sort()默认将每个元素转换为字符串,并比较这些值。因此["value", "text", "selected"]被排序为"value, text, selected"。在大多数情况下,这可能会很好。

如果您确实想单独对值进行排序,或者将值解释为数字,那么您可以将比较函数传递给sort():

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

答案 8 :(得分: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();

答案 9 :(得分: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();
});

答案 10 :(得分:0)

似乎 jquery 对于 html select 元素中的排序选项仍然不是特别有用。 下面是一些用于排序选项的普通 JavaScript 代码:

function sortOptionsByText(a,b) {
  // I keep an empty value option on top, b.value comparison to 0 might not be necessary if empty value is always on top...
  if (a.value.length==0 || (b.value.length>0 && a.text <= b.text)) return -1; // no sort: a, b
  return 1; // sort switches places: b, a
}
function sortOptionsByValue(a,b) {
  if (a.value <= b.value) return -1; // a, b
  return 1; // b, a
}
function clearChildren(elem) {
  if (elem) {
    while (elem.firstChild) {
      elem.removeChild(elem.firstChild);
    }
  }
}
function sortSelectElem(sel,byText) {
  const val=sel.value;
  const tmp=[...sel.options];
  tmp.sort(byText?sortOptionsByText:sortOptionsByValue);
  clearChildren(sel);
  sel.append(...tmp);
  sel.value=val;
}
RACE: <select id="list" size="6">
  <option value="">--PICK ONE--</option>
  <option value="1">HUMANOID</option>
  <option value="2">AMPHIBIAN</option>
  <option value="3">REPTILE</option>
  <option value="4">INSECTOID</option>
</select><br>
<button type="button" onclick="sortSelectElem(document.getElementById('list'));">SORT LIST BY VALUE</button><br>
<button type="button" onclick="sortSelectElem(document.getElementById('list'),true);">SORT LIST BY TEXT</button>