views:

102

answers:

2

Hi, Jquery stopPropagation method dosen't work with live method. Below the code is works fine with click instead of live method. Any help greatly appreciated.

Code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Jquery Propagation and preventDetauls Example for Popup</title>
<style type="text/css">
 .icon.white{background:#FFFFFF;}
 .icon{-moz-border-radius:2px 2px 2px 2px;-moz-box-shadow:0 1px 2px #EAEDF4;background-color:#FFFFFF;border:1px solid #E4E8F1;float:left;margin:0 1% 1% 0;text-align:center;}
 .iconlinks{height:20px;}
 .info{float:right;}
 .icon a.infolink, .downloadlinks a, .iconza a.changecolor {color:#718DB5;display:block;font-size:10px;padding:4px 7px;text-decoration:none;}
 .icon .infolink {background-image:url(images/dwn-arrow.gif);background-position:35px center;background-repeat:no-repeat;padding-right:17px !important;position:relative;}
 .downloadlinks{float:left;width:130px;overflow:hidden;}
 .downloadlinks a{float:left;}
 .infolink:hover{background-image:url(images/arrow-white.gif);}
 .infolink:hover{background-color: #1f75cc;color: white !important;text-decoration: none !important;}
 .infolink.selected{z-index: 100;color: white !important;background-color: #1f75cc !important;background-image: url(images/arrow-white.gif) !important;}
 .icon-image{border:0px;}
 .service-name{font-family:Arial, Helvetica, sans-serif;font-size:14px;line-height:24px;color:#74767A;margin:3px;text-align:left;}
 .describe-icons{position:absolute;right:2px;bottom:2px;}
 .infomenu{text-align:left;margin-left:-150px;margin-top:-1px;position:absolute;width:260px;-moz-box-shadow:2px 2px 5px #2F3B4A;background-color:#FFFFFF;border:2px solid #1F75CC;z-index:50;}
</style>
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
 $(function(){
  $(document).click(function(){
   $("a.infolink").removeClass("selected");
   $("div.infomenu").hide();
  });
  $("a.infolink").live("click",function(e){
   $("a.infolink").removeClass("selected");
   $("div.infomenu").hide();
   $(this).addClass("selected");
   $(this).next().show();
   e.stopPropagation();
  });
  $("div.infomenu").live("click",function(e){
   e.stopPropagation();
   //e.preventDefault();
  });
  $("input.clickme").click(function(e){
   alert("I am fired");
  });
 });
</script>
</head>
<body>
<div id="tserviceslist" style="margin:25px;">         
 <div style="height: 178px; width: 178px;" id="icon-12608" class="icon white">            
  <div class="iconlinks">    
   <div class="info">
    <a href="#" class="infolink"  title="Click here to see more information about this Services." rel="nofollow">INFO</a>              
    <div id="infomenu-12608" class="infomenu" style="display: none;"><input type="button" value="clickme" class="clickme" />Information will come here</div>
   </div>
   <div class="downloadlinks">
    <h3 class="service-name">Cricket</h3>            
   </div>
  </div>
  <br />

 </div>        


</div>
</body>
</html>

Thanking you, sureace.

+2  A: 

That is because .live() relies on event propagation.

The event is not actually placed on the element, but rather on the root node. The event then bubbles up to that node, checks the selector to see if it has a match, and fires if so.

Because the event isn't fired until it is already at the top of the hierarchy, there's no propagation left to stop.

patrick dw
Hi, Thanks for your quick response. But i couldn't get it how to implement. Can u tell me where should i change my code.
@user - See Nick's answer. He has a good solution that uses `e.isPropagationStopped()` to check to see if you stopped propagation.
patrick dw
@user - Are you sure you need `.live()`? Are the elements being added dynamically to the page, or are they there when the page loads? If they exist when the page loads, then don't use `.live()`. Use `.bind()` instead.
patrick dw
yes, elements are added dynamically on the page.
+3  A: 

You just need to change the order of your handlers a bit, and use/check for propagation stopping, like this:

$("a.infolink").live("click",function(e){
    $("a.infolink").removeClass("selected");
    $("div.infomenu").hide();
    $(this).addClass("selected");
    $(this).next().show();
    e.stopPropagation();
});
$("div.infomenu").live("click",function(e){
    e.stopPropagation();
});
$(document).click(function(e){
    if(e.isPropagationStopped()) return;  //important, check for it!
    $("a.infolink").removeClass("selected");
    $("div.infomenu").hide();
});
$("input.clickme").click(function(e){
    alert("I am fired");
});​

Give it a try here, there are a few important points to keep in mind:

  • .live() handlers are on document
  • Event handlers execute in the order they were bound to any given element

You need to stop and check the propagation since we're at the same level. .stopPropagation() would prevent the bubbling from going any higher but that doesn't matter, it's at the same level in the DOM, so you need to check if it was stopped, using .isPropagationStopped(). Also, since the handlers fire in order, you need to bind that document.onclick after your other event handlers, otherwise it'll execute first, before the others tried to stop propagation.

Nick Craver
+1 - I had forgotten about `.isPropagationStopped()`. I was about to suggest a fragile solution that tested the `e.target`. Yours is much nicer. (FYI, you have a typo. Look at your first `e.stopPropagation()`) :o)
patrick dw
@patrick - Fixed, thanks :) I was initially thinking Immediate for consistency here, but it's not really necessary, didn't get all of the "Immediate"s out of there :)
Nick Craver
yes it is working great. Thank u very much nick.
@user400091 - Welcome :) Remember to accept answers to questions via the checkmark beside the one that helped :)
Nick Craver