skip to Main Content

I’ve been coding this selection system that allows me to select widgets and drag a bunch of them, the problem is that when I select two widgets and I drag the other widget that’s not selected, they’re all being dragged, I don’t want that to happen.

What is supposed to happen is that when I put my mouse down on a non-selected widget, all of the selected widgets have to not be selected anymore (that means the ".selected" class is removed). The problem is that I’m confused on how to apply this only to the non-selected widgets, it has to not apply to selected widgets.

Here is the code before I tried:

<!DOCTYPE html>
<html>
<head>
  <style>
    #selection-rectangle {
      position: absolute;
      border: 2px dashed blue;
      pointer-events: none;
      display: none;
      z-index: 9999999;
    }

    .widgets.selected {
      outline-color: blue;
      outline-width: 2px;
      outline-style: dashed;
    }
  </style>
</head>
<body>
  <div id="widget1" class="widgets" style="left: 50px; top: 50px;">
    <div id="widget1header" class="widget-header"></div>
  </div>
  <div id="widget2" class="widgets" style="left: 150px; top: 150px;">
    <div id="widget2header" class="widget-header"></div>
  </div>
  <div id="widget3" class="widgets" style="left: 250px; top: 250px;">
    <div id="widget3header" class="widget-header"></div>
  </div>

  <script>
    let isSelecting = false;
    let selectionStartX, selectionStartY, selectionEndX, selectionEndY;
    let selectionRectangle;
    let draggedElements = [];
    const widgets = document.querySelectorAll('.widgets');
    const widgetContainer = document.getElementById('widget-container');

    document.addEventListener('mousedown', (event) => {
      const header = event.target.closest('.widget-header');
      if (header) {
        const widget = header.parentElement;

        draggedElements = Array.from(widgets).filter((widget) => widget.classList.contains('selected'));
        draggedElements.forEach((widget) => {
          const shiftX = event.clientX - widget.getBoundingClientRect().left;
          const shiftY = event.clientY - widget.getBoundingClientRect().top;

          function moveElement(event) {
            const x = event.clientX - shiftX;
            const y = event.clientY - shiftY;

            widget.style.left = x + 'px';
            widget.style.top = y + 'px';
          }

          function stopMoving() {
            document.removeEventListener('mousemove', moveElement);
            document.removeEventListener('mouseup', stopMoving);
          }

          document.addEventListener('mousemove', moveElement);
          document.addEventListener('mouseup', stopMoving);
        });

        return;
      }

      const isWidgetClicked = Array.from(widgets).some((widget) => {
        const widgetRect = widget.getBoundingClientRect();
        return (
          event.clientX >= widgetRect.left &&
          event.clientX <= widgetRect.right &&
          event.clientY >= widgetRect.top &&
          event.clientY <= widgetRect.bottom
        );
      });

      if (!isWidgetClicked && event.target !== selectionRectangle) { // Check if the target is not the selection rectangle
        isSelecting = true;
        selectionStartX = event.clientX;
        selectionStartY = event.clientY;
        selectionRectangle = document.createElement('div');
        selectionRectangle.id = 'selection-rectangle';
        selectionRectangle.style.position = 'absolute';
        selectionRectangle.style.border = '2px dashed blue';
        selectionRectangle.style.pointerEvents = 'none';
        selectionRectangle.style.display = 'none';
        document.body.appendChild(selectionRectangle);

        // Remove selected class from widgets
        widgets.forEach((widget) => {
          widget.classList.remove('selected');
        });
      }
    });

    document.addEventListener('mousemove', (event) => {
      if (isSelecting) {
        selectionEndX = event.clientX;
        selectionEndY = event.clientY;

        let width = Math.abs(selectionEndX - selectionStartX);
        let height = Math.abs(selectionEndY - selectionStartY);

        selectionRectangle.style.width = width + 'px';
        selectionRectangle.style.height = height + 'px';
        selectionRectangle.style.left = Math.min(selectionEndX, selectionStartX) + 'px';
        selectionRectangle.style.top = Math.min(selectionEndY, selectionStartY) + 'px';
        selectionRectangle.style.display = 'block';

        widgets.forEach((widget) => {
          const widgetRect = widget.getBoundingClientRect();
          const isIntersecting = isRectangleIntersecting(widgetRect, {
            x: Math.min(selectionStartX, selectionEndX),
            y: Math.min(selectionStartY, selectionEndY),
            width,
            height,
          });
          if (isIntersecting) {
            widget.classList.add('selected');
          } else {
            widget.classList.remove('selected');
          }
        });
      }
    });

    document.addEventListener('mouseup', () => {
      if (isSelecting) {
        isSelecting = false;
        selectionRectangle.remove();
      }
    });

    function isRectangleIntersecting(rect1, rect2) {
      return (
        rect1.left >= rect2.x &&
        rect1.top >= rect2.y &&
        rect1.right <= rect2.x + rect2.width &&
        rect1.bottom <= rect2.y + rect2.height
      );
    }
  </script>

  <style>
    .widgets {
      position: absolute;
      z-index: 9;
      background-color: #000000;
      color: white;
      font-size: 25px;
      font-family: Arial, Helvetica, sans-serif;
      border: 2px solid #212128;
      text-align: center;
      width: 500px;
      height: 200px;
      min-width: 166px;
      min-height: 66px;
      overflow: hidden;
      resize: both;
      image-resolution: none;
      border-radius: 10px;
    }

    .widget-header {
      padding: 10px;
      cursor: move;
      z-index: 10;
      background-color: #040c14;
      outline-color: white;
      outline-width: 2px;
      outline-style: solid;
    }
  </style>




<script>
    // Make the DIV element draggable:
    dragElement(document.getElementById("widget1"));
    
    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;
    }
    
    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:
      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;
    }
    }




    // Make the DIV element draggable:
    dragElement(document.getElementById("widget2"));
    
    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;
    }
    
    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:
      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;
    }
    }

    // Make the DIV element draggable:
    dragElement(document.getElementById("widget3"));
    
    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;
    }
    
    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:
      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;
    }
    }
    </script>
</body>
</html>

I tried creating a function that checks if a div is selected or not, if not, when the mouse is down on it, it unselects everything else.

It didn’t work for some reason

2

Answers


  1. add this line and remove dragElement function

     widgets.forEach(function (element) {         
         element.addEventListener('mousedown', (event) => {
             event.target.closest('.widgets').classList.add('selected');
         });
     });
    
    Login or Signup to reply.
  2. Remove your second <script> tag, its content is repeated and unnecessary. In the mousedown handler, check if the clicked widget has selected class or not and add to draggedElements accordingly.

    let isSelecting = false;
    let selectionStartX, selectionStartY, selectionEndX, selectionEndY;
    let selectionRectangle;
    let draggedElements = [];
    const widgets = document.querySelectorAll('.widgets');
    const widgetContainer = document.getElementById('widget-container');
    
    document.addEventListener('mousedown', (event) => {
      const header = event.target.closest('.widget-header');
      if (header) {
        const widget = header.parentElement;
        // If the clicked widget is not selected
        if (!widget.classList.contains('selected')) {
          // deselect all widgets 
          widgets.forEach((widget) => {
            widget.classList.remove('selected');
          });
          // and only drag the clicked one
          draggedElements = [widget];
        } else {
          // otherwise drag the selected 
          draggedElements = Array.from(widgets).filter((widget) => widget.classList.contains('selected'));
        }
    
        draggedElements.forEach((widget) => {
          const shiftX = event.clientX - widget.getBoundingClientRect().left;
          const shiftY = event.clientY - widget.getBoundingClientRect().top;
    
          function moveElement(event) {
            const x = event.clientX - shiftX;
            const y = event.clientY - shiftY;
    
            widget.style.left = x + 'px';
            widget.style.top = y + 'px';
          }
    
          function stopMoving() {
            document.removeEventListener('mousemove', moveElement);
            document.removeEventListener('mouseup', stopMoving);
          }
    
          document.addEventListener('mousemove', moveElement);
          document.addEventListener('mouseup', stopMoving);
        });
    
        return;
      }
    
      const isWidgetClicked = Array.from(widgets).some((widget) => {
        const widgetRect = widget.getBoundingClientRect();
        return (
          event.clientX >= widgetRect.left &&
          event.clientX <= widgetRect.right &&
          event.clientY >= widgetRect.top &&
          event.clientY <= widgetRect.bottom
        );
      });
    
      if (!isWidgetClicked && event.target !== selectionRectangle) { // Check if the target is not the selection rectangle
        isSelecting = true;
        selectionStartX = event.clientX;
        selectionStartY = event.clientY;
        selectionRectangle = document.createElement('div');
        selectionRectangle.id = 'selection-rectangle';
        selectionRectangle.style.position = 'absolute';
        selectionRectangle.style.border = '2px dashed blue';
        selectionRectangle.style.pointerEvents = 'none';
        selectionRectangle.style.display = 'none';
        document.body.appendChild(selectionRectangle);
    
        // Remove selected class from widgets
        widgets.forEach((widget) => {
          widget.classList.remove('selected');
        });
      }
    });
    
    document.addEventListener('mousemove', (event) => {
      if (isSelecting) {
        selectionEndX = event.clientX;
        selectionEndY = event.clientY;
    
        let width = Math.abs(selectionEndX - selectionStartX);
        let height = Math.abs(selectionEndY - selectionStartY);
    
        selectionRectangle.style.width = width + 'px';
        selectionRectangle.style.height = height + 'px';
        selectionRectangle.style.left = Math.min(selectionEndX, selectionStartX) + 'px';
        selectionRectangle.style.top = Math.min(selectionEndY, selectionStartY) + 'px';
        selectionRectangle.style.display = 'block';
    
        widgets.forEach((widget) => {
          const widgetRect = widget.getBoundingClientRect();
          const isIntersecting = isRectangleIntersecting(widgetRect, {
            x: Math.min(selectionStartX, selectionEndX),
            y: Math.min(selectionStartY, selectionEndY),
            width,
            height,
          });
          if (isIntersecting) {
            widget.classList.add('selected');
          } else {
            widget.classList.remove('selected');
          }
        });
      }
    });
    
    document.addEventListener('mouseup', () => {
      if (isSelecting) {
        isSelecting = false;
        selectionRectangle.remove();
      }
    });
    
    function isRectangleIntersecting(rect1, rect2) {
      return (
        rect1.left >= rect2.x &&
        rect1.top >= rect2.y &&
        rect1.right <= rect2.x + rect2.width &&
        rect1.bottom <= rect2.y + rect2.height
      );
    }
    #selection-rectangle {
      position: absolute;
      border: 2px dashed blue;
      pointer-events: none;
      display: none;
      z-index: 9999999;
    }
    
    .widgets.selected {
      outline-color: blue;
      outline-width: 2px;
      outline-style: dashed;
    }
    
    .widgets {
      position: absolute;
      z-index: 9;
      background-color: #000000;
      color: white;
      font-size: 25px;
      font-family: Arial, Helvetica, sans-serif;
      border: 2px solid #212128;
      text-align: center;
      width: 500px;
      height: 200px;
      min-width: 166px;
      min-height: 66px;
      overflow: hidden;
      resize: both;
      image-resolution: none;
      border-radius: 10px;
    }
    
    .widget-header {
      padding: 10px;
      cursor: move;
      z-index: 10;
      background-color: #040c14;
      outline-color: white;
      outline-width: 2px;
      outline-style: solid;
    }
    <div id="widget1" class="widgets" style="left: 50px; top: 50px;">
      <div id="widget1header" class="widget-header"></div>
    </div>
    <div id="widget2" class="widgets" style="left: 150px; top: 150px;">
      <div id="widget2header" class="widget-header"></div>
    </div>
    <div id="widget3" class="widgets" style="left: 250px; top: 250px;">
      <div id="widget3header" class="widget-header"></div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search