代码之家  ›  专栏  ›  技术社区  ›  Julius A

Javascript对select元素的内容进行排序

  •  31
  • Julius A  · 技术社区  · 17 年前

    请告诉我你有什么想法。

    <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>
    
    18 回复  |  直到 17 年前
        1
  •  74
  •   Andrew T.    12 年前

    这样就行了。只需将选择元素a la传递给它: 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;
    }
    
        2
  •  46
  •   Community Mohan Dere    9 年前

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

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

    从…起 Sorting dropdown list using Javascript

        3
  •  6
  •   Matt K    14 年前

    根据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);
    
        4
  •  5
  •   protoEvangelion    7 年前

    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毫秒 在我的机器上。

        5
  •  4
  •   Bill the Lizard    17 年前

    W3C FAQ :

    尽管许多编程语言都有下拉框之类的设备,能够在将项目列表显示为其功能的一部分之前对其进行排序,但HTML<选择>函数没有这样的功能。它列出了<选项>按照收到的订单。

    对于静态HTML文档,您必须手动对它们进行排序,对于动态文档,您必须求助于Javascript或其他编程排序。

        6
  •  4
  •   mikehowles    15 年前

    另一种选择:

    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;
    }
    
        7
  •  4
  •   Tony Chiboucas    12 年前

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

    • 乔克最好最简单的答案。
    • Terry Porter的简易jQuery方法。
    • SmokeyHP的可配置功能。

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

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

    按文本排序示例(所有示例都将按文本排序):

     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);
    

    主排序函数

    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;
    }
    
        8
  •  3
  •   Marco Lazzeri    17 年前

    我也有同样的问题。这是我的建议 jQuery解决方案 我想到了:

      var options = jQuery.makeArray(optionElements).
                           sort(function(a,b) {
                             return (a.innerHTML > b.innerHTML) ? 1 : -1;
                           });
      selectElement.html(options);
    
        9
  •  2
  •   colinbashbash    13 年前

    我有一个类似的问题,除了我希望选中的项目显示在顶部,并且我不想清除选中的项目(多选列表)。我的是基于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);
    }
    
        10
  •  1
  •   Joel Martinez    17 年前

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

    这个 Javascript Sort 方法将是你在这里的朋友。只需从选择列表中拉出值,然后对其进行排序,然后将其放回:-)

        11
  •  1
  •   Matias P.    15 年前

    我认为这是一个更好的选择(我使用@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;
            }
    
        12
  •  1
  •   HoLyVieR    15 年前

    我之所以使用冒泡排序,是因为我无法按照选项数组中的.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;
              }
    }
    
        13
  •  1
  •   MDEV    13 年前

    我很快就创建了一个允许选择方向(“asc”或“desc”)、是否应该对选项值(true或false)进行比较以及是否应该在比较之前修剪前导和尾随空格(布尔值)的选项。

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

    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;
    }
    
        14
  •  1
  •   Community Mohan Dere    9 年前

    受@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;
        }
    })
    

    希望能有所帮助

    First example Second example

        15
  •  1
  •   lsouza    11 年前
    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);
        }
    }
    

    其思想是将selectbox的所有元素拖出到一个数组中,删除selectbox值以避免覆盖,对数组进行排序,然后将排序后的数组推回到selectbox中

        16
  •  0
  •   Geoff    16 年前

    没有Marco的JQuery示例那么漂亮,但是使用prototype(我可能缺少一个更优雅的解决方案),它将是:

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

    然后只需向其传递一个select元素:

    sort_select( $('category-select') );
    
        17
  •  0
  •   jerone    14 年前

    使用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);
    });
    
        18
  •  0
  •   Charles    12 年前

    尝试一下……希望它能为您提供一个解决方案:

    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>
    
        19
  •  0
  •   Joel    11 年前
    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'));
    
        20
  •  0
  •   Jordan Daigle    7 年前

    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;
        }
    }
    
        21
  •  0
  •   Bruno L.    5 年前

    我认为我的函数对于字符串或数字更为通用,如果第一个元素可能表示所有,则不会对其进行排序。

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