Accueil

Traduction

Tutoriel HTML - sommaire

Tutoriel HTML5 - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

API glisser-déposer de HTML 5

Un "drag and drop" consiste à déplacer un élément d'une zone source vers une zone destination avec la souris.
Il peut être intéressant d'introduire cet fonctionnalité dans une page web.

HTML 5 propose désormais une API "glisser-déposer".
Il faut rappeler que framework Jquery proposait déjà des méthodes pour réaliser facilement un "drag & drop".

Drag and drop avec jQuery UI

Pendant longtemps la seule solution pour programmer un "drag and drop" dans une page web était d'utiliser le célèbre framework jQuery et plus précisément son extension : jQuery-UI.

Exemple de drag and drop avec jQuery-UI

Ci-dessous un document HTML avec des images transférables d'un conteneur vers un autre :

Vous pouvez déplacer les images de la boite du haut vers la boite du bas (fond rose) et vice-versa.

Le code de l'exemple

Partie HEAD : il faut charger deux fichiers .js (celui de la librairie jQuery et celui de l'extension jQuery UI).

CSS : Les images sont des éléments inline-block

HTML : Les images sont dans le conteneur "source" et le conteneur "destination" est initialement vide.

Le script :
Il est d'une simplicité déroutante.

La première méthode rend "glissable" les éléments référencés (donc ici les images).
La deuxième méthode rend "déposable" les éléments référencés (ici les DIV).
Donc on pourra faire glisser les images de la boite "source" vers la boite "destination" et vice-versa.

Utilisation de l'API glisser-déposer d'HTML 5

Désormais avec l'API web "glisser-déposer" il est possible de programmer un 'drag and drop' sans recourir à jQuery.

Le rendu

Ci-dessous un document HTML avec des images transférables :

Vous pouvez déplacer les images de la boite du haut vers la boite du bas mais pas l'inverse.

Le code CSS & HTML

Dans la partie HEAD les d'instructions pour charger les librairies de jQuery ont disparu.

Pour être transférables par la souris d'un conteneur vers un autre, les éléments doivent avoir l'attribut draggable ='true' et avoir un ID. En effet l'élément déplacé est référencé par son ID.

Pour un drag & drop unilatéral (de la zone "source" vers la zone "destination") il faut associer l'événement "ondragStart" à la zone source et les deux autres événements à la zone destination.

Le script

À chaque événement est associé une fonction.

function debut(e) // associé à dragstart
{
	e.dataTransfer.effectAllowed ="move";
	e.dataTransfer.setData('text',e.target.getAttribute('id'));
}
function glisser(e) {e.preventDefault(); } // associé à dragover

function deposer(e)  //associé à drop
{
	objet  = e.dataTransfer.getData('text');
	e.currentTarget.appendChild(document.getElementById(objet));
	e.stopPropagation;
}

Pour transférer les données d'une zone source vers une zone destination il faut utiliser l'objet dataTransfer. Cet objet comprend deux méthodes setData() & getData().
La methode setData() permet de mémoriser les données à déposer. Elle comprend deux paramètres : le premier est "text" et le deuxième précise le type de donnée à déposer.
La méthode getData() permet de récupérer les données mémorisées par la méthode précédente et ne comprend qu'un argument : "text".

Fonction debut(e) : récupération de l'ID de l'élément sélectionnée via l'instruction
e.dataTransfer.setData('text',e.target.getAttribute('id'))

Fonction glisser(e) : par défaut le navigateur interdit de déposer un élément à l'intérieur d'un autre conteneur.
Pour autoriser un dépôt, nous devons empêcher la gestion par défaut du navigateur avec l'instruction e.preventDefault()

Fonction deposer(e) : ajout de l'élément transféré au conteneur "destination" via l'instruction
e.currentTarget.appendChild(document.getElementById(objet))

"Drag and drop" dans les deux sens

Dans l'exemple précédent, on peut transférer une image du conteneur "source" vers le conteneur "destination" mais par l'inverse. C'est facheux si on s'est trompé et que l'on veuille annuler un mauvais choix.

Pour un drag & drop bilatéral il suffit d'associer les trois événements aux deux conteneurs.

Le rendu

Ci-dessous un document HTML dans lequel les images sont transférables dans les deux sens.

Le code HTML

Le script ne change pas ! Il suffit d'associer les trois évènements aux conteneurs source et destination ; il suffit donc de modifier le code de la partie BODY.

Les événements sont insensibles à la "casse". Vous pouvez écrire "onDragStart" ou "ondragstart" , "onDragOver" ou "ondragover", "onDrop" ou "ondrop".

Un script générique

Le rendu

Ci-dessous un document HTML avec des images dans un conteneur.

Il n'y a pas de conteneur "destination" mais il y a un bouton de commmande ...

Cliquez sur le bouton de commande ! Notez l'ajout d'une nouvelle boite et la disparition du bouton de commande.
Tentez de déplacer les images d'un conteneur vers un autre.
Je vous invite aussi à lire l'onglet "éléments" de la console pour voir tout le code HTML généré par le script.

Code initial de la partie BODY

Notez l'absence d'attribut ID et draggable pour les images.

Le script

function ajout()
{
	var destination = document.createElement('div');
	destination.setAttribute("id", "destination");
	destination.setAttribute("class","boite");
	document.querySelector('body').appendChild(destination); 

	var images = document.querySelectorAll('img') ; 
	var source = document.getElementById('source');
	var destination = document.getElementById('destination');

	// affectation de deux attributs à chaque image
	for (var i =0 ; i < images.length ; i++)
	{
		images[i].setAttribute("id", "img" + i);
		images[i].setAttribute("draggable",true);
		// instructions provisoires
		console.log(images[i].getAttribute('id')); 
		console.log(images[i].getAttribute('draggable')); 
	}
	// gestion des événements
	source.addEventListener('dragstart', debut); 
	source.addEventListener('dragover', glisser); 
	source.addEventListener('drop', deposer); 
	destination.addEventListener('dragstart', debut); 
	destination.addEventListener('dragover', glisser); 
	destination.addEventListener('drop', deposer); 

	// fonction associée à dragstart
	function debut(e)
	{
		e.dataTransfer.effectAllowed ="move";
		e.dataTransfer.setData('text',e.target.getAttribute('id'));
	}
		// fonction associée à dragover
	function glisser(e) {e.preventDefault(); }

	// fonction associée à drop 
	function deposer(e)
		{
			objet  = e.dataTransfer.getData('text');
			e.currentTarget.appendChild(document.getElementById(objet));
			e.stopPropagation;
		}
	document.querySelector('button').remove();
} // fin ajout

Dans une premier temps le script crée un nouveau DIV avec certains attributs.
Cette boite est insérée à la fin de BODY.
Puis le script crée de nouveaux attributs pour les images (ID et draggable).

Ensuite gestion des six événements (trois par conteneur) avec utilisation de la méthode addEventListener()
Attention à la syntaxe dans le cadre de cette méthode ; les événements sont entre quotes et ne sont plus préfixés "on".

En résumé

Il suffit de rajouter ce script à une page web pour que les images de celle-ci deviennent transférables d'un conteneur vers un autre.
Il est préférable d'externaliser ce script. J'ai donc mis le code dans une fichier nommée "ajout.js" ; ce script se lance automatiquement car j'ai rajouté l'instruction ajout(); // appel de la fonction ajout().
Récupération de ce fichier

La page test

Notez l'instruction qui charge le fichier "ajout.js".

Ouvrez cette page web avec un navigateur.
Observez l'ajout d'un nouveau conteneur.
Vous pouvez faire des drag & drop bilatéraux.