¿Cómo se puede indicar mediante programación a un SELECT HTML que se despliegue (por ejemplo, debido al mouseover)?

105

¿Cómo se puede indicar mediante programación a un HTML selectque se despliegue (por ejemplo, debido al desplazamiento del mouse)?

Corey Trager
fuente
6
Recomendaría no jugar con el comportamiento predeterminado <select>, ya que la gente espera que se comporte de cierta manera y evitará que las personas en otras plataformas (como dispositivos móviles) usen su sitio.
Brian Donovan
1
@BrianDonovan No es que no puedas agregar algo de manejo a eso.
Morg.
@shasikanth: tu violín no funciona ni en Firefox 37 nr en Chrome
rubo77
Ok, creo que el violín funcionó anteriormente. De todos modos estaría borrando mi comentario aquí.
shasi kanth
@BrianDonovan En realidad, el móvil es un buen caso de uso de esto ... generar programáticamente una selección y luego hacer que sus opciones aparezcan automáticamente.
Michael

Respuestas:

15

No puede hacer esto con una etiqueta de selección HTML, pero puede hacerlo con JavaScript y HTML. Hay una variedad de controles existentes que hacen esto, por ejemplo, la lista de "sugerencias" adjunta a la entrada SO "etiqueta interesante / ignorada", o la búsqueda de direcciones de correo electrónico de Gmail.

Hay muchos controles JavaScript + HTML que proporcionan esta capacidad; busque controles de autocompletar para obtener ideas.

Vea este enlace para el control de Autocompletar ... http://ajaxcontroltoolkit.codeplex.com/

rp.
fuente
6
esto es una lástima: los navegadores móviles proporcionan una lista de desplazamiento específica del sistema operativo, y necesito que aparezca automáticamente.
Michael
120

Esto solía ser posible con HTML + Javascript, a pesar de que en todas partes la gente dice que no lo es, pero quedó obsoleto más tarde y no funciona ahora.

Sin embargo, esto solo funcionó en Chrome. Lea más si está interesado.


De acuerdo con el Borrador de trabajo del W3C para HTML5, Sección 3.2.5.1.7. Contenido interactivo :

Ciertos elementos en HTML tienen un comportamiento de activación, lo que significa que el usuario puede activarlos. Esto desencadena una secuencia de eventos que dependen del mecanismo de activación, [...] por ejemplo, mediante el teclado o la entrada de voz, o mediante clics del mouse .

Cuando el usuario activa un elemento con un comportamiento de activación definido de una manera distinta a hacer clic en él, la acción predeterminada del evento de interacción debe ser ejecutar pasos sintéticos de activación de clic en el elemento.

<select>al ser un contenido interactivo, creí que es posible mostrar programáticamente sus <option>s. Después de unas horas de jugar, descubrí que usar document.createEvent()y .dispatchEvent()funciona.

Dicho esto, tiempo de demostración. Aquí hay un violín que funciona.


HTML:

<select id="dropdown">
    <option value="Red">Red</option>
    <option value="Green">Green</option>
    <option value="Blue">Blue</option>
</select>
<br>
<button id="fire" type="button" onclick="runThis()">Show dropdown items</button>​

Javascript:

// <select> element displays its options on mousedown, not click.
showDropdown = function (element) {
    var event;
    event = document.createEvent('MouseEvents');
    event.initMouseEvent('mousedown', true, true, window);
    element.dispatchEvent(event);
};

// This isn't magic.
window.runThis = function () { 
    var dropdown = document.getElementById('dropdown');
    showDropdown(dropdown);
};

Si alguien encuentra una manera de hacer lo mismo pero no en Chrome, no dude en modificar este violín .

Xavier Ho
fuente
2
¡Gracias por esto! Necesitaba emular el comportamiento ALT + FLECHA ABAJO de IE precisamente en Chrome.
J Bryan Price
3
Desearía poder aumentar su recompensa por esto. Muchas gracias.
Adam Tuttle
7
No funciona en: IE10, FF 24. Funciona en: Chrome 30, Safari 6.0.5,Opera 16
hitautodestruct
2
@AdamTuttle Tampoco funciona en Android 4.4.2
Mirko
42
Ahora está obsoleto en Chrome 53+
Washington Guedes
47

La respuesta de Xavier Ho cubre cómo resolver el problema en la mayoría de los navegadores que existen actualmente. Pero, es una buena práctica 'no enviar / modificar' eventos por JavaScript . (Como, mousedownen este caso)

A partir de la versión 53+, Google Chrome no realizará la acción predeterminada para eventos no confiables . Como eventos creados o modificados por script o enviados a través de un dispatchEventmétodo. Este cambio es para alinearse con Firefox e IE, que creo que ya no están realizando la acción.

Para fines de prueba, Fiddle proporcionó la respuesta de Xavier no funcionará en Chrome 53+. (No lo pruebo FF e IE).

Enlaces de referencia:

https://www.chromestatus.com/features/5718803933560832 https://www.chromestatus.com/features/6461137440735232

Y initMouseEvent también está en desuso

Asim KT
fuente
¿Se puede hacer usando MouseEvents? developer.mozilla.org/en-US/docs/Web/API/MouseEvent
Shamal Perera
No lo creo. intentaste algo?
Asim KT
28

Esto es lo más cerca que pude conseguir, cambiar el tamaño del elemento onmouseover y restaurar el tamaño onmouseout:

       <select onMouseOut="this.size=1;" onMouseOver="this.size=this.length;">
        <option>1</option>
        <option>2</option>
        <option>3</option>
        <option>4</option>
        <option>5</option>
      </select>

CMS
fuente
13
o <SELECT onMouseOut = "this.size = 1;" onMouseOver = "this.size = this.length;"> ... </SELECT>
RealHowTo
1
También es necesario agregar onchange = "this.size = 1" para que el menú se colapse tan pronto como se haga la selección. Las reglas CSS del elemento también deben configurarse.
GM2008
Parece funcionar. El ancho de selección se encoge y luego eso provoca un evento de mouse out que restablece la selección a su ancho original. Esto provoca un efecto convulsivo. Establecer un ancho fijo parece arreglarlo. Con más de unos pocos elementos, la lista se expande más allá de la vista.
1,21 gigavatios
16

Tengo este mismo problema y la forma más fácil que encontré para solucionar esto fue con html y css.

select{
  opacity: 0;
  position: absolute;
}
<select>
  <option>option 1</option>
  <option>option 2</option>
  <option>option 3</option>
</select>
<button>click</button>

Rafael Umbelino
fuente
2
Ha pasado mucho tiempo desde que vi este enfoque y es la referencia que esperaba encontrar. Mejor con CSS adicional para que coincida con el tamaño de selección oculta para disparar (botón, img, div, etc.) ... 1) Asegura que la región en la que se puede hacer clic llene el disparador 2) El menú se abre directamente debajo del disparador. Nota: Es posible que también deba agregar un índice Z para garantizar que la región en la que se puede hacer clic sea el elemento superior en algunos diseños.
Mavelo
sin embargo, si el usuario se desplaza hacia abajo en la página, el botón se mueve en consecuencia, pero la selección se mantiene en la misma posición; no realmente como se esperaba. alguna solución para esto?
David Portabella
Solución perfecta. Pero mejor tal vez envuelva el botón y seleccione en div como este <div style='position:relative'><select> <option>option 1</option> <option>option 2</option> <option>option 3</option> </select> <button>click</button></div>@DavidPortabella
Muhammet Can TONBUL
8

Creo que esto ya no es posible en Chrome.

Parece que la versión 53 de Chrome deshabilita esta funcionalidad según lo declarado por Asim K T.

Según la especificación http://www.w3.org/TR/DOM-Level-3-Events/#trusted-events

Los eventos de confianza no deben activar la acción predeterminada (excepto el evento de clic).

Sin embargo, lo han habilitado en la vista web, pero no lo he probado.

Hemos descubierto que algunas vistas web utilizan fastclick dentro de ellas y, debido al riesgo de rotura, vamos a permitir el mousedown en selecciones incluso si no son de confianza.

Y en esta discusión se abandona la idea de permitir que los desarrolladores abran un menú desplegable programáticamente.

Comprensivo
fuente
7

Si alguien todavía está buscando esto:

<select id="dropdown">
    <option value="Red">Red</option>
    <option value="Green">Green</option>
    <option value="Blue">Blue</option>
</select>
<br>
<button id="fire" type="button" >Show dropdown items</button>

Javascript:

var is_visible=false; 

$(document).ready(function(){

    $('#fire').click(function (e) { 
    var element = document.getElementById('dropdown');


    if(is_visible){is_visible=false; return;}
    is_visible = true;

    var event;
    event = document.createEvent('MouseEvents');
    event.initMouseEvent('mousedown', true, true, window);
    element.dispatchEvent(event);

    /* can be added for i.e. compatiblity.
      optionsSelect.focus();
       var WshShell = new ActiveXObject("WScript.Shell");
       WshShell.SendKeys("%{DOWN}");
    */
    e.stopPropagation();
    return false;
});


$(document).click(function(){is_visible=false; });
});

Actualizar:

Uno hasta que no haya una solución perfecta para este problema, pero puede intentar evitar este escenario. ¿Por qué quieres hacer esto? Hace unos meses me preguntaba por una solución para crear un complemento selecto para dispositivos móviles

https://github.com/HemantNegi/jquery.sumoselect

Finalmente terminó enmascarando el div personalizado (o cualquier otro elemento) con un elemento de selección transparente, para que pueda interactuar directamente con el usuario.

Hemant_Negi
fuente
1
Los complementos como github.com/HemantNegi/jquery.sumoselect son la única solución de navegador cruzado que realmente se ve mejor que el control predeterminado.
Justin
iniMouseEventparece funcionar, pero ¿por qué $(select).trigger('mousedown')no funciona?
coding_idiot
3

Esta es la mejor forma que encontré. NOTA Solo funciona con IE en Windows y su web probablemente necesite estar en una zona segura, porque accedemos al shell. El truco es que ALT-Flecha abajo es una tecla de método abreviado para abrir un menú desplegable de selección.

<button id="optionsButton" style="position:absolute;top:10px;left:10px;height:22px;width:100px;z-index:10" onclick="doClick()">OPTIONS</button>
<select id="optionsSelect" style="position:absolute;top:10px;left:10px;height:20px;width:100px;z-index:9">
    <option>ABC</option>
    <option>DEF</option>
    <option>GHI</option>
    <option>JKL</option>
</select>
<script type="text/javascript">
   function doClick() {
       optionsSelect.focus();
       var WshShell = new ActiveXObject("WScript.Shell");
       WshShell.SendKeys("%{DOWN}");
   }
</script>
sproketboy
fuente
3
No funcionará a menos que haga esto .
2011
1
@Knu Internet Explorer agrega automáticamente los ID de los elementos como referencias al elemento en el ámbito global.
user2428118
@KlasMellbourn probablemente. Ahora intentan hacer que sus navegadores sean más compatibles. Utilice la solución de "tamaño" mencionada.
sproketboy
2

Deja de pensar que una cosa es imposible, nada es imposible de hacer, cuando quieres hacer.

Utilice esta función de expansión JS creada por un chico.

http://code.google.com/p/expandselect/

Incluya este JS y simplemente llámelo pasando el parámetro como su ID de selección, así:

ExpandSelect(MySelect)
Paulo Roberto Rosa
fuente
2
Para que quede claro, que JS qué no causan una <SELECT>a caer hacia abajo. Como dice explícitamente "Los navegadores no permiten expandir <seleccionar> en javascript puro, ese control se puede expandir solo haciendo clic directamente en él con el mouse". ¡Entonces es "imposible"! En cambio, el JS dice "Imitamos el control <select> expandido creando otra selección con múltiples opciones que se muestran a la vez ..." Lo cual es bastante diferente, y puede o no ser aceptable para su caso de uso ...
JonBrave
1

Puede que me equivoque, pero no creo que sea posible con el cuadro de selección predeterminado. Podría hacer algo con JS y CSS que logre el resultado deseado, pero no (que yo sepa) el SELECT de vainilla.

Arrojar
fuente
0

Es posible abrir una "selección de HTML" a través de algunas de las soluciones mencionadas en esta pregunta y otras similares. Sin embargo, una forma más limpia de hacer esto es agregar una biblioteca de selección a su proyecto como "select2" o "elegido". Por ejemplo, abrir un select2 mediante programación sería tan fácil como:

$('#target-select').select2('open');
Kasra Ebrahimi
fuente
-2

Esto no es exactamente lo que pediste, pero me gusta esta solución por su simplicidad. En la mayoría de los casos en los que deseo iniciar un menú desplegable, es porque estoy validando que el usuario realmente hizo una selección. Cambio el tamaño del menú desplegable y lo enfoco, lo que resalta muy bien lo que han omitido:

$('#cboSomething')[0].size = 3;
$('#cboSomething')[0].focus();
Rob3C
fuente
No estoy seguro de por qué fue rechazado, ya que no es la "peor" manera de hacerlo. Evitaría esto simplemente porque cambia el diseño de los elementos circundantes. Aunque creo que la solución de @CMS se entiende más fácilmente con los eventos de enfoque / desenfoque en el control.
Mavelo