DEV: cards were leaking mousedown event listener (#14206)

DEV: cards were leaking mousedown event listener (#14206)

diff --git a/app/assets/javascripts/discourse/app/mixins/card-contents-base.js b/app/assets/javascripts/discourse/app/mixins/card-contents-base.js
index bda3d3f..2a1f1b2 100644
--- a/app/assets/javascripts/discourse/app/mixins/card-contents-base.js
+++ b/app/assets/javascripts/discourse/app/mixins/card-contents-base.js
@@ -7,6 +7,7 @@ import { escapeExpression } from "discourse/lib/utilities";
 import headerOutletHeights from "discourse/lib/header-outlet-height";
 import { inject as service } from "@ember/service";
 import { wantsNewWindow } from "discourse/lib/intercept-click";
+import { bind } from "discourse-common/utils/decorators";
 
 const DEFAULT_SELECTOR = "#main-outlet";
 
@@ -97,35 +98,16 @@ export default Mixin.create({
     afterTransition($(this.element), this._hide.bind(this));
     const id = this.elementId;
     const triggeringLinkClass = this.triggeringLinkClass;
-    const clickOutsideEventName = `mousedown.outside-${id}`;
     const previewClickEvent = `click.discourse-preview-${id}-${triggeringLinkClass}`;
     const mobileScrollEvent = "scroll.mobile-card-cloak";
 
     this.setProperties({
       boundCardClickHandler: this._cardClickHandler.bind(this),
-      clickOutsideEventName,
       previewClickEvent,
       mobileScrollEvent,
     });
 
-    $("html")
-      .off(clickOutsideEventName)
-      .on(clickOutsideEventName, (e) => {
-        if (this.visible) {
-          const $target = $(e.target);
-          if (
-            $target.closest(`[data-${id}]`).data(id) ||
-            $target.closest(`a.${triggeringLinkClass}`).length > 0 ||
-            $target.closest(`#${id}`).length > 0
-          ) {
-            return;
-          }
-
-          this._close();
-        }
-
-        return true;
-      });
+    document.addEventListener("mousedown", this._clickOutsideHandler);
 
     _cardClickListenerSelectors.forEach((selector) => {
       document
@@ -336,16 +318,16 @@ export default Mixin.create({
 
   willDestroyElement() {
     this._super(...arguments);
-    const clickOutsideEventName = this.clickOutsideEventName;
-    const previewClickEvent = this.previewClickEvent;
 
-    $("html").off(clickOutsideEventName);
+    document.removeEventListener("mousedown", this._clickOutsideHandler);
+
     _cardClickListenerSelectors.forEach((selector) => {
       document
         .querySelector(selector)
         .removeEventListener("click", this.boundCardClickHandler);
     });
 
+    const previewClickEvent = this.previewClickEvent;
     this.appEvents.off(previewClickEvent, this, "_previewClick");
 
     this.appEvents.off(
@@ -364,4 +346,22 @@ export default Mixin.create({
       target.focus();
     }
   },
+
+  @bind
+  _clickOutsideHandler(event) {
+    if (this.visible) {
+      const $target = $(event.target);
+      if (
+        $target.closest(`[data-${this.elementId}]`).data(this.elementId) ||
+        $target.closest(`a.${this.triggeringLinkClass}`).length > 0 ||
+        $target.closest(`#${this.elementId}`).length > 0
+      ) {
+        return;
+      }
+
+      this._close();
+    }
+
+    return true;
+  },
 });

GitHub sha: 55739fd3c9a36bd44ee5d35896c1b6188991640f

This commit appears in #14206 which was approved by CvX. It was merged by jjaffeux.