Ich habe überall nach einer guten Lösung gesucht, kann aber keine finden, die jQuery nicht verwendet .
Gibt es eine browserübergreifende, normale Methode (ohne seltsame Hacks oder leicht zu brechenden Code), um einen Klick außerhalb eines Elements zu erkennen (das möglicherweise untergeordnete Elemente hat oder nicht)?
javascript
Tiberiu-Ionuț Stan
quelle
quelle
Antworten:
Fügen Sie einen Ereignis-Listener hinzu
document
und verwenden Sie ihnNode.contains()
, um festzustellen, ob sich das Ziel des Ereignisses (das am innersten angeklickte Element) innerhalb des angegebenen Elements befindet. Es funktioniert sogar in IE5var specifiedElement = document.getElementById('a'); //I'm using "click" but it works with any event document.addEventListener('click', function(event) { var isClickInside = specifiedElement.contains(event.target); if (!isClickInside) { //the click was outside the specifiedElement, do something } });
Code-Snippet anzeigen
var specifiedElement = document.getElementById('a'); //I'm using "click" but it works with any event document.addEventListener('click', function(event) { var isClickInside = specifiedElement.contains(event.target); if (isClickInside) { alert('You clicked inside A') } else { alert('You clicked outside A') } });
div { margin: auto; padding: 1em; max-width: 6em; background: rgba(0, 0, 0, .2); text-align: center; }
Is the click inside A or outside? <div id="a">A <div id="b">B <div id="c">C</div> </div> </div>
quelle
Sie müssen das Klickereignis auf Dokumentebene behandeln. Im Ereignisobjekt haben Sie eine
target
Eigenschaft, das innerste DOM-Element, auf das geklickt wurde. Damit überprüfen Sie sich selbst und gehen die Eltern bis zum Dokumentelement hoch, wenn eines davon Ihr überwachtes Element ist.Siehe das Beispiel auf jsFiddle
document.addEventListener("click", function (e) { var level = 0; for (var element = e.target; element; element = element.parentNode) { if (element.id === 'x') { document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked"; return; } level++; } document.getElementById("out").innerHTML = "not x clicked"; });
Wie immer ist dies aufgrund von addEventListener / attachEvent nicht Cross-Bad-Browser-kompatibel, aber es funktioniert so.
Ein Kind wird angeklickt, wenn es nicht event.target ist, aber eines seiner Eltern ist das beobachtete Element (ich zähle einfach die Stufe dafür). Sie können auch eine boolesche Variable haben, wenn das Element gefunden wird oder nicht, um den Handler nicht aus der for-Klausel zurückzugeben. Mein Beispiel beschränkt sich darauf, dass der Handler nur dann beendet wird, wenn nichts übereinstimmt.
Wenn ich die Cross-Browser-Kompatibilität hinzufüge, mache ich das normalerweise so:
var addEvent = function (element, eventName, fn, useCapture) { if (element.addEventListener) { element.addEventListener(eventName, fn, useCapture); } else if (element.attachEvent) { element.attachEvent(eventName, function (e) { fn.apply(element, arguments); }, useCapture); } };
Dies ist browserübergreifender kompatibler Code zum Anhängen eines Ereignis-Listeners / -Handlers, einschließlich des Umschreibens
this
im IE, als Element, wie dies jQuery für seine Ereignishandler tut. Es gibt viele Argumente, um ein bisschen jQuery im Auge zu behalten;)quelle
target
Eigenschaft (die, wie Metadings sagt, das innerste DOM-Element ist) - und alle übergeordneten Elemente. Entweder erreichen Sie Ihr überwachtes Element, dh der Benutzer hat darauf geklickt, oder Sie erreichen das Dokumentelement. In diesem Fall hat er nach außen geklickt. Alternativ können Sie zwei Klick-Listener hinzufügen - einen für das Dokumentelement und einen für das überwachte Element, wobeievent.stopPropagation()
/ verwendet wird,cancelBubble
sodass der Listener für das Dokumentelement nur durch einen Klick außerhalb des überwachten Elements ausgelöst wird.for
. Gibt es aus Neugier einen Grund, ein Element aus einer Variablen nicht mit dem Ziel des Ereignisses zu vergleichen (unter Verwendung eines strengen Vergleichs)?Wie wäre es damit:
jsBin Demo
document.onclick = function(event){ var hasParent = false; for(var node = event.target; node != document.body; node = node.parentNode) { if(node.id == 'div1'){ hasParent = true; break; } } if(hasParent) alert('inside'); else alert('outside'); }
quelle
Um ein Element durch Klicken außerhalb auszublenden, wende ich normalerweise einen so einfachen Code an:
var bodyTag = document.getElementsByTagName('body'); var element = document.getElementById('element'); function clickedOrNot(e) { if (e.target !== element) { // action in the case of click outside bodyTag[0].removeEventListener('click', clickedOrNot, true); } } bodyTag[0].addEventListener('click', clickedOrNot, true);
quelle
Eine andere sehr einfache und schnelle Lösung für dieses Problem besteht darin, das Array von
path
dem vom Listener zurückgegebenen Ereignisobjekt zuzuordnen . Wenn der Nameid
oderclass
Name Ihres Elements mit einem Namen im Array übereinstimmt, befindet sich der Klick in Ihrem Element.(Diese Lösung kann nützlich sein, wenn Sie das Element nicht direkt
document.getElementById('...')
abrufen möchten (z. B. in einer reactjs / nextjs-App in ssr ..).Hier ist ein Beispiel:
document.addEventListener('click', e => { let clickedOutside = true; e.path.forEach(item => { if (!clickedOutside) return; if (item.className === 'your-element-class') clickedOutside = false; }); if (clickedOutside) // Make an action if it's clicked outside.. });
Ich hoffe diese Antwort wird Ihnen helfen! (Lassen Sie mich wissen, ob meine Lösung keine gute Lösung ist oder ob Sie Verbesserungen sehen.)
quelle
Ich habe viel darüber recherchiert, um eine bessere Methode zu finden. Die JavaScript-Methode .contains wird im DOM rekursiv überprüft, ob sie ein Ziel enthält oder nicht. Ich habe es in einem der React-Projekte verwendet, aber wenn sich das React-DOM im festgelegten Status ändert, funktioniert die .contains-Methode nicht. Also habe ich mir diese Lösung ausgedacht
//Basic Html snippet <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="mydiv"> <h2> click outside this div to test </h2> Check click outside </div> </body> </html> //Implementation in Vanilla javaScript const node = document.getElementById('mydiv') //minor css to make div more obvious node.style.width = '300px' node.style.height = '100px' node.style.background = 'red' let isCursorInside = false //Attach mouseover event listener and update in variable node.addEventListener('mouseover', function() { isCursorInside = true console.log('cursor inside') }) /Attach mouseout event listener and update in variable node.addEventListener('mouseout', function() { isCursorInside = false console.log('cursor outside') }) document.addEventListener('click', function() { //And if isCursorInside = false it means cursor is outside if(!isCursorInside) { alert('Outside div click detected') } })
ARBEITSDEMO jsfiddle
quelle