Cách hiệu quả nhất để sắp xếp các Tùy chọn của Html Select theo giá trị, trong khi vẫn giữ nguyên mục hiện được chọn là gì?


80

Tôi có jQuery nhưng tôi không chắc liệu nó có bất kỳ trình trợ giúp sắp xếp tích hợp nào không. Tôi có thể làm cho một mảng 2ngày của từng mục text, valueselectedtài sản, nhưng tôi không nghĩ rằng javascript được tích hợp sẵn Array.sort()sẽ làm việc một cách chính xác.


4
Lưu ý để tự (kể từ khi tôi đã quay trở lại câu hỏi nhiều lần này qua google): đây là một giải pháp tốt mà bạn đã viết: gist.github.com/1072537
Travis

Câu trả lời:


134

Trích xuất các tùy chọn thành một mảng tạm thời, sắp xếp, sau đó xây dựng lại danh sách:

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

Tài liệu sắp xếp của Mozilla (cụ thể là so sánh) và trang Thuật toán sắp xếp của Wikipedia có liên quan.

Nếu bạn muốn phân biệt chữ hoa chữ thường, hãy thay thế textbằngtext.toLowerCase()

Hàm sắp xếp hiển thị ở trên minh họa cách sắp xếp. Việc sắp xếp chính xác các ngôn ngữ không phải tiếng Anh có thể phức tạp (xem thuật toán đối chiếu unicode ). Sử dụng localeCompare trong hàm sắp xếp là một giải pháp tốt, ví dụ:

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

1
xem xét lại câu hỏi này 3 năm sau đó, và tuyến đường này có vẻ như đúng cách để đi
Travis

8
Lưu ý rằng điều này phân biệt chữ hoa chữ thường - nghĩa là, nó sẽ sắp xếp tất cả những thứ bắt đầu bằng chữ hoa trước những thứ bắt đầu bằng chữ thường. Nếu đây là mong muốn, chỉ cần thêm một .toUpperCase()sau mỗi lần.text
TJ Ellis

10
Ngoài ra, nó sẽ không giữ nguyên tùy chọn hiện đang được chọn trong tất cả các trình duyệt (Chrome nhớ những gì đã được chọn, nhưng firefox và tức là không, và chọn phần tử cuối cùng sau khi các tùy chọn được đọc). Để khắc phục điều này, hãy lưu giá trị đã chọn hiện tại trước khi sắp xếp, sau đó chọn lại. tức là, trước khi làm bất cứ điều gì khác var selected = $("#my_select").val(); và sau đó sau khi các tùy chọn được sắp xếp đã được thêm vào, hãy khôi phục val, tức là$("#my_select").val(selected);
TJ Ellis

3
mát mẻ. các từ 'khác' có thể bị loại bỏ. trả về vẫn kết thúc chức năng.
EliSherer

@TJEll liên quan đến phân biệt chữ hoa chữ thường, câu hỏi này cung cấp thêm thông tin tại sao người ta nên sử dụng .toUpperCase()so với .toLowerCase()khi bỏ qua các trường hợp stackoverflow.com/questions/2140627/…
Adrien Be vào

20

Đã sửa đổi một chút câu trả lời của Tom ở trên để nó thực sự sửa đổi nội dung của hộp chọn được sắp xếp, thay vì chỉ trả về các phần tử đã được sắp xếp.

$('#your_select_box').sort_select_box();

Hàm 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
Câu trả lời này là gần phía trên, nhưng không chọn một cách chính xác
thouliha

18

Tôi vừa gói gọn ý tưởng của Mark trong một hàm jquery

$('#your_select_box').sort_select_box();

Hàm 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;
}

làm thế nào tôi có thể thêm điều này vào sự kiện nhấp chuột hiện tại của tôi? $ ('# addwire'). click (function () {return! $ ('# wireelection option: đã chọn'). remove (). appendTo ('# wire'). sort_select_box ();}); dường như không hoạt động
mcgrailm

12

Giải pháp mà tôi đã đề cập trong nhận xét của mình cho @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);
    });
}

Sử dụng:

$("select").sortOptions();

Điều này vẫn có thể được cải thiện, nhưng tôi không cần thêm bất kỳ chuông hoặc còi nào nữa :)


6

Chà, trong IE6, nó dường như sắp xếp trên mục [0] của mảng lồng nhau:

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];
    }
}

Tôi sẽ xem liệu điều này có hoạt động trên các trình duyệt khác không ...

Chỉnh sửa: nó cũng hoạt động trong Firefox, xin chào!

Có cách nào dễ dàng hơn cách này không? có phương pháp nào đó được tích hợp trong javascript hoặc jQuery sắp xếp các lựa chọn mà tôi đang thiếu không, hay đây là cách tốt nhất?


8
Lưu ý rằng hàm này không sắp xếp các phần tử tùy chọn ; nó thay đổi [giá trị, văn bản, đã chọn] trên các phần tử hiện có để chúng được sắp xếp (theo giá trị trong trường hợp này). Điều này là đủ cho hầu hết các ứng dụng, nhưng nếu bạn có các thuộc tính khác (CSS, mẹo công cụ, v.v.) thì cách tiếp cận này sẽ không đủ.
NVRAM

6

một thẻ jQuery đã đóng cho một loại có thể hoạt động, nhưng không được đưa vào lõi.

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

Được tham chiếu từ chuỗi Google Groups , tôi nghĩ bạn chỉ cần chuyển vào một hàm được sử dụng để sắp xếp, như vậy

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

Hy vọng nó giúp!


1
Một số vấn đề về chức năng sortSelect: Chức năng này không xem xét các tùy chọn ngang nhau. Sắp xếp theo giá trị và không theo văn bản. Các đối tượng jQuery không có thuộc tính có tên là "tùy chọn". Không có bất kỳ hiệu ứng nào, vì bạn phải nối các tùy chọn vào một phần tử chọn mới.
simon

4

Đây là một giải pháp tốt hơn. Khai báo một hàm toàn cục cho 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);
}

Và gọi hàm từ mã.

$("#my_select").sortSelect();

1
Tôi đã sử dụng một biến thể cho điều này, gói phần bên trong bằng $ (this) .each () để tôi có thể chuyển nó một bộ chọn để xử lý nhiều hơn một cái cùng một lúc.
Tom Pietrosanti

1
Ngoài ra, bạn cần phải sử dụng $(this)thay vì chỉthis
Tom Pietrosanti

2

Array.sort()mặc định chuyển đổi từng phần tử thành một chuỗi và so sánh các giá trị đó. Vì vậy, ["value", "text", "selected"]được sắp xếp như "value, text, selected". Mà có lẽ sẽ hoạt động tốt, hầu hết thời gian.

Nếu bạn muốn sắp xếp theo giá trị một mình hoặc giải thích giá trị dưới dạng số, thì bạn có thể chuyển một hàm so sánh vào sort ():

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

1

Hãy nhớ: nếu bạn muốn sử dụng bộ chọn ngữ cảnh, chỉ cần nối ID sẽ không hoạt động

$.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

Hơi muộn nhưng vì những gì đáng giá, tôi đã triển khai một chức năng phức tạp hơn mà bạn có thể đưa vào một cách chung chung. Nó có một số tùy chọn cho đầu ra khác nhau. Nó cũng có thể đệ quy thành <OPTGROUP>các thẻ dựa trên nhãn của chúng.

$.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;

};

Sau đó, bạn có thể gọi sortSelect()hàm trên bất kỳ <SELECT>thẻ nào hoặc chỉ một thẻ <OPTGROUP>để chỉ sắp xếp các tùy chọn của một nhóm.

Thí dụ:

$('select').sortSelect();

Đảo ngược thứ tự bằng cách sử dụng tùy chọn "đảo ngược":

$('select').sortSelect({
    reverse: true
});

Bạn có thể áp dụng điều này cho tất cả các lựa chọn tự động, có lẽ chỉ khi chúng bao gồm một lớp quan trọng (ví dụ: "js-sort") với cái này:

$('select.js-sort').each(function(k, v){
    $(v).sortSelect();
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.