1// Config 2const isOpenClass = "modal-is-open"; 3const openingClass = "modal-is-opening"; 4const closingClass = "modal-is-closing"; 5const animationDuration = 500; // ms 6let visibleModal = null; 7 8// Toggle modal 9const toggleModal = (event) => { 10 event.preventDefault(); 11 const modal = document.getElementById( 12 event.currentTarget.getAttribute("data-target"), 13 ); 14 typeof modal != "undefined" && modal != null && isModalOpen(modal) 15 ? closeModal(modal, true) 16 : openModal(modal, true); 17}; 18 19// Switch modal 20const switchModal = (event) => { 21 event.preventDefault(); 22 const modal = document.getElementById( 23 event.currentTarget.getAttribute("data-target"), 24 ); 25 const currentModal = document.getElementById( 26 event.currentTarget.getAttribute("data-current"), 27 ); 28 closeModal(currentModal, false); 29 openModal(modal, false); 30}; 31 32// Is modal open 33const isModalOpen = (modal) => { 34 return modal.hasAttribute("open") && modal.getAttribute("open") != "false" 35 ? true 36 : false; 37}; 38 39// Open modal 40const openModal = (modal, shouldAnimate) => { 41 if (isScrollbarVisible()) { 42 document.documentElement.style.setProperty( 43 "--scrollbar-width", 44 `${getScrollbarWidth()}px`, 45 ); 46 } 47 document.documentElement.classList.add(isOpenClass, openingClass); 48 setTimeout(() => { 49 visibleModal = modal; 50 document.documentElement.classList.remove(openingClass); 51 }, shouldAnimate ? animationDuration : 0); 52 modal.setAttribute("open", true); 53 addInputListeners(modal); 54}; 55 56const clearErrorStates = (modal) => { 57 const errorStates = modal.querySelectorAll(".error"); 58 errorStates.forEach((errorState) => { 59 errorState.classList.remove("error"); 60 }); 61}; 62 63const clearErrorMessages = (modal) => { 64 // error messages are displayed in a p tag that is inside a div with class input-error-container 65 const errorMessages = modal.querySelectorAll(".input-error-container span"); 66 errorMessages.forEach((errorMessage) => { 67 errorMessage.remove(); 68 }); 69}; 70 71const clearModalInputs = (modal) => { 72 clearErrorStates(modal); 73 clearErrorMessages(modal); 74 const inputs = modal.querySelectorAll("input"); 75 inputs.forEach((input) => { 76 if (input.type !== "hidden") { 77 if (input.type === "checkbox") { 78 input.checked = false; 79 } else { 80 input.value = ""; 81 } 82 } 83 }); 84}; 85 86// find all inputs in the modal and add an event-listener to each 87const addInputListeners = (modal) => { 88 const inputs = modal.querySelectorAll("input"); 89 inputs.forEach((input) => { 90 input.addEventListener("input", (e) => { 91 if (e.target.classList.contains("error")) { 92 removeErrorState(e.target); 93 } 94 }); 95 }); 96}; 97 98const removeErrorState = (input) => { 99 input.classList.remove("error"); 100}; 101 102const makePWInvisible = (modal) => { 103 const visibilityDivs = document.querySelectorAll(".toggle-visibility"); 104 const invisibilityDivs = document.querySelectorAll(".toggle-invisibility"); 105 106 invisibilityDivs.forEach(function(div) { 107 const targetId = div.getAttribute("data-target"); 108 const targetInput = document.getElementById(targetId); 109 const visibilityDiv = document.querySelector( 110 `.toggle-visibility[data-target="${targetId}"]`, 111 ); 112 113 targetInput.type = "password"; 114 div.style.display = "none"; 115 visibilityDiv.style.display = "block"; 116 }); 117}; 118 119// Close modal 120const closeModal = (modal, shouldAnimate) => { 121 visibleModal = null; 122 document.documentElement.classList.add(closingClass); 123 setTimeout(() => { 124 document.documentElement.classList.remove(closingClass, isOpenClass); 125 document.documentElement.style.removeProperty("--scrollbar-width"); 126 modal.removeAttribute("open"); 127 clearModalInputs(modal); 128 makePWInvisible(modal); 129 modal.querySelector("form").reset(); 130 }, shouldAnimate ? animationDuration : 0); 131}; 132 133// Close with a click outside 134document.addEventListener("click", (event) => { 135 if (visibleModal != null) { 136 const modalContent = visibleModal.querySelector("article"); 137 const isClickInside = modalContent.contains(event.target); 138 !isClickInside && closeModal(visibleModal, true); 139 } 140}); 141 142// Close with Esc key 143document.addEventListener("keydown", (event) => { 144 if (event.key === "Escape" && visibleModal != null) { 145 closeModal(visibleModal, true); 146 } 147}); 148 149// Get scrollbar width 150const getScrollbarWidth = () => { 151 // Creating invisible container 152 const outer = document.createElement("div"); 153 outer.style.visibility = "hidden"; 154 outer.style.overflow = "scroll"; // forcing scrollbar to appear 155 outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps 156 document.body.appendChild(outer); 157 158 // Creating inner element and placing it in the container 159 const inner = document.createElement("div"); 160 outer.appendChild(inner); 161 162 // Calculating difference between container's full width and the child width 163 const scrollbarWidth = outer.offsetWidth - inner.offsetWidth; 164 165 // Removing temporary elements from the DOM 166 outer.parentNode.removeChild(outer); 167 168 return scrollbarWidth; 169}; 170 171// Is scrollbar visible 172const isScrollbarVisible = () => { 173 return document.body.scrollHeight > screen.height; 174}; 175 176// close all open modals 177const closeAllModals = () => { 178 const modals = document.querySelectorAll("dialog[open]");
179 modals.forEach((modal) => { 180 closeModal(modal); 181 }); 182}; 183 184// close all open modals and open the modal with the given id 185const openModalById = (id) => { 186 closeAllModals(); 187 const modal = document.getElementById(id); 188 openModal(modal); 189}; 190 191// Handle keybindings 192function scrollDown() { 193 window.scrollBy(0, 100); // Adjust the scrolling amount as needed 194} 195 196function scrollUp() { 197 // Move the page content up 198 window.scrollBy(0, -100); // Adjust the scrolling amount as needed 199} 200 201function toggleTheme() { 202 // Toggle between light and dark theme 203 const theme = document.documentElement.getAttribute("data-theme"); 204 if (theme === "light") { 205 document.documentElement.setAttribute("data-theme", "dark"); 206 } else { 207 document.documentElement.setAttribute("data-theme", "light"); 208 } 209}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.