Search code examples
javascriptdrag-and-dropdraggable

Can't drop element after the drag


I'm new in JS and trying to make simple interface with pure JS, where User can dynamically add elements and move them around. I found solutions for create elements and drag'n'drop elements, that perfectly works separatly. But when I tried to unite them, drop function stop working...

What am I doing wrong?

Template:

    <head>
        <title>Int Demo</title>
        <script src='js/script.js'></script>
        <style type="text/css">
            .wrapper {width: 300px; height: 200px; background: #A3A1A1;}
            .textblock {cursor: pointer; background: red;}
        </style>
    </head>

    <body>
        <div class="button" id="button">Add Textbox</div>
        <div class="wrapper" id="wrapper"></div>
    </body>

</html>

My JS file:

document.addEventListener("DOMContentLoaded", function() { init(); }, false);

function init() {
    button = document.getElementById('button');
    wrapper = document.getElementById('wrapper');

    button.addEventListener('click', btnClick, false);
    wrapper.ondblclick  = catchIt;
}

//add element

function btnClick() {
    wrapper.innerHTML += '<p class="draggable textblock">Text Here!</p>';
    sessionStorage.inputBoxes = wrapper;
    console.log(sessionStorage);
}

// Activate Drag'n'Drop

document.onmousedown = function(e) {

  var dragElement = e.target;

  if (!dragElement.classList.contains('draggable')) return;

  var coords, shiftX, shiftY;

  startDrag(e.clientX, e.clientY);

  document.onmousemove = function(e) {
    moveAt(e.clientX, e.clientY);
  };

  dragElement.onmouseup = function() {
    finishDrag();
  };

  function startDrag(clientX, clientY) {

    shiftX = clientX - dragElement.getBoundingClientRect().left;
    shiftY = clientY - dragElement.getBoundingClientRect().top;

    dragElement.style.position = 'fixed';

    document.body.appendChild(dragElement);

    moveAt(clientX, clientY);
  };

  function finishDrag() {
    dragElement.style.top = parseInt(dragElement.style.top) + pageYOffset + 'px';
    dragElement.style.position = 'absolute';

    document.onmousemove = null;
    dragElement.onmouseup = null;
  }

  function moveAt(clientX, clientY) {
    var newX = clientX - shiftX;
    var newY = clientY - shiftY;

    // bottom offset
    var newBottom = newY + dragElement.offsetHeight;

    if (newBottom > document.documentElement.clientHeight) {

      var docBottom = document.documentElement.getBoundingClientRect().bottom;

      var scrollY = Math.min(docBottom - newBottom, 10);


      if (scrollY < 0) scrollY = 0;

      window.scrollBy(0, scrollY);

      newY = Math.min(newY, document.documentElement.clientHeight - dragElement.offsetHeight);
    }


    // top offset
    if (newY < 0) {
      var scrollY = Math.min(-newY, 10);
      if (scrollY < 0) scrollY = 0;

      window.scrollBy(0, -scrollY);
      newY = Math.max(newY, 0);
    }

    if (newX < 0) newX = 0;
    if (newX > document.documentElement.clientWidth - dragElement.offsetHeight) {
      newX = document.documentElement.clientWidth - dragElement.offsetHeight;
    }

    dragElement.style.left = newX + 'px';
    dragElement.style.top = newY + 'px';
  }

  return false;
}

Solution

  • I changed

    dragElement.onmouseup = function() {
        finishDrag();
    };
    

    into

    document.onmouseup = function() {
        finishDrag();
    };
    

    and it started working for me. This does mean that the end user will have to keep the mouse button pressed down to continue dragging and that the element will be placed immediately on mouse button up. But I'm assuming that this is the desired functionality, or do you want the drop to happen only on a second mouse click?