Come nascondere una <option> in un menu <select> con CSS?


103

Mi sono reso conto che Chrome, a quanto pare, non mi permetterà di nascondermi <option>in un file <select>. Firefox lo farà.

Devo nascondere i messaggi di posta <option>elettronica che corrispondono a un criterio di ricerca. Negli strumenti web di Chrome posso vedere che sono stati impostati correttamente display: none;dal mio JavaScript, ma una volta <select>fatto clic sul menu vengono visualizzati.

Come posso fare in modo che questi messaggi <option>che corrispondono ai miei criteri di ricerca NON vengano visualizzati quando si fa clic sul menu? Grazie!


4
Invece di nascondersi e mostrare durante una ricerca. Prova a popolare la selezione in base alla ricerca
Henesnarfel

1
Sono d'accordo con Henesnarfel. Se stai già facendo una ricerca o un qualche tipo di query, dovresti essere in grado di compilare solo quelli che desideri.
Michael Stramel

1
questo funziona bene per me in Chrome 16.0.912.77 m. Sto fraintendendo il problema?
mgibsonbr

3
@mgibsonbr Non funziona cross-browser.
Jasper

3
@Henesnarfel Ci possono essere buoni motivi per nascondere le opzioni. Ad esempio, avevo una pagina con una casella di riepilogo di selezione e collegamenti per nascondere o mostrare gli elementi contrassegnati come inattivi. Nessun motivo per mantenere più elenchi o interrogare il server per un nuovo elenco ogni volta che l'utente modifica tale opzione.
Ryan P

Risposte:


69

Devi implementare due metodi per nasconderti. display: nonefunziona per FF, ma non per Chrome o IE. Quindi il secondo metodo è avvolgere il <option>in un <span>con display: none. FF non lo farà (HTML tecnicamente non valido, secondo le specifiche) ma Chrome e IE lo faranno e nasconderanno l'opzione.

EDIT: Oh sì, l'ho già implementato in 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: Ecco come useresti questa funzione:

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

MODIFICA 3: Aggiunto controllo extra suggerito da @ user1521986


1
Questo folle metodo è l'unico che in realtà ha funzionato completamente su più browser e non ha comportato la creazione di un hack di casella di selezione nascosta.
Jesse Atkinson

15
Stai attento con questo. All'inizio sembra funzionare alla grande, ma da qualche parte lungo la linea si ferma. Ecco una piccola demo: jsfiddle.net/Yb6sk/9
Bill Criswell

17
Sebbene questa soluzione nasconda l'elemento, qualsiasi tentativo di leggere il valore di <select>(utilizzando jQuery .val()) restituirà null. L'ho appena testato in Chrome 29, quindi i googler attenti!
Marco

10
Trucco interessante, ma consiglierei di evitare "HTML tecnicamente non valido" se possibile.
Luca

3
È vero, tutti i browser hanno implementazioni diverse. Ma uno dei motivi per cui i browser non possono implementare rigorosamente le specifiche standard è perché c'è troppo codice live là fuori che non segue le specifiche. IMO: Se non ci sono altre soluzioni, allora usa assolutamente un hack. Ma se puoi seguire le specifiche e risolvere il tuo problema, perché non dovresti? Aiuta il tuo codice a giocare bene con gli altri e aiuta a rafforzare le specifiche.
Luca

82

Per HTML5, puoi utilizzare l'attributo "nascosto".

<option hidden>Hidden option</option>

E ' non supportato da IE <11. Ma se avete bisogno solo di nascondere un paio di elementi, forse sarebbe meglio è sufficiente impostare l'attributo nascosto in combinazione con disabile in confronto ad aggiunta / rimozione di elementi o non fare semanticamente costruzioni corrette.

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

Riferimento .


4
IE 11 lo supporta.
Iván Pérez

7
Questa è la risposta moderna. Idealmente lo stiamo anche impostando in disabledmodo che i browser che non supportano l' attributo globale HTML5hidden abbiano qualche indicazione visiva per l'utente.
Cloudworks

1
Come usi questa tecnica con i CSS?
GetFree

7
Non funziona in Safari, Edge o IE. Bug per Safari ha 10 anni, per favore aiutaci aggiornando le patch esistenti. Impossibile trovare bug nel tracker dei problemi di Edge.
Indolenza

7
Una soluzione alternativa per questo è l'utilizzo <option hidden disabled>, quindi si nasconde in tutti i buoni browser e lo disabilita sugli altri.
Ramon Balthazar

37

Suggerirei di non utilizzare le soluzioni che utilizzano un <span>wrapper perché non è HTML valido, il che potrebbe causare problemi lungo la strada. Penso che la soluzione preferita sia rimuovere effettivamente tutte le opzioni che desideri nascondere e ripristinarle secondo necessità. Usando jQuery, avrai solo bisogno di queste 3 funzioni:

La prima funzione salverà il contenuto originale della selezione . Per sicurezza, potresti voler chiamare questa funzione quando carichi la pagina.

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

La prossima funzione chiama la funzione precedente per assicurarsi che i contenuti originali siano stati salvati e quindi rimuove semplicemente le opzioni dal DOM.

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

L'ultima funzione può essere utilizzata ogni volta che si desidera "ripristinare" tutte le opzioni originali.

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

Nota che tutte queste funzioni si aspettano che tu stia passando elementi jQuery. Per esempio:

// 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

Ecco un esempio funzionante: http://jsfiddle.net/9CYjy/23/


3
Affidabile e non un trucco. Bella risposta!
Jeremy Cook

1
@DanBeaulieu C'era una funzione denominata in modo errato nel precedente jsfiddle. Ho corretto e aggiornato il collegamento sopra. Grazie per averlo capito.
Luca

Sì, anche questa è stata una mia scelta. In realtà sono riuscito a golf il codice un po 'più piccolo, prendendo prima il valore dei dati in una variabile, se non definito, salverà le opzioni, altrimenti ripristinerà le opzioni. Il mio bisogno era specifico per questo.
diynevala

1
Ho dovuto aggiungere var value=$select.val(); $select.html(ogHTML); $select.val(value);per mantenere selezionato il valore selezionato anche dopo il ripristino.
diynevala

Il ciclo di selezione delle opzioni per rimuoverle e rimuoverle ha funzionato solo una volta. Dopodiché, options.remove () non ha avuto alcun effetto per me. Una volta spostato il restoreOptions ($ s) richiama alcune righe in modo da lavorare sempre con un oggetto Select completo e fresco, ha funzionato.
Newclique

18

La risposta di Ryan P dovrebbe essere modificata in:

    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;" />');
        }
    };

Altrimenti viene racchiuso in troppi tag


5
Tieni presente che secondo le specifiche HTML ( w3.org/TR/html5/forms.html#the-select-element ), a <select>dovrebbe contenere solo <option>o <optgroup>o elementi che supportano lo script. Quindi dovresti evitare di usare <span>wrapper non validi .
Luca

9

La funzione toggleOption non è perfetta e ha introdotto brutti bug nella mia applicazione. jQuery verrà confuso con .val () e .arraySerialize () Prova a selezionare le opzioni 4 e 5 per vedere cosa intendo:

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

8

Gli input selezionati sono complicati in questo modo. Che dire invece di disabilitarlo, questo funzionerà cross-browser:

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

Questo disabiliterà ogni altro <option>elemento, ma puoi selezionare quello che vuoi.

Ecco una demo: http://jsfiddle.net/jYWrH/

Nota: se vuoi rimuovere la proprietà disabilitata di un elemento puoi usare .removeProp('disabled').

Aggiornare

È possibile salvare gli <option>elementi che si desidera nascondere nell'elemento di selezione nascosto:

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

È quindi possibile aggiungere <option>nuovamente gli elementi all'elemento di selezione originale:

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

In questi due esempi ci si aspetta che l'elemento select visibile abbia l'id di visiblee l'elemento select nascosto abbia l'id di hidden.

Ecco una demo: http://jsfiddle.net/jYWrH/1/

Nota che .on()è nuovo in jQuery 1.7 e l'utilizzo di questa risposta è lo stesso di .bind(): http://api.jquery.com/on


7

Risposta semplice: non puoi. Gli elementi del modulo hanno capacità di stile molto limitate.

L'alternativa migliore sarebbe quella di impostare disabled=truel'opzione (e forse un colore grigio, poiché solo IE lo fa automaticamente), e questo renderà l'opzione non cliccabile.

In alternativa, se puoi, rimuovi completamente l' optionelemento.


6
// Simplest way

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

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

4

Dato che stai già utilizzando JS, puoi creare un elemento SELECT nascosto nella pagina e, per ogni elemento che stai cercando di nascondere in quell'elenco, spostarlo nell'elenco nascosto. In questo modo possono essere facilmente ripristinati.

Non conosco un modo per farlo in puro CSS ... avrei pensato che il display: nessun trucco avrebbe funzionato.


2

!!! AVVERTIMENTO !!!

Sostituisci il secondo "IF" con "WHILE" o non funziona!

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;" />' );
    }
};

2

Dovresti rimuoverli da <select>JavaScript. Questo è l'unico modo garantito per farli andare via.


1
Utilizzando jQuery, questo può essere fatto con remove:$('options').remove();
Luke

2

questo sembra funzionare per me in Chrome

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');

1
Si prega di aggiungere il formato del codice al codice, indentando con 4 spazi o racchiudendo il codice con `.
Banana

1
questo codice è fantastico! funziona su Chrome, Firefox e IE 11 più recenti, per me va bene :)
Sijav

1
prima del mio ultimo commento, questa cosa funziona anche su IE 7! quindi ff 3.5, questo è quello che mi è venuto in mente all'ultimo, in qualche modo su IE e Chrome conserva il valore che è stato selezionato prima che le opzioni vengano nascoste e se un altro valore non viene impostato dopo aver ripristinato il browser delle opzioni imposterà l'opzione selezionato come prima!
Sijav

0

In ritardo per il gioco, ma la maggior parte di questi sembrano piuttosto complicati.

Ecco come l'ho fatto:

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 di select-1:

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

markup di select-2:

<select id='select-2'>
<option class='t1'>One</option>
<option class='t2'>Two</option>
<option>Always visible</option>
</select>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.