mirror of https://github.com/zulip/zulip.git
portico: Add portico_modals.ts module.
This commit adds portico_modals.ts module which contains functions for supporting modals in portico pages. The new module basically contains code from functions in overlays.ts without the code that is not needed currently for modals in portico pages.
This commit is contained in:
parent
ac8436d46c
commit
866b6cd632
|
@ -1,5 +1,6 @@
|
|||
import "./common";
|
||||
import "../portico/header";
|
||||
import "../portico/google-analytics";
|
||||
import "../portico/portico_modals";
|
||||
import "../../styles/portico/portico_styles.css";
|
||||
import "tippy.js/dist/tippy.css";
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
import $ from "jquery";
|
||||
import Micromodal from "micromodal";
|
||||
|
||||
import * as blueslip from "../blueslip";
|
||||
|
||||
function is_modal_open(): boolean {
|
||||
return $(".micromodal").hasClass("modal--open");
|
||||
}
|
||||
|
||||
function active_modal(): string | undefined {
|
||||
if (!is_modal_open()) {
|
||||
blueslip.error("Programming error — Called active_modal when there is no modal open");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const $micromodal = $(".micromodal.modal--open");
|
||||
return `#${CSS.escape($micromodal.attr("id")!)}`;
|
||||
}
|
||||
|
||||
function close_active_modal(): void {
|
||||
if (!is_modal_open()) {
|
||||
blueslip.warn("close_active_modal() called without checking is_modal_open()");
|
||||
return;
|
||||
}
|
||||
|
||||
const $micromodal = $(".micromodal.modal--open");
|
||||
Micromodal.close(`${CSS.escape($micromodal.attr("id") ?? "")}`);
|
||||
}
|
||||
|
||||
export function open_modal(modal_id: string, recursive_call_count: number = 0): void {
|
||||
if (modal_id === undefined) {
|
||||
blueslip.error("Undefined id was passed into open_modal");
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't accept hash-based selector to enforce modals to have unique ids and
|
||||
// since micromodal doesn't accept hash based selectors.
|
||||
if (modal_id.startsWith("#")) {
|
||||
blueslip.error("hash-based selector passed in to open_modal", {modal_id});
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_modal_open()) {
|
||||
/*
|
||||
Our modal system doesn't directly support opening a modal
|
||||
when one is already open, because the `is_modal_open` CSS
|
||||
class doesn't update until Micromodal has finished its
|
||||
animations, which can take 100ms or more.
|
||||
|
||||
We can likely fix that, but in the meantime, we should
|
||||
handle this situation correctly, by closing the current
|
||||
modal, waiting for it to finish closing, and then attempting
|
||||
to open the current modal again.
|
||||
*/
|
||||
if (recursive_call_count) {
|
||||
recursive_call_count = 1;
|
||||
} else {
|
||||
recursive_call_count += 1;
|
||||
}
|
||||
if (recursive_call_count > 50) {
|
||||
blueslip.error("Modal incorrectly is still open", {modal_id});
|
||||
return;
|
||||
}
|
||||
|
||||
close_active_modal();
|
||||
setTimeout(() => {
|
||||
open_modal(modal_id, recursive_call_count);
|
||||
}, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
blueslip.debug("open modal: " + modal_id);
|
||||
|
||||
// Micromodal gets elements using the getElementById DOM function
|
||||
// which doesn't require the hash. We add it manually here.
|
||||
const id_selector = `#${CSS.escape(modal_id)}`;
|
||||
const $micromodal = $(id_selector);
|
||||
|
||||
$micromodal.find(".modal__container").on("animationend", (event) => {
|
||||
const animation_name = (event.originalEvent as AnimationEvent).animationName;
|
||||
if (animation_name === "mmfadeIn") {
|
||||
// Micromodal adds the is-open class before the modal animation
|
||||
// is complete, which isn't really helpful since a modal is open after the
|
||||
// animation is complete. So, we manually add a class after the
|
||||
// animation is complete.
|
||||
$micromodal.addClass("modal--open");
|
||||
$micromodal.removeClass("modal--opening");
|
||||
} else if (animation_name === "mmfadeOut") {
|
||||
$micromodal.removeClass("modal--open");
|
||||
}
|
||||
});
|
||||
|
||||
$micromodal.find(".modal__overlay").on("click", (e) => {
|
||||
/* Micromodal's data-micromodal-close feature doesn't check for
|
||||
range selections; this means dragging a selection of text in an
|
||||
input inside the modal too far will weirdly close the modal.
|
||||
See https://github.com/ghosh/Micromodal/issues/505.
|
||||
Work around this with our own implementation. */
|
||||
if (!$(e.target).is(".modal__overlay")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (document.getSelection()?.type === "Range") {
|
||||
return;
|
||||
}
|
||||
close_modal(modal_id);
|
||||
});
|
||||
|
||||
Micromodal.show(modal_id, {
|
||||
disableFocus: true,
|
||||
openClass: "modal--opening",
|
||||
});
|
||||
}
|
||||
|
||||
export function close_modal(modal_id: string): void {
|
||||
if (modal_id === undefined) {
|
||||
blueslip.error("Undefined id was passed into close_modal");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_modal_open()) {
|
||||
blueslip.warn("close_active_modal() called without checking is_modal_open()");
|
||||
return;
|
||||
}
|
||||
|
||||
if (active_modal() !== `#${CSS.escape(modal_id)}`) {
|
||||
blueslip.error("Trying to close modal when other is open", {modal_id, active_modal});
|
||||
return;
|
||||
}
|
||||
|
||||
blueslip.debug("close modal: " + modal_id);
|
||||
|
||||
Micromodal.close(modal_id);
|
||||
}
|
Loading…
Reference in New Issue