1

I'm trying to delegate events like JQuery does with its $.on method, triggering events on targeted element and it's children (once when the targeted element has many children and could trigger too many times in events like mouseenter).

I've created some examples of what I've achieved so far and the issues I couldn't solve.

Using .matches:

"mouseenter mouseleave mouseup click".split(" ").forEach(eventType => {
  document.querySelector("#js-matches").addEventListener(eventType, function(event) {
    if (event.target.matches(".target")) showResult(event.type)
  }, true);
});

function showResult(result) {
  const resultBox = document.querySelector("#result")
  resultBox.innerHTML = result + '<br>' + resultBox.innerHTML
}
body > div {
  margin-right: 40px;
}

div {
  border: 1px solid;
  padding: 20px;
  background-color: white;
}

div:hover {
  border-color: yellow;
}

.target {
  cursor: pointer;
  background-color: red;
}
<div id="js-matches">
  <div class="target">
    <div>
      <div class="content">Pure JS with matches</div>
    </div>
  </div>
</div>
<div id="result"></div>
  • Good: mouseenter and mouseleave are triggered only once;
  • Bad: mouseup and click trigger only in the specified element, not in its children;

Using .closest:

"mouseenter mouseleave mouseup click".split(" ").forEach(eventType => {
  document.querySelector("#js-closest").addEventListener(eventType, function(event) {
    if (event.target.closest(".target")) showResult(event.type)
  }, true);
});

function showResult(result) {
  const resultBox = document.querySelector("#result")
  resultBox.innerHTML = result + '<br>' + resultBox.innerHTML
}
body > div {
  margin-right: 40px;
}

div {
  border: 1px solid;
  padding: 20px;
  background-color: white;
}

div:hover {
  border-color: yellow;
}

.target {
  cursor: pointer;
  background-color: red;
}
<div id="js-closest">
  <div class="target">
    <div>
      <div class="content">Pure JS with closest</div>
    </div>
  </div>
</div>
<div id="result"></div>
  • Good: mouseup and click are triggered in the targeted element and its children;
  • Bad: mouseenter and mouseleave are triggered multiple times from targeted element to its children;

Just to exemplify the desired behavior, here's the JQuery snippet:

$("#jquery").on("mouseenter mouseleave mouseup click", ".target", 
  function(event) { showResult(event.type) }
);

function showResult(result) {
  const resultBox = document.querySelector("#result")
  resultBox.innerHTML = result + '<br>' + resultBox.innerHTML
}
body > div {
  margin-right: 40px;
}

div {
  border: 1px solid;
  padding: 20px;
  background-color: white;
}

div:hover {
  border-color: yellow;
}

.target {
  cursor: pointer;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="jquery">
  <div class="target">
    <div>
    <div class="content">JQuery Box <button>Botão</button></div>
    </div>
  </div>
</div>
<div id="result"></div>

That's it, any tips will be helpful.

Marco
  • 1,279
  • 1
  • 15
  • 26
  • 1
    It's best to phrase your question in absolute terms rather than referring to functionality in a library. Does this answer your question? [Vanilla JavaScript Event Delegation](https://stackoverflow.com/questions/23508221/vanilla-javascript-event-delegation) – isherwood Feb 11 '22 at 19:21
  • Thanks for the tip, I agree it was prolix and hard to understand what I'm trying to achieve. About the link you sent, it didn't work with mouseenter, mouseleave events – Marco Feb 12 '22 at 00:06

0 Answers0