picocss/docs/js/modal.js

102 lines
2.7 KiB
JavaScript
Raw Normal View History

2021-11-08 00:10:16 +07:00
/*
* Modal
*
* Pico.css - https://picocss.com
2023-01-28 13:14:38 +07:00
* Copyright 2019-2023 - Licensed under MIT
2021-11-08 00:10:16 +07:00
*/
// Config
2024-01-27 13:53:19 +07:00
const isOpenClass = "modal-is-open"
const openingClass = "modal-is-opening"
const closingClass = "modal-is-closing"
const animationDuration = 400 // ms
let visibleModal = null
2021-11-08 00:10:16 +07:00
// Toggle modal
const toggleModal = event => {
2024-01-27 13:53:19 +07:00
event.preventDefault()
const modal = document.getElementById(
event.currentTarget.getAttribute("data-target")
)
typeof modal != "undefined" && modal != null && isModalOpen(modal)
? closeModal(modal)
: openModal(modal)
2021-11-08 00:10:16 +07:00
}
// Is modal open
const isModalOpen = modal => {
2024-01-27 13:53:19 +07:00
return modal.hasAttribute("open") && modal.getAttribute("open") != "false"
? true
: false
2021-11-08 00:10:16 +07:00
}
// Open modal
const openModal = modal => {
if (isScrollbarVisible()) {
2024-01-27 13:53:19 +07:00
document.documentElement.style.setProperty(
"--scrollbar-width",
`${getScrollbarWidth()}px`
)
}
2024-01-27 13:53:19 +07:00
document.documentElement.classList.add(isOpenClass, openingClass)
2021-11-08 00:10:16 +07:00
setTimeout(() => {
2024-01-27 13:53:19 +07:00
visibleModal = modal
document.documentElement.classList.remove(openingClass)
}, animationDuration)
modal.setAttribute("open", true)
2021-11-08 00:10:16 +07:00
}
// Close modal
const closeModal = modal => {
2024-01-27 13:53:19 +07:00
visibleModal = null
document.documentElement.classList.add(closingClass)
2021-11-08 00:10:16 +07:00
setTimeout(() => {
2024-01-27 13:53:19 +07:00
document.documentElement.classList.remove(closingClass, isOpenClass)
document.documentElement.style.removeProperty("--scrollbar-width")
modal.removeAttribute("open")
}, animationDuration)
2021-11-08 00:10:16 +07:00
}
// Close with a click outside
2024-01-27 13:53:19 +07:00
document.addEventListener("click", event => {
2021-11-08 00:10:16 +07:00
if (visibleModal != null) {
2024-01-27 13:53:19 +07:00
const modalContent = visibleModal.querySelector("article")
const isClickInside = modalContent.contains(event.target)
!isClickInside && closeModal(visibleModal)
2021-11-08 00:10:16 +07:00
}
2024-01-27 13:53:19 +07:00
})
2021-11-08 00:10:16 +07:00
// Close with Esc key
2024-01-27 13:53:19 +07:00
document.addEventListener("keydown", event => {
if (event.key === "Escape" && visibleModal != null) {
closeModal(visibleModal)
2021-11-08 00:10:16 +07:00
}
2024-01-27 13:53:19 +07:00
})
// Get scrollbar width
const getScrollbarWidth = () => {
// Creating invisible container
2024-01-27 13:53:19 +07:00
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
2024-01-27 13:53:19 +07:00
const inner = document.createElement("div")
outer.appendChild(inner)
// Calculating difference between container's full width and the child width
2024-01-27 13:53:19 +07:00
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth
// Removing temporary elements from the DOM
2024-01-27 13:53:19 +07:00
outer.parentNode.removeChild(outer)
2024-01-27 13:53:19 +07:00
return scrollbarWidth
}
// Is scrollbar visible
const isScrollbarVisible = () => {
2024-01-27 13:53:19 +07:00
return document.body.scrollHeight > screen.height
}