jquery: stop infinite recursion? - javascript

How do I stop the infinite recursion here so that a mousedown event can be triggered just once? should it be in a separate method?
$(document).on('mouseover',function (e) {
$(e.target).mousedown(function(e){
e.stopPropagation();
console.log('clicked');
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
})
});
$(document).on('mousedown', 'a', function(e){
hello(e);
});
function hello(e){
console.log('got it');
}
This seems to trigger a never ending loop. Basically I need to bind a mousedown handler on the currently element under the mouse, which will fire a mousedown event that another handler will be able to handle.
The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.

You are making it complicated. Imagine everytime a user move his mouse an event will be added dynamically?
Why not design your element with class names and use it in your mousedown event? This way a sure call to mousedown will trigger always.
$(".className").mousedown(function(e){
console.log('clicked');
return;
})
--The reason I am doing this is because the mouseover works on dynamically generated element so when this happens I need to bind a handler again as the on handler is not able to catch the newly generated element.
If you say so then, add a className to your dynamically generated element to have your mousedown event bind to it.

try like this:
$(document).on('mouseover',function (e) {
$(e.target).trigger('mousedown'); //use hello(e); instead?
return;
});
$(document).on('mousedown','a', function(e){
hello(e);
});
function hello(e){
alert('got it');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
hello

Related

stopPropagation() of a different event

How can I listen to a change event on a checkbox without triggering a click event on its container?
<label><input type="checkbox"> Hello world</label>
I want to trigger an action on the checkbox's change event, but I don't want it to bubble up to a click event on the label.
(function ($) {
$('input').change(function (v) {
v.stopPropagation();
});
$('label').click(function () {
alert('You should not see this message if you click the checkbox itself!');
});
})(jQuery);
http://jsfiddle.net/r49PA/
Any ideas? Thanks!
The issue is that two events are triggered when you click the checkbox -- a change and a click. You're only catching the change, so the click isn't ever being told to stop propagation. You need to either add a second handler on the checkbox for click events, or combine one handler to catch both types, like this:
$('input').on('change, click', function (v) {
v.stopPropagation();
});
Here's a jsFiddle demonstrating a combined handler: http://jsfiddle.net/r49PA/4/
You can stop propagation on click event instead of change event since you bind click event for the parent label:
$('input').click(function (v) {
v.stopPropagation();
});
Updated Fiddle
With plain javascript you can do something like this:
var stopPropagation = false;
selector.addEventListener('mousedown', function(event) {
// simulating hold event
setTimeout(function() {
stopPropagation = true;
// do whatever you want on the `hold` event
})
}
selector.addEventListener('click', function(event) {
if (stopPropagation) { event.stopPropagation(); return false; }
// regular event code continues here...
}
Since mousedown and click events are overlapping, we want the click event to not be triggered when we are trying to get the hold state. This little helper flag variable stopPropagation does the trick.

Trigger click on child but prevent event propagation to parent

How do I trigger click on a child element without letting the click event bubble upto the parent & thereby create a infinite trigger loop of click event.
For example I have like this:
<li>
<a> ... </a>
</li>
I want to trigger a click event on a whenever li is clicked, but to prevent infinite trigger loop, I should avoid event propagation upto parent. How do I do that ?
Something like this?
$('li').on('click','a', function(e) {
e.stopPropagation();
// your code here...
});
By using .stopPropagation() on the anchor you can stop the bubbling. You should be able to use something like:
$('a').click(function (e) {
e.stopPropagation();
console.log('link');
});
$('li').click(function () {
$('a').click();
});
jsFiddle example
You do not state exactly the behavior you want from the click on the link, but if you simply want to stop the click being handled at all, use preventDefault() on the event argument of click:
$('li').on('click','a', function(e) {
e.preventDefault();
});
If you just want to stop the parent seeing the event use stopPropagation() instead:
$('li').on('click','a', function(e) {
e.stopPropagation();
});
The other option is return false, which does the same as both preventDefault() and stopPropagation()
$('li').on('click','a', function(e) {
return false;
});
use event.stopPropagation()() in the event callback.
$('selector').click(function(event){
event.stopPropagation()();
})
Parse the tag name on the parent click handler. (You could also look at class name or ID, among other event filters.) If desirable child tag is detected, then stop the propagation and return true so that this event runs. If desirable child tag is not detected, then prevent default event and return false. Thus, clicking on LI will trigger the click on A without a runaway event loop, and clicking on A will proceed properly without a runaway event loop either. Note also that you can't just fire the .click() event on the tag. You need to send it deeper into the native DOM element, using [0].click(), as I have shown below.
$('LI').click(function(e){
var sTag = e.target.tagName.toUpperCase();
if (sTag == 'A') {
console.log('DEBUG: A click');
e.stopImmediatePropagation();
return true;
} else {
console.log('DEBUG: ' + sTag + ' click');
e.preventDefault();
// the following won't work without the [0]
$(this).find('A')[0].click();
return false;
});

child click event firing parent mouseover event

I have tree structure in which mouse over on node name displays (UL) list. Each item in the list has a click event attached to it. The issue Im facing is when I click on any child item in list, it fires the mouseover event attached to parent span. Can you guys please help how to solve this issue?
<span id="treeNodeText">
<ul><li id="firstItem">First Item</li></ul>
</span>
My code is like this:
I have conman event attach method:
attachEvents(domId,eventType,callBackFunction,otherParams)
In attachEvent function I attach events to dom ids and assign appropriate call back functions
The mouseover event is fired before you click. So, apart with a delay, you can't prevent its handling.
Here's one way to deal with that :
var timer;
document.getElementById("treeNodeText").addEventListener('mouseover', function(){
clearTimeout(timer);
timer = setTimeout(function(){
// handle mouseover
}, 400); // tune that delay (depending on the sizes of elements, for example)
});
document.getElementById("firstItem").addEventListener('click', function(){
clearTimeout(timer); // prevents the mouseover event from being handled
// handle click
};
In JavaScript, events bubble up the DOM. Please read more about it: event order and propagation or preventDefault/stopPropagation.
In short, you can pervent event bubbling by
function callBackFunction(event){
event.stopPropagation()
}
or
function callBackFunction(event){
return false
}
return false also has the effect of preventing the default behavior, so it's technically equivalent to:
function callBackFunction(event){
event.stopPropagation()
event.preventDefault()
}
function myfunction(e){
e.stopPropagation()
e.preventDefault()
}
this will Help

Unbinding click handlers on certain classes

I have a table cell that I want to be able to be clicked. But once it is clicked it will have the class ".clicked". When any table cell has this class, I do not want to be clickable. Is there any way to do this?
Also you can use .off() method to unbind any events.
$('td').on('click', function(){
$(this).addClass('clicked').off('click');
})
This is easily done by inserting some code at the top of the event handler.
$('td').click(function(e) {
if ($(this).hasClass('clicked')) {
e.stopPropagation();
e.preventDefault();
return;
}
// the rest of your code here
});
The other, more involved, way, is to use event delegation and only fire the function if the element doesn't have the class when it's clicked:
$('table').on('click', 'td:not(.clicked)', function() {
// your code here
});
You can use the .one() event registration method to do it, it will un-register the handler once the event is fired.
$('td').one('click', function(){
console.log('hanlded', this)
})
Another solution could be
$('table').on('click', ':not(.clicked)', function(){
console.log('hanlded', this)
})
Just add :not(.clicked) to whatever selector you're using to exclude clicked cells.

Set the mouseover Attribute of a div using JQuery

I would like to set an attribute for a div. I have done this:
$('#row-img_1').onmouseover = function (){ alert('foo'); };
$('#row-img_2').onmouseout = function (){ alert('foo2'); };
However, the above has not worked, it does not alert when mouse is over or when it moves out.
I have also tried the $('#row-img_1').attr(); and I could not get this to work either.
I am aware that I should be using a more effective event handling system but my divs are dynamically generated. Plus this is a small project. ;)
Thanks all for any help.
You need to bind the event function to the element. Setting the event attributes has no effect, as they are interpreted only when the page is loading. Therefore, you need to connect the event callback in a different manner:
$('#row-img_1').mouseover(function() {
alert('foo');
});
$('#row-img_2').mouseout(function() {
alert('foo2');
});
In jQuery, there are two more events: mouseenter and mouseleave. These are similar, but mouseenter does not fire upon moving the mouse from a child element to the main element, whereas mouseover will fire the event again. The same logic applies to mouseleave vs mouseout.
However, jquery provides a shortcut for this kind of usage: the .hover method.
$('#row-img_1').bind('mouseenter', function(event){
// event handler for mouseenter
});
$('#row-img_1').bind('mouseleave', function(event){
// event handler for mouseleave
});
or use jQuerys hover event which effectivly does the same
$('#row-img_1').hover(function(){
// event handler for mouseenter
}, function(){
// event handler for mouseleave
});
Events are registered as functions passed as attributes, like this:
$('#row-img_1').mouseover(function (){ alert('foo'); });
$('#row-img_2').mouseout(function (){ alert('foo2'); });
Also, note the missing on from the onmouseover.
$('#row-img_1').mouseover(function() {
alert('foo');
});

Categories