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();
}
});
Related
I'm trying to build some kind of element inspector (like in Chrome/FF).
Flow is as follows:
You click 'Start inspecting' button.
You hover over necessary element.
You click on that element.
You should see that element in console.
JSFiddle example
Here is the code:
startInspecting = function(){
$('section *').on('mouseover.INSPECTOR', function(e){
$('.hovered-element').removeClass('hovered-element');
$(e.target).addClass('hovered-element');
$(this).on('click.INSPECTOR', function(e){
$('section *').off('mouseover.INSPECTOR');
$('section *').off('click.INSPECTOR');
$('.hovered-element').removeClass("hovered-element");
console.log(e.target);
});
});
};
The problem is: each time I hover over some element - click event handler is attached to it. So if I hover over p element 5 times, and then click on it - I will see 5 console.logs instead of 1.
I tried to implement it using mouseenter/mouseleave, but faced the issue, that each element can be hovered only once - another JSFiddle example
So how can I improve my code that no matter how many times I hover over the element, it will have only one click handler?
Thanks in advance, any help will be appreciated!
Did you try moving the onclick handler outside the mouseover?
startInspecting = function(){
$('section *').on('mouseover.INSPECTOR', function(e){
$('.hovered-element').removeClass('hovered-element');
$(e.target).addClass('hovered-element');
}).on('click.INSPECTOR', function (e) {
$('section *').off('mouseover.INSPECTOR click.INSPECTOR');
console.log(e.target);
});
};
DEMO
I'd suggest breaking it up into parts. The user clicks on "Start Inspecting" and your page goes into inspecting mode where it adds css dynamically to every element that is hovered over so it looks similar to Chrome. When you click on an element in inspecting mode then you can handle it how you want. This way you only have to add one hover and one click handler per element, thus only triggering the event once.
I'm building a widget akin to a datepicker, but I can't figure out how to make it disappear when when either (a) the user tabs out of the input box, or (b) clicks outside both the widget and input.
It's easy to bind a blur event to the input box, but the problem is that it will get triggered when you click on the widget, and there doesn't appear to be a reliable way to determine which element the focus was changed to from inside the blur event.
Closing the widget when the user clicks outside of the input is a bit sketchy too, but it's doable:
$('body').on('click', function(e) {
if(e.target != self.element[0] && e.target != self.clock[0] && !$.contains(self.clock[0], e.target)) {
self.clock.hide();
}
});
But I wouldn't need that if I could figure out how to handle the blur event properly (which may also be triggered by tabbing outside of the element).
Turns out the solution is actually quite simple. Thanks to rojoca's suggestion, I came up with this:
this.timepicker.on('mousedown', function(e) {
return false;
});
this.element.on('blur', function(e) {
self._parseInput();
self._refreshInput();
self._close();
});
The mousedown event fires first, and by returning false it prevents the blur event from triggering when clicking on the widget. Everything else (clicking outside the widget and input box, or tabbing away) causes a blur, which closes the widget as desired.
Further, it had the unintended by pleasant side-effect of keeping your cursor inside the textbox while interacting with the widget.
I have a button which, when clicked, changes the visibility of a div as such:
<button type="button" id="editbutton" onclick="plus()" alt="Edit"></button>
function plus() {
var f = document.getElementById('edit');
if (f.style.visibility == 'hidden') {
f.style.visibility = 'visible';
}
else
f.style.visibility = 'hidden';
}
This works fine. But now I want to add the functionality so that if the user clicks anywhere outside of the div, the div will go back to being hidden.
Initially I tried my own methods, but was unsuccessful because whenever I click the button to make the div visible, it is made hidden again by the new code. I've looked into some of the jQuery examples others have posted, however none of the ones I have tried fix this problem. Any help would me much appreciated.
EDIT: To clarify, the issue is that because the div is initially made visible by the user clicking on a button, whenever I click the button, the div is made visible but is immediately hidden again because that counts as clicking on the body of the page.
You could call 'e.stopPropagation()' on the event from within your click event handler when a user clicks within your div - this will stop the event from 'bubbling' up the DOM.
And then if you attach an event handler to the BODY element listening for clicks, you can use that event handler to hide the DIV; knowing that a click on the DIV itself won't bubble the event up to the BODY handler.
In this way any click on another element, unless the handler also calls stopPropagation(), will get caught by your handler. So if there are other cases where you don't want the div to hide you can stop it happening by calling stopPropagation() as required.
E.g.:
$("#edit-button").click( function(e) {
$("#edit").toggle();
e.stopPropagation();
});
$('#edit').click(function(e) {
e.stopPropagation();
});
$("body").click( function(e) {
$("#edit").hide();
});
Set a click handler on the body element. In the event you can check event.target to see if it matches the div, if it does: do nothing, else: hide it.
document.body.onclick = function(event) {
if (event.target === f) {
// user clicked on the div, do nothing
} else {
f.style.visibility = "hidden";
}
};
This becomes a bit more complex if you have elements within the edit div (and the .target doesn't match), but I'm sure you can come up with a solution :) (it can be done).
you seem like you know what you're doing so I'll keep it short.
write a .click function in jquery.
you give your button an id (or the div it is in)
$('#buttonidordiv').click(function(){
$('#divtoshow').show() // put in a number to create a fade in seconds.
//your stuff here
}
and if someone clicks anywhere outside it... I think you should be able to use window. Else you can use another div (like your wrapper).
so
$('window').click(function(){
$('#samediv').hide() //same as above
//your stuff here
}
do realize, I suck with the )}; so you might have to add one of those somewhere ;)
best of luck!
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
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);
}
});