¿Cómo ocultar una <opción> en un menú <seleccionar> con CSS?

103

Me di cuenta de que Chrome, al parecer, no me permitirá esconderme <option>en un <select>. Firefox lo hará.

Necesito ocultar los mensajes de correo <option>electrónico que coinciden con un criterio de búsqueda. En las herramientas web de Chrome puedo ver que display: none;mi JavaScript las está configurando correctamente , pero una vez que <select>se hace clic en el menú, se muestran.

¿Cómo puedo hacer que estos <option>mensajes de correo electrónico que coinciden con mis criterios de búsqueda NO se muestren cuando se hace clic en el menú? ¡Gracias!

Jesse Atkinson
fuente
4
En lugar de esconderse y aparecer en una búsqueda. Intente completar la selección según la búsqueda
Henesnarfel
1
Estoy de acuerdo con Henesnarfel. Si ya está haciendo una búsqueda o algún tipo de consulta, debería poder completar las que desee.
Michael Stramel
1
esto funciona bien para mí en Chrome 16.0.912.77 m. ¿Estoy entendiendo mal el problema?
mgibsonbr
3
@mgibsonbr No funciona en varios navegadores.
Jasper
3
@Henesnarfel Puede haber buenas razones para ocultar opciones. Por ejemplo, tenía una página con un cuadro de lista de selección y enlaces para ocultar o mostrar elementos marcados como inactivos. No hay razón para mantener múltiples listas o consultar al servidor por una nueva lista cada vez que el usuario cambia esa opción.
Ryan P

Respuestas:

69

Tienes que implementar dos métodos para esconderte. display: nonefunciona para FF, pero no para Chrome o IE. Entonces, el segundo método es envolver el <option>en un <span>condisplay: none . FF no lo hará (HTML técnicamente no válido, según la especificación) pero Chrome e IE lo harán y ocultará la opción.

EDITAR: Oh sí, ya implementé esto en 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;" />' );
    }
};

EDITAR 2: Así es como usaría esta función:

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

EDITAR 3: Se agregó una verificación adicional sugerida por @ user1521986

Ryan P
fuente
1
Este método loco es el único que realmente funcionó completamente en todos los navegadores y no implicó la creación de un truco de cuadro de selección oculto falsamente.
Jesse Atkinson
15
Tenga cuidado con esto. Parece funcionar muy bien al principio, pero en algún momento se detiene. Aquí hay una pequeña demostración: jsfiddle.net/Yb6sk/9
Bill Criswell
17
Aunque esta solución oculta el elemento, cualquier intento de leer el valor de <select>(usando jQuery's .val()) regresará null. Acabo de probar esto en Chrome 29, así que ¡cuidado con los empleados de Google!
Mark
10
Interesante truco, pero recomendaría evitar "HTML técnicamente inválido" si es posible.
Luke
3
Es cierto que todos los navegadores tienen diferentes implementaciones. Pero una razón por la que los navegadores no pueden implementar estrictamente las especificaciones estándar es porque hay demasiado código en vivo que no sigue las especificaciones. OMI: Si no hay otras soluciones, entonces use un truco. Pero si puede seguir las especificaciones y resolver su problema, ¿por qué no lo haría? Ayuda a su código a jugar bien con los demás y ayuda a fortalecer la especificación.
Lucas
82

Para HTML5, puede utilizar el atributo 'oculto'.

<option hidden>Hidden option</option>

Se no soportado por el IE <11. Pero si sólo se necesita para ocultar algunos elementos, tal vez sería mejor simplemente establecer el atributo oculto en combinación con personas con discapacidad en comparación con la adición / eliminación de elementos o no hacer construcciones semánticamente correctas.

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

Referencia .

Lukas Jelinek
fuente
4
IE 11 es compatible con esto.
Iván Pérez
7
Esta es la respuesta moderna. Idealmente, también estamos configurando esto para disabledque aquellos navegadores que no admiten el atributo global HTML5hidden tengan alguna indicación visual para el usuario.
Cloudworks
1
¿Cómo usas esta técnica con CSS?
GetFree
7
No funciona en Safari, Edge ni IE. Bug for Safari tiene 10 años, ayúdenos actualizando los parches existentes. No se puede encontrar un error en el rastreador de problemas de Edge.
Indolering
7
Se usa una solución alternativa para esto <option hidden disabled>, por lo que se oculta en todos los buenos navegadores y lo desactiva en los demás.
Ramon Balthazar
37

Sugeriría que no use las soluciones que usan un <span>contenedor porque no es HTML válido, lo que podría causar problemas en el futuro. Creo que la solución preferida es eliminar las opciones que desee ocultar y restaurarlas según sea necesario. Con jQuery, solo necesitará estas 3 funciones:

La primera función guardará el contenido original de la selección . Para estar seguro, es posible que desee llamar a esta función cuando cargue la página.

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

Esta siguiente función llama a la función anterior para asegurarse de que el contenido original se haya guardado y luego simplemente elimina las opciones del DOM.

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

La última función se puede utilizar siempre que desee "restablecer" todas las opciones originales.

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

Tenga en cuenta que todas estas funciones esperan que esté pasando elementos de jQuery. Por ejemplo:

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

Aquí hay un ejemplo de trabajo: http://jsfiddle.net/9CYjy/23/

Luke
fuente
3
Confiable y no un truco. ¡Gran respuesta!
Jeremy Cook
1
@DanBeaulieu Había una función nombrada incorrectamente en el jsfiddle anterior. Arreglé y actualicé el enlace de arriba. Gracias por captar eso.
Lucas
Sí, esta también fue mi elección. De hecho, logré ajustar el código un poco más pequeño, primero tomando el valor de los datos en una variable, si no está definido, guardará las opciones, de lo contrario, las restaurará. Mi necesidad era específica para eso.
diynevala
1
Tuve que agregar var value=$select.val(); $select.html(ogHTML); $select.val(value);para mantener el valor seleccionado seleccionado incluso después de la restauración.
diynevala
El ciclo de seleccionar las opciones para eliminarlas y eliminarlas solo funcionó una vez. Después de eso, options.remove () no tuvo ningún efecto para mí. Una vez que moví las opciones restoreOptions ($ s) para llamar algunas líneas para que siempre estuviera trabajando con un objeto Select completo y nuevo, funcionó.
Newclique
18

La respuesta de Ryan P debe cambiarse a:

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

De lo contrario, se envuelve en demasiadas etiquetas.

JeffT
fuente
5
Tenga en cuenta que de acuerdo con las especificaciones de HTML ( w3.org/TR/html5/forms.html#the-select-element ), a <select>solo debe contener <option>o <optgroup>elementos de soporte de script. Por lo tanto, debe evitar el uso de <span>contenedores no válidos .
Lucas
9

La función toggleOption no es perfecta e introdujo errores desagradables en mi aplicación. jQuery se confundirá con .val () y .arraySerialize () Intente seleccionar las opciones 4 y 5 para ver lo que quiero decir:

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

Las entradas seleccionadas son complicadas de esta manera. ¿Qué hay de deshabilitarlo en su lugar? Esto funcionará en todos los navegadores:

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

Esto desactivará todos los demás <option> elementos, pero puede seleccionar el que desee.

Aquí hay una demostración: http://jsfiddle.net/jYWrH/

Nota: Si desea eliminar la propiedad deshabilitada de un elemento, puede usar .removeProp('disabled').

Actualizar

Puede guardar los <option>elementos que desea ocultar en el elemento de selección oculto:

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

Luego, puede volver a agregar los <option>elementos al elemento seleccionado original:

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

En estos dos ejemplos, se espera que el elemento de selección visible tenga la identificación de visibley el elemento de selección oculto tenga la identificación de hidden.

Aquí hay una demostración: http://jsfiddle.net/jYWrH/1/

Tenga en cuenta que .on()es nuevo en jQuery 1.7 y el uso de esta respuesta es el mismo que .bind(): http://api.jquery.com/on

Jaspe
fuente
7

Respuesta simple: no puedes. Los elementos de formulario tienen capacidades de estilo muy limitadas.

La mejor alternativa sería establecer disabled=truela opción (y tal vez un color gris, ya que solo IE lo hace automáticamente), y esto hará que no se pueda hacer clic en la opción.

Alternativamente, si puede, elimine completamente el optionelemento.

Niet the Dark Absol
fuente
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
fuente
4

Como ya está utilizando JS, puede crear un elemento SELECT oculto en la página y, para cada elemento que intente ocultar en esa lista, muévalo a la lista oculta. De esta manera, se pueden restaurar fácilmente.

No sé cómo hacerlo en CSS puro ... Hubiera pensado que la pantalla: ningún truco habría funcionado.

Derreck Dean
fuente
2

!!! ADVERTENCIA !!!

Reemplace el segundo "SI" por "MIENTRAS" o no funciona.

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

Debe eliminarlos del <select>uso de JavaScript. Esa es la única forma garantizada de hacer que desaparezcan.

Jordán
fuente
1
Usando jQuery, esto se puede hacer con eliminar:$('options').remove();
Lucas
2

este parece funcionar para mí en Chrome

$("#selectid span option").unwrap();
$("#selectid option:not([filterattr=filtervalue])").wrap('<span/>');
exiliado
fuente
1
Agregue formato de código a su código, ya sea sangrando con 4 espacios o envolviendo su código con `.
Banana
1
este código es genial! funciona en los últimos Chrome, Firefox e IE 11, eso es lo suficientemente bueno para mí :)
Sijav
1
antes de mi último comentario, ¡esto también funciona en IE 7! así que ff 3.5, esto es lo que se me ocurrió al final, de alguna manera en IE y Chrome conserva el valor que se ha seleccionado antes de que las opciones se oculten y si otro valor no se establece después de traer de vuelta el navegador de opciones establecerá la opción seleccionado como antes!
Sijav
0

Tarde para el juego, pero la mayoría de estos parecen bastante complicados.

Así es como lo hice:

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

});

marcado de select-1:

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

marcado de select-2:

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