Bagaimana cara menyembunyikan <option> di menu <select> dengan CSS?

103

Saya menyadari bahwa Chrome, tampaknya, tidak mengizinkan saya bersembunyi <option>di file <select>. Firefox akan.

Saya perlu menyembunyikan <option>s yang cocok dengan kriteria pencarian. Di alat web Chrome saya dapat melihat bahwa mereka disetel dengan benar display: none;oleh JavaScript saya, tetapi setelah <select>menu diklik, mereka ditampilkan.

Bagaimana saya bisa membuat ini <option>yang sesuai dengan kriteria pencarian saya TIDAK muncul saat menu diklik? Terima kasih!

Jesse Atkinson
sumber
4
Alih-alih bersembunyi dan muncul di pencarian. Coba dan isi pilihan tergantung pada pencarian
Henesnarfel
1
Saya setuju dengan Henesnarfel. Jika Anda sudah melakukan pencarian atau beberapa jenis kueri, Anda harus dapat mengisi yang Anda inginkan.
Michael Stramel
1
ini berfungsi dengan baik untuk saya di Chrome 16.0.912.77 m. Apakah saya salah memahami masalahnya?
mgibsonbr
3
@mgibsonbr Tidak berfungsi lintas browser.
Jasper
3
@Henesnarfel Ada alasan bagus untuk menyembunyikan opsi. Misalnya, saya memiliki halaman dengan kotak daftar pilih dan tautan untuk menyembunyikan atau menampilkan item yang ditandai sebagai tidak aktif. Tidak ada alasan untuk menyimpan beberapa daftar atau meminta server untuk daftar baru setiap kali pengguna mengubah opsi itu.
Ryan P

Jawaban:

69

Anda harus menerapkan dua metode untuk bersembunyi. display: noneberfungsi untuk FF, tetapi tidak untuk Chrome atau IE. Jadi metode kedua membungkus <option>dalam <span>dengan display: none. FF tidak akan melakukannya (HTML secara teknis tidak valid, sesuai spesifikasi) tetapi Chrome dan IE akan dan itu akan menyembunyikan opsi.

EDIT: Oh ya, saya sudah menerapkan ini di jQuery:

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        if( jQuery( this ).parent( 'span.toggleOption' ).length == 0 )
            jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

EDIT 2: Inilah cara Anda menggunakan fungsi ini:

jQuery(selector).toggleOption(true); // show option
jQuery(selector).toggleOption(false); // hide option

EDIT 3: Menambahkan pemeriksaan ekstra yang disarankan oleh @ user1521986

Ryan P.
sumber
1
Metode gila ini adalah satu-satunya yang benar-benar berfungsi sepenuhnya lintas browser dan tidak melibatkan pembuatan peretasan kotak pilih yang tersembunyi.
Jesse Atkinson
15
Hati-hati dengan ini. Tampaknya berfungsi dengan baik pada awalnya tetapi di suatu tempat di sepanjang garis itu berhenti. Ini demo kecilnya: jsfiddle.net/Yb6sk/9
Bill Criswell
17
Meskipun solusi ini menyembunyikan elemen, setiap upaya untuk membaca nilai <select>(menggunakan jQuery's .val()) akan kembali null. Saya baru saja menguji ini di Chrome 29, jadi berhati-hatilah bagi Karyawan Google!
Tandai
10
Retasan yang menarik, tetapi saya akan merekomendasikan untuk menghindari "HTML yang secara teknis tidak valid" jika memungkinkan.
Luke
3
Benar, semua browser memiliki implementasi yang berbeda. Tetapi satu alasan browser tidak dapat secara ketat menerapkan spesifikasi standar adalah karena terlalu banyak kode langsung di luar sana yang tidak mengikuti spesifikasi. IMO: Jika tidak ada solusi lain, maka gunakan cara hack. Tetapi jika Anda dapat mengikuti spesifikasi dan menyelesaikan masalah Anda, mengapa tidak? Ini membantu kode Anda untuk bermain bagus dengan orang lain dan membantu memperkuat spesifikasi.
Lukas
82

Untuk HTML5, Anda dapat menggunakan atribut 'tersembunyi'.

<option hidden>Hidden option</option>

Itu tidak didukung oleh IE <11. Tetapi jika Anda hanya perlu menyembunyikan beberapa elemen, mungkin akan lebih baik untuk hanya mengatur atribut tersembunyi dalam kombinasi dengan nonaktif dibandingkan dengan menambahkan / menghapus elemen atau melakukan konstruksi yang tidak benar secara semantik.

<select>  
  <option>Option1</option>
  <option>Option2</option>
  <option hidden>Hidden Option</option>
</select>

Referensi .

Lukas Jelinek
sumber
4
IE 11 mendukung ini.
Iván Pérez
7
Ini adalah jawaban modern. Idealnya kami juga menyetel ini disabledsehingga browser yang tidak mendukung atribut global HTML5hidden akan memiliki beberapa indikasi visual untuk pengguna.
cloudworks
1
Bagaimana Anda menggunakan teknik ini dengan CSS?
Dapatkan Gratis
7
Tidak berfungsi di Safari, Edge, atau IE. Bug untuk Safari sudah 10 tahun, tolong bantu dengan memperbarui tambalan yang ada. Tidak dapat menemukan bug di pelacak masalah Edge.
Memanjakan diri
7
Solusi untuk ini adalah menggunakan <option hidden disabled>, jadi itu bersembunyi di semua browser yang baik dan menonaktifkannya di browser lain.
Ramon Balthazar
37

Saya menyarankan agar Anda tidak menggunakan solusi yang menggunakan <span>pembungkus karena ini bukan HTML yang valid, yang dapat menyebabkan masalah di kemudian hari. Saya pikir solusi yang disukai adalah benar-benar menghapus opsi apa pun yang ingin Anda sembunyikan, dan memulihkannya sesuai kebutuhan. Menggunakan jQuery, Anda hanya membutuhkan 3 fungsi berikut:

Fungsi pertama akan menyimpan konten asli yang dipilih . Untuk amannya, Anda mungkin ingin memanggil fungsi ini saat Anda memuat halaman.

function setOriginalSelect ($select) {
    if ($select.data("originalHTML") == undefined) {
        $select.data("originalHTML", $select.html());
    } // If it's already there, don't re-set it
}

Fungsi selanjutnya ini memanggil fungsi di atas untuk memastikan bahwa konten asli telah disimpan, dan kemudian menghapus opsi dari DOM.

function removeOptions ($select, $options) {
    setOriginalSelect($select);
    $options.remove();
 }

Fungsi terakhir dapat digunakan kapan pun Anda ingin "mengatur ulang" kembali ke semua opsi awal.

function restoreOptions ($select) {
    var ogHTML = $select.data("originalHTML");
    if (ogHTML != undefined) {
        $select.html(ogHTML);
    }
}

Perhatikan bahwa semua fungsi ini mengharapkan Anda meneruskan elemen jQuery. Sebagai contoh:

// in your search function...
var $s = $('select.someClass');
var $optionsThatDontMatchYourSearch= $s.find('options.someOtherClass');
restoreOptions($s); // Make sure you're working with a full deck
removeOptions($s, $optionsThatDontMatchYourSearch); // remove options not needed

Berikut adalah contoh yang berfungsi: http://jsfiddle.net/9CYjy/23/

Luke
sumber
3
Dapat diandalkan dan bukan hack. Jawaban yang bagus!
Jeremy Cook
1
@DanBeaulieu Ada fungsi bernama salah di jsfiddle sebelumnya. Saya memperbaiki dan memperbarui tautan di atas. Terima kasih sudah menangkapnya.
Lukas
Ya, ini juga pilihanku. Saya benar-benar berhasil membuat kode golf sedikit lebih kecil, dengan terlebih dahulu mengambil nilai data ke dalam variabel, jika tidak ditentukan, itu akan menyimpan opsi, kalau tidak itu akan mengembalikan opsi. Kebutuhan saya khusus untuk itu.
diynevala
1
Saya harus menambahkan var value=$select.val(); $select.html(ogHTML); $select.val(value);agar nilai yang dipilih tetap dipilih bahkan setelah pemulihan.
diynevala
Siklus pemilihan opsi untuk menghapus dan menghapusnya hanya bekerja satu kali. Setelah itu, options.remove () tidak berpengaruh bagi saya. Setelah saya memindahkan pemanggilan restoreOptions ($ s) beberapa baris sehingga saya selalu bekerja dengan objek Select yang lengkap dan segar, itu berhasil.
Newclique
18

Jawaban Ryan P harus diubah menjadi:

    jQuery.fn.toggleOption = function (show) {
        $(this).toggle(show);
        if (show) {
            if ($(this).parent('span.toggleOption').length)
                $(this).unwrap();
        } else {
            **if ($(this).parent('span.toggleOption').length==0)**
                $(this).wrap('<span class="toggleOption" style="display: none;" />');
        }
    };

Jika tidak, tag akan terbungkus terlalu banyak

JeffT
sumber
5
Perhatikan bahwa menurut spesifikasi HTML ( w3.org/TR/html5/forms.html#the-select-element ), a <select>hanya boleh berisi <option>atau <optgroup>atau elemen pendukung skrip. Jadi, Anda harus menghindari penggunaan <span>pembungkus yang tidak valid .
Lukas
9

Fungsi toggleOption tidak sempurna dan menimbulkan bug jahat di aplikasi saya. jQuery akan bingung dengan .val () dan .arraySerialize () Coba pilih opsi 4 dan 5 untuk melihat apa yang saya maksud:

<select id="t">
<option value="v1">options 1</option>
<option value="v2">options 2</option>
<option value="v3" id="o3">options 3</option>
<option value="v4">options 4</option>
<option value="v5">options 5</option>
</select>
<script>
jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        if( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};

$("#o3").toggleOption(false); 
$("#t").change(function(e) {
    if($(this).val() != this.value) {
    console.log("Error values not equal", this.value, $(this).val());
    }
});
</script>
Batiste Bieler
sumber
8

Pilih masukan rumit dengan cara ini. Bagaimana dengan menonaktifkannya, ini akan berfungsi lintas browser:

$('select').children(':nth-child(even)').prop('disabled', true);

Ini akan menonaktifkan setiap <option>elemen lainnya , tetapi Anda dapat memilih mana yang Anda inginkan.

Ini demo nya: http://jsfiddle.net/jYWrH/

Catatan: Jika Anda ingin menghapus properti nonaktif dari suatu elemen, Anda dapat menggunakan .removeProp('disabled').

Memperbarui

Anda dapat menyimpan <option>elemen yang ingin Anda sembunyikan di elemen pilih tersembunyi:

$('#visible').on('change', function () {
    $(this).children().eq(this.selectedIndex).appendTo('#hidden');
});

Anda kemudian dapat menambahkan <option>elemen kembali ke elemen pilih asli:

$('#hidden').children().appendTo('#visible');

Dalam dua contoh ini, diharapkan elemen pemilihan yang terlihat memiliki id visibledan elemen pemilihan tersembunyi memiliki id hidden.

Ini demonya: http://jsfiddle.net/jYWrH/1/

Perhatikan bahwa .on()ini baru di jQuery 1.7 dan dalam penggunaan untuk jawaban ini sama dengan .bind(): http://api.jquery.com/on

Jasper
sumber
7

Jawaban sederhana: Anda tidak bisa. Elemen bentuk memiliki kemampuan penataan yang sangat terbatas.

Alternatif terbaik adalah mengatur disabled=trueopsi (dan mungkin warna abu-abu, karena hanya IE yang melakukannya secara otomatis), dan ini akan membuat opsi tidak dapat diklik.

Atau, jika Anda bisa, hapus optionelemen sepenuhnya .

Niet the Dark Absol
sumber
6
// Simplest way

var originalContent = $('select').html();

$('select').change(function() {
    $('select').html(originalContent); //Restore Original Content
    $('select option[myfilter=1]').remove(); // Filter my options
});
Rene Berwanger
sumber
4

Karena Anda sudah menggunakan JS, Anda dapat membuat elemen SELECT yang tersembunyi di halaman, dan untuk setiap item yang Anda coba sembunyikan di daftar itu, pindahkan ke daftar tersembunyi. Dengan cara ini, mereka dapat dengan mudah dipulihkan.

Saya tidak tahu cara begitu saja melakukannya dalam CSS murni ... Saya akan berpikir bahwa trik display: none akan berhasil.

Derreck Dean
sumber
2

!!! PERINGATAN !!!

Ganti "IF" kedua dengan "WHILE" atau tidak berfungsi!

jQuery.fn.toggleOption = function( show ) {
    jQuery( this ).toggle( show );
    if( show ) {
        while( jQuery( this ).parent( 'span.toggleOption' ).length )
            jQuery( this ).unwrap( );
    } else {
        jQuery( this ).wrap( '<span class="toggleOption" style="display: none;" />' );
    }
};
Arraxas
sumber
2

Anda harus menghapusnya dari <select>menggunakan JavaScript. Itulah satu-satunya cara yang dijamin untuk membuat mereka pergi.

Yordania
sumber
1
Menggunakan jQuery, ini dapat dilakukan dengan menghapus:$('options').remove();
Luke
2

yang satu ini sepertinya berhasil untuk saya di chrome

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');
diasingkan
sumber
1
Harap tambahkan format kode ke kode Anda, baik dengan membuat indentasi dengan 4 spasi atau membungkus kode Anda dengan `.
Pisang
1
kode ini bagus! ini berfungsi pada chrome, firefox, dan IE 11 terbaru, itu cukup baik untuk saya :)
Sijav
1
sebelum komentar terakhir saya, hal ini juga berfungsi di IE 7! jadi ff 3.5, inilah yang saya dapatkan pada akhirnya, entah bagaimana di IE dan chrome mempertahankan nilai yang telah dipilih sebelum opsi disembunyikan dan jika nilai lain tidak diatur setelah mengembalikan opsi, browser akan mengatur opsi dipilih seperti sebelumnya!
Sijav
0

Terlambat dalam permainan, tetapi sebagian besar tampaknya cukup rumit.

Begini cara saya melakukannya:

var originalSelect = $('#select-2').html();

// filter select-2 on select-1 change
$('#select-1').change(function (e) {

    var selected = $(this).val();

    // reset select ready for filtering
    $('#select-2').html(originalCourseSelect);

    if (selected) {
        // filter
        $('#select-2 option').not('.t' + selected).remove();
    }

});

markup pilihan-1:

<select id='select-1'>
<option value=''>Please select</option>
<option value='1'>One</option>
<option value='2'>Two</option>
</select>

markup dari pilih-2:

<select id='select-2'>
<option class='t1'>One</option>
<option class='t2'>Two</option>
<option>Always visible</option>
</select>
RichardAtHome
sumber