2941 Stimmen

Wie kann ich einen Klick außerhalb eines Elements erkennen?

Ich habe einige HTML-Menüs, die ich vollständig anzeige, wenn ein Benutzer auf den Kopf dieser Menüs klickt. Ich möchte diese Elemente ausblenden, wenn der Benutzer außerhalb des Bereichs der Menüs klickt.

Ist so etwas mit jQuery möglich?

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

22voto

2020 Lösung mit nativer JS API am nächsten Methode.

document.addEventListener('click', ({ target }) => {
  if (!target.closest('.el1, .el2, #el3')) {
    alert('click outside')
  }
})

19voto

Chu Yeow Punkte 977

Ich habe mit so etwas Erfolg gehabt:

var $menuscontainer = ...;

$('#trigger').click(function() {
  $menuscontainer.show();

  $('body').click(function(event) {
    var $target = $(event.target);

    if ($target.parents('#menuscontainer').length == 0) {
      $menuscontainer.hide();
    }
  });
});

Die Logik ist: Wenn #menuscontainer angezeigt wird, binden Sie einen Click-Handler an den Body, der die #menuscontainer nur, wenn das Ziel (des Klicks) kein Kind davon ist.

17voto

tim-mccurrach Punkte 6072

Utilice focusout für die Zugänglichkeit

Es gibt hier eine Antwort, die (ganz richtig) besagt, dass die Konzentration auf click Ereignisse sind ein Problem für die Zugänglichkeit, da wir die Tastaturbenutzer berücksichtigen wollen. Die Website focusout Ereignis ist das Richtige, um hier zu verwenden, aber es kann viel einfacher als in der anderen Antwort (und in reinem Javascript auch) getan werden:

Eine einfachere Art, dies zu tun:

Das "Problem" bei der Verwendung von focusout ist, dass, wenn ein Element in Ihrem Dialog/Modal/Menü den Fokus verliert, um etwas auch "innerhalb" das Ereignis noch ausgelöst wird. Wir können überprüfen, dass dies nicht der Fall ist, indem wir uns Folgendes ansehen event.relatedTarget (was uns sagt, welches Element den Fokus erhalten hat).

dialog = document.getElementById("dialogElement")

dialog.addEventListener("focusout", function (event) {
    if (
        // we are still inside the dialog so don't close
        dialog.contains(event.relatedTarget) ||
        // we have switched to another tab so probably don't want to close 
        !document.hasFocus()  
    ) {
        return;
    }
    dialog.close();  // or whatever logic you want to use to close
});

Es gibt einen kleinen Haken an der Sache, nämlich dass relatedTarget können sein null . Dies ist in Ordnung, wenn der Benutzer außerhalb des Dialogs klickt, aber es wird ein Problem sein, wenn der Benutzer innerhalb des Dialogs klickt und der Dialog nicht fokussierbar ist. Um dies zu beheben, müssen Sie sicherstellen, dass Sie tabIndex=0 damit Ihr Dialog fokussierbar ist.

17voto

Dan Philip Punkte 3894

Das Ereignis hat eine Eigenschaft namens event.path des Elements, die eine "statische geordnete Liste aller Vorfahren in Baumreihenfolge" . Um zu prüfen, ob ein Ereignis von einem bestimmten DOM-Element oder einem seiner Kinder stammt, wird einfach der Pfad für dieses spezifische DOM-Element geprüft. Es kann auch verwendet werden, um mehrere Elemente zu überprüfen, indem man logisch OR der Elementprüfung in der some Funktion.

$("body").click(function() {
  target = document.getElementById("main");
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  })
  if (flag) {
    console.log("Inside")
  } else {
    console.log("Outside")
  }
});

#main {
  display: inline-block;
  background:yellow;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
  <ul>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
    <li>Test-Main</li>
  </ul>
</div>
<div id="main2">
  Outside Main
</div>

In Ihrem Fall müsste es also lauten

$("body").click(function() {
  target = $("#menuscontainer")[0];
  flag = event.path.some(function(el, i, arr) {
    return (el == target)
  });
  if (!flag) {
    // Hide the menus
  }
});

16voto

Bohdan Lyzanets Punkte 1571

Als eine Variante:

var $menu = $('#menucontainer');
$(document).on('click', function (e) {

    // If element is opened and click target is outside it, hide it
    if ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {
        $menu.hide();
    }
});

Sie hat kein Problem mit Anhalten der Ereignisausbreitung und unterstützt besser mehrere Menüs auf derselben Seite, wobei beim Klicken auf ein zweites Menü, während das erste geöffnet ist, das erste in der stopPropagation-Lösung geöffnet bleibt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X