fkosmala /
superhive
| 1 | /* |
||
| 2 | * Modal |
||
| 3 | * |
||
| 4 | * Pico.css - https://picocss.com |
||
| 5 | * Copyright 2019-2022 - Licensed under MIT |
||
| 6 | */ |
||
| 7 | |||
| 8 | /** global: screen */ |
||
| 9 | |||
| 10 | // Config |
||
| 11 | const isOpenClass = 'modal-is-open'; |
||
| 12 | const openingClass = 'modal-is-opening'; |
||
| 13 | const closingClass = 'modal-is-closing'; |
||
| 14 | const animationDuration = 400; // ms |
||
| 15 | let visibleModal = null; |
||
| 16 | |||
| 17 | |||
| 18 | // Toggle modal |
||
| 19 | const toggleModal = event => { |
||
|
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
|
|||
| 20 | event.preventDefault(); |
||
| 21 | const modal = document.getElementById(event.currentTarget.getAttribute('data-target')); |
||
| 22 | (typeof(modal) !== 'undefined' && modal !== null) |
||
| 23 | && isModalOpen(modal) ? closeModal(modal) : openModal(modal) |
||
| 24 | } |
||
| 25 | |||
| 26 | // Is modal open |
||
| 27 | const isModalOpen = modal => { |
||
|
0 ignored issues
–
show
|
|||
| 28 | return modal.hasAttribute('open') && modal.getAttribute('open') != 'false' ? true : false; |
||
| 29 | } |
||
| 30 | |||
| 31 | // Open modal |
||
| 32 | const openModal = modal => { |
||
|
0 ignored issues
–
show
|
|||
| 33 | if (isScrollbarVisible()) { |
||
| 34 | document.documentElement.style.setProperty('--scrollbar-width', `${getScrollbarWidth()}px`); |
||
| 35 | } |
||
| 36 | document.documentElement.classList.add(isOpenClass, openingClass); |
||
| 37 | setTimeout(() => { |
||
| 38 | visibleModal = modal; |
||
| 39 | document.documentElement.classList.remove(openingClass); |
||
| 40 | }, animationDuration); |
||
| 41 | modal.setAttribute('open', true); |
||
| 42 | } |
||
| 43 | |||
| 44 | // Close modal |
||
| 45 | const closeModal = modal => { |
||
| 46 | visibleModal = null; |
||
| 47 | document.documentElement.classList.add(closingClass); |
||
| 48 | setTimeout(() => { |
||
| 49 | document.documentElement.classList.remove(closingClass, isOpenClass); |
||
| 50 | document.documentElement.style.removeProperty('--scrollbar-width'); |
||
| 51 | modal.removeAttribute('open'); |
||
| 52 | }, animationDuration); |
||
| 53 | } |
||
| 54 | |||
| 55 | // Close with a click outside |
||
| 56 | document.addEventListener('click', event => { |
||
| 57 | if (visibleModal !== null) { |
||
| 58 | const modalContent = visibleModal.querySelector('article'); |
||
| 59 | const isClickInside = modalContent.contains(event.target); |
||
| 60 | !isClickInside && closeModal(visibleModal); |
||
| 61 | } |
||
| 62 | }); |
||
| 63 | |||
| 64 | // Close with Esc key |
||
| 65 | document.addEventListener('keydown', event => { |
||
| 66 | if (event.key === 'Escape' && visibleModal !== null) { |
||
| 67 | closeModal(visibleModal); |
||
| 68 | } |
||
| 69 | }); |
||
| 70 | |||
| 71 | // Get scrollbar width |
||
| 72 | const getScrollbarWidth = () => { |
||
|
0 ignored issues
–
show
|
|||
| 73 | |||
| 74 | // Creating invisible container |
||
| 75 | const outer = document.createElement('div'); |
||
| 76 | outer.style.visibility = 'hidden'; |
||
| 77 | outer.style.overflow = 'scroll'; // forcing scrollbar to appear |
||
| 78 | outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps |
||
| 79 | document.body.appendChild(outer); |
||
| 80 | |||
| 81 | // Creating inner element and placing it in the container |
||
| 82 | const inner = document.createElement('div'); |
||
| 83 | outer.appendChild(inner); |
||
| 84 | |||
| 85 | // Calculating difference between container's full width and the child width |
||
| 86 | const scrollbarWidth = (outer.offsetWidth - inner.offsetWidth); |
||
| 87 | |||
| 88 | // Removing temporary elements from the DOM |
||
| 89 | outer.parentNode.removeChild(outer); |
||
| 90 | |||
| 91 | return scrollbarWidth; |
||
| 92 | } |
||
| 93 | |||
| 94 | // Is scrollbar visible |
||
| 95 | const isScrollbarVisible = () => { |
||
|
0 ignored issues
–
show
|
|||
| 96 | return document.body.scrollHeight > screen.height; |
||
| 97 | } |
||
| 98 |