开发者

How to stop propagation of a bound function not the entire event?

开发者 https://www.devze.com 2023-01-02 13:57 出处:网络
I have a click function bound to many elements.It is possible that sometimes these elements may sit within one another. So, the click event is bound to a child and also bound to its parent. The method

I have a click function bound to many elements. It is possible that sometimes these elements may sit within one another. So, the click event is bound to a child and also bound to its parent. The method is specific to the element clicked. Naturally, because of event bubbling, the child's event is fired first, and then the parents. I cannot have them both called at the same time because the parents event overwrites the event of the child. So I could use event.stopPropagation() so only the first element clicked receives the event. The problem is that there are other click events also attached to the element, for example, I am using jQuery's draggable on these elements. If I stop the propagation of the click event, then draggable doesn't work, and the following click events are not called.

So my question is: Is there a way to stop the event bubbling of the method the event will call and not the entire event?


Brilliant John, but here is the problem:

<div id="Elm1"><!-- relative -->
 <div class="Elmchildren"></div><!-- absolute-->
 <div class="Elmchildren"></div><!-- absolute-->
 <div class="Elmchildren"></div><!-- absolute-->

 <div id="Elm2"><!-- relative -->
  <div class="Elmchildren"></div><!-- absolute-->
  <div class="Elmchildren"></div><!-- absolute-->
  <div class="Elmchildren"></div><!-- absolute-->
 </div>

</div>

Click event is bound to #Elm1 and #Elm2. The .Elmchildren are width and height 100%. So they are 开发者_如何转开发actually the current targets.


try someting like this

$(mySelector).click(function(evt) {
  if (evt.target == evt.currentTarget) {
      ///run your code.  The if statment will only run this click event on the target element
      ///all other click events will still run.
  }
});


The suggested solution

evt.target == evt.currentTarget

is nice, but there are cases where it does not help.

Example: A (suckerfish-style) menu structure with nested ul/li lists.
The mousemove event comes from a link inside a list item, which is a child of an ul-list, which is again a child of another list item. Typical for a html menu structure with submenus.
The evt.target would be the link tag, but we are interested in the mousemove on the list item.
Even worse: The link tag could contain span or img tags or other nested stuff. Then evt.target would be this span or img.

What seems to work here is to catch the event on a parent / root item, and then check the parents of evt.target.

Like this (with jQuery),

var $menu = $('div#menu');
$('body').mousemove(function(evt){
  var element = evt.target;
  // find the deepest list item that was affected by this mouseover event.
  var list_item;
  var in_menu = false;
  while (element) {
    if (element == $menu[0]) {
      in_menu = true;
      break;
    }
    else if (!list_item && element.tagName == 'LI') {
      // we found a list item, but we are not sure if we are inside the menu tree.
      list_item = element;
    }
  }
  // do something with the result.
  if (!in_menu) {
        .. // close all submenus
  }
  if (list_item) {
    .. // open the submenu for this list item.
  }
  else {
    // mouse in menu, but not hovering an item.
    // leave the submenus open. (?)
  }
});

Maybe some of this could be abbreviated with jQuery like $(evt.target).parents().is($menu), but I did not get this to work. Also, I would guess that this explicit loop with element.tagName is faster.

0

精彩评论

暂无评论...
验证码 换一张
取 消