현재 선택된 항목을 유지하면서 Html Select의 옵션을 값별로 정렬하는 가장 효율적인 방법은 무엇입니까?


81

jQuery가 있지만 내장 정렬 도우미가 있는지 확실하지 않습니다. 각 항목의 text, valueselected속성에 대한 2d 배열을 만들 수는 있지만 javascript가 내장되어 Array.sort()제대로 작동 하지 않을 것이라고 생각 합니다.


4
본인에게 메모 (Google을 통해이 질문에 여러 번 돌아 왔기 때문에) : 여기에 작성한 좋은 솔루션이 있습니다. gist.github.com/1072537
travis

답변:


135

옵션을 임시 배열로 추출하고 정렬 한 다음 목록을 다시 작성합니다.

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의 정렬 문서 (특히 compareFunction)와 Wikipedia의 정렬 알고리즘 페이지 는 관련이 있습니다.

정렬 대소 문자를 구분하지 않으려면 다음으로 바꾸십시오 text.text.toLowerCase()

위에 표시된 정렬 기능은 정렬 방법을 보여줍니다. 영어가 아닌 언어를 정확하게 정렬하는 것은 복잡 할 수 있습니다 ( 유니 코드 데이터 정렬 알고리즘 참조 ). 정렬 함수에서 localeCompare 를 사용 하는 것이 좋은 해결책입니다. 예 :

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

1
나중에 3 년이 질문을 다시 방문,이 경로를 이동하는 올바른 방법처럼 보인다 것은
트래비스

8
대소 문자를 구분합니다. 즉, 소문자로 시작하는 항목보다 먼저 대문자로 시작하는 모든 항목을 정렬합니다. 이 바람직하지 않은 경우, 단지를 추가 .toUpperCase()각 후.text
TJ 엘리스

10
또한 모든 브라우저에서 현재 선택된 옵션을 그대로 유지하지 않습니다 (Chrome은 선택한 항목을 기억했지만 firefox는 기억하지 않았고 옵션을 읽은 후 마지막 요소를 선택했습니다). 이 문제를 해결하려면 정렬하기 전에 현재 선택한 값을 저장 한 다음 다시 선택하십시오. 즉, 다른 작업을 수행하기 전에 var selected = $("#my_select").val(); 정렬 된 옵션이 추가 된 후 val을 복원합니다. 즉$("#my_select").val(selected);
TJ Ellis

3
멋있는. 'else'단어는 제거 할 수 있습니다. 어쨌든 반환은 기능을 종료합니다.
EliSherer

하나를 사용해야하는 이유 대소 문자 구분에 관한 @TJEllis,이 문제는 더 많은 정보를 제공한다 .toUpperCase().toLowerCase()무시하는 경우 때 stackoverflow.com/questions/2140627/...
아드는 수

20

정렬 된 요소를 반환하는 대신 정렬 할 선택 상자의 내용을 실제로 수정하도록 Tom의 대답을 약간 수정했습니다.

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

1
이 답변은 상단에 근접하지만, 제대로 선택하지 않습니다
thouliha

18

Mark의 아이디어를 jquery 함수로 래핑했습니다.

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

현재 클릭 이벤트에 어떻게 추가 할 수 있습니까? $ ( '# addwire'). click (function () {return! $ ( '# wireselection option : selected'). remove (). appendTo ( '# wires'). sort_select_box ();}); 작동하지 않는 것 같습니다
mcgrailm

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

이것은 여전히 ​​개선 될 수 있지만 더 이상 종이나 휘파람을 추가 할 필요가 없습니다. :)


6

음, 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에서도 작동합니다, 우후!

그래도 이것보다 쉬운 방법이 있습니까? 내가 놓친 선택을 정렬하는 자바 스크립트 또는 jQuery에 내장 된 방법이 있습니까? 아니면 이것이 가장 좋은 방법입니까?


8
이 함수는 옵션 요소를 정렬하지 않습니다 . 기존 요소 의 [value, text, selected] 를 변경하여 정렬되도록합니다 (이 경우 값별로). 이것은 대부분의 응용 프로그램에 충분하지만 다른 속성 (CSS, 도구 설명 등)이있는 경우에는이 방법으로 충분하지 않습니다.
NVRAM

6

거기에 폐쇄 jQuery를 티켓 작동합니다 일종의에 대한,하지만 단지의 핵심에 포함되지 않았습니다.

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

Google 그룹스 스레드 에서 참조 하면 정렬에 사용되는 함수를 다음과 같이 전달하는 것 같습니다.

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

도움이 되었기를 바랍니다.


1
sortSelect 함수에 대한 몇 가지 문제 : 동일한 옵션을 고려하지 않습니다. 텍스트가 아닌 값에 따라 정렬합니다. jQuery 객체에는 "options"라는 속성이 없습니다. 새 선택 요소에 옵션을 추가해야하므로 효과가 없습니다.
사이먼

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

1
나는 이것에 변형을 사용하여 $ (this) .each () 내부 부분을 래핑하여 한 번에 여러 개를 처리하도록 선택자를 전달할 수 있습니다.
Tom Pietrosanti 2012 년

1
또한, $(this)대신 사용해야 합니다this
Tom Pietrosanti

2

Array.sort()기본적으로 각 요소를 문자열로 변환하고 해당 값을 비교합니다. 그래서 ["value", "text", "selected"]으로 분류됩니다 "value, text, selected". 대부분의 경우 잘 작동합니다.

값만 기준으로 정렬하거나 값을 숫자로 해석하려면 비교 함수를 sort ()에 전달할 수 있습니다.

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

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

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

"reverse"옵션을 사용하여 역순 :

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

모든 선택에 자동으로 적용 할 수 있습니다. 아마도 다음과 같이 중요한 클래스 (예 : "js-sort")를 포함하는 경우에만 가능합니다.

$('select.js-sort').each(function(k, v){
    $(v).sortSelect();
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.