mirror of
https://github.com/discourse/DiscoTOC.git
synced 2026-09-16 23:42:13 -04:00
FEATURE: Toggle between timeline and TOC (#68)
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
<div class="d-toc-mini">
|
||||
<DButton
|
||||
class="btn-primary"
|
||||
@action={{this.showTOCOverlay}}
|
||||
@label={{theme-prefix "table_of_contents"}}
|
||||
/>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div class="d-toc-mini" {{did-insert this.resetBodyClass}}>
|
||||
<DButton class="btn-primary" @action={{this.showTOCOverlay}} @icon="stream" />
|
||||
</div>
|
||||
+5
@@ -6,4 +6,9 @@ export default class DTocMini extends Component {
|
||||
showTOCOverlay() {
|
||||
document.querySelector(".d-toc-wrapper").classList.toggle("overlay");
|
||||
}
|
||||
|
||||
@action
|
||||
resetBodyClass() {
|
||||
document.body.classList.add("d-toc-timeline-visible");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import domUtils from "discourse-common/utils/dom-utils";
|
||||
import I18n from "I18n";
|
||||
|
||||
let TOChidden = localStorage.getItem("discourse_toc-hidden") === "true";
|
||||
|
||||
export default {
|
||||
name: "disco-toc-main",
|
||||
|
||||
@@ -80,13 +82,29 @@ export default {
|
||||
);
|
||||
|
||||
api.onAppEvent("topic:current-post-changed", (args) => {
|
||||
if (!document.querySelector(".d-toc-cooked")) {
|
||||
return;
|
||||
// manages the timeline area width via CSS
|
||||
if (document.querySelector(".d-toc-cooked")) {
|
||||
document.body.classList.add("d-toc-available");
|
||||
}
|
||||
|
||||
// manages timeline visibility
|
||||
if (args.post.post_number === 1) {
|
||||
document.body.classList.add("d-toc-timeline-visible");
|
||||
if (!TOChidden) {
|
||||
handleButtonAndBody("show");
|
||||
} else {
|
||||
handleButtonAndBody("hide");
|
||||
}
|
||||
|
||||
// don't show the toggle if there's only 1 post
|
||||
if (args.post.topic.posts_count !== 1) {
|
||||
document.body.classList.add("d-toc-timeline-toggleable");
|
||||
}
|
||||
} else {
|
||||
document.body.classList.remove("d-toc-timeline-visible");
|
||||
handleButtonAndBody("hide");
|
||||
}
|
||||
|
||||
if (args.post.topic.posts_count === 1) {
|
||||
document.body.classList.remove("d-toc-timeline-toggleable");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -103,7 +121,7 @@ export default {
|
||||
});
|
||||
|
||||
api.cleanupStream(() => {
|
||||
document.body.classList.remove("d-toc-timeline-visible");
|
||||
document.body.classList.remove("d-toc-available");
|
||||
document.removeEventListener("click", this.clickTOC, false);
|
||||
});
|
||||
});
|
||||
@@ -150,30 +168,67 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
insertTOC(headings) {
|
||||
createMainDiv() {
|
||||
const dToc = document.createElement("div");
|
||||
dToc.classList.add("d-toc-main");
|
||||
dToc.innerHTML = `<div class="d-toc-icons">
|
||||
<a href="#" class="scroll-to-bottom" title="${I18n.t(
|
||||
themePrefix("post_bottom_tooltip")
|
||||
)}">${iconHTML("downward")}</a>
|
||||
<a href="#" class="d-toc-close">${iconHTML("times")}</a></div>`;
|
||||
dToc.innerHTML = `<div class="d-toc-icons"><a href="#" class="d-toc-close">${iconHTML(
|
||||
"times"
|
||||
)}</a></div>`;
|
||||
return dToc;
|
||||
},
|
||||
|
||||
createScrollLink() {
|
||||
const scrollLink = document.createElement("a");
|
||||
scrollLink.href = "#";
|
||||
scrollLink.className = "scroll-to-bottom";
|
||||
scrollLink.title = I18n.t(themePrefix("post_bottom_tooltip"));
|
||||
scrollLink.innerHTML = `${iconHTML("downward")} ${I18n.t(
|
||||
themePrefix("jump_bottom")
|
||||
)}`;
|
||||
return scrollLink;
|
||||
},
|
||||
|
||||
createToggleButton() {
|
||||
const toggleButton = document.createElement("button");
|
||||
toggleButton.className =
|
||||
"d-toc-timeline-toggle btn btn-default btn-icon-text";
|
||||
toggleButton.innerHTML =
|
||||
iconHTML("timeline") + I18n.t(themePrefix("topic_timeline"));
|
||||
|
||||
return toggleButton;
|
||||
},
|
||||
|
||||
insertTOC(headings) {
|
||||
const dToc = this.createMainDiv();
|
||||
const scrollLink = this.createScrollLink();
|
||||
this.toggleButton = this.createToggleButton();
|
||||
|
||||
const existing = document.querySelector(".d-toc-wrapper .d-toc-main");
|
||||
const wrapper = document.querySelector(".d-toc-wrapper");
|
||||
|
||||
if (existing) {
|
||||
document.querySelector(".d-toc-wrapper").replaceChild(dToc, existing);
|
||||
wrapper.replaceChild(dToc, existing);
|
||||
} else {
|
||||
document.querySelector(".d-toc-wrapper").appendChild(dToc);
|
||||
wrapper.appendChild(dToc);
|
||||
wrapper.appendChild(this.toggleButton);
|
||||
}
|
||||
|
||||
const result = this.buildTOC(Array.from(headings));
|
||||
document.querySelector(".d-toc-main").appendChild(result);
|
||||
dToc.appendChild(result);
|
||||
dToc.appendChild(scrollLink);
|
||||
document.addEventListener("click", this.clickTOC, false);
|
||||
},
|
||||
|
||||
clickTOC(e) {
|
||||
const classNames = ["d-toc-timeline-visible", "archetype-docs-topic"];
|
||||
|
||||
// toggle timeline visibility
|
||||
if (e.target.closest(".d-toc-timeline-toggle")) {
|
||||
handleButtonAndBody("toggle");
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
!classNames.some((className) =>
|
||||
document.body.classList.contains(className)
|
||||
@@ -212,7 +267,7 @@ export default {
|
||||
top: rect.bottom + window.scrollY - headerOffset() - 10,
|
||||
behavior: "smooth",
|
||||
});
|
||||
|
||||
document.querySelector(".d-toc-wrapper").classList.remove("overlay");
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
@@ -317,3 +372,42 @@ function parentsUntil(el, selector, filter) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function handleButtonAndBody(action) {
|
||||
const body = document.body;
|
||||
const button = document.querySelector("button.d-toc-timeline-toggle");
|
||||
|
||||
switch (action) {
|
||||
case "toggle":
|
||||
body.classList.toggle("d-toc-timeline-visible");
|
||||
TOChidden = !TOChidden;
|
||||
localStorage.setItem("discourse_toc-hidden", TOChidden.toString());
|
||||
|
||||
break;
|
||||
|
||||
case "hide":
|
||||
body.classList.remove(
|
||||
"d-toc-timeline-visible",
|
||||
"d-toc-timeline-toggleable"
|
||||
);
|
||||
break;
|
||||
|
||||
case "show":
|
||||
body.classList.add("d-toc-timeline-visible", "d-toc-timeline-toggleable");
|
||||
break;
|
||||
}
|
||||
|
||||
if (button) {
|
||||
const translationKey = body.classList.contains("d-toc-timeline-visible")
|
||||
? "topic_timeline"
|
||||
: "table_of_contents";
|
||||
|
||||
const icon = body.classList.contains("d-toc-timeline-visible")
|
||||
? "timeline"
|
||||
: "stream";
|
||||
|
||||
button.innerHTML = `${iconHTML(icon)}${I18n.t(
|
||||
themePrefix(translationKey)
|
||||
)} `;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user