web-dev-qa-db-fra.com

Comment masquer une <option> dans un menu <select> avec CSS?

J'ai compris que Chrome, me semble-t-il, ne me permettra pas de cacher <option> dans un <select>. Firefox le fera.

Je dois masquer le <option>s qui correspond à un critère de recherche. Dans les outils Web Chrome, je peux constater qu'ils sont correctement configurés sur display: none; à l'aide de mon JavaScript, mais une fois le menu <select> cliqué, ils sont affichés.

Comment puis-je faire en sorte que ces <option> correspondant à mes critères de recherche ne s'affichent PAS lorsque l'utilisateur clique sur le menu? Merci!

97
Jesse Atkinson

Vous devez mettre en œuvre deux méthodes pour se cacher. display: none fonctionne pour FF, mais pas Chrome ou IE. Donc, la deuxième méthode encapsule le <option> dans un <span> avec display: none. FF ne le fera pas (HTML techniquement non valide, conformément à la spécification), mais Chrome et IE le masqueront.

EDIT: Oh oui, j'ai déjà implémenté cela dans 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: Voici comment vous utiliseriez cette fonction:

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

EDIT 3: vérification supplémentaire suggérée par @ user1521986

69
Ryan P

Pour HTML5, vous pouvez utiliser l'attribut "caché".

<option hidden>Hidden option</option>

Il est pas pris en charge par IE <11. Mais si vous n'avez besoin que de masquer quelques éléments, il serait peut-être préférable de il suffit de définir l'attribut masqué en combinaison avec disabled par rapport à l'ajout/la suppression d'éléments ou à la non sémantique des constructions.

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

référence .

61
Lukas Jelinek

Je suggérerais que vous n'utilisiez pas les solutions qui utilisent un wrapper <span> car ce n'est pas du code HTML valide, ce qui pourrait causer des problèmes la route. Je pense que la solution à privilégier consiste à supprimer toutes les options que vous souhaitez masquer et à les restaurer au besoin. Avec jQuery, vous n’avez besoin que de ces 3 fonctions:

La première fonction sauvegardera le contenu original de la sélection . Pour votre sécurité, vous pouvez appeler cette fonction lorsque vous chargez la page.

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

Cette fonction suivante appelle la fonction ci-dessus pour s'assurer que le contenu d'origine a été sauvegardé, puis supprime simplement les options du DOM.

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

La dernière fonction peut être utilisée chaque fois que vous souhaitez "réinitialiser" toutes les options d'origine.

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

Notez que toutes ces fonctions s’attendent à ce que vous transmettiez des éléments jQuery. Par exemple:

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

Voici un exemple de travail: http://jsfiddle.net/9CYjy/23/

34
Luke

La réponse de Ryan P devrait être changée en:

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

Sinon, il est emballé dans trop de tags

18
JeffT

La fonction toggleOption n'est pas parfaite et introduit de méchants bugs dans mon application. jQuery sera confondu avec .val () et .arraySerialize () Essayez de sélectionner les options 4 et 5 pour voir ce que je veux dire:

<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>
9
Batiste Bieler

Certaines entrées sont délicates de cette façon. Pourquoi ne pas le désactiver, cela fonctionnera sur plusieurs navigateurs:

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

Cela désactivera tous les autres éléments <option>, mais vous pourrez sélectionner celui de votre choix.

Voici une démo: http://jsfiddle.net/jYWrH/

Remarque: Si vous souhaitez supprimer la propriété disabled d'un élément, vous pouvez utiliser .removeProp('disabled').

Mise à jour

Vous pouvez enregistrer les éléments <option> que vous souhaitez masquer dans l'élément de sélection masqué:

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

Vous pouvez ensuite rajouter les éléments <option> à l'élément de sélection d'origine:

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

Dans ces deux exemples, on s'attend à ce que l'élément de sélection visible ait l'id de visible et l'élément de sélection caché à l'id de hidden.

Voici une démo: http://jsfiddle.net/jYWrH/1/

Notez que .on() est nouveau dans jQuery 1.7 et que l'utilisation de cette réponse est identique à .bind(): http://api.jquery.com/on

8
Jasper

Réponse simple: vous ne pouvez pas. Les éléments de forme ont des capacités de style très limitées.

La meilleure alternative serait de définir disabled=true sur l'option (et peut-être une couleur grise, puisque seul IE le fait automatiquement), ce qui rend l'option non cliquable.

Sinon, si vous le pouvez, supprimez complètement l'élément option.

6
Niet the Dark Absol
// Simplest way

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

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

Comme vous utilisez déjà JS, vous pouvez créer un élément SELECT masqué sur la page et, pour chaque élément que vous essayez de masquer dans cette liste, déplacez-le vers la liste masquée. De cette façon, ils peuvent être facilement restaurés.

Je ne connais pas le moyen de le faire en pur CSS ... J'aurais pensé que l'affichage: aucun truc n'aurait fonctionné.

4
Derreck Dean

Vous devez les supprimer du <select> à l'aide de JavaScript. C'est le seul moyen garanti de les faire partir.

2
Jordan

!!! ATTENTION !!!

Remplacez le second "IF" par "WHILE" ou ne fonctionne pas!

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
Arraxas

celui-ci semble fonctionner pour moi en chrome

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

En retard au jeu, mais la plupart d’entre eux semblent assez compliqués.

Voici comment je l'ai fait:

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

});

balisage de select-1:

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

balisage de select-2:

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