mirror of
https://github.com/zulip/zulip.git
synced 2025-11-03 05:23:35 +00:00
ES and TypeScript modules are strict by default and don’t need this directive. ESLint will remind us to add it to new CommonJS files and remove it from ES and TypeScript modules. Signed-off-by: Anders Kaseorg <anders@zulip.com>
96 lines
3.3 KiB
JavaScript
96 lines
3.3 KiB
JavaScript
"use strict";
|
|
|
|
function collapse_spoiler(spoiler) {
|
|
const spoiler_height = spoiler.height();
|
|
|
|
// Set height to rendered height on next frame, then to zero on following
|
|
// frame to allow CSS transition animation to work
|
|
requestAnimationFrame(() => {
|
|
spoiler.height(spoiler_height + "px");
|
|
spoiler.removeClass("spoiler-content-open");
|
|
|
|
requestAnimationFrame(() => {
|
|
spoiler.height("0px");
|
|
});
|
|
});
|
|
}
|
|
|
|
function expand_spoiler(spoiler) {
|
|
// 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.
|
|
const spoiler_height = spoiler.prop("scrollHeight");
|
|
spoiler.height(spoiler_height + "px");
|
|
// The `spoiler-content-open` class has CSS animations defined on it which
|
|
// will trigger on the frame after this class change.
|
|
spoiler.addClass("spoiler-content-open");
|
|
|
|
spoiler.on("transitionend", () => {
|
|
spoiler.off("transitionend");
|
|
// When the CSS transition is over, reset the height to auto
|
|
// This keeps things working if, e.g., the viewport is resized
|
|
spoiler.height("");
|
|
});
|
|
}
|
|
|
|
exports.hide_spoilers_in_notification = (content) => {
|
|
content.find(".spoiler-block").each((i, elem) => {
|
|
$(elem).find(".spoiler-content").remove();
|
|
let text = $(elem).find(".spoiler-header").text().trim();
|
|
if (text.length > 0) {
|
|
text = `${text} `;
|
|
}
|
|
text = `${text}(…)`;
|
|
$(elem).find(".spoiler-header").text(text);
|
|
});
|
|
return content;
|
|
};
|
|
|
|
exports.initialize = function () {
|
|
$("body").on("click", ".spoiler-header", function (e) {
|
|
const button = $(this).children(".spoiler-button");
|
|
const arrow = button.children(".spoiler-arrow");
|
|
const spoiler_content = $(this).siblings(".spoiler-content");
|
|
const target = $(e.target);
|
|
|
|
// Spoiler headers can contain markdown, including links. We
|
|
// return so that clicking such links will be be processed by
|
|
// the browser rather than opening the header.
|
|
if (target.closest("a").length > 0) {
|
|
return;
|
|
}
|
|
|
|
// Allow selecting text inside a spoiler header.
|
|
if (document.getSelection().type === "Range") {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
if (spoiler_content.hasClass("spoiler-content-open")) {
|
|
// Content was open, we are collapsing
|
|
arrow.removeClass("spoiler-button-open");
|
|
|
|
// Modify ARIA roles for screen readers
|
|
button.attr("aria-expanded", "false");
|
|
spoiler_content.attr("aria-hidden", "true");
|
|
|
|
collapse_spoiler(spoiler_content);
|
|
} else {
|
|
// Content was closed, we are expanding
|
|
arrow.addClass("spoiler-button-open");
|
|
|
|
// Modify ARIA roles for screen readers
|
|
button.attr("aria-expanded", "true");
|
|
spoiler_content.attr("aria-hidden", "false");
|
|
|
|
expand_spoiler(spoiler_content);
|
|
}
|
|
});
|
|
};
|
|
|
|
window.spoilers = exports;
|