<nav aria-label="Skip links" class="skip-menu">
  <a class="site-skip" href="#main-content">Skip to content</a>
</nav>

<main class="container" id="main-content">

  <div class="row mt-2 mb-5">
    <div class="col-md-6 offset-md-3 d-flex align-items-center flex-column">
      <p class="mb-4 lead">Single button with attached multiple event handlers</p>
      <button type="button" id="actionButton" class="btn btn-primary mb-4">Action</button>

      <div id="results"></div>
    </div>
  </div>

</main>
html,
body {
  height: 100%;
  width: 100%;
}

body {
  background: #fff;
  color: #000;
  font-family: "Helvetica Neue", "Segoe UI", Helvetica, Arial, "Lucida Grande",
    sans-serif;
  font-weight: 400;
  font-size: 1em;
  padding: 0 1em 1em 1em;
}

p {
  margin-bottom: 1rem;
}

@media (max-width: 575.98px) {
  h1 {
    text-align: center;
  }
}

button {
  box-shadow: 0 4px 4px rgba(8 8 8 / 8%), 0 1px 2px rgba(8 8 8 / 20%),
    inset 0 6px 12px rgba(255 255 255 / 12%),
    inset 0 1px 1px rgba(255 255 255 / 20%);
}

.skip-menu a {
  left: 50%;
  transform: translate(-50%, 0);
  background-color: #0070d1;
  border-radius: 0;
  box-shadow: 0px 0px 18px -1px rgb(0 0 0 / 32%);
  color: #fff;
  display: block;
  padding: 1rem;
  position: absolute;
  text-align: center;
  top: -7rem;
  transition: top 0.3s ease-in-out;
  z-index: 999999;
}

.skip-menu a:focus {
  background-color: #0070d1;
  color: #fff;
  outline-color: #0070d1;
  top: 4px;
}
(function () {
  const resultsElement = document.querySelector("#results");
  const actionButton = document.querySelector("#actionButton");
  let processedEvent = false;

  const redispatchEvent = (event, target) => {
    // Uncaught (in promise) DOMException: Failed to execute 'dispatchEvent' on 'EventTarget': The event is already being dispatched.
    try {
      target.dispatchEvent(event);
    } catch (e) {
      // silence
    }

    processedEvent = false;
    target.disabled = false;
  };

  const onClickFirstHandler = async (event) => {
    const target = event.target;

    if (
      processedEvent ||
      target === null ||
      (target.nodeName.toLowerCase() === "button" &&
        target.type !== "button") ||
      event.type !== "click"
    ) {
      return;
    }

    resultsElement.insertAdjacentHTML(
      "beforeend",
      "<p>First event handler. Waiting 3 seconds to finish the asynchronous operation.</p>"
    );

    processedEvent = true;

    target.disabled = true;
    event.stopPropagation();

    const action = () => {
      return new window.Promise((resolve, reject) => {
        window.setTimeout(() => {
          console.log("[onClickFirstHandler]", event);
          processedEvent = true;
          resolve();
        }, 3000);
      });
    };

    await action();

    redispatchEvent(event, target);
  };

  const onClickSecondHandler = (event) => {
    console.log("[onClickSecondHandler]", event);
    resultsElement.insertAdjacentHTML(
      "beforeend",
      "<p>Second event handler</p>"
    );
  };

  const onClickThirdHandler = (event) => {
    console.log("[onClickThirdHandler]", event);
    resultsElement.insertAdjacentHTML(
      "beforeend",
      "<p>Third event handler</p>"
    );
  };

  const addEventListenerOptions = {
    capture: true
  };

  actionButton.addEventListener(
    "click",
    onClickFirstHandler,
    addEventListenerOptions
  );
  actionButton.addEventListener("click", onClickSecondHandler);
  actionButton.addEventListener("click", onClickThirdHandler);

  // Google Analytics
  const loadGTM = () => {
    const gtmScript = document.createElement("script");
    const documentHead = document.head;

    gtmScript.src = "https://www.googletagmanager.com/gtag/js?id=G-JTTSY0KNFH";
    gtmScript.type = "text/javascript";
    gtmScript.async = true;

    gtmScript.onload = () => {
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
      gtag("js", new Date());
      gtag("config", "G-JTTSY0KNFH");
    };

    documentHead.insertBefore(gtmScript, documentHead.firstChild);
  };

  let url = new URL(window.location.href);

  if (url.protocol !== "file:") {
    loadGTM();
  }
})();

External CSS

  1. https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css

External JavaScript

This Pen doesn't use any external JavaScript resources.