Stop draggable element from exiting the boundaries of its container during drag operation

I have a draggable element with id mydiv that is contained within another element with id container. I want to restrict the movement of mydiv so that it stays inside the container without leaving its boundaries. How can I achieve this?

Below is the code snippet:

//Make the DIV element draggagle:
dragElement(document.getElementById("mydiv"));

function dragElement(elmnt) {
  var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  if (document.getElementById(elmnt.id + "header")) {
    /* if present, the header is where you move the DIV from:*/
    document.getElementById(elmnt.id + "header").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) {
    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:
    var container = document.getElementById('container');
    var containerRect = container.getBoundingClientRect();
    var elementRect = elmnt.getBoundingClientRect();

    if ((elementRect.left - pos1) >= containerRect.left &&
        (elementRect.right - pos1) <= containerRect.right &&
        (elementRect.top - pos2) >= containerRect.top &&
        (elementRect.bottom - pos2) <= containerRect.bottom) {
      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;
  }
}
#container {
    border: 1px solid red;
    height: 300px;
    width: 400px;
}

#mydiv {
  position: absolute;
  z-index: 9;
  background-color: #f1f1f1;
  text-align: center;
  border: 1px solid #d3d3d3;
}

#mydivheader {
  padding: 10px;
  cursor: move;
  z-index: 10;
  background-color: #2196F3;
  color: #fff;
}
<h1>Draggable Element</h1>

<p>Click and hold the mouse button down while moving the element</p>

<div id="container">
  <div id="mydiv">
    <div id="mydivheader">Click here to move</div>
    <p>Move</p>
    <p>this</p>
    <p>element</p>
  </div>
</div>

To keep the element inside the container, modifications need to be made in the elementDrag(e) function. You can use conditional statements to ensure the element does not go beyond the container boundaries. It's important to maintain the existing code structure and use only pure JavaScript for the solution.

Answer №1

Let me share my solution with you.

I located #container in the DOM and stored it as a variable,

I assigned position: relative to the container to ensure the box is positioned relative to it

I replaced all onevents with native addEventListeners on the elements and removed unnecessary variables like (pos1, pos2, pose3, pos4) since they were no longer needed

The mouseup event is attached to the document while the mousemove is attached to the container to keep the box within its boundaries.

The calculations (e.clientY - containerY) and (e.clientX - containerX) determine the exact position of the mouse relative to the container. The values for containerX and containerY are obtained using getBoundingClientRect() on the container element

const container = document.getElementById('container');
dragElement(document.getElementById("mydiv"));

function dragElement(elmnt) {
  const {
    x: containerX,
    y: containerY
  } = container.getBoundingClientRect();

  if (document.getElementById(elmnt.id + "header")) document.getElementById(elmnt.id + "header").addEventListener('mousedown', dragMouseDown);
  else elmnt.addEventListener('mousedown', dragMouseDown);

  function dragMouseDown(e) {
    e = e || window.event;
    e.preventDefault();
    document.addEventListener('mouseup', closeDragElement);
    container.addEventListener('mousemove', elementDrag);
  }

  function elementDrag(e) {
    e = e || window.event;
    e.preventDefault();

    elmnt.style.top = (e.clientY - containerY) + "px";
    elmnt.style.left = (e.clientX - containerX) + "px";
  }

  function closeDragElement() {
    document.removeEventListener('mouseup', closeDragElement);
    container.removeEventListener('mousemove', elementDrag);
  }
}
#container {
  position: relative; /* This is very important */
  border: 1px solid red;
  height: 300px;
  width: 400px;
  overflow: hidden;
}

#mydiv {
  width: 144px; /* This is very important */
  position: absolute;
  z-index: 9;
  background-color: #f1f1f1;
  text-align: center;
  border: 1px solid #d3d3d3;
}

#mydivheader {
  padding: 10px;
  cursor: move;
  z-index: 10;
  background-color: #2196F3;
  color: #fff;
}
<h1>Draggable DIV Element</h1>

<p>Click and hold the mouse button down while moving the DIV element</p>

<div id="container">
  <div id="mydiv">
    <div id="mydivheader">Click here to move</div>
    <p>Move</p>
    <p>this</p>
    <p>DIV</p>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Choose not to alter the display value during keyup and keydown events, while still triggering the change event

$(function(){ $(".cls_user_details select").keyup(function(){ $(".cls_user_details select").val("Profile"); }) }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="cls_user_setti ...

Phonegap Application: Page design gets distorted following keyboard input

After a user enters login details and the next page loads, the layout shifts as shown in the image below. The entire app layout breaks and the view moves down to accommodate the size of the onscreen keyboard. This issue persists unless the orientation is ...

What steps can you take to convert your current menu into a responsive design?

I am currently developing a website using PHP, HTML, and CSS. The site is not responsive, and I want to make the menu responsive. My global navigation and admin interface are not adapting properly as they are designed using tables. Is there a method I can ...

Another option could be to either find a different solution or to pause the loop until the

Is it possible to delay the execution of a "for" loop until a specific condition is met? I have a popup (Alert) that appears within the loop, prompting the user for confirmation with options to Agree or Cancel. However, the loop does not pause for the co ...

Error in jQuery: Unexpected token ILLEGAL during Asp.Net page loading

I am encountering an issue with using jQuery where even simple functions are causing an error message Uncaught SyntaxError: Unexpected token ILLEGAL to appear on page load. Unfortunately, I do not possess enough knowledge about jQuery to troubleshoot such ...

Warning from Google Chrome: Ensure password forms include optional hidden username fields for improved accessibility

Upon visiting the "reset password" route of my single-page application and checking the Chrome browser console, I am presented with a warning message: [DOM] Password forms should contain (optionally hidden) username fields for accessibility: (More info: g ...

css code creates a stable block with a blurred transparent effect

I need assistance with creating a transparent fixed header using only CSS and no JS. I attempted to use ::before for creating a blur effect with a negative z-index, but so far, my attempts have failed. I know how to achieve this using jQuery, but I am spec ...

React - Implementing pre-fetching of data prior to rendering

As a beginner in react, I have encountered a best practice dilemma that is causing me to make mistakes. My issue arises when I call an API to get information and then update an array in the state once the response is received. However, in the "render" func ...

Is it possible to assign multiple attributes using the setAttribute function of the DOM?

Imagine I'm looking to streamline the process of creating an input element through the DOM. Rather than the conventional method shown below var input = document.createElement("input"); input.setAttribute("class", "my-class"); input.setAttribute("type ...

Learn the method for printing CSS outlines and background colors in IE8 using JQuery's printElement feature

Printing my HTML calendar table in Chrome results in a perfect display. However, when I try to print it in IE8, the background colors and images are not included. Despite following steps from a helpful post on setting it as the default option, there were n ...

Can the loading of the window be postponed?

I've created a script that displays a message when the user first visits the website. The message then fades out, followed by another section fading in after a short delay. $(window).load(function() { $(".greeting").delay(1500).fadeOut("500"); ...

The try and catch block in JavaScript is failing to correctly capture the HTTP status

I have a function that successfully posts JSON to an API endpoint. Here is the code I am using: function sendValuesPageLoad(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { try { if (xhr.readyState === ...

Tips on showcasing lengthy string content from JSON in a structured list format using react with typescript

Is there a way to display long string data from a JSON file in a list format when the description string is too lengthy? How can I split or format the description using React and TypeScript? The JSON data I have is as follows: "options": [ ...

Discover the offsetTop value of a child element in React using TypeScript

How can I retrieve the offsetTop of React children in Typescript? Here is an example of my component: export default class FadeIn extends Component { private onScroll = () => { React.Children.forEach(this.props.children, child => { // G ...

Attempting to conditionally apply CSS to a component based on a prop, but unfortunately it is not functioning as expected

.storyMobile{ color:green; } .storyWeb{ color:red; } <div class="storyMobile"> hii </div> <div class="storyWeb"> hii </div> //main view <div> <story :story="stories[0]"/> </div> //here it prints ...

Issue with passing props to screen not displaying on initial load

Greetings, I'm a newcomer to the world of react native and currently facing an issue: const Tab = createMaterialTopTabNavigator(); export const CurriculumMenu = ({navigation, item}) => { const data = item.Title; console.log(data) return ( ...

The correlation among the event loop, libuv, and the V8 engine

Exploring the intricacies of Node.js architecture has led me to several thought-provoking questions. Is the event loop a component of libuv or v8? Does the event queue operate within the event loop? And if so, is it generated by libuv, v8 engine, or th ...

What is the impact of a floated element on vertical spacing?

I have come across an article discussing the usage of CSS, but I am puzzled as to why image number four is not positioned below image number one. Instead, it appears below image number three. Can someone please explain this to me? Here is the HTML code sni ...

Best practices for organizing fonts in SCSS 7-1 architecture?

My current project restructuring involves implementing the 7-1 architecture recommended by . As part of this process, I am incorporating flaticons into my project. I'm unsure of where to place the folder and scss file provided by flaticon within the ...

Discrepancy in Timestamp Deviation for Older Dates Between Java and Javascript (1 Hour)

When I try to convert a string date representation to numeric values, I noticed a discrepancy between Java/Groovy/PHP and Javascript. Specifically, for certain dates before 1970, the JS timestamp is exactly 3600 seconds behind the Java timestamp. This issu ...