diff --git a/plugins/footnote/assets/javascripts/initializers/inline-footnotes.js b/plugins/footnote/assets/javascripts/initializers/inline-footnotes.js
index 1d209a637f7..cd25b9e9c7e 100644
--- a/plugins/footnote/assets/javascripts/initializers/inline-footnotes.js
+++ b/plugins/footnote/assets/javascripts/initializers/inline-footnotes.js
@@ -29,47 +29,49 @@ function applyInlineFootnotes(elem) {
}
function buildTooltip() {
- let html = `
+ const template = document.createElement("template");
+ template.innerHTML = `
- `;
+ `.trim();
- let template = document.createElement("template");
- html = html.trim();
- template.innerHTML = html;
return template.content.firstChild;
}
-function footNoteEventHandler(event) {
- inlineFootnotePopper?.destroy();
-
+function footnoteEventHandler(event) {
const tooltip = document.getElementById("footnote-tooltip");
+ const displayedFootnoteId = tooltip?.dataset.footnoteId;
+ const expandableFootnote = event.target;
+ const footnoteId = expandableFootnote.dataset.footnoteId;
- // reset state by hidding tooltip, it handles "click outside"
- // allowing to hide the tooltip when you click anywhere else
+ inlineFootnotePopper?.destroy();
tooltip?.removeAttribute("data-show");
+ tooltip?.removeAttribute("data-footnote-id");
- // if we didn't actually click a footnote button, exit early
if (!event.target.classList.contains("expand-footnote")) {
+ // dismissing the tooltip by clicking outside
return;
}
event.preventDefault();
event.stopPropagation();
- // append footnote to tooltip body
- const expandableFootnote = event.target;
- const cooked = expandableFootnote.closest(".cooked");
- const footnoteId = expandableFootnote.dataset.footnoteId;
- const footnoteContent = tooltip.querySelector(".footnote-tooltip-content");
- let newContent = cooked.querySelector(footnoteId);
+ if (displayedFootnoteId === footnoteId) {
+ // dismissing the tooltip by clicking the footnote button
+ return;
+ }
+ // append footnote to tooltip body
+ const footnoteContent = tooltip.querySelector(".footnote-tooltip-content");
+ const cooked = expandableFootnote.closest(".cooked");
+ const newContent = cooked.querySelector(footnoteId);
footnoteContent.innerHTML = newContent.innerHTML;
// display tooltip
tooltip.dataset.show = "";
+ tooltip.dataset.footnoteId = footnoteId;
// setup popper
inlineFootnotePopper?.destroy();
@@ -104,9 +106,8 @@ export default {
return;
}
- document.documentElement.append(buildTooltip());
-
- window.addEventListener("click", footNoteEventHandler);
+ document.body.append(buildTooltip());
+ window.addEventListener("click", footnoteEventHandler);
withPluginApi("0.8.9", (api) => {
api.decorateCookedElement((elem) => applyInlineFootnotes(elem), {
@@ -115,16 +116,18 @@ export default {
});
api.onPageChange(() => {
- document
- .getElementById("footnote-tooltip")
- ?.removeAttribute("data-show");
+ inlineFootnotePopper?.destroy();
+
+ const tooltip = document.getElementById("footnote-tooltip");
+ tooltip?.removeAttribute("data-show");
+ tooltip?.removeAttribute("data-footnote-id");
});
});
},
teardown() {
inlineFootnotePopper?.destroy();
- window.removeEventListener("click", footNoteEventHandler);
+ window.removeEventListener("click", footnoteEventHandler);
document.getElementById("footnote-tooltip")?.remove();
},
};
diff --git a/plugins/footnote/test/javascripts/acceptance/footnote-test.js b/plugins/footnote/test/javascripts/acceptance/footnote-test.js
index 4ff4d8f6603..c7af4c92397 100644
--- a/plugins/footnote/test/javascripts/acceptance/footnote-test.js
+++ b/plugins/footnote/test/javascripts/acceptance/footnote-test.js
@@ -1,12 +1,10 @@
import { click, visit } from "@ember/test-helpers";
import { test } from "qunit";
import topicFixtures from "discourse/tests/fixtures/topic";
-import { acceptance, exists } from "discourse/tests/helpers/qunit-helpers";
+import { acceptance } from "discourse/tests/helpers/qunit-helpers";
import { cloneJSON } from "discourse-common/lib/object";
-acceptance("Discourse Foonote Plugin", function (needs) {
- needs.user();
-
+acceptance("Discourse Footnote Plugin", function (needs) {
needs.settings({
display_footnotes_inline: true,
});
@@ -28,30 +26,47 @@ acceptance("Discourse Foonote Plugin", function (needs) {
});
});
- test("displays the foonote on click", async function (assert) {
- await visit("/t/45");
+ test("displays the footnote on click", async function (assert) {
+ await visit("/t/-/45");
- const tooltip = document.getElementById("footnote-tooltip");
- assert.ok(exists(tooltip));
+ assert.dom("#footnote-tooltip", document.body).exists();
+ // open
await click(".expand-footnote");
- assert.equal(
- tooltip.querySelector(".footnote-tooltip-content").textContent.trim(),
- "consectetur adipiscing elit ↩︎"
- );
+ assert
+ .dom(".footnote-tooltip-content", document.body)
+ .hasText("consectetur adipiscing elit ↩︎");
+ assert.dom("#footnote-tooltip", document.body).hasAttribute("data-show");
+
+ // close by clicking outside
+ await click(document.body);
+ assert
+ .dom("#footnote-tooltip", document.body)
+ .doesNotHaveAttribute("data-show");
+
+ // open again
+ await click(".expand-footnote");
+ assert
+ .dom(".footnote-tooltip-content", document.body)
+ .hasText("consectetur adipiscing elit ↩︎");
+ assert.dom("#footnote-tooltip", document.body).hasAttribute("data-show");
+
+ // close by clicking the button
+ await click(".expand-footnote");
+ assert
+ .dom("#footnote-tooltip", document.body)
+ .doesNotHaveAttribute("data-show");
});
test("clicking a second footnote with same name works", async function (assert) {
- await visit("/t/45");
+ await visit("/t/-/45");
- const tooltip = document.getElementById("footnote-tooltip");
- assert.ok(exists(tooltip));
+ assert.dom("#footnote-tooltip", document.body).exists();
await click(".second .expand-footnote");
-
- assert.equal(
- tooltip.querySelector(".footnote-tooltip-content").textContent.trim(),
- "consectetur adipiscing elit ↩︎"
- );
+ assert
+ .dom(".footnote-tooltip-content", document.body)
+ .hasText("consectetur adipiscing elit ↩︎");
+ assert.dom("#footnote-tooltip", document.body).hasAttribute("data-show");
});
});