stop jquery live from hooking all the children - javascript

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
});

Related

Enable click on only one child jquery

So I have the following html
<li clas='k-item'>
<input type='checkbox'>
<span>ABC</span>
</li>
Is there any way I can bind click to only input and disable for span and li?
This is what I tried, but it doesn't seem to work
$('.k-item').on('click', function (e) {
$(this).unbind('click');
if ($(e.target).is('input')) {
$('input').bind('click');
}
});
I do not have much experience with jquery
You need to use:
$('.k-item input').click(function(){
//modify the rest handler code...
});
Update: if click is defined for li, and you don't want that to be triggered on child span then you will need to stop event propagation.
$('.k-item span').click(function(e){
e.stopPropagation();//do not trigger parent click on child span
});
Why not just target the input to begin with? You can then use e.stopPropagation() to prevent the LI from getting the click event (which is I gather your aim):
$('.k-item input').click(function (e) {
// Stop the LI from firing a click event
e.stopPropagation();
// input is clicked
});
You need only this:
$('.k-item').on('click', function (e) {
if ($(e.target).is('input')) {// or event.target.type
//do stuff
}
});
Just select the desired element and apply the event listener:
$('.k-item > input').on('click', function() { // ... });

Click on parent, ignore its children [duplicate]

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');
};
});
});

jquery selector help. Everything but the specified selector

I have the following function to open an overlay menu:
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
});
To hide the menu, I would like the user to be able to click on any area outside ".context-switch-menu"
I am trying with :not() but with no success..
$('body').click(function(e) {
if ($(e.target).hasClass('context-switch')) {
return;
}
$(".context-switch-menu").hide();
});
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
return false;
});
The reason this can be difficult is because of event bubbling.
You can try something like this:
$('.context-switch').click(function(e) {
e.stopPropagation();
$(".context-switch-menu").toggle();
});
$(".context-switch-menu").click(function(e){
e.stopPropagation();
});
$("body").click(function(e){
$(".context-switch-menu").hide();
});
The e.stopPropagation() prevents the click event from bubbling to the body handlers. Without it, any click to .context-switch or .context-switch-menu would also trigger the body event handler, which you don't want, as it would nullify the effect of the .context-switch click half the time. (ie, if the state is hidden, and then you click to show, the event would bubble and trigger the body handler that would then hide the .context-switch-menu again.)
Without testing, would something like this work?:
$('.context-switch').click(function() {
$(".context-switch-menu").show();
});
$(document).click(function() {
$(".context-switch-menu").hide();
});
Instead of using document, 'html' or 'body' may work as well.
$(document).on('click', function(e) {
if (e.target.className !='context-switch-menu') {
$(".context-switch-menu").hide();
}
});
Just an idea here, based on what what others have suggested in the past:
$(document).click(function(e){
//this should give you the clicked element's id attribute
var elem = $(e.target).attr('classname');
if(elem !== 'context-switch-menu'){
$('.context-switch-menu').slideUp('slow');
//or however you want to hide it
}
});
try this, we don't want to call a function when you clicked on the element itself, and not when we click inside the element. That's why we need 2 checks.
You want to use e.target which is the element you clicked.
$("html").click(function(e){
if( !$(e.target).is(".context-switch-menu") &&
$(e.target).closest(".context-switch-menu").length == 0
)
{
alert("CLICKED OUTSIDE");
}
});
Live fiddle: http://jsfiddle.net/Xc25K/1/

jQuery making selection

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
}
});
// ...

JQuery event.stopPropagation() not working

In my html I have a span of class dragHandle embedded within a li.
<div class='treeView'>
<ul class='tree'>
<li><span class="dragHandle"></span>Item 1
<ul>
<li><span class="dragHandle"></span>Item 2 link</li>
</ul>
</li>
</ul>
I attach event handlers using jQuery as follows:
$(".tree li").click(function(event) {
alert("click");
event.stopPropagation();
});
$(".dragHandle").mousedown(function(event) {
alert("down");
event.stopPropagation();
});
$(".dragHandle").mouseup(function(event) {
alert("Up");
event.stopPropagation();
});
When I mousedown and mouse up over the element I get the down and up alerts, however I also get the click alert of the li's event handler too. I thought that this should be prevented from by the call to event.stopPropagation in the mousedown and mouseup handlers. How do I stop the click event being called for mousedown/up events on the dragHandle?
TIA,
Adam
How do I stop the click event being called for mousedown/up events on the dragHandle?
You capture... and eat... that event:
$(".dragHandle").click(function(event) { event.stopPropagation(); });
The key here is that click, mousedown, and mouseup are distinct events. Although you might think of a click as being a mousedown followed by a mouseup, in reality you might have click events triggered by user actions that don't even involve the mouse, as well as combinations of mousedown and mouseup that don't result in any click events at all.
You could create a simple wrapper-"class", that keeps track of mouse-down and up events:
(function () {
var DragDropHandler = {
isDrag: false,
mouseDownHandler: function (event) {
alert("down");
event.stopPropagation();
this.isDrag = true;
},
mouseUpHandler: function (event) {
alert("Up");
event.stopPropagation();
this.isDrag = false;
},
clickHandler: function (event) {
event.stopPropagation();
// Check if we've already received a mouseDown-event. If we have,
// disregard the click event since we want drag-functionality
if(this.isDrag) { return; }
alert("click");
}
};
$(".tree li").click(function(event) {
DragDropHandler.clickHandler.call(DragDropHandler, event);
});
$(".dragHandle").mousedown(function(event) {
DragDropHandler.mouseDownHandler.call(DragDropHandler, event);
});
$(".dragHandle").mouseup(function(event) {
DragDropHandler.mouseUpHandler.call(DragDropHandler, event);
});
})();
This creates a closure and delegates the event handling to the DragDropHandler-object. Note that I've used function.call (the first parameter is the context) to ensure that this refers to the DragDropHandler-object inside its methods. Since we have created an anonymous function that can not be reached from global space, I think it's acceptable to use the DragDropHandler reference inside the wrapper event handlers.

Categories