web-dev-qa-db-fra.com

problème de commande onclick () et onblur ()

J'ai un champ de saisie qui fait apparaître un menu déroulant personnalisé. Je voudrais les fonctionnalités suivantes:

  • Lorsque l'utilisateur clique n'importe où en dehors du champ de saisie, le menu doit être supprimé.
  • Si, plus précisément, l'utilisateur clique sur un div dans le menu, celui-ci doit être supprimé, et un traitement spécial doit avoir lieu en fonction du div sur lequel l'utilisateur a cliqué.

Voici ma mise en œuvre:

Le champ de saisie comporte un événement onblur() qui supprime le menu (en définissant la variable innerHTML de son parent sur une chaîne vide) chaque fois que l'utilisateur clique en dehors du champ de saisie. Les divs dans le menu ont aussi des événements onclick() qui exécutent le traitement spécial.

Le problème est que les événements onclick() ne se déclenchent jamais lorsque l'utilisateur clique sur le menu, car la fonction onblur() du champ de saisie est déclenchée en premier et supprime le menu, y compris la fonction onclick()s! 

J'ai résolu le problème en scindant la fonction onclick() des divs de menu en événements onmousedown() et onmouseup(), puis en définissant un indicateur global au-dessus de la souris, qui est effacé au passage de la souris, comme dans la suggestion cette réponse . Étant donné que onmousedown() se déclenche avant onblur(), l'indicateur sera défini dans onblur() si l'un des div du menu a été cliqué, mais pas si un autre élément de l'écran l'a été. Si vous avez cliqué sur le menu, je reviens immédiatement de onblur() sans le supprimer, puis attendez que la onclick() se déclenche, point auquel je peux supprimer le menu en toute sécurité.

Y a-t-il une solution plus élégante?

Le code ressemble à ceci:

<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;
    ...
}
65
1''

J'avais exactement le même problème que vous, mon interface utilisateur est conçue exactement comme vous le décrivez. J'ai résolu le problème en remplaçant simplement le onClick pour les éléments de menu par un onMouseDown. Je n'ai rien fait d'autre; no onMouseUp, pas de drapeaux. Cela a résolu le problème en laissant le navigateur réorganiser automatiquement en fonction de la priorité de ces gestionnaires d'événements, sans aucun travail supplémentaire de ma part.

Y a-t-il une raison pour laquelle cela n'aurait pas aussi fonctionné pour vous?

105
johnbakers

Remplacez le onmousedown par onfocus . Donc, cet événement sera déclenché lorsque le focus est dans la zone de texte.

Remplacez le onmouseup par onblur . Dès que vous vous concentrez sur textbox, onblur sera exécuté.

Je suppose que c'est ce dont vous pourriez avoir besoin.

METTRE &AGRAVE; JOUR:

lorsque vous exécutez votre fonction onfocus -> supprimez les classes que vous allez appliquer dans onblur et ajoutez les classes que vous voulez exécuter, onfocus

et

lorsque vous exécutez votre fonction onblur -> supprimez les classes que vous appliquerez dans onfocus .__ et ajouterez les classes que vous souhaitez exécuter sur blur

Je ne vois pas le besoin de variables de drapeau.

MISE À JOUR 2:

Vous pouvez utiliser les événements onmouseout et onmouseover

onmouseover- Détecte quand le curseur est dessus.

onmouseout- Détecte le départ du curseur.

4
HIRA THAKUR

Une solution plus élégante (mais probablement moins performante):

Au lieu d'utiliser onblur de l'entrée pour supprimer le menu, utilisez document.onclick, qui se déclenche après onblur

Toutefois, cela signifie également que le menu est supprimé lorsque l'utilisateur clique sur l'entrée elle-même, ce qui constitue un comportement indésirable. Définissez un input.onclick avec event.stopPropagation() pour éviter de propager des clics sur l'événement de clic du document.

2
1''

onClick ne doit pas être remplacé par onMouseDown.

Bien que cette approche fonctionne quelque pe, les deux sont des événements fondamentalement différents qui ont des attentes différentes aux yeux de l'utilisateur. Utiliser onMouseDown au lieu de onClick ruinerait la prévisibilité de votre logiciel dans ce cas. Ainsi, les deux événements ne sont pas interchangeables.

Pour illustrer ce qui suit: lorsqu'ils cliquent accidentellement sur un bouton, les utilisateurs s'attendent à pouvoir maintenir le clic de la souris enfoncé, à faire glisser le curseur en dehors de l'élément et à relâcher le bouton de la souris, ce qui ne donne finalement aucune action. onClick le fait. onMouseDown ne permet pas à l'utilisateur de maintenir la souris enfoncée, mais déclenche immédiatement une action, sans aucun recours pour l'utilisateur. onClick est la norme selon laquelle nous nous attendons à déclencher des actions sur un ordinateur.

Dans cette situation, appelez event.preventDefault() sur l'événement onMouseDown. Par défaut, onMouseDown provoquera un événement de flou par défaut et ne le fera pas lorsque preventDefault sera appelé. Ensuite, onClick aura une chance d'être appelé. Un événement de flou se produira toujours, uniquement après onClick.

Après tout, l’événement onClick est une combinaison de onMouseDown et onMouseUp, si et seulement s’ils se produisent tous deux dans le même élément.

1
eyeino

change onclick de onfocus

même si onblur et onclick ne s'entendent pas très bien, mais évidemment onfocus et oui onblur puisque même après la fermeture du menu, l’onfocus est toujours valable pour l’élément cliqué à l’intérieur.

Je l'ai fait et ça a marché.

0
Brasil