简体   繁体   中英

How to stop children from triggering parent mouseenter event

My buttons have one image inside them, and the mouseenter event gets triggered by both the button AND the image. I would like the event to be triggered only once by "hovering" the BUTTON, not the image.

HTML, the only relevant part of the code are the buttons and their IDs.

<div class="catalogue-hidden">
        <div id="product-1" class="product estusFlask">
          <img src="./products/Item_Estus_Flask.png" />
          <span>Estus Flask</span>
          <button id="btn-1" class="button">
            1000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-2" class="product">
          <img src="./products/Mask_of_the_Father.png" />
          <span>Mask of the Father</span>
          <button id="btn-2" class="button">
            8000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-3" class="product">
          <img src="./products/Giant_Armor.png" />
          <span>Giant Armor</span>
          <button id="btn-3" class="button">
            5000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-4" class="product">
          <img src="./products/Giant_Gauntlets.png" />
          <span>Giant Gauntlets</span>
          <button id="btn-4" class="button">
            5000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-5" class="product">
          <img src="./products/Giant_Leggings.png" />
          <span>Giant Leggings</span>
          <button id="btn-5" class="button">
            5000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-6" class="product">
          <img src="./products/Wpn_Zweihander.png" />
          <span>Zweihander</span>
          <button id="btn-6" class="button">
            3500
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-7" class="product">
          <img src="./products/Grass_crest_shield.png" />
          <span>Grass Crest Shield</span>
          <button id="btn-7" class="button">
            1500
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-8" class="product">
          <img src="./products/Havel's_Ring.png" />
          <span>Havel's Ring</span>
          <button id="btn-8" class="button">
            2000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-9" class="product">
          <img src="./products/Ring_of_Favor_and_Protection.png" />
          <span class="fap">Ring of Favor and Protection</span>
          <button id="btn-9" class="button">
            2000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-10" class="product">
          <img src="./products/Pyro_Pyromancy_Flame.png" />
          <span>Pyromancy Flame</span>
          <button id="btn-10" class="button">
            1000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div id="product-11" class="product">
          <img src="./products/Black_Flame.png" />
          <span>Black Flame</span>
          <button id="btn-11" class="button">
            5000
            <img src="./icons/soul_of_a_proud_paladin.png" />
          </button>
        </div>

        <div onclick="stopBgm(); changeVideo(); hideHud()" id="product-12" class="product-hidden">
          <img src="./products/7011.png" />
          <span>Well, what is it?</span>
          <button id="btn-12" class="button-hidden">
            PWN SOME NOOBZ
          </div>

JavaScript


function selectSfx() {
  var audio = document.querySelector(".selectSfx");
  audio.currentTime = 0;
  audio.play();
}

for (let idNumber = 1; idNumber < 13; idNumber++) {
  setTimeout(() => {
    document
      .getElementById(`btn-${idNumber}`)
      .addEventListener("mouseenter", selectSfx, true);

    document
      .getElementById(`btn-${idNumber}`)
      .addEventListener("click", (e) => {
        condition++;
        console.log(condition);
        okSfx();

        document.getElementById(`product-${idNumber}`).className =
          "product-fake";

        document.getElementById(`btn-${idNumber}`).disabled = true;

        document
          .getElementById(`btn-${idNumber}`)
          .removeEventListener("mouseenter", selectSfx, true);

        if (condition >= 11) {
          document.querySelector(".product-hidden").className = "product";
          document.getElementById("btn-12").className = "button";
        }
      });
  }, 4000);
}

When I add the mouseenter event like this, the SelectSfx(); does NOT play when I hover the images within the buttons. The sound plays only once, which is the desired result. But unfortunately I am unable to disable the event once the button gets disabled.

function selectSfx() {
  var audio = document.querySelector(".selectSfx");
  audio.currentTime = 0;
  audio.play();
}

for (let idNumber = 1; idNumber < 14; idNumber++) {
  setTimeout(() => {
    document
      .getElementById(`btn-${idNumber}`)
      .addEventListener("mouseenter", (e) => {
        selectSfx();
      });
  }, 4000);
}

Add the following code just below your "setTimeout" line in your javascript file:

document
  .getElementById(`btn-${idNumber}`)
  .querySelectorAll('img')
  .forEach((img) => {
    img.style.pointerEvents = 'none';
  });

The code removes pointer events from images that are within the desired buttons.

Edit:

Perhaps, the "more correct" answer is to remove the third argument of the 'addEventListener' function call:

ORIGINAL:

document
  .getElementById(`btn-${idNumber}`)
  .addEventListener('mouseenter', selectSfx, true);

FIXED:

document
  .getElementById(`btn-${idNumber}`)
  .addEventListener('mouseenter', selectSfx);

When useCapture is set to true, the event listener is triggered during the capturing phase of the event propagation process. This means that the event is first captured by the outermost element and then propagated to the inner elements.

When useCapture is set to false or not specified, the event listener is triggered during the bubbling phase of the event propagation process. This means that the event is first captured by the innermost element and then propagated to the outer elements.

You can ignore pointer events on the image using CSS and that way the pointer will only interact with the button.

<style>
.button img {
  pointer-events: none;
}
</style>

Just use the Element: mouseover event with CSS pointer-events: none .

The mouseover event is fired at an Element when a pointing device (such as a mouse or trackpad) is used to move the cursor onto the element or one of its child elements.

 let button = document.querySelector("button"); document.querySelector("button > img").style.pointerEvents = 'none'; button.addEventListener("mouseover", function (e) { console.log(e.target.tagName); }, false);
 <div id="product-1" class="product estusFlask"> <button id="btn-1" class="button"> 1000 <img src="https://www.aexp-static.com/cdaas/one/statics/axp-static-assets/1.8.0/package/dist/img/logos/dls-logo-bluebox-solid.svg" /> </button> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM