2723 votes

Comment détecter un clic à l'extérieur d'un élément ?

J'ai quelques menus HTML, que j'affiche complètement lorsqu'un utilisateur clique sur l'en-tête de ces menus. Je voudrais cacher ces éléments lorsque l'utilisateur clique en dehors de la zone des menus.

Est-ce que quelque chose comme cela est possible avec jQuery ?

$("#menuscontainer").clickOutsideThisElement(function() {
    // Hide the menus
});

47 votes

Voici un exemple de cette stratégie : jsfiddle.net/tedp/aL7Xe/1

21 votes

Comme Tom l'a mentionné, vous voudrez lire css-tricks.com/dangers-stopping-event-propagation avant d'utiliser cette approche. L'outil jsfiddle est cependant assez cool.

3 votes

Obtenir une référence à l'élément puis à event.target, et enfin != ou == les deux, puis exécuter le code en conséquence

27voto

Jitendra Damor Points 768

Une solution simple pour cette situation est :

$(document).mouseup(function (e)
{
    var container = $("YOUR SELECTOR"); // Give you class or ID

    if (!container.is(e.target) &&            // If the target of the click is not the desired div or section
        container.has(e.target).length === 0) // ... nor a descendant-child of the container
    {
        container.hide();
    }
});

Le script ci-dessus masquera l'élément div si en dehors de la div l'événement de clic est déclenché.

Vous pouvez consulter le blog suivant pour plus d'informations : http://www.codecanal.com/detect-click-outside-div-using-javascript/

26voto

34m0 Points 1710

Je ne pense pas que vous ayez vraiment besoin de fermer le menu lorsque l'utilisateur clique à l'extérieur ; ce dont vous avez besoin, c'est que le menu se ferme lorsque l'utilisateur clique n'importe où sur la page. Si vous cliquez sur le menu, ou en dehors du menu, il devrait se fermer, n'est-ce pas ?

N'ayant pas trouvé de réponses satisfaisantes, j'ai décidé d'écrire ce qui suit cet article de blog l'autre jour. Pour les plus pédants, il y a un certain nombre d'inconvénients à noter :

  1. Si vous attachez un gestionnaire d'événement de clic à l'élément body au moment du clic, assurez-vous d'attendre le deuxième clic avant de fermer le menu et de délier l'événement. Sinon, l'événement de clic qui a ouvert le menu sera transmis à l'écouteur qui doit fermer le menu.
  2. Si vous utilisez event.stopPropogation() sur un événement de type "clic", aucun autre élément de votre page ne peut avoir une fonction "cliquer partout pour fermer".
  3. Attacher indéfiniment un gestionnaire d'événement de clic à l'élément body n'est pas une solution performante.
  4. En comparant la cible de l'événement et ses parents au créateur du gestionnaire, on suppose que ce que vous voulez, c'est fermer le menu lorsque vous cliquez dessus, alors que ce que vous voulez vraiment, c'est le fermer lorsque vous cliquez n'importe où dans la page.
  5. L'écoute des événements sur l'élément body rendra votre code plus fragile. Un style aussi innocent que celui-ci le casserait : body { margin-left:auto; margin-right: auto; width:960px;}

26voto

benb Points 358

Comme l'a dit un autre poster, il y a beaucoup de problèmes, surtout si l'élément que vous affichez (dans ce cas un menu) a des éléments interactifs. J'ai trouvé la méthode suivante assez robuste :

$('#menuscontainer').click(function(event) {
    //your code that shows the menus fully

    //now set up an event listener so that clicking anywhere outside will close the menu
    $('html').click(function(event) {
        //check up the tree of the click target to check whether user has clicked outside of menu
        if ($(event.target).parents('#menuscontainer').length==0) {
            // your code to hide menu

            //this event listener has done its job so we can unbind it.
            $(this).unbind(event);
        }

    })
});

22voto

Chris MacDonald Points 3261

Vérifiez la cible de l'événement de clic de la fenêtre (il devrait se propager à la fenêtre, à condition qu'il ne soit pas capturé ailleurs), et assurez-vous qu'il ne s'agit pas d'un des éléments du menu. Si ce n'est pas le cas, vous êtes en dehors de votre menu.

Ou bien vérifiez la position du clic, et voyez s'il est contenu dans la zone de menu.

21voto

Iman Sedighi Points 100

Solution1

Au lieu d'utiliser event.stopPropagation() qui peut avoir des effets secondaires, il suffit de définir une simple variable drapeau et d'ajouter un if condition. J'ai testé cela et cela a fonctionné correctement sans aucun effet secondaire de stopPropagation :

var flag = "1";
$('#menucontainer').click(function(event){
    flag = "0"; // flag 0 means click happened in the area where we should not do any action
});

$('html').click(function() {
    if(flag != "0"){
        // Hide the menus if visible
    }
    else {
        flag = "1";
    }
});

Solution2

Avec un simple if condition :

$(document).on('click', function(event){
    var container = $("#menucontainer");
    if (!container.is(event.target) &&            // If the target of the click isn't the container...
        container.has(event.target).length === 0) // ... nor a descendant of the container
    {
        // Do whatever you want to do when click is outside the element
    }
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X