I'm trying to get a form to show and hide using two different triggers. One element when clicked shows the div holding the form, then the cancel button of the form hides the div.
I've tried several options and cannot get this to work so I've stripped it down and put the code here on jsfiddle (link)
The containing div shows but then won't hide... any suggestions?
Just return false from the cancel handler.
Otherwise the click event bubbles, and since the button is nested inside the li element that opens the form, both elements receive the click.
The cancel button tries to hide it and then the li re-opens it..
$("#h-nav li#hn-contact #cancel").click(function() {
$("#h-nav li#hn-contact").find("div.dd").hide();
return false;
});
demo at http://jsfiddle.net/gaby/5CpeW/2/
Notice, since id are unique, you do not have to describe the hierarchy in your jquery selectors. Just use a selector from the last id and forward..
This is due to event bubbling. Use return false in click event's callback.
$("#h-nav li#hn-contact #cancel").click(function() {
$("#h-nav li#hn-contact").find("div.dd").hide();
return false;
});
For more information on this subject, go to Events Order It's worth understanding when you're going to be dealing with javascript in the future.
That actually gives you the cross-browser way of stoping propagation:
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
try:
$("#h-nav li#hn-contact").click(function() {
$(".dd").show();
});
But it would be better to give that div an id and use that.
I would also suggest using toggle() rather than show/hide as then you don't need to change the manually behaviour when it is clicked
Related
I have a button that clears a list, the click on this button shows a dialog that asks for validation (Yes/No). What I want is to disable the "Clear" button after clearing the list (Click on Yes). Here's my code :
$('#clearBtn').click(function() {
$('#alert5').show();
$('#bg').show();
$('#Yes').click(function(){
$('.list1').empty();
$('#clearBtn').disable(true);
$('#clearBtn').click(function(e){
e.preventDefault();
});
$(".alert").fadeOut(250);
$(".alertbg").fadeOut(250);
});
});
the preventDefault() function doesn't seem to work.
First never nest event handlers.
$('#cleatBtn').click(function () {
$('#alert5').show();
$('#bg').show();
});
$('#Yes').click(function () {
$('.list1').empty();
$('#cleatBtn').attr('disabled', true);
$(".alert").fadeOut(250);
$(".alertbg").fadeOut(250);
});
If you just want to disable then use the following syntax
$('#cleatBtn').attr('disabled', true);
Remove the innermost event completely.. That is not required.
Use on to bind the events, if you want the button to be enabled but turn off the event handler using off
One more option you have is to apply a class to the button when you press yes and execute the code only when the class is not present.
$('#cleatBtn').click(function () {
if( !$(this).hasClass('active')) {
$('#alert5').show();
$('#bg').show();
}
});
$('#Yes').click(function () {
$('.list1').empty();
$('#cleatBtn').attr('disabled', true);
$('#cleatBtn').addClass('active');
$(".alert").fadeOut(250);
$(".alertbg").fadeOut(250);
});
To disable a button, call the prop function with the argument true on it:
$('#cleatBtn').prop("disabled", true);
e.preventDefault(); is the correct way of cancelling events. Some older browsers also expect a return type of false. Which I think will cause jQuery to call preventDefault()?
Here's a good answer: What's the effect of adding 'return false' to a click event listener?
I think your structure looks a bit odd. you don't need to attach click events within a click event.
Just attach them all separately on document.ready events. At the moment they are nested, then go back to trying to cancel your event. The dom tree might be confused by the way the events are nested.
Hope that helps.
I'm trying to create a function that disables voting button after an Ajax POST success. The voting buttons are enabled until POST completes, and then are fixed with 'disabled' styling and are in-clickable. I'm trying to use jQuery .not() to disable starting the function from clicked buttons (with the class 'disabled') but I'm not having much luck. Here's a fiddle of my function so you can see my problem, I'm not sure what I'm missing but I'm hoping someone can help me find my error, it's frustrating me : )
jQuery Code:
$("a.votebutton").not(".disabled").each(function(index) {
var el = $(this);
$(this).click(function() {
el.addClass("active disabled").unbind("click");
el.siblings().addClass("disabled");
});
});
The problem is that your code:
$("a.votebutton").not(".disabled")
selects all of the links that are not disabled at the time that line of code runs, and then you loop through assigning click handlers. These click handlers remain bound to those links even if they happen to be given the "disabled" class at a later time - so when you add the "disabled" class to the clicked element's siblings those siblings still have a working click handler. If you unbind the click from the siblings that should fix it:
// change
el.siblings().addClass("disabled");
// to be
el.siblings().addClass("disabled").unbind("click");
Note that you don't need the .each():
$("a.votebutton").not(".disabled").click(function() {
$(this).addClass("active disabled").unbind("click")
.siblings().addClass("disabled").unbind("click");
});
Another way to do it would be to use delegated event handling:
$("div.panel").on("click", "a.votebutton:not(.disabled)", function() {
$(this).addClass("active disabled")
.siblings().addClass("disabled");
});
That way the clicks are only handled once they bubble up to the containing div ("div.panel"), at which time your click handler is only run if the event's source element matches the selector that is the second parameter to .on().
Updated demo: http://jsfiddle.net/RSezp/2/
I have a script that slides a div out of view when the user clicks on the background (the <body>).
Here's my code:
// Slide back out of view.
$('body').click(function(){
$('.presentationArea').animate({'height': '0px'}, 1000);
});
But, see, here's the problem; If the user clicks ANYWHERE on the page, I.E. Menu links, buttons, textfields, images, the above function gets called! I only want it to be called if the user clicks the "body", you know, that thing BEHIND everything else? :) How would one do this?
Thank you
I only want it to be called if the user clicks the "body", you know, that thing BEHIND everything else? :)
You can check event.target and see if it's the actual document.body element. (Live example) But I suspect people are going to find it difficult to click that as opposed to (say) a p element, because the body doesn't typically fill the display area unless something is there to expand it (although you can do it with CSS).
But fundamentally, you can use event.target to see where the click was and decide at that point whether it's a click you want to handle (whether it was technically actually on body itself or something else you want to go ahead and treat the same way).
Alternately, you could hook up a handler to stop event bubbling via stopPropagation on all of the elements you don't want clicked — e.g., for a elements:
$('a').click(function(event) {
event.stopPropagation();
});
stopPropagation just stops bubbling, not the default action (e.g., it doesn't keep people from following the link). But the side-effects of that might be a pain (I haven't done it globally like that, only targeted).
You should check whether e.target is the <body> element.
You are experiencing "bubbling" your click will bubble from the child element all the way up to the parent and trigger the function.
See the answer on this thread for more details:
How to stop event bubbling with jquery live?
Basically, you'll have to add a new function that on click has return false to stop the bubbling.
$('#wrapper').bind(void(0), false)
Should work assuming you have a wrapper div, as the second parameter "false" prevents bubbling.
Okay, I've got it:
$("body").click(function(event) {
if(event.target.nodeName == "body" || event.target.nodeName == "BODY")
{
$('.presentationArea').animate({'height': '50px'}, 1000);
}
});
use something like this:
// Slide back out of view.
$('body').click(function(event){
if (event.target === this) {
$('.presentationArea').animate({'height': '0px'}, 1000);
}
});
I have a div, I want to set it so that when I click on something else, it would hide the div.
So I did
$('body').click(function(){
if(loginOpened)
{
$('#loginWindow').animate({
'width':'0px',
'height':'0px'
},"fast");
}
loginOpened=false;
});
However, even when I click in the div itself the event is fired, is there anyway to prevent this?
You can stop it using
e.stopPropagation(); if there is a click event bound to the <div /> tag.
See event.stopPropagation()
Prevents the event from bubbling up
the DOM tree, preventing any parent
handlers from being notified of the
event.
Otherwise you can check the target of the event inside the body click. Check whether event.target is the same as your div.
See event.target
Just check the event.target. If the element that triggered the event is your div do not execute the code.
$('body').click(function(evt){
evt = evt || window.event
if ($(evt.target) != $('#loginWindow')) {
if(loginOpened)
{
$('#loginWindow').animate({
'width':'0px',
'height':'0px'
},"fast");
}
loginOpened=false;
}
});
Yes, but of course Microsoft and the rest of the world came to different conclusions about how to do it. This site gives a good clear rundown of what's needed: http://www.quirksmode.org/js/events_order.html .
I don't use jQuery but the jQuery way appears to be event.stopImmediatePropagation(); as seen in this question: jQuery Multiple Event Handlers - How to Cancel? .
A couple of changes from John's code:
$('body').click(function(ev){
// jQuery means never having to say "window.event"!
// Also, code's cleaner and faster if you don't branch,
// and choose simple breaks over more complex ones
if(!loginOpened) return;
// Lastly, compare using the DOM element;
// jQuery objects never compare as the "same"*
if (ev.target == $('#loginWindow').get(0)) return;
$('#loginWindow').animate({
'width':'0px',
'height':'0px'
},"fast");
loginOpened=false;
});
If trapping it in the body event doesn't work for you, you can just add a simple event handler to the div:
$('#loginWindow').click(function (ev) { ev.stopPropagation(); });
I was going to say return false, but that would prevent other things from firing off the div. stopPropagation just keeps the event from bubbling outward.
I could be really picky, of course...
//Delegation via the document element permits you to bind the event before
// the DOM is complete; no flashes of unbehaviored content
$(document).delegate('body', 'click', function(ev){
//You only have one instance of an id per page, right?
if(!loginOpened || ev.target.id == 'loginWindow') return;
//quotes and px? not necessary. This isn't json, and jQ's smart
$('#loginWindow').animate({width:0,height:0},"fast");
loginOpened=false;
});
* Don't believe me? Try:
jQuery('#notify-container') == jQuery('#notify-container')
Then try
jQuery('#notify-container').get(0) == jQuery('#notify-container').get(0)
I have a search input box that appears upon rollover of a button. Rather than having its own close button I would like to be able to click anywhere on the page to re-hide the Search.
If I attach a click handler to the document this works fine but the problem being is that the search itself is part oofthe document. So if you click the input (which of course you need to do in order to type in a search) the search disappers.
I had hoped I'd be able to write a function soemthing like this...
$(document).not("#search").click(function(){
$('#search_holder').fadeOut('fast');
});
i.e apply a click handler to the entire document APART from the search. Unfortunately that doesn't work.
so whats the answer?
thanking You in advance
Cancel the click event from propagating when it originates from the button you care about:
$("#search").click(function(event){
event.stopPropagation();
});
You can do it by stopping the click event from bubbling, like this:
$(document).click(function() {
$('#search_holder').fadeOut('fast');
});
$("#search").click(function(e) {
e.stopPropagation();
});
event.stopPropagation() prevents the bubble from going any higher, all the way to document triggering the .fadeOut(), everywhere else (by default) will bubble to document, causing the fade to occur.
Try this Its working perfect for me.
$(document).mouseup(function (e)
{
var searchcontainer = $("#search_container");
if (!searchcontainer.is(e.target) // if the target of the click isn't the container...
&& searchcontainer.has(e.target).length === 0) // ... nor a descendant of the container
{
searchcontainer.hide();
}
});