How to check if some DOM element in another DOM element tree?

余生长醉 提交于 2019-12-25 04:22:22

问题


How to check if some DOM element in another DOM element tree?

For example to hide menu when you click on main page content instead of menu you can:

document.addEventListener(function (e) {
    var node = e.target;
    do {
        if (node.classList.contains('menu-area'))
            return;
        node = node.parentNode;
    } while (node instanceof HTMLElement);
    closeMenu();
});

Note that usual solution to hide menu when you click to non-menu area is event.stopPropagation() on menu and non-conditional document.addEventListener().

I make test code with iteration loop over node = node.parentNode and === operator:

<style>
div {
  margin: 20px;
  padding: 5px;
  border: 1px green dotted;
}
</style>

<div id="lvl1">
  <div id="lvl2">
    <div id="lvl3">
      Click me
    </div>
  </div>
</div>
<div id="result"></div>


<script>
  var lvl1Node = document.getElementById('lvl1');
  document.addEventListener('click', function(e) {
    var node = e.target;
    do {
      if (lvl1Node === node) {
        document.getElementById('result').innerHTML = "Event from: " + e.target.id;
        return;
      }
      node = node.parentNode;
    } while (node instanceof HTMLElement);
  });
</script>

So only click inside <div id='lvl1'> change <div id="result"> area. Is that right solution (according to standard)?

That jQuery/Backbone/Underscore/Mojo/etc have to this?


回答1:


I wouldn't use instanceof for this (not least because it won't work in IE8, which sadly continues to linger). Test for === the node where you want to stop, probably document.body or document.documentElement (the <html> element):

document.addEventListener("click", function (e) {
    var node = e.target;
    do {
        if (node.classList.contains('menu-area'))
            return;
        node = node.parentNode;
    } while (node !== document.documentElement);
    closeMenu();
});

Or as your loop has initialization, test, and "increment," it's a good match for for:

document.addEventListener("click", function (e) {
    var node;
    for (node = e.target; node !== document.documentElement; node = node.parentNode) {
        if (node.classList.contains('menu-area')) {
            return;
        }
    }
    closeMenu();
});

That jQuery/Backbone/Underscore/Mojo/etc have to this?

For what you're doing above, jQuery does, yes, in two ways:

  1. jQuery supports event delegation, so it does the checks for you. But I'm not immediately sure that applies to what you're doing.

  2. If for some reason you couldn't use that, jQuery's closest would probably help:

    if (!$(e.target).closest(".menu-area")[0]) {
        closeMenu();
    }
    

    closest tests the element against a selector and, if it doesn't match, checks its parent node, and so on. The [0] at the end tells us whether jQuery found anything. In the above, if it didn't find anything (the ! at the beginning), we close the menu.



来源:https://stackoverflow.com/questions/25185512/how-to-check-if-some-dom-element-in-another-dom-element-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!