現在選択されているアイテムを保持しながら、HTML選択のオプションを値で並べ替える最も効率的な方法は何ですか?


81

jQueryを使用していますが、ソートヘルパーが組み込まれているかどうかはわかりません。私は、各項目のの2次元配列にすることができtextvalueおよびselectedプロパティを、私はに建てられたJavaScriptのはないと思いますArray.sort()正常に動作します。


4
自己への注意(私はグーグルを経由して戻ってこの質問への複数回来ているので):ここにあなたが書いたことは良い解決策だ:gist.github.com/1072537は
トラヴィス

回答:


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のソートアルゴリズムページが関連しています。

あなたは小文字を区別しないソートケースを作りたい場合は、交換するtexttext.toLowerCase()

上記の並べ替え関数は、並べ替えの方法を示しています。英語以外の言語を正確にソートすることは複雑になる可能性があります(Unicode照合アルゴリズムを参照)。sort関数でlocaleCompareを使用することは、良い解決策です。例:

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

1
3年後にこの質問を再検討すると、このルートは正しい道のように思えます
travis 2011

8
これは大文字と小文字が区別されることに注意してください。つまり、大文字で始まるすべてのものを小文字で始まるものの前にソートします。これが望ましくない場合は、.toUpperCase()それぞれの後にを追加してください.text
TJ Ellis

10
また、現在選択されているオプションをすべてのブラウザでそのまま保持するわけではありません(Chromeは選択されたものを記憶していましたが、Firefoxなどは記憶しておらず、オプションが再読み込みされた後に最後の要素を選択しました)。これを修正するには、ソートする前に現在選択されている値を保存してから、再度選択します。つまり、他の処理を行う前 var selected = $("#my_select").val(); に、ソートされたオプションが追加された後、値を復元します。つまり、$("#my_select").val(selected);
TJ Ellis

3
涼しい。「else」の単語は削除できます。とにかくリターンエンド機能。
EliSherer 2014年

大文字と小文字の区別に関する@TJEllis 1を使用する必要がありますなぜ、この質問は、さらに多くの情報を提供して.toUpperCase().toLowerCase()無視する場合は、ときstackoverflow.com/questions/2140627/...
エイドリアンはして

20

上記のトムの回答をわずかに変更して、並べ替えられた要素を返すだけでなく、並べ替えられる選択ボックスの内容を実際に変更するようにしました。

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

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 2011

12

@JuanPerezへのコメントで言及した解決策

$.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でも動作します。

しかし、これよりも簡単な方法はありますか?欠落している選択をソートするjavascriptまたはjQueryに組み込まれているメソッドはありますか、それともこれが最善の方法ですか?


8
この関数はオプション要素をソートしないことに注意してください。既存の要素の[value、text、selected]を変更して、(この場合は値で)並べ替えます。ほとんどのアプリケーションではこれで十分ですが、他の属性(CSS、ツールチップなど)がある場合は、このアプローチでは不十分です。
NVRAM

6

あります、閉じたjQueryのチケット動作するはずソートのためには、ちょうどコアに含まれていませんでした。

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

グーグルグループのスレッドから参照されいるので、ソートに使用される関数を渡すだけだと思います。

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

それが役に立てば幸い!


1
sortSelect関数に関するいくつかの問題:これは等しいオプションを考慮していません。テキストではなく値に従ってソートします。jQueryオブジェクトには、「options」という名前のプロパティがありません。新しいselect要素にオプションを追加する必要があるため、効果はありません。
simon 2012

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()でラップし、一度に複数を処理するセレクターを渡すことができるようにしました。
トムピエトロサンティ2012

1
また、$(this)代わりに使用する必要がありますthis
Tom Pietrosanti 2012

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>タグで関数を呼び出すか、1つ<OPTGROUP>だけでグループのオプションのみを並べ替えることができます。

例:

$('select').sortSelect();

「逆」オプションを使用した逆順:

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