J'ai un champ de saisie qui fait apparaître un menu déroulant personnalisé. Je voudrais les fonctionnalités suivantes:
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;
...
}
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?
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.
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.
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.
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é.