Stop propagation with jQuery delegate/live function not working - javascript

Here's the problem html:
<ul id="update-list">
<li class="update" onclick="window.location('some_url')">
<h2> some header </h2>
<p> some paragraph </p>
<div>
<a class="popup-link">
<span> Show Popup </span>
<span> + </span>
</a>
</div>
</li>
// this repeats n times
//...
</ul>
When I click on .popup-link link, it should open the lightbox popup only (which it does) but the inline onclick on li also fires. The thing is that the li tags are all part of some partial which is fetched via ajax on different pages. So I use jQuery's delegate to bind the events as follows:
$('#update-list').delegate('.popup-link', 'click', function(e){
// e.target is <span> while e.currentTarget is .popup-link
e.stopPropagation();
//console.log(e.isPropagationStopped()); this shows 'true' in console
$.popup(); // launch popup
e.preventDefault(); // or return false
});
This doesn't seem to work and the inline onclick fires anyway. I've tried with live() as well but no success. Is there something I am missing here?

AFAIK you cannot reliably prevent an inline event handler from firing by stopping the bubbling within an attached event handler.
Furthermore, using live() or .delegate() you cannot use preventDefault() nor stopPropagation(). You need to return false to prevent the bubble phase and the default behavior.
Anyway, as I already mention you can't prevent the inline event handler to fire with that.
So either, create it completely unobtrusive (which is what I highly recommend) or remove that inline click handler in code.
Example:
$('#update-list').delegate('.popup-link', 'click', function(e){
$.popup(); // launch popup
return false;
}).delegate('.update', 'click', function(){
window.location('some_url');
})
// the rest of this is unnecessary if you can just omit the onclick attribute
.find('.update')
.removeAttr('onclick');
Ref.: .delegate()

$('#update-list').delegate('.popup-link', 'click', function(e){
e.stopImmediatePropagation();
e.preventDefault();
// do something...
});

Can you try this?
$('#update-list').delegate('.popup-link', 'click', function(e){
// e.target is <span> while e.currentTarget is .popup-link
e.stopPropagation();
e.preventDefault(); // or return false
// open popup in a timeout so that this function can return false
window.setTimeout(function() {$.popup();}, 20);
// for IE
e.cancelBubble = true;
return false;
});

You can try this as .delegate() has been superseded by the .on() method.
It will work fine

Related

Span Child Object on Click

How can I get this code to only execute its button:
​<span id="spanClicker">
<span id="subClicker">
[Click Me]
</span>
​</span>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
like this fiddle: http://jsfiddle.net/rpCVy/
http://jsfiddle.net/malet/rpCVy/3/
You can use e.stopPropagation() to prevent the click event firing for both elements.
Also on a side note the .live function is deprecated as of jQuery 1.7 .on should be used instead.
Here is what you're looking for:
$( '#subClicker' ).on( 'click', function (e) {
alert( 'subClicker' )
// Now here is the magic you want:
e.stopPropagation( )
} )
As you can guess, e.stopPropagation() allows you to prevent the event from propagating to its parent elements.
This ought to do it.
http://jsfiddle.net/rpCVy/2/
New javascript
$(function()
{
$("#spanClicker").live("click",function()
{
alert('Span Clicked');
});
$("#subClicker").live("click",function(e)
{
alert('Button Clicked');
e.stopPropagation();
});
});​
The anonymous function associated with .click can take an event for the first argument. Call the stopPropagation() method of the event object to stop the click event from bubbling up to containers of the target element of the event.

Can I trigger click on href element without triggering href link?

I have a piece of code that will sometimes need to be triggered by a script, but I don't want it to change the URL on my page. (it messes up the history state for some odd reason)
The code I need to trigger:
$(".photos-bottom .albums #albums li").live("click", function() {
// my action here
});
The code I use to trigger it:
$(".photos-bottom .albums #albums li:first").trigger("click");
The link to click, however I just noticed, it's suppose to click the li and the li is inside of the href so i don't know why it's still clicking it..
<a href="#/photos/1/album/42/" rel="address:/photos/1/album/42/">
<li id="42">
try triggerHandler() instead: http://api.jquery.com/triggerHandler/
The .triggerHandler() method behaves similarly to .trigger(), with the following exceptions:
The .triggerHandler() method does not cause the default behavior of an event to occur (such as a form submission)... [omissis]
Otherwise use trigger() with an extraparameter in the call (see http://api.jquery.com/trigger/) and in your handler just check the arguments passed. If a parameter was passed then you will prevent the default link action with. <evt>.preventDefault()
(note: I assume you handler is attached to links element, not to the list item, since you cannot wrap a list item into a link)
I think this is caused by live(). This is because the events bubble up to the <body> and triggers the click event on the <a>. You could use delegate() or on() (jQuery > 1.7) to attache the event handler on the <a> and then return false from the function to stop it from triggering the redirect
You could do
$(".photos-bottom .albums #albums a").delegate(".photos-bottom .albums #albums li", "click", function(e) {
// my action here
alert("hi");
//return false so that you stop the immediate propagation of the event
return false;
});
$(".photos-bottom .albums #albums li:first").trigger("click");
Fiddle working with delegate http://jsfiddle.net/3CQFK/
Yep, it's a normal task. There's a function you can call on the event which the callback receives which prevents the browser's default action, called preventDefault. Your code would be:
$(".photos-bottom .albums #albums li").live("click", function(event) {
event.preventDefault();
// your code here
// ...
});

does e.stopPropagation() in jquery works on anchor tag

i want prevent eventpropogation from element inside an anchor tag i m trying to use e.stopPropagation(); it doesn't seem to work is it possible or i m just wasting time please help me out of here
javascript is:
$(document).ready(function(){
$('.alink .p').click(function(e){
alert("hi");
e.stopPropagation();
});
html is :
<div>
<a href="http://google.com" class="alink" >Google links
<p class="p">Another Links to prevent default</p>
</a>
</div>
thanks for your precious time
event.stopPropagation() stops passing the event to handlers further away in DOM structure from the element, on which originally event was triggered. It does not, although, prevent action that has already been triggered.
You should use event.preventDefault() to stop mentioned above default action.
Sources:
event.preventDefault()
event.stopPropagation()
Description
It will not stop any default behaviours (such as link clicks) and you might want to consider using event.preventDefault() in addition to this method.
event.stopPropagation() is only for event handlers, not default behavior.
event.preventDefault() If this method is called, the default action of the event will not be triggered.
You had some spelling errors in your script and its document not "document".
Check out the Sample and this jsFiddle Demonstration
Sample
$(document).ready(function(){
$('.alink, .alink > .p').click(function(e){
e.preventDefault();
e.stopPropagation();
alert("hi");
});
});
More Information
jQuery - event.preventDefault()
jQuery - event.stopPropagation()
try this
$(document).ready(function(){
$('.alink .p').click(function(e){
e.preventDefault();
e.stopImmediatePropagation();
alert("hi");
return false;
});
});
you should use- e.preventDefault() to stop default behavior. stopPropagation is used to stop event bubbling.
You've missed enclosing brackets here, didn't you?
$('document').ready(function(){
$('.alink .p').click(function(e){
alert("hi");
e.stopPropagation();
});
Fix brackets and then use e.preventDefault() instead.

jQuery live() and stopPropagation() issue

I know that the live() event handles event bubbling different than all other jQuery events. jQuery recommends using 'return false', but in my case that doesn't work.
The issue is:
I have a DIV which contains an anchor tag.
The DIV is bound using live(). Whenever I click the anchor tag inside this DIV it bubbles and calls the DIV's event. If I bind an event to that A tag which returns false it prevents the link from opening. Neither stopPropagation() or return false work in this case. Are there any other options? Ideally I'd like to keep the live() event around.
element.preventDefault();
stopPropagation will stop the bubbling whereas preventDefault will make sure the default action of the affected element will not trigger.
this should work as long has your anchor href is to a url, not sure what would happen if it was a javascript method call - guessing would not be good.
$("#the-div").live('click', function (e) {
var tag = e.target.tagName;
if (tag === "A") {
window.location.href = e.target.href;
return false;
}
// else do the div click handling
});
seems like there is probably a more elegant way to do this, but I have no clue.

How to stop event bubbling with jquery live?

I am trying to stop some events but stopPropagation does not work with "live" so I am not sure what to do. I found this on their site.
Live events do not bubble in the
traditional manner and cannot be
stopped using stopPropagation or
stopImmediatePropagation. For example,
take the case of two click events -
one bound to "li" and another "li a".
Should a click occur on the inner
anchor BOTH events will be triggered.
This is because when a
$("li").bind("click", fn); is bound
you're actually saying "Whenever a
click event occurs on an LI element -
or inside an LI element - trigger this
click event." To stop further
processing for a live event, fn must
return false
It says that fn must return false so what I tried to do
$('.MoreAppointments').live('click', function(e) {
alert("Hi");
return false;
});
but that did not work so I am not sure how to make it return false.
Update
Here is some more information.
I have a table cell and I bind a click event to it.
$('#CalendarBody .DateBox').click(function(e)
{
AddApointment(this);
});
So the AddApointment just makes some ui dialog box.
Now the live code(MoreAppointments) sits in this table cell and is basically an anchor tag. So when I click on the anchor tag it first goes to the above code(addApointment - so runs that event first) runs that but does not launch my dialog box instead it goes straight to the (MoreAppointment) event and runs that code. Once that code has run it launches the dialog box from "addApointment".
Update 2
Here is some of the html. I did not copy the whole table since it is kinda big and all the cells repeat itself with the same data. If needed I will post it.
<td id="c_12012009" class="DateBox">
<div class="DateLabel">
1</div>
<div class="appointmentContainer">
<a class="appointments">Fkafkafk fakfka kf414<br />
</a><a class="appointments">Fkafkafk fakfka kf414<br />
</a><a class="appointments">Fkafkafk fakfka kf414<br />
</a><a class="appointments">Fkafkafk fakfka kf414<br />
</a><a class="appointments">Fkafkafk fakfka kf414<br />
</a>
</div>
<div class="appointmentOverflowContainer">
<div>
<a class="MoreAppointments">+1 More</a></div>
</div>
</td>
The short answer is simply, you can't.
The problem
Normally, you can stop an event from "bubbling up" to event handlers on outer elements because the handlers for inner elements are called first. However, jQuery's "live events" work by attaching a proxy handler for the desired event to the document element, and then calling the appropriate user-defined handler(s) after the event bubbles up the document.
(source: shog9.com)
This generally makes "live" binding a rather efficient means of binding events, but it has two big side-effects: first, any event handler attached to an inner element can prevent "live" events from firing for itself or any of its children; second, a "live" event handler cannot prevent any event handlers attached directly to children of the document from firing. You can stop further processing, but you can't do anything about processing that has already occurred... And by the time your live event fires, the handler attached directly to the child has already been called.
Solution
Your best option here (so far as I can tell from what you've posted) is to use live binding for both click handlers. Once that's done, you should be able to return false from the .MoreAppointments handler to prevent the .DateBox handler from being called.
Example:
$('.MoreAppointments').live('click', function(e)
{
alert("Hi");
return false; // prevent additional live handlers from firing
});
// use live binding to allow the above handler to preempt
$('#CalendarBody .DateBox').live('click', function(e)
{
AddApointment(this);
});
I've used such kind if code and it worked for me:
$('#some-link').live('click', function(e) {
alert("Link clicked 1");
e.stopImmediatePropagation();
});
$('#some-link').live('click', function(e) {
alert("Link clicked 2");
});
so, it seems to me, that now JQuery support stopImmediatePropagation with live events
Maybe you could check that the click event didn't occur on an a element:
$('#CalendarBody .DateBox').click(function(e) {
// if the event target is an <a> don't process:
if ($(e.target).is('a')) return;
AddApointment(this);
});
Might Work?
I'm using this:
if(event.target != this)return; // stop event bubbling for "live" event
I use
e.stopPropagation(); // to prevent event from bubbling up
e.preventDefault(); // then cancel the event (if it's cancelable)
I've used this in certain situations. Note: not always applicable, so assess for your needs as always:
html:
Click me
js (in your live event handler):
if(e.target.className == 'my-class-name') {
e.preventDefault();
// do something you want to do...
}
This way, my live event only 'runs' when a particular element type/classname attr is clicked.
The e.preventDefault() here is to stop the link I'm clicking moving the scroll-position to the top of the page.
Simply use **"on"** function to bind click event of child as well as parent element.
Example : $("#content-container").on("click","a.childElement",function(e){
alert("child clicked");
e.stopPropagation() ;
});
$("#content-container").on("click","div.parentElement",function(e){
alert("parent clicked");
});
( where content-container is the outer div containing both parent as well as child elements. )
Here only "child clicked" alert will occur.
Thanks.

Categories

Resources