modals - 03

revision:


modals positioning indepedently on the screen, when opened.

Click this trigger. . to open a modal.

Close a modal by clicking: 1/ off to the side, 2/ clicking the X, or 3/ pressing Escape.

code:
            <div class="spec">
                <p><a href="#" class="modal-trigger" data-modal-id="modal1">Click this trigger
                </a>. . to open a modal.</p>
                <p>Close a modal by clicking: 1/ off to the side, 2/ clicking the X, or 
                3/ pressing Escape.</p>
                <div class="modal-wrapper">
                    <section class="modal-window" id="modal1">
                    <header class="modal-header">
                        <h3>The first modal</h3>
                        <button
                        type="button" class="close-modal-button" aria-label="Close modal window">
                        X</button>
                    </header>
                    <p>You have opened the first modal!</p>
                    <p>Now, open the second modal by clicking the link.</p>
                    <a href="#" class="modal-trigger" data-modal-id="modal2">Second modal</a> !
                    </p>
                    </section>
                    <section class="modal-window" id="modal2">
                    <header class="modal-header">
                        <h3>The second modal 🤯</h3>
                        <button type="button" class="close-modal-button" aria-label="Close modal 
                        window">X</button>
                    </header>
                    <p>Nice.This is the second modal.</p>
                    </section>
                </div>
            </div>
            <style>
                .modal-wrapper {align-items: center; bottom: 0; display: flex; flex-wrap: wrap; height: 
                    100vh; justify-content: center; left: 0; opacity: 0; position: fixed; right: 0; 
                    transition: all 0.2s ease-in-out; visibility: hidden;  width: 40%; z-index: 1000;}
                .modal-wrapper.visible {opacity: 1;visibility: visible;}
                .modal-window {background-image:linear-gradient(red, yellow, black); border-radius: 1vw;
                     box-shadow: 0 .3vw .7vw rgba(0, 0, 0, 0.3); padding: 2vw; transform: scale(0); 
                     transition: 0.2s ease-in-out all; position: absolute; margin: 1vw;}
                .modal-window.visible {transform: scale(1); position: relative;}
                .modal-header {align-items: center;border-bottom: .2vw solid blue; display: flex;
                    justify-content: space-between; margin-bottom: 2vw; padding-bottom: 2vw;}
                .close-modal-button { border: none; background-color: transparent; color: darkgreen;
                     cursor: pointer; font-size: 2vw; padding: 0.2vw;}
                .close-modal-button:hover {color: black;}
                .modal-trigger {color:blue; cursor: pointer; text-decoration: underline;}
            </style>
            <script>
                let currentlyOpenModals = {};
                const noModalsOpen = () => !Object.keys(currentlyOpenModals).length;
                const modalWrapper = document.querySelector(".modal-wrapper");
    
                const openModal = modalId => {
                // If we're opening the first modal, make sure the wrapper becomes visible too
                if (noModalsOpen()) {
                    modalWrapper.classList.add("visible");
                }
    
                const modal = document.getElementById(modalId);
                modal.classList.add("visible");
                currentlyOpenModals[modalId] = modal;
                };
    
                const closeModal = modalId => {
                if (noModalsOpen()) {
                    return;
                }
    
                const modal = currentlyOpenModals[modalId];
                modal.classList.remove("visible");
                delete currentlyOpenModals[modalId];
    
                // If we closed the last open modal, hide the wrapper
                    if (noModalsOpen()) {
                        modalWrapper.classList.remove("visible");
                    }
                    };
        
                    const closeAllModals = () => {
                    // Iterate over the IDs in our map and close each modal with that ID
                    Object.keys(currentlyOpenModals).forEach(closeModal);
                    };
        
                    const modalTriggers = document.querySelectorAll(".modal-trigger");
                    modalTriggers.forEach(modalTrigger => {
                    modalTrigger.addEventListener("click", clickEvent => {
                        const trigger = clickEvent.target;
                        const modalId = trigger.getAttribute("data-modal-id");
                        openModal(modalId);
                    });
                    });
        
                    document.querySelectorAll(".modal-window").forEach(modal => {
                    modal.addEventListener("click", clickEvent => {
                        clickEvent.stopPropagation();
                    });
                    });
        
                    modalWrapper.addEventListener("click", () => {
                    closeAllModals();
                    });
        
                    document.querySelectorAll(".close-modal-button").forEach(closeModalButton => {
                    closeModalButton.addEventListener("click", clickEvent => {
                        const modalToClose = clickEvent.target.closest(".modal-window");
                        closeModal(modalToClose.id);
                    });
                    });
        
                    document.body.addEventListener("keyup", keyEvent => {
                    if (keyEvent.key === "Escape") {
                        closeAllModals();
                    }
                    });
                </script>