28sept/1117

Tutoriel: Drag and drop jQuery / AJAX

Publié par Sébastien dans Développement, Tutoriel

L'apparition du drag and drop sur la toile ne date pas d'hier, et cela peut s'avérer très utile dans un back office, par exemple pour gérer l'ordre des éléments d'un menu ou d'une galerie d'images.

Mais pour que ce soit vraiment puissant, il faut bien évidemment que les modifications soient enregistrées en base de données, et en temps réel!

Guillaume Voisin a présenté un tutoriel très clair sur la façon de mettre en place un système de drag and drop dans son article Drag and Drop jQuery. C'est pourquoi, à partir de cette base, je me limiterai à la partie sauvegarde en live en base de données.

Voir la DEMO - Télécharger l'archive

Base de données

Avant de se lancer dans le code, il faut avant tout avoir une table en base de données avec au minimum l'architecture suivante:

Structure de la table en base de données

Structure de la liste HTML

On va pouvoir reprendre la liste HTML du tutoriel de Guillaume Voisin à un petit détail près: il faut préciser pour chaque ligne l'identifiant en base de données de l'élément affiché.

<ul>
	<li id="Element_1">Milk</li>
	<li id="Element_2">Red wine</li>
	<li id="Element_3">Sugar</li>
	<li id="Element_4">Ice Cream</li>
</ul>

Mise en place du drag and drop

Comme dit précédemment, le tutoriel de Drag and Drop jQuery de Guillaume Voisin explique en détail comment mettre en place une liste qu'on peut facilement réordonner à l'aide du drag and drop.

On va donc partir de cet exemple en se limitant à la partie "tri drag and drop" de la liste, pour ajouter le code nécessaire à la mémorisation en base de données.

Vous devrez donc avoir dans le fichier appelé jquery.shoppingList.js le code suivant:


$(obj).sortable({
	axis: "y", // Le sortable ne s'applique que sur l'axe vertical
	containment: ".shoppingList", // Le drag ne peut sortir de l'élément qui contient la liste
	handle: ".item", // Le drag ne peut se faire que sur l'élément .item (le texte)
	distance: 10, // Le drag ne commence qu'à partir de 10px de distance de l'élément
	// Évènement appelé lorsque l'élément est relâché
	stop: function(event, ui){
		// Pour chaque item de liste
		$(obj).find("li").each(function(){
			// On actualise sa position
			index = parseInt($(this).index()+1);
			// On la met à jour dans la page
			$(this).find(".count").text(index);
		});
	}
});

C'est dans ce code que nous allons pouvoir intégrer un appel à la mise à jour de l'ordre des éléments de la liste.

Appel de la mise à jour

On va maintenant demander à notre code jQuery d'appeler une page, qu'on appellera updateListe.php, contenant un script php qui va mettre à jour la position des éléments en base de donnée.

Il suffit donc d'ajouter dans le code précédent le code suivant:

update: function()
{
	// On prépare la variable contenant les paramètres
	var order = $(this).sortable("serialize")+'&action=updateListeOrder';
	// $(this).sortable("serialize") sera le paramètre "element", un tableau contenant les différents "id"
	// action sera le paramètre qui permet éventuellement par la suite de gérer d'autres scripts de mise à jour

	// Ensuite on appelle notre page updateListe.php en lui passant en paramètre la variable order
	$.post("/updateListe.php", order, function(theResponse){});
} 

Il est possible de récupérer une réponse du script pour afficher un message à l'utilisateur. Notre script jQuery final (pour la partie concernant le tri) aura donc cette allure:

$(obj).sortable({
	axis: "y", // Le sortable ne s'applique que sur l'axe vertical
	containment: ".shoppingList", // Le drag ne peut sortir de l'élément qui contient la liste
	handle: ".item", // Le drag ne peut se faire que sur l'élément .item (le texte)
	distance: 10, // Le drag ne commence qu'à partir de 10px de distance de l'élément
	// Évènement appelé lorsque l'élément est relâché
	stop: function(event, ui){
		// Pour chaque item de liste
		$(obj).find("li").each(function(){
			// On actualise sa position
			index = parseInt($(this).index()+1);
			// On la met à jour dans la page
			$(this).find(".count").text(index);
		});
	},
	update: function()
	{
		// On prépare la variable contenant les paramètres
		var order = $(this).sortable("serialize")+'&action=updateListeOrder';
		// $(this).sortable("serialize") sera le paramètre "element", un tableau contenant les différents "id"
		// action sera le paramètre qui permet éventuellement par la suite de gérer d'autres scripts de mise à jour

		// Ensuite on appelle notre page updateListe.php en lui passant en paramètre la variable order
		$.post("/updateListe.php", order, function(theResponse)
		{
			// On affiche dans l'élément portant la classe "reponse" le résultat du script de mise à jour
			$(".reponse").html(theResponse).fadeIn("fast");
			setTimeout(function()
			{
				$(".reponse").fadeOut("slow");
			}, 2000);
		});
	}
});

Script de mise à jour de la base de données

Il ne reste maintenant plus qu'à lancer le script de mise à jour de la base de données.

On va donc créer notre fichier updateListe.php, à qui on va passer en paramètre l'action à effectuer ainsi que le tableau des identifiants de chaque élément.

Le fichier va contenir le script suivant:

// On se connecte à notre base de données
$host = "myDBServer";
$user = "myDBUser";
$db = "myDBName";
$pass = "myDBPassword";

mysql_connect($host, $user, $pass) or die(mysql_error());
mysql_select_db($db) or die(mysql_error());

// On analyse la variable POST action (qui permet éventuellement de gérer plusieurs scripts de mise à jour)
if( $_POST['action'] == "updateListeOrder")
{
	// On récupère le tableau des ID de chaque élément
	$elements = $_POST['element']

	// On indique le premier indice de position souhaité
	$position = 1;

	// Et on met à jour la base de données
	foreach($elements as $id)
	{
		$sql = 'UPDATE rubriques SET position = '.$position.' WHERE id='.$id;
		mysql_query($sql) or die(mysql_error());
		$position++;
	}
}

Conclusion

Vous avez maintenant tout ce qu'il faut pour que votre drag and drop mémorise en temps réel la position de vos éléments en base de données.

A partir de là, vous pouvez faire évoluer ce script pour que toutes les actions du tutoriel de Guillaume Voisin soient aussi mémorisées dans la table de vos éléments!

Commentaires (17) Trackbacks (1)
  1. ce drag and drop est exactement ce qu’il me faut, sauf qu’il ne fonctionne pas avec explorer. avez-vous une astuce, ou un lien vers un autre code qui fait la même chose (modif de la base de donnée) et compatible explorer ?
    merci d’avance,

    petite fée

    • Alors effectivement il y a un petit problème, mais seulement avec IE9 (sur les versions précédentes ça fonctionne à priori). Il semblerait que ce soit le drag-and-drop qui ne fonctionne pas, sûrement une petite erreur de ma part lors de la reprise du code de Guillaume Voisin, puisque son tuto est sensé fonctionner sous IE9.
      Je travaille sur mac, du coup je regarderais tout ça dès que j’ai accès à un PC !

      • Bonjour Sébastien, et merci de ta réponse.
        je découvre le jquery, et il me semble évident que je dois apprendre et intégrer maintenant ce fonctionnement dans la construction de mes sites.
        je tatonne donc, et je suis prise par le temps.
        je suis allée voir le tuto d’origine de Guillaume voisin, mais sa démo de drag and drop ne fonctionne pas non plus avec mon explorer 9… firefox est ok par contre.

        le problème ne vient donc pas de toi.

        peut-être as-tu une idée, ou quelqu’un en visite sur ce forum, pour régler ce problème ?
        soit par une correction du code (je ne maitrise pas encore assez cette technique pour le faire) ou en m’indiquant une autre source drag and drop compatible explorer 9 ?

        d’avance merci,

        Petite fée

        • Re-bonjour

          Problème corrigé, il suffisait de mettre à jour les librairies jQuery et le tour est joué!

          Ce tuto drag and drop fonctionne donc pour, à priori, tous les navigateurs (Firefox, Chrome, Safari, Opera, IE9, IE8, IE7)

          • Merci beaucoup,
            pour ta rapidité d’intervention et aussi ton travail.
            pas facile de trouver des tutos et des sources qui fonctionnent simplement, et surtout, EN FRANCAIS !!

            chapeau m’sieur :o )

  2. excellent! mais il me semble que l’exemple live n’est pas tout à fait iso avec le code dans la page ou dans l’archive.
    perso, en partant de l’archive, la sauvegarde du nouvel ordre en base est OK, mais suite à un refresh de la page, l’ordre n’est pas rétabli :-(

  3. Bonjour deadfish,
    tu as bien vérifié que dans la base l’odre est bien le bon ?
    parce que :
    soit l’ordre est bon sur ta vérif sur la page mais pas dans la base ce qui pourrait venir d’un problème de ta requête (update…)
    soit la base est bien mise à jour quand tu regardes dedans, et c’est le refresh qui n’est pas bon, peut-être parce que ton navigateur te réaffiche ta page d’après une archive conservée en cache.
    vérifies les données dans ta base après avoir fait ton glissé-déposé, mais AVANT de rafraichir la page.
    encore une idée : ta requête d’affichage se fait avant ou après la requête update ?
    il est possible qu’en raffraichissant ta page celle-ci conserve les anciens emplacement (et donc le précédent array), et que ta requête d’update se re-lance et remodifie la base (c’est pourquoi je te propose de vérifier les données de ta base avant de rafraichir la page)

    @ +
    Elizabeth

  4. Bonjour,

    j’essaye de faire fonctionner votre script sans trop de succès malheureusement. J’ai aucun action d’enregistrement qui ce fait dans MYSQL.

    if( $_POST['action'] == « updateListeOrder ») devrait être if( $_GET['action'] == « updateListeOrder »)

    Merci de votre aide

    Christophe

  5. bonjour,
    même problème pour moi,
    le message « positions mise à jour » n’apparait pas comme il le fait dans la démo,
    et la base de donnée n’est pas modifiée…
    christophe, as-tu trouvé la solution ?

  6. Alors il y a trois points où il faut faire attention en reprenant le code source du tuto:

    1) dans le fichier index, bien remplacer « nom » dans $res['nom'] par le nom de votre élément dans la table
    2) dans jquery.shoppingList.js, vérifier que l’url passé en paramètre de la fonction $.post est correct, c’est ce qui permet la mise à jour.
    3) vérifier que les paramètres d’accès à la DB sont corrects dans le fichier db.php

    Si ça ne fonctionne toujours pas, vous pouvez encore essayer de mettre à jour vos fichiers jquery.min.s et jquery-ui.custom.min.js, mais à priori c’est sensé fonctionner avec ceux de l’archive…

  7. Dans jquery.shoppingList.js, enlever le premier « / » à la ligne 47 (Modification de l’URL)

    Remplacer /inc/updateListe.php
    Par inc/updateListe.php

    La mise à jour devrais se faire.

  8. Merci pour le tuto,
    le jquery fonctionne bien, mais pas la mise à jour, lorsque je drag un élément, j’ai le message « no datables selected », pourtant, j’ai bien sélectionné ma base de données et vérifié les chemins…
    Une idée ?

  9. Bonjour Sophie,
    j’ai eu le même problème,
    ajoute simplement un appel à ta base juste avant ta requête :
    mysql_select_db($database_client, $client);
    …et ensuite ta requete …$query = « SELECT * FROM etc.

  10. Merci petite fée,
    en fait le pb ne vient pas du sélect (je suis bien connectée à la base, ma page écho bien le contenu dans la page index), le problème vient de la mise à jour, donc de l’update (la connexion ne semble pas se faire…)

  11. j’ai trouvé, j’ai ajouté mysql_select_db avant l’update … il n’y était effectivement pas et bien que familière de ce genre de requête, je l’ai happé!
    Merci !

  12. c’est une erreur que je fais tout le temps…
    et je suis familière aussi !
    du coup c’est ce que je regarde en premier quand ça ne fonctionne pas :o )


Laisser un commentaire

(required)

Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.