admin管理员组文章数量:1134247
I'd like to detect a click inside or outside a div area. The tricky part is that the div will contain other elements and if one of the elements inside the div is clicked, it should be considered a click inside, the same way if an element from outside the div is clicked, it should be considered an outside click.
I've been researching a lot but all I could find were examples in jquery and I need pure javascript.
Any suggestion will be appreciated.
I'd like to detect a click inside or outside a div area. The tricky part is that the div will contain other elements and if one of the elements inside the div is clicked, it should be considered a click inside, the same way if an element from outside the div is clicked, it should be considered an outside click.
I've been researching a lot but all I could find were examples in jquery and I need pure javascript.
Any suggestion will be appreciated.
Share Improve this question asked Apr 18, 2016 at 13:29 user4697579user4697579 3 |12 Answers
Reset to default 253It depends on the individual use case but it sounds like in this example there are likely to be other nested elements inside the main div e.g. more divs, lists etc. Using Node.contains would be a useful way to check whether the target element is within the div that is being checked.
window.addEventListener('click', function(e){
if (document.getElementById('clickbox').contains(e.target)){
// Clicked in box
} else{
// Clicked outside the box
}
});
An example that has a nested list inside is here.
You can check if the clicked Element is the div you want to check or not:
document.getElementById('outer-container').onclick = function(e) {
if(e.target != document.getElementById('content-area')) {
console.log('You clicked outside');
} else {
console.log('You clicked inside');
}
}
Referring to Here.
you can apply if check for that inside your click event
if(event.target.parentElement.id == 'yourID')
In Angular 6 and IONIC 3, I do same as here:
import {Component} from 'angular/core';
@Component({
selector: 'my-app',
template: `
<ion-content padding (click)="onClick($event)">
<div id="warning-container">
</div>
</ion-content>
`
})
export class AppComponent {
onClick(event) {
var target = event.target || event.srcElement || event.currentTarget;
if (document.getElementById('warning-container').contains(target)){
// Clicked in box
} else{
// Clicked outside the box
}
}
}
This working fine on web/android/ios. It might be helpful for someone, Thanks.
closePopover () {
var windowBody = window
var popover = document.getElementById('popover-wrapper') as HTMLDivElement;
windowBody?.addEventListener('click', function(event){
if(popover === event.target) {
console.log("clicked on the div")
}
if(popover !== event.target) {
console.log("clicked outside the div")
}
})
} }
In React you can use useClickOutside
hook from react-cool-onclickoutside.
Demo from Github:
import { useClickOutside } from 'use-events';
const Example = () => {
const ref1 = React.useRef(null);
const ref2 = React.useRef(null);
const [isActive] = useClickOutside([ref1, ref2], event => console.log(event));
return (
<div>
<div ref={ref1} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
<br />
<div ref={ref2} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
</div>
);
};
Live demo
Try this solution it uses pure javascript and it solves your problem. I added css just for better overview... but it is not needed.
document.getElementById('outer-div').addEventListener('click', function(){
alert('clicked outer div...');
});
document.getElementById('inner-div').addEventListener('click', function(e){
e.stopPropagation()
alert('clicked inner div...');
});
#outer-div{
width: 200px;
height: 200px;
position: relative;
background: black;
}
#inner-div{
top: 50px;
left: 50px;
width: 100px;
height: 100px;
position: absolute;
background: red;
}
<div id="outer-div">
<div id="inner-div">
</div>
</div>
I came up with a hack for this that's working well for me and that might help others.
When I pop up my dialog DIV, I simultaneously display another transparent DIV just behind it, covering the whole screen.
This invisible background DIV closes the dialog DIV onClick.
This is pretty straightforward, so I'm not going to bother with the code here. LMK in the comments if you want to see it and I'll add it in.
HTH!
I recently needed a simple vanilla JS solution which solves for:
- Ignoring specific selectors including whether a parent contains one of these selectors
- Ignoring specific DOM nodes
This solution has worked quite well in my app.
const isClickedOutsideElement = ({ clickEvent, elToCheckOutside, ignoreElems = [], ignoreSelectors = [] }) => {
const clickedEl = clickEvent.srcElement;
const didClickOnIgnoredEl = ignoreElems.filter(el => el).some(element => element.contains(clickedEl) || element.isEqualNode(clickedEl));
const didClickOnIgnoredSelector = ignoreSelectors.length ? ignoreSelectors.map(selector => clickedEl.closest(selector)).reduce((curr, accumulator) => curr && accumulator, true) : false;
if (
isDOMElement(elToCheckOutside) &&
!elToCheckOutside.contains(clickedEl) &&
!didClickOnIgnoredEl &&
!didClickOnIgnoredSelector
){
return true;
}
return false;
}
const isDOMElement = (element) => {
return element instanceof Element || element instanceof HTMLDocument;
}
Here, I override the Element prototype {add,remove}eventListener
methods prototype to add a new event clickOutside
, this adds a new event, that you can listen, I used this because I needed something simple without writing too much code for lots of elements, and to avoid code repeating itself. Hope this helps someone!
function extendElementclickoutside() {
(function () {
if (!Element.prototype.__customEventsExtended) {
// Mark the prototype to prevent multiple executions.
Element.prototype.__customEventsExtended = true;
// Retrieve original methods dynamically from the Element's prototype in the prototype chain.
const originalAddEventListener = Element.prototype.addEventListener;
const originalRemoveEventListener = Element.prototype.removeEventListener;
Element.prototype.addEventListener = function (type, listener, options) {
if (type === "clickOutside") {
const outsideClickListener = (event) => {
if (!this.contains(event.target) && this.isConnected) {
event.type = "clickOutside";
listener.call(this, event);
}
};
// Adding the listener to the document to capture all click events
document.addEventListener("click", outsideClickListener, options);
// Store in a map to properly remove later
this._outsideEventListeners =
this._outsideEventListeners || new Map();
this._outsideEventListeners.set(listener, outsideClickListener);
} else {
// Call the original addEventListener for other types of events
originalAddEventListener.call(this, type, listener, options);
}
};
Element.prototype.removeEventListener = function (
type,
listener,
options
) {
if (type === "clickOutside") {
const registeredListener =
this._outsideEventListeners &&
this._outsideEventListeners.get(listener);
if (registeredListener) {
document.removeEventListener("click", registeredListener, options);
this._outsideEventListeners.delete(listener);
if (this._outsideEventListeners.size === 0) {
delete this._outsideEventListeners;
}
}
} else {
// Call the original removeEventListener for other types of events
originalRemoveEventListener.call(this, type, listener, options);
}
};
}
})();
}
extendElementclickoutside()
const myElement = document.getElementById('myElement');
function handleOutsideClick(event) {
console.log('Clicked outside the element!');
}
myElement.addEventListener('clickOutside', handleOutsideClick);
#myElement {
padding: 20px;
border: 2px solid #007BFF;
background-color: #e7f1ff;
width: 300px;
text-align: center;
position: relative;
margin: 0 auto;
}
<div id="myElement">
Click inside this box and nothing special happens. Click outside this box to log a message to the console.
</div>
Most of these solutions are with the assumption you only have one popover/menu/modal at a time. If you have several items, each with its own menu, they won't work without significant modification. My solution is as follows:
document.addEventListener('click', (event) => {
// Check if click done inside popover
const container = event.target.closest('.popover');
// Check if popover open/close button was clicked
const buttonTarget = event.target.dataset.target;
// Ensure all popovers are closed if not requested or clicked inside
for (let popover of document.getElementsByClassName('popover')) {
if (popover.id === buttonTarget && popover.style.display !== `block`) {
popover.style.display = `block`;
} else if (!container) {
popover.style.display = `none`;
}
}
}, false);
Note that the above requires a data-target
attribute on the button/input/link set to the modal/popover's id, and a class of popover on all modal/popover items. You can adjust as necessary. You can also dispense with the container check if you want the menu to close as soon as any option has been clicked.
<button onclick="window.dialog.showModal()">Open dialog</button>
<dialog id="dialog" style="padding: 0; border: 0;">
<form method="dialog">
<div>Hello from dialog element. You can close me by clicking outside or Close button</div>
<button>Close</button>
</form>
</dialog>
function onClick(event) {
if (event.target === dialog) {
dialog.close();
}
}
const dialog = document.querySelector("dialog");
dialog.addEventListener("click", onClick);
dialog.showModal();
I found the code very simple.
Font: https://codepen.io/dvdvdmt/pen/BaavWbp
本文标签: Detect click outside div using javascriptStack Overflow
版权声明:本文标题:Detect click outside div using javascript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736780002a1952543.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
<div onclick="yourFunction()"> </div>
– Kishore Barik Commented Apr 18, 2016 at 13:34