47

有没有一种快速的方法来对选择元素的项目进行排序?还是我不得不求助于编写javascript?

请有任何想法。

<select size="4" name="lstALL" multiple="multiple" id="lstALL" tabindex="12" style="font-size:XX-Small;height:95%;width:100%;">
<option value="0"> XXX</option>
<option value="1203">ABC</option>
<option value="1013">MMM</option>
</select>
4

21 回答 21

75

这会成功的。只需将您的选择元素传递给它:document.getElementById('lstALL')当您需要对列表进行排序时。

function sortSelect(selElem) {
    var tmpAry = new Array();
    for (var i=0;i<selElem.options.length;i++) {
        tmpAry[i] = new Array();
        tmpAry[i][0] = selElem.options[i].text;
        tmpAry[i][1] = selElem.options[i].value;
    }
    tmpAry.sort();
    while (selElem.options.length > 0) {
        selElem.options[0] = null;
    }
    for (var i=0;i<tmpAry.length;i++) {
        var op = new Option(tmpAry[i][0], tmpAry[i][1]);
        selElem.options[i] = op;
    }
    return;
}
于 2008-11-10T17:08:40.240 回答
46

这个解决方案对我使用 jquery 非常有效,我想我会在这里交叉引用它,因为我在另一个页面之前找到了这个页面。其他人可能也会这样做。

$("#id").html($("#id option").sort(function (a, b) {
    return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
}))

使用 Javascript 排序下拉列表

于 2011-09-19T03:33:42.613 回答
6

使用 Marco Lazzeri 和 Terre Porter 提供的答案(如果这个答案有用,请投票),我想出了一个稍微不同的解决方案,可以保留所选值(可能不保留事件处理程序或附加数据)使用jQuery .

// save the selected value for sorting
var v = jQuery("#id").val();

// sort the options and select the value that was saved
j$("#id")
    .html(j$("#id option").sort(function(a,b){
        return a.text == b.text ? 0 : a.text < b.text ? -1 : 1;}))
    .val(v);
于 2012-02-08T19:55:04.697 回答
6

Vanilla JS es6 本地化选项排序示例

const optionNodes = Array.from(selectNode.children);
const comparator = new Intl.Collator(lang.slice(0, 2)).compare;

optionNodes.sort((a, b) => comparator(a.textContent, b.textContent));
optionNodes.forEach((option) => selectNode.appendChild(option));

我的用例是使用区域感知排序来本地化国家/地区选择下拉列表。这用于 250 + 选项,并且在我的机器上性能非常好~ 10 毫秒。

于 2019-06-21T22:12:46.713 回答
4

来自W3C 常见问题解答

尽管许多编程语言都有像下拉框这样的设备,它们能够在显示项目列表之前对其进行排序,作为其功能的一部分,但 HTML <select> 函数没有这样的能力。它按收到的顺序列出 <options>。

对于静态 HTML 文档,您必须手动对它们进行排序,或者对动态文档使用 Javascript 或其他一些编程排序。

于 2008-11-10T15:18:13.020 回答
4

另外一个选项:

function sortSelect(elem) {
    var tmpAry = [];
    // Retain selected value before sorting
    var selectedValue = elem[elem.selectedIndex].value;
    // Grab all existing entries
    for (var i=0;i<elem.options.length;i++) tmpAry.push(elem.options[i]);
    // Sort array by text attribute
    tmpAry.sort(function(a,b){ return (a.text < b.text)?-1:1; });
    // Wipe out existing elements
    while (elem.options.length > 0) elem.options[0] = null;
    // Restore sorted elements
    var newSelectedIndex = 0;
    for (var i=0;i<tmpAry.length;i++) {
        elem.options[i] = tmpAry[i];
        if(elem.options[i].value == selectedValue) newSelectedIndex = i;
    }
    elem.selectedIndex = newSelectedIndex; // Set new selected index after sorting
    return;
}
于 2011-03-30T18:14:33.737 回答
4

这是我在这个板上最喜欢的 3 个答案的重新编译:

  • jOk 的最佳和最简单的答案。
  • Terry Porter 的简单 jQuery 方法。
  • SmokeyPHP 的可配置函数。

结果是一个易于使用且易于配置的功能。

第一个参数可以是选择对象、选择对象的 ID 或至少具有 2 维的数组。

第二个参数是可选的。默认按选项文本排序,索引 0。可以传递任何其他索引,因此对其进行排序。可以传递 1 或文本“值”,以按值排序。

按文本示例排序(全部按文本排序):

 sortSelect('select_object_id');
 sortSelect('select_object_id', 0);
 sortSelect(selectObject);
 sortSelect(selectObject, 0);

按值排序(全部按值排序):

 sortSelect('select_object_id', 'value');
 sortSelect('select_object_id', 1);
 sortSelect(selectObject, 1);

按另一个索引对任何数组进行排序:

var myArray = [
  ['ignored0', 'ignored1', 'Z-sortme2'],
  ['ignored0', 'ignored1', 'A-sortme2'],
  ['ignored0', 'ignored1', 'C-sortme2'],
];

sortSelect(myArray,2);

最后一个将按 index-2 对数组进行排序,即 sortme 的。

主要排序功能

function sortSelect(selElem, sortVal) {

    // Checks for an object or string. Uses string as ID. 
    switch(typeof selElem) {
        case "string":
            selElem = document.getElementById(selElem);
            break;
        case "object":
            if(selElem==null) return false;
            break;
        default:
            return false;
    }

    // Builds the options list.
    var tmpAry = new Array();
    for (var i=0;i<selElem.options.length;i++) {
        tmpAry[i] = new Array();
        tmpAry[i][0] = selElem.options[i].text;
        tmpAry[i][1] = selElem.options[i].value;
    }

    // allows sortVal to be optional, defaults to text.
    switch(sortVal) {
        case "value": // sort by value
            sortVal = 1;
            break;
        default: // sort by text
            sortVal = 0;
    }
    tmpAry.sort(function(a, b) {
        return a[sortVal] == b[sortVal] ? 0 : a[sortVal] < b[sortVal] ? -1 : 1;
    });

    // removes all options from the select.
    while (selElem.options.length > 0) {
        selElem.options[0] = null;
    }

    // recreates all options with the new order.
    for (var i=0;i<tmpAry.length;i++) {
        var op = new Option(tmpAry[i][0], tmpAry[i][1]);
        selElem.options[i] = op;
    }

    return true;
}
于 2013-10-19T07:00:38.573 回答
3

我有同样的问题。这是我想出的jQuery 解决方案:

  var options = jQuery.makeArray(optionElements).
                       sort(function(a,b) {
                         return (a.innerHTML > b.innerHTML) ? 1 : -1;
                       });
  selectElement.html(options);
于 2009-06-05T13:17:00.797 回答
2

我有一个类似的问题,除了我希望所选项目显示在顶部,并且我不想清除哪些项目被选中(多选列表)。我的是基于jQuery的...

function SortMultiSelect_SelectedTop(slt) {
    var options =
        $(slt).find("option").sort(function (a, b) {
            if (a.selected && !b.selected) return -1;
            if (!a.selected && b.selected) return 1;
            if (a.text < b.text) return -1;
            if (a.text > b.text) return 1;
            return 0;
        });
    $(slt).empty().append(options).scrollTop(0);
}

如果没有在顶部选择,它看起来像这样。

function SortMultiSelect(slt) {
    var options =
        $(slt).find("option").sort(function (a, b) {
            if (a.text < b.text) return -1;
            if (a.text > b.text) return 1;
            return 0;
        });
    $(slt).empty().append(options).scrollTop(0);
}
于 2013-07-17T14:54:00.997 回答
1

是的,DOK 有正确的答案......要么在编写 HTML 之前对结果进行预排序(假设它是动态的并且你负责输出),要么你编写 javascript。

Javascript 排序方法将成为您的朋友。只需将值从选择列表中拉出,然后对其进行排序,然后将它们放回去:-)

于 2008-11-10T15:16:35.100 回答
1

Í 认为这是一个更好的选择(我使用@Matty 的代码并进行了改进!):

function sortSelect(selElem, bCase) {
                var tmpAry = new Array();
                bCase = (bCase ? true : false);
                for (var i=0;i<selElem.options.length;i++) {
                        tmpAry[i] = new Array();
                        tmpAry[i][0] = selElem.options[i].text;
                        tmpAry[i][1] = selElem.options[i].value;
                }
                if (bCase)
                    tmpAry.sort(function (a, b) {
                        var ret = 0;
                        var iPos = 0;
                        while (ret == 0 && iPos < a.length && iPos < b.length)
                        {
                            ret = (String(a).toLowerCase().charCodeAt(iPos) - String(b).toLowerCase().charCodeAt(iPos));
                            iPos ++;
                        }
                        if (ret == 0)
                        {
                            ret = (String(a).length - String(b).length);
                        }
                        return ret;
                        });
                else
                    tmpAry.sort();
                while (selElem.options.length > 0) {
                    selElem.options[0] = null;
                }
                for (var i=0;i<tmpAry.length;i++) {
                        var op = new Option(tmpAry[i][0], tmpAry[i][1]);
                        selElem.options[i] = op;
                }
                return;
        }
于 2011-03-04T20:46:31.417 回答
1

我使用了这种冒泡排序,因为我无法通过选项数组中的 .value 对它们进行排序,并且它是一个数字。这样我就可以正确订购它们。我希望它对你也有用。

function sortSelect(selElem) {
  for (var i=0; i<(selElem.options.length-1); i++)
      for (var j=i+1; j<selElem.options.length; j++)
          if (parseInt(selElem.options[j].value) < parseInt(selElem.options[i].value)) {
              var dummy = new Option(selElem.options[i].text, selElem.options[i].value);
              selElem.options[i] = new Option(selElem.options[j].text, selElem.options[j].value);
              selElem.options[j] = dummy;
          }
}
于 2011-06-29T13:26:38.010 回答
1

我很快将一个允许选择方向(“asc”或“desc”)、是否应在选项值(真或假)上进行比较以及是否应在比较前修剪前导和尾随空格的方法放在一起(布尔值)。

这种方法的好处是保留了选定的选项,并且还应保留所有其他特殊属性/触发器。

function sortOpts(select,dir,value,trim)
{
    value = typeof value == 'boolean' ? value : false;
    dir = ['asc','desc'].indexOf(dir) > -1 ? dir : 'asc';
    trim = typeof trim == 'boolean' ? trim : true;
    if(!select) return false;
    var opts = select.getElementsByTagName('option');

    var options = [];
    for(var i in opts)
    {
        if(parseInt(i)==i)
        {
            if(trim)
            {
                opts[i].innerHTML = opts[i].innerHTML.replace(/^\s*(.*)\s*$/,'$1');
                opts[i].value = opts[i].value.replace(/^\s*(.*)\s*$/,'$1');
            }
            options.push(opts[i]);
        }
    }
    options.sort(value ? sortOpts.sortVals : sortOpts.sortText);
    if(dir == 'desc') options.reverse();
    options.reverse();
    for(var i in options)
    {
        select.insertBefore(options[i],select.getElementsByTagName('option')[0]);
    }
}
sortOpts.sortText = function(a,b) {
    return a.innerHTML > b.innerHTML ? 1 : -1;
}
sortOpts.sortVals = function(a,b) {
    return a.value > b.value ? 1 : -1;
}
于 2013-07-17T15:44:07.677 回答
1

受@Terre Porter 回答的启发,我认为这个实现起来非常简单(使用jQuery)

var $options = jQuery("#my-dropdownlist-id > option"); 
// or jQuery("#my-dropdownlist-id").find("option")

$options.sort(function(a, b) {
    return a.text == b.text ? 0 : a.text < b.text ? -1 : 1
})

但是,对于字母/数字下拉列表:

灵感来自:https ://stackoverflow.com/a/4340339/1598891

var $options = jQuery(dropDownList).find("option");

var reAlpha = /[^a-zA-Z]/g;
var reNumeric = /[^0-9]/g;
$options.sort(function AlphaNumericSort($a,$b) {
    var a = $a.text;
    var b = $b.text;
    var aAlpha = a.replace(reAlpha, "");
    var bAlpha = b.replace(reAlpha, "");
    if(aAlpha === bAlpha) {
        var aNumeric = parseInt(a.replace(reNumeric, ""), 10);
        var bNumeric = parseInt(b.replace(reNumeric, ""), 10);
        return aNumeric === bNumeric ? 0 : aNumeric > bNumeric ? 1 : -1;
    } else {
        return aAlpha > bAlpha ? 1 : -1;
    }
})

希望它会有所帮助

第一个例子 第二个例子

于 2014-06-27T19:52:26.890 回答
1
function call() {
    var x = document.getElementById("mySelect");
    var optionVal = new Array();

    for (i = 0; i < x.length; i++) {
        optionVal.push(x.options[i].text);
    }

    for (i = x.length; i >= 0; i--) {
        x.remove(i);
    }

    optionVal.sort();

    for (var i = 0; i < optionVal.length; i++) {
        var opt = optionVal[i];
        var el = document.createElement("option");
        el.textContent = opt;
        el.value = opt;
        x.appendChild(el);
    }
}

想法是将选择框的所有元素拉出到一个数组中,删除选择框值以避免覆盖,对数组进行排序,然后将排序后的数组推回选择框

于 2015-01-07T17:37:25.813 回答
0

不像 Marco 的 JQuery 示例那么漂亮,但使用原型(我可能缺少更优雅的解决方案)它将是:

function sort_select(select) {
  var options = $A(select.options).sortBy(function(o) { return o.innerHTML });
  select.innerHTML = "";
  options.each(function(o) { select.insert(o); } );
}

然后只需传递一个选择元素:

sort_select( $('category-select') );
于 2010-04-13T19:50:20.403 回答
0

使用 jQuery 的另一种方法:

// sorting;
var selectElm = $("select"),
    selectSorted = selectElm.find("option").toArray().sort(function (a, b) {
        return (a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase()) ? 1 : -1;
    });
selectElm.empty();
$.each(selectSorted, function (key, value) {
    selectElm.append(value);
});
于 2012-08-31T07:39:12.967 回答
0

试试这个......希望它会为您提供解决方案:

function sortlist_name()
{

    var lb = document.getElementById('mylist');
    arrTexts = new Array();
    newTexts = new Array();
    txt = new Array();
    newArray =new Array();
    for(i=0; i<lb.length; i++)
    {
      arrTexts[i] = lb.options[i].text;
    }
    for(i=0;i<arrTexts.length; i++)
    {
        str = arrTexts[i].split(" -> ");
        newTexts[i] = str[1]+' -> '+str[0];
    }
    newTexts.sort();
    for(i=0;i<newTexts.length; i++)
    {
        txt = newTexts[i].split(' -> ');
        newArray[i] = txt[1]+' -> '+txt[0];
    }
    for(i=0; i<lb.length; i++)
    {
        lb.options[i].text = newArray[i];
        lb.options[i].value = newArray[i];
    }
}
/***********revrse by name******/
function sortreverse_name()
{

    var lb = document.getElementById('mylist');
    arrTexts = new Array();
    newTexts = new Array();
    txt = new Array();
    newArray =new Array();
    for(i=0; i<lb.length; i++)
    {
      arrTexts[i] = lb.options[i].text;
    }
    for(i=0;i<arrTexts.length; i++)
    {
        str = arrTexts[i].split(" -> ");
        newTexts[i] = str[1]+' -> '+str[0];
    }
    newTexts.reverse();
    for(i=0;i<newTexts.length; i++)
    {
        txt = newTexts[i].split(' -> ');
        newArray[i] = txt[1]+' -> '+txt[0];
    }
    for(i=0; i<lb.length; i++)
    {
        lb.options[i].text = newArray[i];
        lb.options[i].value = newArray[i];
    }
}

function sortlist_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();

for(i=0; i<lb.length; i++)  {
  arrTexts[i] = lb.options[i].text;
}

arrTexts.sort();

for(i=0; i<lb.length; i++)  {
  lb.options[i].text = arrTexts[i];
  lb.options[i].value = arrTexts[i];
}
}

/***********revrse by id******/
function sortreverse_id() {
var lb = document.getElementById('mylist');
arrTexts = new Array();

for(i=0; i<lb.length; i++)  {
  arrTexts[i] = lb.options[i].text;
}

arrTexts.reverse();

for(i=0; i<lb.length; i++)  {
  lb.options[i].text = arrTexts[i];
  lb.options[i].value = arrTexts[i];
}
}
</script>



  ID<a href="javascript:sortlist_id()"> &#x25B2;  </a> <a href="javascript:sortreverse_id()">&#x25BC;</a> |  Name<a href="javascript:sortlist_name()"> &#x25B2;  </a> <a href="javascript:sortreverse_name()">&#x25BC;</a><br/>

<select name=mylist id=mylist size=8 style='width:150px'>

<option value="bill">4 -> Bill</option>
<option value="carl">5 -> Carl</option>
<option value="Anton">1 -> Anton</option>
<option value="mike">2 -> Mike</option>
<option value="peter">3 -> Peter</option>
</select>
<br>
于 2013-11-29T07:01:26.523 回答
0
function sortItems(c) {
var options = c.options;
Array.prototype.sort.call(options, function (a, b) {
    var aText = a.text.toLowerCase();
    var bText = b.text.toLowerCase();
    if (aText < bText) {
        return -1;
    } else if (aText > bText) {
        return 1;
    } else {
        return 0;
    }
});
}

sortItems(document.getElementById('lstALL'));
于 2015-07-27T12:21:27.050 回答
0

对于那些想要排序是否有optgroup的人:

/**
 * Sorting options 
 * and optgroups
 * 
 * @param selElem select element
 * @param optionBeforeGroup ?bool if null ignores, if true option appear before group else option appear after group
 */
function sortSelect(selElem, optionBeforeGroup = null) {
    let initialValue = selElem.tagName === "SELECT" ? selElem.value : null; 
    let allChildrens = Array.prototype.slice.call(selElem.childNodes);
    let childrens = [];

    for (let i = 0; i < allChildrens.length; i++) {
        if (allChildrens[i].parentNode === selElem && ["OPTGROUP", "OPTION"].includes(allChildrens[i].tagName||"")) {
            if (allChildrens[i].tagName == "OPTGROUP") {
                sortSelect(allChildrens[i]);
            }
            childrens.push(allChildrens[i]);
        }
    }

    childrens.sort(function(a, b){
        let x = a.tagName == "OPTGROUP" ? a.getAttribute("label") : a.innerHTML;
        let y = b.tagName == "OPTGROUP" ? b.getAttribute("label") : b.innerHTML;
        x = typeof x === "undefined" || x === null ? "" : (x+"");
        y = typeof y === "undefined" || y === null ? "" : (y+"");

        if (optionBeforeGroup === null) {
            if (x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
            if (x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
        } else if (optionBeforeGroup === true) {
            if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
            if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
        } else if (optionBeforeGroup === false) {
            if ((a.tagName == "OPTGROUP" && b.tagName == "OPTION") || x.toLowerCase().trim() < y.toLowerCase().trim()) {return -1;}
            if ((a.tagName == "OPTION" && b.tagName == "OPTGROUP") || x.toLowerCase().trim() > y.toLowerCase().trim()) {return 1;}
        }
        return 0;
    });

    if (optionBeforeGroup !== null) {
        childrens.sort(function(a, b){
            if (optionBeforeGroup === true) {
                if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return -1;}
                if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return 1;}
            } else {
                if (a.tagName == "OPTGROUP" && b.tagName == "OPTION") {return -1;}
                if (a.tagName == "OPTION" && b.tagName == "OPTGROUP") {return 1;}
            }
            return 0;
        });
    }

    selElem.innerHTML = "";
    for (let i = 0; i < childrens.length; i++) {
        selElem.appendChild(childrens[i]);
    }

    if (selElem.tagName === "SELECT") {
        selElem.value = initialValue;
    }
}
于 2019-09-18T17:29:44.913 回答
0

我认为我的函数对于字符串或数字更通用,并且如果第一个元素可能意味着全部,则不会对其进行排序。

/** Check if a string can be parsed as a number. */
function isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) };

/** Sort options of HTML elements. */
function sortOptions(selectElement, exceptFirstOpt=false) {

    // List of options.
    var options = selectElement.options;
    // If empty list, do nothing.
    if(!options || options.length==0) return;

    // Array.
    var optionsArray = [];
    for (var i = (exceptFirstOpt ? 1 : 0); i < options.length; i++)
        optionsArray.push(options[i]);
    // Sort.
    optionsArray = optionsArray.sort(function (a, b) {      
        let v1 = a.innerHTML.toLowerCase();
        let v2 = b.innerHTML.toLowerCase();
        if((v1==undefined || v1 == '') && (v2==undefined || v2 == ''))
            return 0;
        else if(v1==undefined || v1.trim() == '') return 1;
        else if(v2==undefined || v2.trim() == '') return -1;

        // If number.
        if(isNumber(v1) && isNumber(v2))
            return parseFloat(v1)>parseFloat(v2);

        return v1.localeCompare(v2);   
    });

    // Update options.
    for (var i = 0; i <= optionsArray.length; i++)            
        options[i + (exceptFirstOpt ? 1 : 0)] = optionsArray[i];
    // First option selected by default.
    options[0].selected = true;
}
于 2021-06-06T16:15:16.723 回答