Tengo un campo de entrada que se abre una personalizada en el menú desplegable. Me gustaría que la siguiente funcionalidad:

  • Cuando el usuario hace clic en cualquier lugar fuera del campo de entrada, el menú debe ser eliminado.
  • Si, más específicamente, el usuario hace clic en un div dentro del menú, el menú debe ser eliminado, y procesamiento especial debe ocurrir basa en que el div se hizo clic.

Aquí está mi aplicación:

El campo de entrada tiene un onblur() evento que elimina el menú de configuración de su padre el innerHTML a una cadena vacía) cada vez que el usuario hace clic fuera del campo de entrada. Los divs dentro del menú también han onclick() eventos que ejecutar el procesamiento especial.

El problema es que la onclick() eventos nunca el fuego cuando el menú se hace clic, debido a que el campo de entrada del onblur() dispara primero y elimina el menú, incluyendo la onclick()s!

He resuelto el problema mediante la división del menú divs’ onclick() en onmousedown() y onmouseup() eventos y establecer un indicador global del ratón hacia abajo que está desactivada en el ratón, similar a lo sugerido en esta respuesta. Porque onmousedown() incendios antes de onblur(), la bandera será el fijado en el onblur() si uno de los menú divs se hizo clic, pero no se si en algún otro lugar en la pantalla. Si el menú se hace clic, inmediatamente me regreso de onblur() sin eliminar el menú, a continuación, espere a que el onclick() a fuego, en el que yo puede eliminar de forma segura el menú.

Hay una solución más elegante?

El código se ve algo como esto:

<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />

var mouseflag;

function setFlag() {
    mouseflag = true;
}

function removeMenu() {
    if (!mouseflag) {
        document.getElementById('menu').innerHTML = '';
    }
}

function doProcessing(id, name) {
    mouseflag = false;
    ...
}
InformationsquelleAutor | 2013-07-21

6 Comentarios

  1. 146

    Yo estaba teniendo el mismo problema que tú, mi interfaz de usuario está diseñado exactamente como se describe. He resuelto el problema mediante la simple sustitución de la onClick para los elementos de menú con un onMouseDown. Yo no hice nada más; no onMouseUp, no hay banderas. Esto resuelve el problema al permitir que el navegador automáticamente re-orden basado en la prioridad de estos controladores de eventos, sin ningún trabajo adicional de mí.

    Hay ninguna razón por qué esto no habría trabajado también para usted?

    • Lo siento, no he hecho diseño de páginas web en un tiempo, así que me he olvidado de las complejidades de la cuestión. Podría alguien comentar sobre si esto funciona?
    • Esto funciona en realidad. Yo lo he probado en FF y funciona como un encanto.
    • Funciona. Parece onmousedown se ejecuta antes de onblur Probado en Firefox, Chrome e Internet Explorer.
    • Facepalm, funcionó a la perfección
    • Vale la pena destacar que esto hace cambiar el comportamiento de un poco de forma natural – haga clic en la interacción se gestiona en el ratón hacia abajo en lugar de ratón hacia arriba. Para la mayoría de la gente que puede estar bien (yo incluido, en este caso), pero hay algunos inconvenientes. Más en particular, a menudo me haga clic en, a continuación, arrastre fuera del botón si he misclicked, lo que impide onclick ser llamado – si el botón, se ejecuta un no-función Pura (eliminar, correo, etc) es posible que desee conservar este e ir con la bandera de enfoque.
    • ¿Qué acerca de la accesibilidad en el momento de mouseDown en lugar de onClick de matar a la accesibilidad para todos, <botón> elementos :/
    • funcionaba a la perfección! gracias!
    • Muy bien hecho.

  2. 4

    Reemplazar en onmousedown con onfocus. Por lo que este evento se activa cuando el foco está en el interior del cuadro de texto.

    Reemplazar en onmouseup con onblur. Al momento de tomar su enfoque fuera de la caja de texto, onblur se va a ejecutar.

    Supongo que esto es lo que usted pueda necesitar.

    ACTUALIZACIÓN:

    al ejecutar la función onfocus–>eliminar las clases que se aplican en onblur y agregar las clases que desea ser ejecutado onfocus

    y

    al ejecutar la función onblur–>eliminar las clases que se aplican en onfocus
    y agregar las clases que desea ser ejecutado onblur

    No veo ninguna necesidad de la bandera de las variables.

    ACTUALIZACIÓN 2:

    Puede utilizar los eventos onmouseout y onmouseover

    onmouseover-Detecta cuando el cursor está sobre ella.

    onmouseout-Detecta cuando el cursor sale.

    • He editado mi pregunta para mayor claridad. ¿Cómo funciona esta solución evita la necesidad de establecer un indicador? También, yo uso onmousedown() y onmouseup() en el menú, no el cuadro de texto / campo de entrada.
    • la respuesta, si usted piensa que su digno!!!
    • Yo no puedo aceptar esta respuesta todavía, porque no sé de que es correcta. Podría usted responder a las preocupaciones planteadas en mi comentario anterior?
    • seguro,acabo de actualizar..si usted todavía no está satisfecho..dejenme saber..
    • Seguro, puedo ver cómo podría utilizar los eventos onmouseover y onmouseout de manera similar a lo que estoy haciendo actualmente, para establecer un indicador cuando el ratón está sobre el menú. Sin embargo, todavía creo que sería necesario establecer un indicador en onmouseover que se borra en onmouseout, para que usted pueda saber si estaban sobre el menú al hacer clic. Se puede pensar de una manera que no requiere la configuración de una bandera?
    • Puedo ver el código…lo puso en un violín…sólo tienes que poner la pieza en cuestión y su completamente de acuerdo si no me ven los resultados..solo el código..
    • He puesto las partes pertinentes del código en mi respuesta.
    • permítanos continuar esta discusión en el chat

  3. 2

    Más elegante (pero probablemente menos eficiente) solución:

    Lugar de utilizar la entrada del onblur para quitar el menú, utilice document.onclick, que se desencadena después de onblur.

    Sin embargo, esto también significa que el menú se quita cuando la entrada en sí, se hace clic en, que es el mal comportamiento. Establecer un input.onclick con event.stopPropagation() para evitar la propagación de clics para que el documento haga clic en eventos.

    • Bueno, el problema con esta respuesta, sin embargo, es que si no era un evento de clic que terminó desencadenando el efecto de desenfoque. ¿Y si el usuario con pestañas de la entrada? Que haría que el desenfoque de eventos para desencadenar pero el menú desplegable todavía sería visible.
  4. 2

    onClick no debe ser reemplazado con onMouseDown.

    Mientras que este enfoque algo funciona, los dos son fundamentalmente diferentes eventos que tienen diferentes expectativas en los ojos del usuario. El uso de onMouseDown en lugar de onClick va a arruinar la previsibilidad de su software, en este caso. Por lo tanto, los dos eventos son noninterchangeable.

    Para ilustrar: cuando accidentalmente hace clic en un botón, los usuarios esperan ser capaces de mantener presionado el clic del ratón, arrastre el cursor fuera del elemento, y suelte el botón del ratón, lo que se traduce en la no acción. onClick hace esto. onMouseDown no permite que el usuario mantenga pulsado el botón del ratón, y en su lugar inmediatamente desencadenar una acción, sin recurso alguno para el usuario. onClick es el estándar que nos espera para activar acciones en un equipo.

    En esta situación, llame a event.preventDefault() en el onMouseDown evento. De forma predeterminada, onMouseDown va a causar un efecto de desenfoque evento por defecto, y no hacerlo cuando preventDefault se llama. Entonces, onClick tendrá la oportunidad de ser llamado. Un desenfoque evento va a suceder, sólo después de onClick.

    Después de todo, la onClick evento es una combinación de onMouseDown y onMouseUp, si y sólo si ambos ocurren dentro del mismo elemento.

    • Esta es una buena solución para cuando onClick debe ser utilizado.
    • Esto es de hecho una buena solución también!
  5. 0

    cambio onclick por onfocus

    incluso si el onblur y onclick no se llevan muy bien, pero obviamente onfocus y sí onblur. ya que incluso después de que el menú se cierra el onfocus es válido para el elemento clic en el interior.

    Yo lo hice y funcionó.

  6. -4

    Puede utilizar un setInterval función dentro de su onBlur controlador, como este:

    <input id="input" onblur="removeMenu()" ... />
    
    function removeMenu() {
        setInterval(function(){
            if (!mouseflag) {
                document.getElementById('menu').innerHTML = '';
            }
        }, 0);
    }

    la setInterval función de eliminar su onBlur función de la pila de llamadas, agregar porque se establece el tiempo a 0, esta función se llama inmediatamente después de otro controlador de eventos terminado

    • setInterval es una mala idea, nunca la cancelación de la misma por lo que continuamente ejecutar su función y la causa más probable de su sitio para uso máximo de cpu. Uso setTimeout lugar si usted va a utilizar esta técnica (que no recomiendo). Hacer que la aplicación depende de la sincronización de determinados eventos es un negocio arriesgado.
    • EL PELIGRO ROBINSON! PELIGRO! Condición de carrera por delante!
    • La primera vez que vine con esta solución (bien setTimeout no setInterval), pero he tenido que subir a 250ms antes de que el tiempo suceder en el orden correcto. Este error probablemente todavía existen en los dispositivos más lentos y también hace que el retraso notable. He probado el onMouseDown y funciona bien. Me pregunto si se necesita el toque de los eventos así.
    • Algo así como un intervalo no es malo si usted realmente desea utilizar onClick. Pero usted quiere un recursiva de tiempo de espera con una condición, en lugar de un intervalo para que no se ejecute para siempre. Este es el mismo patrón utilizado por el Selenio condicional espera.

Dejar respuesta

Please enter your comment!
Please enter your name here