I'm currently using jQuery to make a div clickable and in this div I also have anchors. The problem I'm running into is that when I click on an anchor both click events are firing (for the div and the anchor). How do I prevent the div's onclick event from firing when an anchor is clicked?
Here's the broken code:
JavaScript
var url = $("#clickable a").attr("href");
$("#clickable").click(function() {
window.location = url;
return true;
})
HTML
<div id="clickable">
<!-- Other content. -->
<a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
This question is related to
javascript
jquery
event-propagation
You can check whether the target is not your div-element and then issue another click event on the parent after which you will "return" from the handle.
$('clickable').click(function (event) {
let div = $(event.target);
if (! div.is('div')) {
div.parent().click();
return;
}
// Then Implement your logic here
}
ignoreParent() is a pure JavaScript solution.
It works as an intermediary layer that compares the coordinates of the mouse click with the coordinates of the child element/s. Two simple implementation steps:
1. Put the ignoreParent() code on your page.
2. Instead of the parent's original onclick="parentEvent();", write:
onclick="ignoreParent(['parentEvent()', 'child-ID']);"
You may pass IDs of any number of child elements to the function, and exclude others.
If you clicked on one of the child elements, the parent event doesn't fire. If you clicked on parent, but not on any of the child elements [provided as arguments], the parent event is fired.
<a onclick="return false;" href="http://foo.com">I want to ignore my parent's onclick event.</a>
e.stopPropagation()
is a correct solution, but in case you don't want to attach any event handler to your inner anchor, you can simply attach this handler to your outer div:
e => { e.target === e.currentTarget && window.location = URL; }
If you have multiple elements in the clickable div, you should do this:
$('#clickable *').click(function(e){ e.stopPropagation(); });
Use stopPropagation method, see an example:
$("#clickable a").click(function(e) {
e.stopPropagation();
});
As said by jQuery Docs:
stopPropagation
method prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event.
Keep in mind that it does not prevent others listeners to handle this event(ex. more than one click handler for a button), if it is not the desired effect, you must use stopImmediatePropagation
instead.
add a
as follows:
<a href="http://foo.com" onclick="return false;">....</a>
or return false;
from click handler for #clickable
like:
$("#clickable").click(function() {
var url = $("#clickable a").attr("href");
window.location = url;
return false;
});
Here my solution for everyone out there looking for a non-jQuery code (pure javascript)
document.getElementById("clickable").addEventListener("click", function( e ){
e = window.event || e;
if(this === e.target) {
// put your code here
}
});
Your code wont be executed if clicked on parent's childs
Using return false;
or e.stopPropogation();
will not allow further code to execute. It will stop flow at this point itself.
Here's an example using Angular 2+
For example, if you wanted to close a Modal Component if the user clicks outside of it:
// Close the modal if the document is clicked.
@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
this.closeModal();
}
// Don't close the modal if the modal itself is clicked.
@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
event.stopPropagation();
}
you can also try this
$("#clickable").click(function(event) {
var senderElementName = event.target.tagName.toLowerCase();
if(senderElementName === 'div')
{
// do something here
}
else
{
//do something with <a> tag
}
});
var inner = document.querySelector("#inner");_x000D_
var outer = document.querySelector("#outer");_x000D_
inner.addEventListener('click',innerFunction);_x000D_
outer.addEventListener('click',outerFunction);_x000D_
_x000D_
function innerFunction(event){_x000D_
event.stopPropagation();_x000D_
console.log("Inner Functiuon");_x000D_
}_x000D_
_x000D_
function outerFunction(event){_x000D_
console.log("Outer Functiuon");_x000D_
}
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
<head>_x000D_
<meta charset="utf-8">_x000D_
<meta name="viewport" content="width=device-width">_x000D_
<title>Pramod Kharade-Event with Outer and Inner Progration</title>_x000D_
</head>_x000D_
<body>_x000D_
<div id="outer" style="width:100px;height:100px;background-color:green;">_x000D_
<div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>_x000D_
</div>_x000D_
</body>_x000D_
</html>
_x000D_
Here is a non jQuery solution that worked for me.
<div style="background:cyan; width:100px; height:100px;" onclick="if (event.srcElement==this) {console.log('outer');}">
<a style="background:red" onclick="console.log('inner');">Click me</a>
</div>
_x000D_
Inline Alternative:
<div>
<!-- Other content. -->
<a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>
If you do not intend to interact with the inner element/s in any case, then a CSS solution might be useful for you.
Just set the inner element/s to pointer-events: none
in your case:
.clickable > a {
pointer-events: none;
}
or to target all inner elements generally:
.clickable * {
pointer-events: none;
}
This easy hack saved me a lot of time while developing with ReactJS
Browser support could be found here: http://caniuse.com/#feat=pointer-events
All solution are complicated and of jscript. Here is the simplest version:
var IsChildWindow=false;
function ParentClick()
{
if(IsChildWindow==true)
{
IsChildWindow==false;
return;
}
//do ur work here
}
function ChildClick()
{
IsChildWindow=true;
//Do ur work here
}
If it is in inline context, in HTML try this:
onclick="functionCall();event.stopPropagation();
If a child element is clicked, then the event bubbles up to the parent and event.target !== event.currentTarget.
So in your function, you can check this and return early, i.e.:
var url = $("#clickable a").attr("href");
$("#clickable").click(function(event) {
if ( event.target !== event.currentTarget ){
// user clicked on a child and we ignore that
return;
}
window.location = url;
return true;
})
To specify some sub element as unclickable write the css hierarchy as in the example below.
In this example I stop propagation to any elements (*) inside td inside tr inside a table with the class ".subtable"
$(document).ready(function()
{
$(".subtable tr td *").click(function (event)
{
event.stopPropagation();
});
});
In case someone had this issue using React, this is how I solved it.
scss:
#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }
#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }
Component's render():
render() {
...
return (
<div id='loginBackdrop' onClick={this.props.closeLogin}>
<div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
... [modal content] ...
</div>
</div>
)
}
By a adding an onClick function for the child modal (content div) mouse click events are prevented to reach the 'closeLogin' function of the parent element.
This did the trick for me and I was able to create a modal effect with 2 simple divs.
Source: Stackoverflow.com