mirror of
https://github.com/picocss/pico.git
synced 2025-02-24 00:39:20 -05:00
95 lines
2.7 KiB
JavaScript
95 lines
2.7 KiB
JavaScript
/*
|
|
* Modal
|
|
*
|
|
* Pico.css - https://picocss.com
|
|
* Copyright 2019-2021 - 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.target.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;
|
|
} |