Close a div by clicking outside - javascript

I want to hide a div by clicking on the close link in it, or by clicking anywhere outside that div.
I am trying following code, it opens and close the div by clicking close link properly, but if I have problem to close it by clicking anywhere outside the div.
$(".link").click(function() {
$(".popup").fadeIn(300);
}
);
$('.close').click(function() {
$(".popup").fadeOut(300);
}
);
$('body').click(function() {
if (!$(this.target).is('.popup')) {
$(".popup").hide();
}
}
);
<div class="box">
Open
<div class="popup">
Hello world
<a class="close" href="#">Close</a>
</div>
</div>
Demo:
http://jsfiddle.net/LxauG/

An other way which makes then your jsfiddle less buggy (needed double click on open).
This doesn't use any delegated event to body level
Set tabindex="-1" to DIV .popup ( and for style CSS outline:0 )
DEMO
$(".link").click(function(e){
e.preventDefault();
$(".popup").fadeIn(300,function(){$(this).focus();});
});
$('.close').click(function() {
$(".popup").fadeOut(300);
});
$(".popup").on('blur',function(){
$(this).fadeOut(300);
});

You need
$('body').click(function(e) {
if (!$(e.target).closest('.popup').length){
$(".popup").hide();
}
});

I'd suggest using the stopPropagation() method as shown in the modified fiddle:
Fiddle
$('body').click(function() {
$(".popup").hide();
});
$('.popup').click(function(e) {
e.stopPropagation();
});
That way you can hide the popup when you click on the body, without having to add an extra if, and when you click on the popup, the event doesn't bubble up to the body by going through the popup.

You'd better go with something like this. Just give an id to the div which you want to hide and make a function like this.
call this function by adding onclick event on body.
function myFunction(event) {
if(event.target.id!="target_id")
{
document.getElementById("target_id").style.display="none";
}
}

Add a transparent background taking up the whole window size, just before your popup div
.transparent-back{
position: fixed;
top: 0px;
left:0px;
width: 100%;
height: 100%;
background-color: rgba(255,255,255,0.5);
}
Then on its click, dismiss the popup.
$(".transparent-back").on('click',function(){
$('popup').fadeOut(300);
});

This question might have been answered here. There might be some potential issues when event propagation is interrupted, as explained by Philip Walton in this post.
A better approach/solution would be to create a custom jQuery event, e.g. clickoutside. Ben Alman has a great post (here) that explains how to implement one (and also explains how special events work), and he's got a nice implementation of it (here).
More reading on jQuery events API and jQuery special events:
Introduction to custom events
jQuery event extensions

var modal = document.getElementById("reject-popup");
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}

//for closeing the popover when user click outside it will close all popover
var hidePopover = function(element) {
var elementScope = angular.element($(element).siblings('.popover')).scope().$parent;
elementScope.isOpen = false;
elementScope.$apply();
//Remove the popover element from the DOM
$(element).siblings('.popover').remove();
};
$(document).ready(function(){
$('body').on('click', function (e) {
$("a").each(function () {
//Only do this for all popovers other than the current one that cause this event
if (!($(this).is(e.target) || $(this).has(e.target).length > 0)
&& $(this).siblings('.popover').length !== 0 && $(this).siblings('.popover').has(e.target).length === 0)
{
hidePopover(this);
}
});
});
});

Related

click event listener on javascript [duplicate]

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. -->
I don't want #clickable to handle this click event.
</div>
Events bubble to the highest point in the DOM at which a click event has been attached. So in your example, even if you didn't have any other explicitly clickable elements in the div, every child element of the div would bubble their click event up the DOM to until the DIV's click event handler catches it.
There are two solutions to this is to check to see who actually originated the event. jQuery passes an eventargs object along with the event:
$("#clickable").click(function(e) {
var senderElement = e.target;
// Check if sender is the <div> element e.g.
// if($(e.target).is("div")) {
window.location = url;
return true;
});
You can also attach a click event handler to your links which tell them to stop event bubbling after their own handler executes:
$("#clickable a").click(function(e) {
// Do something
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.
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 children
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
Inline Alternative:
<div>
<!-- Other content. -->
<a onclick='event.stopPropagation();' href="http://foo.example">I don't want #clickable to handle this click event.</a>
</div>
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
}
});
Writing if anyone needs (worked for me):
event.stopImmediatePropagation()
From this solution.
Using return false; or e.stopPropogation(); will not allow further code to execute. It will stop flow at this point itself.
If you have multiple elements in the clickable div, you should do this:
$('#clickable *').click(function(e){ e.stopPropagation(); });
I compare to ev.currentTarget when this is not available (React, etc).
$("#clickable").click(function(e) {
if (e.target === e.currentTarget) {
window.location = url;
return true;
}
})
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();
}
If it is in inline context, in HTML try this:
onclick="functionCall();event.stopPropagation();
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; }
var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);
function innerFunction(event){
event.stopPropagation();
console.log("Inner Functiuon");
}
function outerFunction(event){
console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
<div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>
You need to stop the event from reaching (bubbling to) the parent (the div).
See the part about bubbling here, and jQuery-specific API info here.
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();
});
});
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
}
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>
for those that are not using jQuery
document.querySelector('.clickable').addEventListener('click', (e) =>{
if(!e.target.classList.contains('clickable')) return
// place code here
})
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.
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;
})
This is what you are looking for
mousedown event. this works on every DOM elements to prevent javascript focus handler like this:
$('.no-focus').mousedown(function (e) {
e.prevenDefault()
// do stuff
}
in vue.js framework, you can use modifier like this:
<span #mousedown.prevent> no focus </span>
Note that using on the input will prevent text selection handler
add a as follows:
....
or return false; from click handler for #clickable like:
$("#clickable").click(function() {
var url = $("#clickable a").attr("href");
window.location = url;
return false;
});
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
}
<a onclick="return false;" href="http://foo.example">I want to ignore my parent's onclick event.</a>

jQuery stopPropagation not stopping click through

I have a panzoom plugin that is working well. When I click on var elem it adds a small div cp_select in the correct location. Then, when I click on that newly created cp_select div, it removes that div. So you can add and remove it accordingly. However, when I click on the cp_select div, it removes it then immediately adds it back in because the click is propagating through. I have tried event.stopPropagation() and event.stopImmediatePropagation() with no luck. Any ideas how to prevent the cp_select firing the map_click(e)?
window.panzoom = panzoom(elem, {
onClick(e) {
map_click(e);
}
})
function map_click(e) {
$(".map_cont").prepend('<div class="cp_select" style="left:'+calc_x+'px ;top:'+calc_y+'px"></div>');
}
$('body').on('click', '.cp_select', function(event) {
event.stopImmediatePropagation()
$(this).remove()
return false;
});
The problem must be specifically with however panzoom is dealing with its onClick, or otherwise in code not shown in the question; if I substitute a plain click event handler on the window in place of your panzoom call, event.stopPropagation() works as expected.
// nonessential code removed and simplified for demo
function map_click() {
$(".map_cont").prepend('<div class="cp_select"></div>');
}
$('body').on('click', '.cp_select', function(event) {
$(this).remove();
event.stopPropagation();
});
window.onclick = map_click // stand-in for your panzoom function
.cp_select {
border: 3px solid;
height: 20px; width: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
(click anywhere)
<div class="map_cont"></div>

How to treat child element as separate from it's parent in html [duplicate]

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. -->
I don't want #clickable to handle this click event.
</div>
Events bubble to the highest point in the DOM at which a click event has been attached. So in your example, even if you didn't have any other explicitly clickable elements in the div, every child element of the div would bubble their click event up the DOM to until the DIV's click event handler catches it.
There are two solutions to this is to check to see who actually originated the event. jQuery passes an eventargs object along with the event:
$("#clickable").click(function(e) {
var senderElement = e.target;
// Check if sender is the <div> element e.g.
// if($(e.target).is("div")) {
window.location = url;
return true;
});
You can also attach a click event handler to your links which tell them to stop event bubbling after their own handler executes:
$("#clickable a").click(function(e) {
// Do something
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.
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 children
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
Inline Alternative:
<div>
<!-- Other content. -->
<a onclick='event.stopPropagation();' href="http://foo.example">I don't want #clickable to handle this click event.</a>
</div>
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
}
});
Writing if anyone needs (worked for me):
event.stopImmediatePropagation()
From this solution.
Using return false; or e.stopPropogation(); will not allow further code to execute. It will stop flow at this point itself.
If you have multiple elements in the clickable div, you should do this:
$('#clickable *').click(function(e){ e.stopPropagation(); });
I compare to ev.currentTarget when this is not available (React, etc).
$("#clickable").click(function(e) {
if (e.target === e.currentTarget) {
window.location = url;
return true;
}
})
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();
}
If it is in inline context, in HTML try this:
onclick="functionCall();event.stopPropagation();
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; }
var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);
function innerFunction(event){
event.stopPropagation();
console.log("Inner Functiuon");
}
function outerFunction(event){
console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
<div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>
You need to stop the event from reaching (bubbling to) the parent (the div).
See the part about bubbling here, and jQuery-specific API info here.
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();
});
});
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
}
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>
for those that are not using jQuery
document.querySelector('.clickable').addEventListener('click', (e) =>{
if(!e.target.classList.contains('clickable')) return
// place code here
})
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.
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;
})
This is what you are looking for
mousedown event. this works on every DOM elements to prevent javascript focus handler like this:
$('.no-focus').mousedown(function (e) {
e.prevenDefault()
// do stuff
}
in vue.js framework, you can use modifier like this:
<span #mousedown.prevent> no focus </span>
Note that using on the input will prevent text selection handler
add a as follows:
....
or return false; from click handler for #clickable like:
$("#clickable").click(function() {
var url = $("#clickable a").attr("href");
window.location = url;
return false;
});
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
}
<a onclick="return false;" href="http://foo.example">I want to ignore my parent's onclick event.</a>

Hiding Bootstrap Popover on Click Outside Popover

I'm trying to hide the Bootstrap Popover when the user clicks anywhere outside the popover. (I'm really not sure why the creators of Bootstrap decided not to provide this functionality.)
I found the following code on the web but I really don't understand it.
// Hide popover on click anywhere on the document except itself
$(document).click(function(e) {
// Check for click on the popup itself
$('.popover').click(function() {
return false; // Do nothing
});
// Clicking on document other than popup then hide the popup
$('.pop').popover('hide');
});
The main thing I find confusing is the line $('.popover').click(function() { return false; });. Doesn't this line add an event handler for the click event? How does that prevent the call to popover('hide') that follows from hiding the popover?
And has anyone seen a better technique?
Note: I know variations of this question has been asked here before, but the answers to those questions involve code more complex than the code above. So my question is really about the code above
I made http://jsfiddle.net/BcczZ/2/, which hopefully answers your question
Example HTML
<div class="well>
<a class="btn" data-toggle="popover" data-content="content.">Popover</a>
<a class="btn btn-danger bad">Bad button</a>
</div>
JS
var $popover = $('[data-toggle=popover]').popover();
//first event handler for bad button
$('.bad').click(function () {
alert("clicked");
});
$(document).on("click", function (e) {
var $target = $(e.target),
var isPopover = $target.is('[data-toggle=popover]'),
inPopover = $target.closest('.popover').length > 0
//Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT
$('.bad').click(function () {
console.log('clicked');
return false;
});
//hide only if clicked on button or inside popover
if (!isPopover && !inPopover) $popover.popover('hide');
});
As I mentioned in my comment, event handlers don't get overwritten, they just stack. Since there is already an event handler on the .bad button, it will be fired, along with any other event handler
Open your console in the jsfiddle, press 5 times somewhere on the page (not the popover button) and then click bad button you should see clicked printed the same amount of times you pressed
Hope it helps
P.S:
If you think about it, you already saw this happening, especially in jQuery.
Think of all the $(document).ready(...) that exist in a page using multiple jquery plugins. That line just registers an event handler on the document's ready event
I just did a more event based solution.
var $toggle = $('.your-popover-button');
$toggle.popover();
var hidePopover = function() {
$toggle.popover('hide');
};
$toggle.on('shown', function () {
var $popover = $toggle.next();
$popover.on('mousedown', function(e) {
e.stopPropagation();
});
$toggle.on('mousedown', function(e) {
e.stopPropagation();
});
$(document).on('mousedown',hidePopover);
});
$toggle.on('hidden', function () {
$(document).off('mousedown', hidePopover);
});
short answer
insert this to bootstrap min.js
when popout onblur will hide popover
when popout more than one, older popover will be hide
$count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;});
None of the above solutions worked 100% for me because I had to click twice on another, or the same, popover to open it again. I have written the solution from scratch to be simple and effective.
$('[data-toggle="popover"]').popover({
html:true,
trigger: "manual",
animation: false
});
$(document).on('click','body',function(e){
$('[data-toggle="popover"]').each(function () {
$(this).popover('hide');
});
if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target).popover('show');
}
else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') {
e.preventDefault();
$(e.target.parentElement).popover('show');
}
});
My solution, works 100%, for Bootstrap v3
$('html').on('click', function(e) {
if(typeof $(e.target).data('original-title') !== 'undefined'){
$('[data-original-title]').not(e.target).popover('hide');
}
if($(e.target).parents().is('[data-original-title]')){
$('[data-original-title]').not($(e.target).closest('[data-original-title]')).popover('hide');
}
if (typeof $(e.target).data('original-title') == 'undefined' &&
!$(e.target).parents().is('.popover.in') && !$(e.target).parents().is('[data-original-title]')) {
$('[data-original-title]').popover('hide');
}
});

How do I prevent a parent's onclick event from firing when a child anchor is clicked?

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. -->
I don't want #clickable to handle this click event.
</div>
Events bubble to the highest point in the DOM at which a click event has been attached. So in your example, even if you didn't have any other explicitly clickable elements in the div, every child element of the div would bubble their click event up the DOM to until the DIV's click event handler catches it.
There are two solutions to this is to check to see who actually originated the event. jQuery passes an eventargs object along with the event:
$("#clickable").click(function(e) {
var senderElement = e.target;
// Check if sender is the <div> element e.g.
// if($(e.target).is("div")) {
window.location = url;
return true;
});
You can also attach a click event handler to your links which tell them to stop event bubbling after their own handler executes:
$("#clickable a").click(function(e) {
// Do something
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.
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 children
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
Inline Alternative:
<div>
<!-- Other content. -->
<a onclick='event.stopPropagation();' href="http://foo.example">I don't want #clickable to handle this click event.</a>
</div>
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
}
});
Writing if anyone needs (worked for me):
event.stopImmediatePropagation()
From this solution.
Using return false; or e.stopPropogation(); will not allow further code to execute. It will stop flow at this point itself.
If you have multiple elements in the clickable div, you should do this:
$('#clickable *').click(function(e){ e.stopPropagation(); });
I compare to ev.currentTarget when this is not available (React, etc).
$("#clickable").click(function(e) {
if (e.target === e.currentTarget) {
window.location = url;
return true;
}
})
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();
}
If it is in inline context, in HTML try this:
onclick="functionCall();event.stopPropagation();
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; }
var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);
function innerFunction(event){
event.stopPropagation();
console.log("Inner Functiuon");
}
function outerFunction(event){
console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
<div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>
You need to stop the event from reaching (bubbling to) the parent (the div).
See the part about bubbling here, and jQuery-specific API info here.
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();
});
});
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
}
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>
for those that are not using jQuery
document.querySelector('.clickable').addEventListener('click', (e) =>{
if(!e.target.classList.contains('clickable')) return
// place code here
})
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.
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;
})
This is what you are looking for
mousedown event. this works on every DOM elements to prevent javascript focus handler like this:
$('.no-focus').mousedown(function (e) {
e.prevenDefault()
// do stuff
}
in vue.js framework, you can use modifier like this:
<span #mousedown.prevent> no focus </span>
Note that using on the input will prevent text selection handler
add a as follows:
....
or return false; from click handler for #clickable like:
$("#clickable").click(function() {
var url = $("#clickable a").attr("href");
window.location = url;
return false;
});
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
}
<a onclick="return false;" href="http://foo.example">I want to ignore my parent's onclick event.</a>

Categories

Resources