This repository has been archived by the owner on Oct 24, 2023. It is now read-only.
/
inline-footnotes.js
114 lines (93 loc) · 3.05 KB
/
inline-footnotes.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { createPopper } from "@popperjs/core";
import { withPluginApi } from "discourse/lib/plugin-api";
import { iconHTML } from "discourse-common/lib/icon-library";
let inlineFootnotePopper;
function applyInlineFootnotes(elem) {
const footnoteRefs = elem.querySelectorAll("sup.footnote-ref");
footnoteRefs.forEach((footnoteRef) => {
const button = document.createElement("button");
button.classList.add("expand-footnote", "btn", "btn-icon", "no-text");
button.innerHTML = iconHTML("ellipsis-h");
button.dataset.footnoteId = footnoteRef
.querySelector("a")
.id.replace("footnote-ref-", "");
footnoteRef.after(button);
});
if (footnoteRefs.length) {
elem.classList.add("inline-footnotes");
}
}
function buildTooltip() {
let html = `
<div id="footnote-tooltip" role="tooltip">
<div class="footnote-tooltip-content"></div>
<div id="arrow" data-popper-arrow></div>
</div>
`;
let template = document.createElement("template");
html = html.trim();
template.innerHTML = html;
return template.content.firstChild;
}
function footNoteEventHandler(event) {
inlineFootnotePopper?.destroy();
const tooltip = document.getElementById("footnote-tooltip");
// reset state by hidding tooltip, it handles "click outside"
// allowing to hide the tooltip when you click anywhere else
if (tooltip) {
tooltip.removeAttribute("data-show");
}
// if we didn't actually click a footnote button, exit early
if (!event.target.classList.contains("expand-footnote")) {
return;
}
// append footnote to tooltip body
const button = event.target;
const cooked = button.closest(".cooked");
const footnoteId = button.dataset.footnoteId;
const footnoteContent = tooltip.querySelector(".footnote-tooltip-content");
const newContent = cooked.querySelector(`#footnote-${footnoteId}`);
footnoteContent.innerHTML = newContent.innerHTML;
// remove backref from tooltip
const backRef = footnoteContent.querySelector(".footnote-backref");
backRef.parentNode.removeChild(backRef);
// display tooltip
tooltip.dataset.show = "";
// setup popper
inlineFootnotePopper?.destroy();
inlineFootnotePopper = createPopper(button, tooltip, {
modifiers: [
{
name: "arrow",
options: { element: tooltip.querySelector("#arrow") },
},
{
name: "offset",
options: {
offset: [0, 12],
},
},
],
});
}
export default {
name: "inline-footnotes",
initialize(container) {
if (!container.lookup("site-settings:main").display_footnotes_inline) {
return;
}
document.documentElement.append(buildTooltip());
window.addEventListener("click", footNoteEventHandler);
withPluginApi("0.8.9", (api) => {
api.decorateCookedElement((elem) => applyInlineFootnotes(elem), {
onlyStream: true,
id: "inline-footnotes",
});
});
},
teardown() {
inlineFootnotePopper?.destroy();
window.removeEventListener("click", footNoteEventHandler);
document.getElementById("footnote-tooltip")?.remove();
},
};