Search code examples
javascripthtml

How to stop a draggable div when it reaches the end of the viewport?


I have a draggable div, which is a popup window, when a button gets clicked.

When I drag the div to the end of the viewport, I can drag it also out of it. So the body of the page keeps getting bigger. I want to have something like a barrier, which stops the div, when it hits it.

First of all, this is my code:

(not plain html --> jsp)

<html>
    <head>
        <link rel="stylesheet" href="/www/css/styles.css">
        <link id="favicon" rel="icon" type="image/x-icon" href="/www/images/favicon-dark-mode.png">
        <title>${title}</title>
    </head>
    <body class="${cssClass}">
        <header class="main-site-header">
            <g:navigation activeItem="${activeItem}"/>
            <div class="header-title">${title}</div>
            <ul class="navigation-buttons ul-scaling">
                <li><a href="mailto:[email protected]">Contact Us</a></li>
                <li><a target="_blank" href="https://javawebapp.onrender.com/">Other Projects</a>
                </li>
                <li><a target="_blank" href="https://www.getabstract.com/en/">Click Me</a></li>
            </ul>
        </header>
        <main>
            <div class="popup-flex">
                <div class="hidden-add-author-popup">
                    <div class="draggable"></div>
                    <h1 style="z-index: -1;">Add Author</h1>
                    <form>
                        <input type="text" class="label-text" placeholder="Firstname">
                    </form>
                    <form>
                        <input type="text" class="label-text" placeholder="Surname">
                    </form>
                    <form>
                        <input type="text" class="label-text" placeholder="Gender">
                    </form>
                    <button class="submit-button" id="cancel-button">Cancel</button>
                    <input type="submit" class="submit-button" id="submit-popup">
                </div>
            </div>
            <jsp:doBody/>
        </main>
        <script src="/www/js/scripts.js" type="text/javascript"></script>
    </body>
</html>
.draggable {
    position: absolute;
    width: 15rem;
    height: 5rem;
    cursor: move;
    z-index: 10;
}

.popup-flex {
    display: flex;
    justify-content: center;
    align-items: center;
}

.hidden-add-author-popup {
    position: absolute;
    background-color: var(--current-popup-color);
    color: var(--current-header-color);
    z-index: 9;
    margin-top: 45rem;
    display: none;
    border: solid var(--current-header-color);
    border-radius: 1rem;
    padding: 1rem;
    box-shadow: 0 0 10px 0 var(--current-text-color);
}
//--------------------------------------------------------------------
//                    POPUP AUTHOR FIELD LOGIC
//--------------------------------------------------------------------

submitButtonPopup.addEventListener('click', () => {
    addAuthorPopup.style.display = 'none';
})

addAuthorButton.addEventListener('click', () => {
    addAuthorPopup.style.display = 'block';
});

//--------------------------------------------------------------------
//                  CANCEL BUTTON ONCLICK EVENTS
//--------------------------------------------------------------------
cancelButton.addEventListener('click', () =>{
    authorFirstnameInnerText.value = '';
    authorSurnameInnerText.value = '';
    authorGenderInnerText.value = '';
    addAuthorPopup.style.display = 'none';
});

//--------------------------------------------------------------------
//                  MAKE AUTHOR POPUP DRAGGABLE
//--------------------------------------------------------------------
// Make the DIV element draggable:
dragElement(document.querySelector(".hidden-add-author-popup"));

function dragElement(elmnt) {
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    if (document.querySelector(".draggable")) {
        // if present, the header is where you move the DIV from:
        document.querySelector(".draggable").onmousedown = dragMouseDown;
    } else {
        // otherwise, move the DIV from anywhere inside the DIV:
        elmnt.onmousedown = dragMouseDown;
    }

    function dragMouseDown(e) {
        e.preventDefault();
        // get the mouse cursor position at startup:
        document.onmouseup = closeDragElement;
        // call a function whenever the cursor moves:
        document.onmousemove = elementDrag;
    }

    function elementDrag(e) {
        e.preventDefault();
        // calculate the new cursor position:
        // set the element's new position:
        if (e.clientY === 1003 || e.clientY > 1003) {
            moveDown = false;
        }
        if(moveDown) {
            elmnt.style.top = e.clientY - 743 + "px";
        }
        elmnt.style.left = e.clientX - 139 + "px";
        console.log('x: ' + e.clientX);
        console.log('Y: ' + e.clientY);
    }

    function closeDragElement() {
        // stop moving when mouse button is released:
        document.onmouseup = null;
        document.onmousemove = null;
    }
}

I've tried to track the position of the cursor, and when it reaches 1003 or below, the draggable object should stop. That's not a good way to solve this problem, because there are different screen sizes. So 1003 would be inappropriate with other screens.

Thank you for responding!


Solution

  • Answer to my own question:

    I can get the available screen size with the properties

    window.innerWidth and window.innerHeight.

    In combination with getBoundingClientRect, I can get the distance from the div to the end of the viewport. When the div touches for example the left edge of the viewport, the 'left' property is going to be added by 0.1px. It looks a little weird, but I'm fine with that for now.

    Here is the code:

    //--------------------------------------------------------------------
    //                  MAKE AUTHOR POPUP DRAGGABLE
    //--------------------------------------------------------------------
    // Make the DIV element draggable:
    dragElement(document.querySelector(".hidden-add-author-popup"));
    
    function dragElement(elmnt) {
        var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        if (document.querySelector(".draggable")) {
            // if present, the header is where you move the DIV from:
            document.querySelector(".draggable").onmousedown = dragMouseDown;
        } else {
            // otherwise, move the DIV from anywhere inside the DIV:
            elmnt.onmousedown = dragMouseDown;
        }
    
        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            // get the mouse cursor position at startup:
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            // call a function whenever the cursor moves:
            document.onmousemove = elementDrag;
        }
    
        function elementDrag(e) {
            const popupBoundingClientRect = elmnt.getBoundingClientRect();
            const popupLeft = popupBoundingClientRect.left;
            const popupRight = popupBoundingClientRect.right;
            const popupTop = popupBoundingClientRect.top;
            const popupBottom = popupBoundingClientRect.bottom;
            const popupWidth = popupBoundingClientRect.width;
            const popupHeight = popupBoundingClientRect.height;
            if(popupLeft <= 0) {
                elmnt.style.left = "0.1px";
            }
            else if(window.innerWidth <= popupRight) {
                elmnt.style.left = `${window.innerWidth - popupWidth - 0.1}px`;
            }
            else {
                //IF POPUP WINDOW IS WITHIN DEFAULT VIEWPORT [ONLY X-AXIS]
                e = e || window.event;
                e.preventDefault();
                // calculate the new cursor position:
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;
                // set the element's new position:
                elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
                elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
            }
            if(popupTop <= 0) {
                elmnt.style.top = "0.1px";
            }
            else if(window.innerHeight <= popupBottom) {
                elmnt.style.top = `${window.innerHeight - popupHeight - 0.1}px`;
            }
            else {
                //IF POPUP WINDOW IS WITHIN DEFAULT VIEWPORT [ONLY X-AXIS]
                e = e || window.event;
                e.preventDefault();
                // calculate the new cursor position:
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;
                // set the element's new position:
                elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
                elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
            }
        }
    
        function closeDragElement() {
            // stop moving when mouse button is released:
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    I hope this helps, comment if not.