Comment créer des éléments par glisser-déposer avec Vanilla JavaScript et HTML

Introduction

Le glisser-déposer est une interaction utilisateur courante que vous pouvez trouver dans de nombreuses interfaces graphiques.

Il existe des bibliothèques JavaScript préexistantes permettant d'ajouter une fonction de glisser-déposer à votre application. Toutefois, il peut arriver qu'une bibliothèque ne soit pas disponible ou qu'elle introduise une surcharge ou une dépendance dont votre projet n'a pas besoin. Dans de telles situations, la connaissance des API dont vous disposez dans les navigateurs web modernes peut vous offrir des solutions alternatives.

L’API HTML Drag and Drop s'appuie sur le modèle d'événement de DOM pour obtenir des informations sur ce qui est glissé ou déposé et pour mettre à jour cet élément par glisser-déposer. Grâce aux gestionnaires d'événements JavaScript, vous pouvez transformer n'importe quel élément en un élément pouvant être glissé ou déposé.

Dans ce tutoriel, nous allons construire un exemple de glisser-déposer en utilisant l'API HTML Drag and Drop avec Vanilla JavaScript pour utiliser les gestionnaires d'événements.

Conditions préalables

Pour suivre ce tutoriel, vous aurez besoin de :

  • Un navigateur web moderne qui supporte l'API Drag and Drop (Chrome 4+, Firefox 3.5+, Safari 3.1+, Edge 18+).

Étape 1 – Création du projet et balisage initial

Notre projet consistera en un conteneur avec deux types d'éléments enfant :

  • Des éléments enfant que vous pouvez faire glisser
  • Des éléments enfant dans lesquels il est possible de déposer des éléments

Tout d'abord, ouvrez la fenêtre de votre terminal et créez un nouveau répertoire de projets :

  • mkdir drag-and-drop-example

Ensuite, naviguez vers ce répertoire :

  • cd drag-and-drop-example

Puis créez un fichier index.html dans ce répertoire :

  • nano index.html

Ajoutez maintenant du code passe-partout pour une page web HTML :

index.html

<!DOCTYPE html> <html>   <head>     <title>My Drag-and-Drop Example</title>     <link rel="stylesheet" href="style.css" />   </head>   <body>   </body> </html> 

Et entre les balises <body> ajoutez votre élément draggable et votre dropzone (cible de largage) :

index.html

<div class="example-parent">   <div class="example-origin">     <div       id="draggable-1"       class="example-draggable"     >       draggable     </div>   </div>    <div     class="example-dropzone"   >     dropzone   </div> </div> 

Enregistrez et fermez le fichier. Ensuite, créez un fichier style.css :

  • nano style.css

Puis, ajoutez des styles pour les éléments de notre fichier index.html :

style.css

.example-parent {   border: 2px solid #DFA612;   color: black;   display: flex;   font-family: sans-serif;   font-weight: bold; }  .example-origin {   flex-basis: 100%;   flex-grow: 1;   padding: 10px; }  .example-draggable {   background-color: #4AAE9B;   font-weight: normal;   margin-bottom: 10px;   margin-top: 10px;   padding: 10px; }  .example-dropzone {   background-color: #6DB65B;   flex-basis: 100%;   flex-grow: 1;   padding: 10px; } 

Cela permettra d'ajouter un certain formatage à l'application. Vous pouvez maintenant visualiser index.html dans le navigateur et observer que cela produit un dragable <div> et un dropzone <div>.

Capture d'écran des div draggable et dropzone

Ensuite, nous rendrons explicitement le premier <div> glissant en ajoutant l'attribut draggable :

index.html

<div class="example-parent">   <div class="example-origin">     <div       id="draggable-1"       class="example-draggable"       draggable="true"     >       draggable     </div>   </div>    <div     class="example-dropzone"   >     dropzone   </div> </div> 

Enregistrez et fermez le fichier.

Enfin, regardez à nouveau index.html dans le navigateur. Si nous cliquons sur le draggable <div> et le faisons glisser sur l'écran, il doit y avoir une indication visuelle de son déplacement.

La valeur par défaut de l'attribut draggable est auto. Cela signifie que la possibilité de faire glisser l'élément sera déterminée par le comportement par défaut de votre navigateur. En général, cela signifie que les sélections de texte, les images et les liens peuvent être glissés sans qu'il soit nécessaire de spécifier draggable=" true".

Vous avez maintenant un fichier HTML avec un élément glissant. Nous passerons à l'ajout de gestionnaires onevents.

Étape 2 – Gestion des événements par glisser-déposer avec JavaScript

Actuellement, si nous relâchons la souris tout en faisant glisser l'élément déplaçable, il ne se passe rien. Pour déclencher une action sur les éléments du DOM par glisser-déposer, nous devons utiliser l'API Drag and Drop :

  • ondragstart : ce gestionnaire d'événement sera attaché à notre élément draggable et se déclenchera lorsqu'un événement dragstart se produira.
  • ondragover : ce gestionnaire d'événements sera attaché à notre élément dropzone et se déclenchera lorsqu'un événement dragover se produira.
  • ondrop : ce gestionnaire d'événements sera également attaché à notre élément dropzone et se déclenchera lorsqu'un événement drop se produira.

Remarque : il y a huit gestionnaires d'événements au total : ondrag, ondragend, ondragenter, ondragexit, ondragleave, ondragover, ondragstart et ondrop. Dans le cadre de notre exemple, nous n'aurons pas besoin de tous.

Tout d'abord, référençons un nouveau fichier script.js dans notre index.html :

index.html

<body>   ...   <script src="script.js"></script> </body> 

Ensuite, nous allons créer un nouveau fichier script.js :

  • nano script.js

L'objet DataTransfer conservera les informations relatives à la traînée actuelle. Pour mettre à jour notre élément par glisser-déposer, nous devons accéder directement à l'objet DataTransfer. Pour ce faire, nous pouvons sélectionner la propriété dataTransfer de l'élément DOM DragEvent.

Remarque : l'objet DataTransfer peut techniquement suivre les informations de plusieurs éléments glissés en même temps. Dans le cadre de notre exemple, nous nous concentrerons sur le glissement d'un élément.

La méthode setData de l'objet dataTransfer peut être utilisée afin de définir les informations d'état de glissement pour votre élément actuellement glissé. Il faut deux paramètres :

  • une chaîne qui déclare le format du deuxième paramètre
  • les données réelles transférées

Notre objectif est de déplacer notre élément draggable vers un nouvel élément parent. Nous devons pouvoir sélectionner notre élément draggable avec un identifiant unique. Nous pouvons définir l’identifiant de l'élément glissé avec la méthode setData pour qu'il puisse être utilisé plus tard.

Revisitons notre fichier script.js et créons une nouvelle fonction pour utiliser setData :

script.js

function onDragStart(event) {   event     .dataTransfer     .setData('text/plain', event.target.id); } 

Remarque : Internet Explorer 9 à 11 aurait des problèmes avec l'utilisation de "text/plain". Le format doit être 'text' pour ce navigateur.

Pour mettre à jour le style CSS de l'élément glissé, nous pouvons accéder à ses styles en utilisant à nouveau l'événement DOM et en définissant les styles que nous voulons pour la currentTarget.

Ajoutons-les à notre fonction et changeons la backgroundColor en yellow :

script.js

function onDragStart(event) {   event     .dataTransfer     .setData('text/plain', event.target.id);    event     .currentTarget     .style     .backgroundColor = 'yellow'; } 

Remarque : tous les styles que vous modifiez devront être à nouveau mis à jour manuellement sur drop si vous souhaitez des styles par glisser-déposer. Si vous changez quelque chose quand il commence à glisser, l'élément glissé conservera ce nouveau style à moins que vous ne le changiez à nouveau.

Maintenant, nous avons notre fonction JavaScript pour le démarrage du glissement.

Nous pouvons ajouter ondragstart à l'élément draggable dans index.html :

index.html

<div class="example-parent">   <div class="example-origin">     <div       id="draggable-1"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       draggable     </div>   </div>    <div class="example-dropzone">     dropzone   </div> </div> 

Consultez index.html dans votre navigateur. Si vous essayez de faire glisser votre objet maintenant, le style déclaré dans notre fonction sera appliqué :

Gif animé représentant un élément se faisant glisser mais ne pouvant pas être déposer

Cependant, rien ne se passera lorsque vous relâcherez votre clic.

Le prochain gestionnaire d'événements déclenché dans cette séquence est ondragover.

Le comportement par défaut de certains éléments DOM comme <div> dans les navigateurs n'accepte généralement pas d'être déposé. Ce comportement interceptera le comportement que nous essayons de mettre en œuvre. Pour nous assurer que nous obtenons le comportement drop souhaité, nous appliquerons preventDefault.

Revisitons notre fichier script.js et créons une nouvelle fonction pour utiliser preventDefault. Ajoutez ce code à la fin du fichier :

script.js

function onDragOver(event) {   event.preventDefault(); } 

Maintenant, nous pouvons ajouter ondragover à notre élément dropzone dans index.html :

index.html

<div class="example-parent">   <div class="example-origin">     <div       id="draggable-1"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       draggable     </div>   </div>    <div     class="example-dropzone"     ondragover="onDragOver(event);"   >     dropzone   </div> </div> 

À ce stade, nous n'avons toujours pas de code écrit pour gérer le dépôt réel. Le dernier gestionnaire d'événements déclenché dans cette séquence est ondrop.

Revoyons notre fichier script.js et créons une nouvelle fonction.

Nous pouvons référencer les données que nous avons enregistrées précédemment avec la méthode setData de l'objet dataTransfer. Nous utiliserons la méthode getData de l'objet dataTransfer. Les données que nous avons établies étaient l’id, c'est donc ce qui nous sera renvoyé :

script.js

function onDrop(event) {   const id = event     .dataTransfer     .getData('text'); } 

Sélectionnons notre élément draggable avec l’id que nous avons récupéré :

script.js

function onDrop(event) {   // ...    const draggableElement = document.getElementById(id); } 

Sélectionnons notre élément dropzone :

script.js

function onDrop(event) {   // ...    const dropzone = event.target; } 

Ajoutons notre élément draggable à la dropzone :

script.js

function onDrop(event) {   // ...    dropzone.appendChild(draggableElement); } 

Réinitialisons notre objet DataTransfer :

script.js

function onDrop(event) {   // ...    event     .dataTransfer     .clearData(); } 

Maintenant, nous pouvons ajouter ondrop à notre élément dropzone dans index.html :

index.html

<div class="example-parent">   <div class="example-origin">     <div       id="draggable-1"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       draggable     </div>   </div>    <div     class="example-dropzone"     ondragover="onDragOver(event);"     ondrop="onDrop(event);"   >     dropzone   </div> </div> 

Une fois que cela est fait, nous avons une fonction de glisser-déposer fonctionnelle. Affichez index.html dans votre navigateur et faites glisser l'élément draggable sur la dropzone.

Gif animé représentant un élément glissé et déposé dans une cible de largage

Notre exemple porte sur le scénario d'un seul objet pouvant être déplacé et d'une seule cible de largage. Vous pouvez avoir plusieurs objets à faire glisser, plusieurs cibles où les déposer, et personnaliser tout cela avec tous les autres gestionnaires d'événements de l'API Drag and Drop.

Étape 3 – Construction d'un exemple complexe avec plusieurs éléments glissants

Voici un autre exemple de la manière dont vous pourriez utiliser cette API : une liste de tâches avec des tâches glissantes que vous pouvez déplacer d'une colonne "To-do" à une colonne "Done".

Gif animé représentant plusieurs tâches glissées et déposées dans une colonne Done

Pour créer votre propre liste de tâches, ajoutez à index.html d'autres éléments à faire glisser avec des ids uniques :

index.html

<div class="example-parent">   <h1>To-do list</h1>   <div class="example-origin">     To-do     <div       id="draggable-1"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       thing 1     </div>     <div       id="draggable-2"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       thing 2     </div>     <div       id="draggable-3"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       thing 3     </div>     <div       id="draggable-4"       class="example-draggable"       draggable="true"       ondragstart="onDragStart(event);"     >       thing 4     </div>   </div>    <div     class="example-dropzone"     ondragover="onDragOver(event);"     ondrop="onDrop(event);"   >     Done   </div> </div> 

Affichez index.html dans votre navigateur et faites glisser les éléments de la colonne To-do vers la colonne Done. Vous avez créé une application to-do et testé la fonctionnalité.

Conclusion

Dans cet article, vous avez créé une application to-do pour explorer la fonctionnalité de glisser-déposer qui est disponible pour les navigateurs web modernes.

L'API Drag and Drop offre de multiples options pour personnaliser vos actions au-delà du simple glisser-déposer. Par exemple, vous pouvez mettre à jour le style CSS de vos éléments glissés. Vous pouvez également, au lieu de déplacer l'élément, choisir de copier votre élément déplaçable afin qu'il soit reproduit lors du dépôt.

Gardez à l'esprit que si de nombreux navigateurs web prennent en charge cette technologie, vous ne pourrez peut-être pas vous y fier si votre public se compose d’appareils qui ne prennent pas en charge cette fonctionnalité.

Pour en savoir plus sur tout ce que vous pouvez déposer avec l'API Drag and Drop, consultez les documents du MDN à ce sujet.