I need to fire an event after stopPropagation has been called.
I am hiding the div on html click and when someone clicks on the notif_noti button I am showing the div which then loads some items with the id #freq.
The problem is #freq will be inside #notification_load which is inside of #notification_box and the stopPropagation is attached to #notif_noti and also #notification_box so basically when you click on these two items it will not fire the event I am trying to fire. e.g you can not .click() on #freq because it will not register because it is inside of #notification_box
Hopefully someone can help me as to how to achieve this. If you do not understand I will try to rewrite this for you.
Thanks
$("#notif_noti, #notification_box").click(function(event){
event.stopPropagation();
});
$("#notif_noti").click(function() {
$("#notification_box").show();
$("#notification_load").html('<div style="width:100%; text-align:center; height: 20px;line-height: 50px;padding-top: 20px;padding-bottom: 20px;color: #999;"><i class="fa fa-circle-o-notch fa-spin" style="font-size:20px;"></i></div>');
});
$("html").click(function() {
$("#notification_box").hide();
});
<div id='notification_box'>
<div id='notification_arrow'></div>
<div id='notification_hd'>
<span id='notification_header' style='padding-left:05px;'></span>
</div>
<div id='notification_load'></div>
</div>
Provide the full code snippet. remaining that once call the event.stopPropagation() method. it can not be resumed so you use the below work around:
var stop = false;
// do your logic here
if(stop){
event.stopPropagation();
}
$(document).mouseup(function (e)
{
var container = $("YOUR CONTAINER SELECTOR");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});
this works. thanks.
Related
Trying to get a mobile footer menu (#mobile-menu) to hide / show when the floating button is clicked or tapped. I'm able to add the click event handler to the button (#mobile-footer-btn) which in turns applies a class to the menu and animates it off screen.
<footer id="mobile-footer">
<div id="mobile-menu">
<div id="mobile-footer-container">
<div class="mobile-link">
My Account
</div>
<div class="mobile-link">
Reviews
</div>
<div class="mobile-link">
Contact Us
</div>
</div>
</div>
<div id="mobile-footer-close">
<button id="mobile-footer-btn">
<div class="mobile-btn-close">
<span></span>
</div>
</button>
</div>
</footer>
For whatever reason, I'm not able to remove that class and add a new class to the same ID, which would add a class to show the menu again.
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
//Trigger closing the footer menu
$(mobileBtn).on("click", function() {
$(mobileMenu).addClass('mobile-menu-hide');
});
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
if($(mobileMenu).hasClass('mobile-menu-hide')) {
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
});
}
});
Any help would be much appreciated!
You only need one on click event! Your if condition never gets evaluated to true, therefor your onclick event is never triggered. It's better to house it in one onclick event. Here's the code:
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
if($(mobileMenu).hasClass('mobile-menu-hide')) {
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
} else {
$(mobileMenu).removeClass("mobile-menu-show").addClass("mobile-menu-hide");
}
});
});
Here's the plunker: https://plnkr.co/edit/SG8eFns91wV4adxapFDB
Even better now that I think about it: just toggle the one class that hides the menu and just use jQuery's toggleClass function. Something like this:
$(mobileBtn).on("click", function(e) {
e.stopPropagation();
$(mobileMenu).toggleClass('mobile-menu-hide');
});
The problem is that your if condition in the block only executes once. However, you need it to be called on every click. Hence, you need to update your code to following
jQuery(document).ready(function($){
// Store menu container
var mobileMenu = '#mobile-menu';
// Store Trigger
var mobileBtn = '#mobile-footer-btn';
//Trigger closing the footer menu
$(mobileBtn).on("click", function() {
// moved your if block inside the click handler
if($(mobileMenu).hasClass('mobile-menu-hide')) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
} else {
$(mobileMenu).addClass('mobile-menu-hide');
}
});
$('.mobile-btn-close').click(function() {
$(this).addClass('is-rotating');
});
});
Your $(mobileBtn).on("click", function(e) { ... code never executes and, therefore, never adds the click event handler because the menu doesn't start out as .mobile-menu-hide Try this
$(mobileBtn).on("click", function(e) {
if($(mobileMenu).hasClass('mobile-menu-hide')) {
e.stopPropagation();
$(mobileMenu).removeClass("mobile-menu-hide").addClass("mobile-menu-show");
}
});
So I have the following code:
JS
function overlay() {
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
return true;
}
$("#close-link").click(function(event) {
event.preventDefault();
var targetUrl = $("#confirm").attr("href");
});
$("#confirm").click(function(event) {
event.preventDefault();
});
$("#go").click(function(event) {
event.preventDefault();
});
HTML
<div id="overlay">
<div id="dialog">
<h3 class="top-bar">Leaving so soon?</h3>
<span class="close-button-container">[X]</span><br /><br /><br />
Example text
<br />No, take me there anyway...
</div>
</div>
<!-- ... -->
Example Link
The Problem
I tried adding a link to another site. But I wanted to add a confirmation box once this link is clicked. The #close-link is used to close the dialog and the #confirm link as seen above should open it. The #go link is inside the dialog and if clicked brings the user to the location of the #confirm link. But something went wrong... Now when I click #confirm it opens the dialog for a second and directly sends me to its href. Shouldn't event.preventDefault fix this? If so, then why doesn't it?
Add an event to overlay(event). This function needs to prevent the click so it should have the e.preventDefault()
Example Link
function overlay(event) {
event.preventDefault();
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
var href = event.target.href
//If click button close
//Hidden div, no go
//If click button go
//window.location = href
}
Explanation
Your <a> has two events binded to it. One with #confirm and one with the inline onclick=. You should choose only one :)
So, a few things;
Remove all inline event handlers
When using jQuery, make the most of it and avoid writing vanilla javascript unless there is a reason to do so.
Do not use A for any other purpose than an actual link (The close button in your case). Use a button/other tags.
Take a look the below code and see if that's what you wanted.
$("#confirm, #close-link").click(overlay);
function overlay(evt) {
evt.preventDefault();
var el = $("#overlay");
el.css({"visibility": el.css("visibility") === "visible" && "hidden" || "visible"});
if ( this.tagName === 'A' ) {
el.find("a").attr("href", this.href);
}
}
#overlay {
height: 150px;
width: 200px;
background: green;
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="overlay">
<div id="dialog">
<h3 class="top-bar">Leaving so soon?</h3>
<span class="close-button-container" id="close-link">[X]</span><br /><br /><br />
Example text
<br />No, take me there anyway...
</div>
</div>
<!-- ... -->
Example Link
If your code was called as part of an event listener callback, event.preventDefault() would work. But your code is running due to onclick which simply runs the function overlay() - attaching listeners to various elements (#close-link, #go, #confirm) using jQuery. After the listeners are attached, they start listening for events, which never come since the <a href="..."> changes the page.
Solution:
It is best to stop using on* attributes for all your codes. Take it out. Then use only event listeners for all your needs.
$('#confirm').on('click', function(event) {
event.preventDefault(); // this will work
// Do your toggle visibility and whatever else you need here.
});
There are other possible solutions that continue to use onclick calling a function, but I wouldn't recommend it.
Try attaching the click event to the #confirm element inside $(document).ready:
$(document).ready(function() {
$("#confirm").on("click", function(event) {
event.preventDefault();
});
});
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jQuery: click function exclude children.
I have two divs, something like this:
<div id="parent" style="width: 100%; height: 100%; background-color:red;" />
<h1>I'm the parent!</h1>
<div id="child" style="width: 300px; height: 200px; background-color:yellow;">
</h2>..and I'm the child!</h2>
</div>
</div>
Additionally, I have the following JavaScript code:
$(document).ready(function(){
$('#parent').click(function(){
alert('Parent was clicked');
});
});
The problem is, if I click on the child, the event is triggered. How can I limit this event to the parent only?
Edit: Just to clarify; I want this action to trigger when the user clicks anywhere in the red. As said in the comments; the h1 is not the parent. Tjirp's answer did the trick, and there's a lots of working variants of this solution in the answers.
This should work
$(document).ready(function() {
$('#parent').click(function(e) {
if (e.target == this) {
alert('Parent was clicked');
}
}
}
This way you won't have to bind anything to your childs. The click event is propagated to your click handler, and it checks if the target of the click event is indeed the element you added the event on.
Edit: I was right. this is not the most efficient way, Alessandro Minoccheri answer should be way faster. I updated my code with his.
Try this:
$('#parent').click(function(data, handler){
if (data.target == this) {
//Do Stuff (only element clicked, not children)
}
});
h1 is not the parent, div#parent is the parent.
clicking div#child triggers click on div#parent because of event bubbling.
this will prevent event bubbling:
$('#child').on("click", function() {
return false;
});
The easiest solution is to check that the element that originated the event (event.target) is the same as the element handling the click event handler (this):
$('#parent').click(function(event){
if(this === event.target) {
alert('Parent was clicked');
}
});
Here's a working jsFiddle.
You can try something like:
$(document).ready(function(){
$('#parent h1').click(function(){
alert('Parent was clicked');
});
});
$(document).ready(function(){
$('#parent').click(function(){
if($(this).not("#parent")) {
return false;
} else {
alert('Parent was clicked');
};
});
});
I have a nested div like this
<div id="one">
<div id="two">
id two goes here
</div>
<div id="three">
id three goes here
</div>
<div id="four">
id four goes here
</div>
</div>
Now i want to handle click and doubleclick events on all divs except in div#four,
like this
$('#one').live('dblclick', function() {
my javascript code goes here
});
('#one').live('click', function() {
my javascript code goes here
});
How can i use the above script and exclude the last nested div #four.
Thanks
Like this:
$('#one, #one > div').not('#four').delegate('dblclick, click', function(){
// my javascript code goes here
});
EDIT: Based on further clarification, try this:
$('#one').bind('click dblclick', function( event ) {
var id = event.target.id;
if(id == "one" || id == "two" || id == "three") {
if(event.type == "click") {
// code for click event
} else {
// code for double click event
}
}
});
EDIT: Based on our conversation under another answer, it seems like you want the #one element to be clickable, but none of its child elements. If that is right, try this:
$('#one').click(function() {
// code to run when `one` is clicked.
}).children().click(function( event ) {
event.stopPropagation();
});
Now if there's any text in #one, the code for that element will fire, but it will not fire when you click any children of #one.
Let me know if that was what you wanted.
EDIT:
If you are saying that you will have a dynamic number of elements inside #one, and the last one will not get the event, then do this:
$('#one').delegate('div:not(:last-child)', 'click dblclick', function( event ) {
if(event.type == 'click') {
// do something for the click event
} else {
// do something for the double click event
}
});
Note that this assumes there will not be nested divs. Results may be unexpected if there are. Also, the #one element doesn't fire events. Only its children.
Original answer:
$('#one,#two,#three').bind('click', function(){
// code for click event
})
.bind('dblclick', function() {
// code for double click event
});
Or replace .bind with .live if you really need it.
I would use an additional class:
HTML:
<div id="one">
<div id="two" class="clickable">
id two goes here
</div>
<div id="three" class="clickable">
id three goes here
</div>
<div id="four">
id four goes here
</div>
</div>
JS:
('.clickable').live('click', function() {
});
Use not method, more on this here: How can I exclude these elements from a jQuery selection?
You must use $('#one') instead $('.one') aren't you?
$("div:not(#four)")
or
$("#one :not(#four)")
Will select any div that does not have the id="four" set. Basically the :not is what you are looking for. Anything in the :not parenthesis is negated for selection purposes.
http://api.jquery.com/not-selector/
An alternative is to attach a single click/double click handler to the parent which means no need for .live or anything, and in the handler ensure that you are receiving a click from an acceptable child with $(event.target).is(":not(#id)")
$("#one").click(function(event) {
if (this != event.target && $(event.target).is(':not(#four)')) {
// do work on event.target
}
});
// ...
I can't stop the stupid thing from firing off an event when hovering over the children of item.
I only want the event to fire via the div.item element, not the div.itemChild. This is driving me nuts please help.
event.stopPropigation does not work. nor does if(!$(event.source).is('itemChild')), for some reason is() alway returns false.
HTML
<div id="items">
<div class="item">
<div class="itemChild">
</div>
<div class="itemChild">
</div>
</div>
</div>
JS
//on hover event for each post
$('div.item', '#items').live('mouseover mouseout', function(event){
if (event.type == 'mouseover'){
//fire mouseover handler
}
else{
//fire mouseout handler
}
});
Is there a way to stop live from firing when hovering the children of div.item?
By the way the children of div.item cover it completely.
Basically I want this to act like .hover() but bind to things loaded via ajax.
It's not binding to the children. It's bubbling up to the parent.
Also, your syntax isn't correct. This:
$("div.item", "div.items")...
is saying "find me all the divs with class item that are descendants of divs with class of items. But you have no such divs (with class items). You have a div with an ID of items.
Combining all this try:
$("#items div").live("mouseover mouseout", function(event) {
if ($(event.source).hasClass("itemChild")) {
return false;
} else if (event.type == "mouseover") {
...
} else {
...
}
});
Or, alternatively:
$("#items > div.item").live("mouseover mouseout", function(event) {
if (!($this).is("div.item")) {
return false;
}
...
});
Basically, there are many ways to skin this cat but like I said in the first sentence, you have to understand that events bubble up until the handlers stop propagation, either directly (by calling event.stopPropagation() or by returning false from the event handler, which is equivalent to event.stopPropagation(); event.preventDefault();).
Also, if you're doing mouseenter and mouseout you might as well just use the hover() event that does both of those:
$("#items > div.item").live("hover", function(event) {
// mouseenter
}, function(event) {
// mouseout
});