2021-03-11 05:43:45 +01:00
|
|
|
import $ from "jquery";
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
function collapse_spoiler($spoiler: JQuery): void {
|
2023-04-20 00:50:38 +02:00
|
|
|
const spoiler_height = $spoiler.height() ?? 0;
|
2020-04-04 22:14:34 +02:00
|
|
|
|
|
|
|
// Set height to rendered height on next frame, then to zero on following
|
|
|
|
// frame to allow CSS transition animation to work
|
2020-07-02 01:45:54 +02:00
|
|
|
requestAnimationFrame(() => {
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.height(`${spoiler_height}px`);
|
|
|
|
$spoiler.removeClass("spoiler-content-open");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
2020-07-02 01:45:54 +02:00
|
|
|
requestAnimationFrame(() => {
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.height("0px");
|
2020-04-04 22:14:34 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
function expand_spoiler($spoiler: JQuery): void {
|
2020-04-04 22:14:34 +02:00
|
|
|
// Normally, the height of the spoiler block is not defined absolutely on
|
|
|
|
// the `spoiler-content-open` class, but just set to `auto` (i.e. the height
|
|
|
|
// of the content). CSS animations do not work with properties set to
|
|
|
|
// `auto`, so we get the actual height of the content here and temporarily
|
|
|
|
// put it explicitly on the element styling to allow the transition to work.
|
2024-05-24 00:02:38 +02:00
|
|
|
const spoiler_height = $spoiler[0]!.scrollHeight;
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.height(`${spoiler_height}px`);
|
2020-04-04 22:14:34 +02:00
|
|
|
// The `spoiler-content-open` class has CSS animations defined on it which
|
|
|
|
// will trigger on the frame after this class change.
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.addClass("spoiler-content-open");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.on("transitionend", () => {
|
|
|
|
$spoiler.off("transitionend");
|
2020-04-04 22:14:34 +02:00
|
|
|
// When the CSS transition is over, reset the height to auto
|
|
|
|
// This keeps things working if, e.g., the viewport is resized
|
2022-01-25 11:36:19 +01:00
|
|
|
$spoiler.height("");
|
2020-04-04 22:14:34 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
export const hide_spoilers_in_notification = ($content: JQuery): JQuery => {
|
|
|
|
$content.find(".spoiler-block").each((_i, elem) => {
|
2020-07-15 01:29:15 +02:00
|
|
|
$(elem).find(".spoiler-content").remove();
|
|
|
|
let text = $(elem).find(".spoiler-header").text().trim();
|
2020-07-15 02:08:01 +02:00
|
|
|
if (text.length > 0) {
|
|
|
|
text = `${text} `;
|
|
|
|
}
|
|
|
|
text = `${text}(…)`;
|
2020-07-15 01:29:15 +02:00
|
|
|
$(elem).find(".spoiler-header").text(text);
|
2020-07-15 02:08:01 +02:00
|
|
|
});
|
2022-01-25 11:36:19 +01:00
|
|
|
return $content;
|
2020-07-15 02:08:01 +02:00
|
|
|
};
|
|
|
|
|
2021-06-14 20:22:05 +02:00
|
|
|
export function initialize(): void {
|
2024-05-03 00:09:00 +02:00
|
|
|
$("body").on("click", ".spoiler-header", function (this: HTMLElement, e) {
|
2022-01-25 11:36:19 +01:00
|
|
|
const $button = $(this).children(".spoiler-button");
|
|
|
|
const $arrow = $button.children(".spoiler-arrow");
|
|
|
|
const $spoiler_content = $(this).siblings(".spoiler-content");
|
|
|
|
const $target = $(e.target);
|
2020-06-17 21:57:12 +02:00
|
|
|
|
2020-08-11 01:47:49 +02:00
|
|
|
// Spoiler headers can contain Markdown, including links. We
|
2023-10-09 21:28:43 +02:00
|
|
|
// return so that clicking such links will be processed by
|
2020-07-02 00:26:00 +02:00
|
|
|
// the browser rather than opening the header.
|
2022-01-25 11:36:19 +01:00
|
|
|
if ($target.closest("a").length > 0) {
|
2020-07-02 00:26:00 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow selecting text inside a spoiler header.
|
2021-06-14 20:22:05 +02:00
|
|
|
const selection = document.getSelection();
|
|
|
|
if (selection && selection.type === "Range") {
|
2020-06-17 21:57:12 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-04-04 22:14:34 +02:00
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
if ($spoiler_content.hasClass("spoiler-content-open")) {
|
2020-04-04 22:14:34 +02:00
|
|
|
// Content was open, we are collapsing
|
2022-01-25 11:36:19 +01:00
|
|
|
$arrow.removeClass("spoiler-button-open");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
|
|
|
// Modify ARIA roles for screen readers
|
2022-01-25 11:36:19 +01:00
|
|
|
$button.attr("aria-expanded", "false");
|
|
|
|
$spoiler_content.attr("aria-hidden", "true");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
collapse_spoiler($spoiler_content);
|
2020-04-04 22:14:34 +02:00
|
|
|
} else {
|
|
|
|
// Content was closed, we are expanding
|
2022-01-25 11:36:19 +01:00
|
|
|
$arrow.addClass("spoiler-button-open");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
|
|
|
// Modify ARIA roles for screen readers
|
2022-01-25 11:36:19 +01:00
|
|
|
$button.attr("aria-expanded", "true");
|
|
|
|
$spoiler_content.attr("aria-hidden", "false");
|
2020-04-04 22:14:34 +02:00
|
|
|
|
2022-01-25 11:36:19 +01:00
|
|
|
expand_spoiler($spoiler_content);
|
2020-04-04 22:14:34 +02:00
|
|
|
}
|
|
|
|
});
|
2021-02-10 17:10:39 +01:00
|
|
|
}
|