Informatique


Le drag&drop

Aller à

Un élément "draggable"

HTML propose une API permettant de déplacer des objets sur la page, et même entre différentes pages!
Pour ce faire est apparu l'attribut draggable qui accepte les valeurs true ou false

Démo
<body>
    <h1 id=maintitre>Un beau contenu</h1>
    <p id=plouc1 draggable=true>Un contenu "draggable".</p>
    <p id=plouc2>Un contenu non "draggable".</p>
</body>

On peut rendre l'objet dynamiquement draggable.

Démo
<body>
    <h1 id=maintitre>Un beau contenu</h1>
    <p id=plouc1>Un contenu "draggable".</p>
    <p id=plouc2>Un contenu non "draggable".</p>
	<script>
		var monpara=document.querySelector('#plouc1');
		monpara.draggable=true;
	</script>
</body>

Préparer l'élément "draggable"

L'élément déplaçable utilisera 2 événements, dragstart et dragend.

  • dragstart, déclenché au moment où commence le déplacement
  • dragend, déclenché au moment où l'élément où on dépose l'élément dans la zone de drop

Démo
<head>
<title>Gestion du drag and drop</title>
<style type="text/css">
div.dragdrop {
	display:inline-block;
	margin:5px;
	padding:5px;
	border:2px solid #333;
	border-radius:3px;
	cursor: move;
	}
div#drop1, div#drop2 {
	display:block;
	margin:10px;
	padding:10px;
	border:2px solid #000;
	width:20%;
	height:200px;
	}
</style>
</head>
<body>
<h1 id=maintitre>Un beau contenu</h1>
<div id="drop1">Division 1<br>
	<div id=d1 class="dragdrop" draggable="true">Un contenu "draggable".</div>
</div>
<div id="drop2">Division 2<br></div>   

<script type="text/javascript">
var element;
var drags=document.querySelector("div.dragdrop");
drags.addEventListener("dragstart", function(e) {
	this.style.border="dashed 2px  #aaa"; 
	element=this; 
}); 
drags.addEventListener("dragend", function(e) {
	this.style.border="solid 2px  #000";
	element=null;
});      
</script>    
</body>

Analysons le code:

  • la variable element est destinée à recevoir l'élément que l'on déplace, il s'agit d'un clone de l'élément déplacé, on crée ce clone pour pouvoir le déposer dans la zone de drop
  • la variable drags contient l'élément que l'on désire déplacé
  • avec l'événement dragstart on fait deux choses: associer un style à l'élément à déplacer et créer le clone en faisant element=this
  • avec l'événement dragend on fait deux choses: associer un style à l'élément déposer et libérer la variable qui contient le clone en faisant element=null

Pour le moment l'événement dragend ne produit aucun effet car nous n'avons pas encore défini de zone de drop !!!


La zone de drop

Un élément en cours de déplacement ne peut pas être déposé n'importe où, il faut définir une balise HTML qui sera définie comme la zone de réception.

On constate dans l'exemple précédent que le paragraphe draggable est accompagné d'un petit cercle barré!
Cela veut dire qu'il ne peut être déposé n'importe où, et même nulle part puisque HTML interdit par défaut de déposer des éléments dans la page.

Par défaut une balise HTML ne peut rien recevoir ! On va changer ce comportement par défaut.


Il faut définir une balise HTML qui sera définie comme la zone de réception, on va donc utiliser une fonction qui permettra d'empêcher le comportement par défaut d'un élément de la page: preventDefault()

Démo
<head>
<title>Gestion du drag and drop</title>
<style type="text/css">
div.dragdrop {
	display:inline-block;
	margin:5px;
	padding:5px;
	border:2px solid #333;
	border-radius:3px;
	cursor: move;
	}
div#drop1, div#drop2 {
	display:block;
	margin:10px;
	padding:10px;
	border:2px solid #000;
	width:20%;
	height:200px;
	}
</style>
</head>
<body>
<h1 id=maintitre>Un beau contenu</h1>
<div id="drop1">Division 1<br>
	<div id=d1 class="dragdrop" draggable="true">Drag and drop me, please!</div>
</div>
<div id="drop2">Division 2<br></div>   
<script>
	dropzone=document.querySelector('#drop2');
	dropzone.addEventListener('dragover', function(e) {
	e.preventDefault(); // Annule l'interdiction du drop
	});

</script>

On constate que lorsqu'on survole la division pour laquelle on a supprimé le comportement par défaut le cercle barré qui accompagne le déplacement disparaît, ce qui indique que l'élément déplacé peut être déposé.


Les événements de la zone de drop

Les événements de la zone de drop sont:

  • dragenter, déclenché au moment où l'élément déplacé entre dans la zone de drop
  • dragover, déclenché au moment où l'élément déplacé se déplace dans la zone de drop
  • dragleave, déclenché au moment où l'élément déplacé quitte dans la zone de drop

Démo
<head>
<title>Gestion du drag and drop</title>
<style type="text/css">
div.dragdrop {
	display:inline-block;
	margin:5px;
	padding:5px;
	border:2px solid #333;
	border-radius:3px;
	cursor: move;
}
div#drop1, div#drop2 {
	display:block;
	margin:10px;
	padding:10px;
	border:2px solid #000;
	width:20%;
	height:200px;
}
</style>
</head>
<body>
<h1 id=maintitre>Un beau contenu</h1>
<div id="drop1">Division 1<br>
<div id=d1 class="dragdrop" draggable="true">Drag and drop me, please!</div>
</div>
<div id="drop2">Division 2<br></div>   
<script>
dropzone=document.querySelector('#drop2');
dropzone.addEventListener('dragover', function(e) {
	e.preventDefault(); // Annule l'interdiction du drop
	this.style.border="solid 2px red";
});
dropzone.addEventListener('dragleave', function(e) {
	e.preventDefault(); // Annule l'interdiction du drop
	this.style.border="solid 2px blue";
});
</script>
</body>

Déposer un élément dans la zone de drop

Jusqu'ici, qu'avons-nous fait?

  • on rendu un élément "draggable", et donc prêt à être déplacé
  • on a préparé le départ et l'arrivée de cet élément "draggable"
  • on a préparé une zone de drop, cette zone est représentée par une balise qui fera office de container

il ne reste plus qu'à effectivement déposer l'élément dans la zone de drop en utilisant appendchild() avec pour paramètre l'élément qu'on déplace qui se trouve dans la variable element.

Démo
<head>
<title>Gestion du drag and drop</title>
<style type="text/css">
div.dragdrop {
	display:inline-block;
	margin:5px;
	padding:5px;
	border:2px solid #333;
	border-radius:3px;
	cursor: move;
}
div#drop1, div#drop2 {
	display:block;
	margin:10px;
	padding:10px;
	border:2px solid #000;
	width:20%;
	height:200px;
}
</style>
</head>
<body>
<h1 id=maintitre>Un beau contenu</h1>
<div id="drop1">Division 1<br>
<div id=d1 class="dragdrop" draggable="true">Un contenu "draggable".</div>
</div>
<div id="drop2">Division 2<br></div>   

<script type="text/javascript">
//On prépare l'élément qu'on veut déplacer
var element;
var drags=document.querySelector("div.dragdrop");
drags.addEventListener("dragstart", function(e) {
	this.style.border="dashed 2px  #aaa"; 
	element=this; 
}); 
drags.addEventListener("dragend", function(e) {
	this.style.border="solid 2px  #000";
	element=null;
});  

//On prépare la zone de drop (de réception)
dropzone=document.querySelector('#drop2');
dropzone.addEventListener('dragover', function(e) {
	e.preventDefault(); 
	this.style.border="solid 2px red";
});
dropzone.addEventListener('dragleave', function(e) {
	e.preventDefault(); 
	this.style.border="solid 2px black";
});

//On dépose l'élément qu'on déplace
dropzone.addEventListener('drop', function(e) {
	e.preventDefault(); 
	this.style.border="solid 2px black";
	this.appendChild(element);
	element=null;
});
</script>    
</body>


Ramener l'objet déplacé à sa position d'origine

On va transférer une image placée dans une div d'une zone dans une autre zone.

Explication du code.

  • on sélectionne la div à déplacer
    var drags=document.querySelector("div.dragdrop");
  • au moment où démarre le déplacement avec dragstart on associe à la div déplacée un style qui indique qu'on déplace la div et on en profite pour sauver dans element la div que l'on déplace
  • à la fin du déplacement avec dragend, quand le drop a été fait, on restitue à la div déplacée le style original et on libère la variable element
  • On prépare les 2 zones où la div peut être déposée au moment du survol, dragover
  • On ajoute la div dans la zone avec le drop, drop
Démo
<html>
<head>
<title>Gestion du drag and drop</title>
<style type="text/css">
div.dragdrop {
display:inline-block;
margin:5px;
border:2px solid #333;
border-radius:3px;
cursor: move;
}
div#drop1, div#drop2 {
display:block;
margin:10px;
padding:10px;
border:2px solid #000;
width:20%;
height:200px;
}
</style>
</head>
<body>
<h1>Drag and drop d'une image</h1>
<div id="drop1">Division 1<br>
<div id=d1 class="dragdrop" draggable="true" data-name="i1"><img src="../../image/bakounine1.jpg"></div>
</div>
<div id="drop2">Division 2<br></div>   
<script type="text/javascript">
var drags=document.querySelector("div.dragdrop");
	drags.addEventListener("dragstart", function(evt) {
	// On modifie le style de l'élément au départ 
	this.style.border="2px dashed #aaa"; 
	// Sauvegarde de l'élément déplacé 
	element=this; 
	}); 
	drags.addEventListener("dragend", function(evt) {
	//On modifie le style de l'élément à l'arrivée  
	this.style.border="2px solid #000";
	//On libère element
	element=null;
	});      
//On prépare les zones de drop  
var drop2=document.getElementById("drop2");
var drop1=document.getElementById("drop1");
	drop2.addEventListener("dragover", function(evt) {
	event.preventDefault(); /* Pour autoriser le drop par JS */
	});
	drop1.addEventListener("dragover", function(evt) {
	event.preventDefault();/* Pour autoriser le drop par JS */
	});

	//Passage de la div qui contient l'image de drop1 vers drop2 
	drop2.addEventListener("drop", function(evt) {
	this.appendChild(element); /* Déplacement de l'élément vers drop2 */
	element=null;
	});

//Passage de la div qui contient l'image de drop2 vers drop1
	drop1.addEventListener("drop", function(evt) {
	this.appendChild(element); /* Déplacement de l'élément vers drop1 */
	element=null;
	}); 
</script>    
</body>
</html>