How to implement drag & amp; drop in pure JavaScript

In this tutorial, we'll look at how to implement drag & drop effect in vanilla JavaScript. The literal translation from English - "pull and drop" - reflects the essence of the effect, this is well known to any user dragging and dropping interface elements.





Drag & drop may be needed in different situations - for example, in the following:





  • Simple visual repositioning of an element.





  • Sort items using drag and drop. An example is sorting task cards in a task tracker.





  • Changing the context of an element. Example - transferring a task in a task tracker from one list to another.





  • Moving local files to the browser window.





We'll take a look at drag & drop using sorting as an example. To do this, we will create an interactive task list.





HTML Drag and Drop API

The  HTML5 standard has an API that allows for drag & drop. It makes it possible to control the capture of an element on the page by the mouse and its movement to a new position using special events. Let's take a closer look at this API.





  ,   .  , ,  . , draggable



true



.





<div draggable="true">Draggable element</div>
      
      



,   .  MDN,    .





  • drag



    โ€”  , .





  • dragstart



    โ€”    .





  • dragend



    โ€”   , .





  • dragover



    โ€”  , ,   .





  • drop



    โ€”    , ,     .





  .      . ,   , dragover



drop



        preventDefault



.  โ€”     .   .





  API.   ,     . , DataTransfer



,   , .     ,   DataTransfer



 , , ,     ,   - .    MDN.





     ,  HTML Drag and Drop API.





 

   . .  โ€”  , ul



.





<section class="tasks">
  <h1 class="tasks__title">To do list</h1>

  <ul class="tasks__list">
    <li class="tasks__item">learn HTML</li>
    <li class="tasks__item">learn CSS</li>
    <li class="tasks__item">learn JavaScript</li>
    <li class="tasks__item">learn PHP</li>
    <li class="tasks__item">stay alive</li>
  </ul>
</section>
      
      



:





body {
  font-family: "Tahoma", sans-serif;
  font-size: 18px;
  line-height: 25px;
  color: #164a44;

  background-color: #b2d9d0;
}

.tasks__title {
  margin: 50px 0 20px 0;

  text-align: center;
  text-transform: uppercase;
 }

.tasks__list {
  margin: 0;
  padding: 0;

  list-style: none;
}

.tasks__item {
  transition: background-color 0.5s;
  margin-bottom: 10px;
  padding: 5px;

  text-align: center;
  border: 2px dashed #b2d9d0;
  border-radius: 10px;
  cursor: move;
  background-color: #dff2ef;

  transition: background-color 0.5s;
}

.tasks__item:last-child {
  margin-bottom: 0;
}

.selected {
  opacity: 0.6;
}
      
      



  ,   โ€” move



. ,    move



  , .





  selected



,  





drag & drop

 1.

 JavaScript.   draggable



  true



, .     JavaScript.





const tasksListElement = document.querySelector(`.tasks__list`);
const taskElements = tasksListElement.querySelectorAll(`.tasks__item`);

//        
for (const task of taskElements) {
  task.draggable = true;
}
      
      



,     .  , .





 2.    

dragstart



dragend



  .   selected



,   . .





tasksListElement.addEventListener(`dragstart`, (evt) => {
  evt.target.classList.add(`selected`);
})

tasksListElement.addEventListener(`dragend`, (evt) => {
  evt.target.classList.remove(`selected`);
});
      
      



 3.

     โ€” . ,   dragover



. , ,           . :





  1. .





  2. .selected



      ,   dragover



    .





  3. , dragover



       ,  โ€”     .





  4. , dragover



        . ,    ,    .





  5. , . ,  ,   .





  6.   .





:





tasksListElement.addEventListener(`dragover`, (evt) => {
  //      
  evt.preventDefault();

  //   
  const activeElement = tasksListElement.querySelector(`.selected`);
  //  ,       
  const currentElement = evt.target;
  // ,   :
  // 1.    ,   ,
  // 2.    
  const isMoveable = activeElement !== currentElement &&
    currentElement.classList.contains(`tasks__item`);

  //  ,   
  if (!isMoveable) {
    return;
  }

  //  ,    
  const nextElement = (currentElement === activeElement.nextElementSibling) ?
      currentElement.nextElementSibling :
      currentElement;

  //  activeElement  nextElement
  tasksListElement.insertBefore(activeElement, nextElement);
});
      
      



nextElement



  .      , , .





     โ€” . ,   .      โ€”   ,   .  .     .     , ,     . , nextElement



.





 4.

    ,   dragover



.     ,   . ,   ,     , .   ,  .





getNextElement()



.   , , .     ,  .





, getBoundingClientRect()



.       ,       . y



,   height



,



,   .





const getNextElement = (cursorPosition, currentElement) => {
  //      
  const currentElementCoord = currentElement.getBoundingClientRect();
  //      
  const currentElementCenter = currentElementCoord.y + currentElementCoord.height / 2;

  //     ,   
  //    โ€”  DOM-
  const nextElement = (cursorPosition < currentElementCenter) ?
      currentElement :
      currentElement.nextElementSibling;

  return nextElement;
};
      
      



 . ,    โ€” ,   .      ,  ,  DOM  .   , ,     .





,   ,    -     . ,  ,    .           DOM    dragover



.  ,      DOM.   , .





tasksListElement.addEventListener(`dragover`, (evt) => {
  evt.preventDefault();

  const activeElement = tasksListElement.querySelector(`.selected`);
  const currentElement = evt.target;
  const isMoveable = activeElement !== currentElement &&
    currentElement.classList.contains(`tasks__item`);

  if (!isMoveable) {
    return;
  }

  // evt.clientY โ€”     ,
  //   
  const nextElement = getNextElement(evt.clientY, currentElement);

  // ,     
  if (
    nextElement && 
    activeElement === nextElement.previousElementSibling ||
    activeElement === nextElement
  ) {
    //  ,   ,      DOM
    return;
  }

  tasksListElement.insertBefore(activeElement, nextElement);
});
      
      



, :   ,  DOM  , ,  โ€” !  โ€”   .





  • HTML Drag and Drop API  MDN.  API.





  • Native HTML5 Drag and Drop.   API   .  .





  • How to make a Drag-and-Drop file uploader with vanilla JavaScript.  ,   drag & drop.





  • Drag & drop   . , HTML Drag and Drop API. , , - API .





  • 10 Best Drag And Drop JavaScript Libraries. JavaScript-,   drag & drop.






HTML Academy ยซReact-ยป โ€” JavaScript React.js . , . โ€” . 95% . 27 .








All Articles