-
Notifications
You must be signed in to change notification settings - Fork 0
/
modal.js
101 lines (88 loc) · 2.78 KB
/
modal.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
/*
* Modal
*
* Pico.css - https://picocss.com
* Copyright 2019-2022 - Licensed under MIT
*/
// Config
const isOpenClass = "modal-is-open";
const openingClass = "modal-is-opening";
const closingClass = "modal-is-closing";
const animationDuration = 400; // ms
let visibleModal = null;
// Toggle modal
const toggleModal = (event) => {
event.preventDefault();
const modal = document.getElementById(
event.currentTarget.getAttribute("data-target")
);
typeof modal != "undefined" && modal != null && isModalOpen(modal)
? closeModal(modal)
: openModal(modal);
};
// Is modal open
const isModalOpen = (modal) => {
return modal.hasAttribute("open") && modal.getAttribute("open") != "false"
? true
: false;
};
// Open modal
const openModal = (modal) => {
if (isScrollbarVisible()) {
document.documentElement.style.setProperty(
"--scrollbar-width",
`${getScrollbarWidth()}px`
);
}
document.documentElement.classList.add(isOpenClass, openingClass);
setTimeout(() => {
visibleModal = modal;
document.documentElement.classList.remove(openingClass);
}, animationDuration);
modal.setAttribute("open", true);
};
// Close modal
const closeModal = (modal) => {
visibleModal = null;
document.documentElement.classList.add(closingClass);
setTimeout(() => {
document.documentElement.classList.remove(closingClass, isOpenClass);
document.documentElement.style.removeProperty("--scrollbar-width");
modal.removeAttribute("open");
}, animationDuration);
};
// Close with a click outside
document.addEventListener("click", (event) => {
if (visibleModal != null) {
const modalContent = visibleModal.querySelector("article");
const isClickInside = modalContent.contains(event.target);
!isClickInside && closeModal(visibleModal);
}
});
// Close with Esc key
document.addEventListener("keydown", (event) => {
if (event.key === "Escape" && visibleModal != null) {
closeModal(visibleModal);
}
});
// Get scrollbar width
const getScrollbarWidth = () => {
// Creating invisible container
const outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.overflow = "scroll"; // forcing scrollbar to appear
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
// Creating inner element and placing it in the container
const inner = document.createElement("div");
outer.appendChild(inner);
// Calculating difference between container's full width and the child width
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
// Removing temporary elements from the DOM
outer.parentNode.removeChild(outer);
return scrollbarWidth;
};
// Is scrollbar visible
const isScrollbarVisible = () => {
return document.body.scrollHeight > screen.height;
};