Il est toujours compliqué de proposer au internautes de trier des éléments et faire ça de manière simple et ergonomique. On peut, par exemple, proposer de saisir la position pour chaque élément. Mais ça reste contraignant.
C’est dans cette optique qu’apparaît l’option du drag’n'drop (glisser-déposer en français). Je pense que c’est ce qu’il y a de plus simple et intuitif pour l’internaute. Il faut néanmoins le prévenir que l’on attend un glisser-déposer de sa part car ce n’est pas encore répandu absolument partout !
Voir la démo du tutorial
Pour réaliser cela, JQueryUI nous propose le widget nommé Sortable. Il permet de créer et de configurer le drag’n'drop pour une liste d’éléments. Pour commencer, il faut donc inclure : JQuery et JQueryUI (javascript et CSS).
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <link rel="stylesheet" href="jquery-ui-1.8.5.custom.css" type="text/css" /> <script type="text/javascript" src="jquery-ui-1.8.5.custom.min.js"></script>
Pour sauvegarder le tri fait par l’internaute, il faut enregistrer le tout dans la base de données. Je te fournis donc celle utilisée dans la démo. Où chauqe élément à un id unique, name contient le nom du fichier de la photo et position pour enregistrer l’ordre des photos.
-- -- Structure de la table `demo_photo` -- CREATE TABLE `demo_photo` ( `id` int(11) NOT NULL auto_increment, `name` varchar(255) collate latin1_german2_ci NOT NULL, `position` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `order` (`position`) ) AUTO_INCREMENT=6 ; -- -- Contenu de la table `demo_photo` -- INSERT INTO `demo_photo` VALUES (1, '1.jpg', 2); INSERT INTO `demo_photo` VALUES (2, '2.jpg', 3); INSERT INTO `demo_photo` VALUES (3, '3.jpg', 4); INSERT INTO `demo_photo` VALUES (4, '4.jpg', 1); INSERT INTO `demo_photo` VALUES (5, '5.jpg', 0);
Ensuite il faut préparer la liste d’éléments sur lequel se portera le tri. Les attributs « id » des éléments de la liste devront respecter une syntaxe particulière : « nomGenerique_id ». Ou nomGenerique est le même pour tout les éléments (par exemple « photo ») et id l’identifiant unique (dans la base de données) de l’élément à trier.
Pour afficher la liste, on récupère bien sûr les éléments dans la base de données, en respectant l’ordre enregistré :
<ul id="list-photos"> <?php //connexion à la base de données define('DB_NAME', 'nom_de_la_base'); define('DB_USER', 'nom_utilisateur'); define('DB_PASSWORD', 'mot_de_passe'); define('DB_HOST', 'localhost'); $link = mysql_connect( DB_HOST , DB_USER , DB_PASSWORD ); mysql_select_db( DB_NAME , $link ); // récupération des photos dans le bon ordre $result = mysql_query( 'SELECT demo_photo.id, demo_photo.name FROM demo_photo ORDER BY demo_photo.position ASC' , $link ); while( $photo = mysql_fetch_assoc( $result )) { ?> <li id="photo_<?php echo $photo['id'] ?>"> <img src="photos_NY/<?php echo $photo['name'] ?/>" alt="Photos NY - Arnaud-k" /> <p>par Arnaud-k</p> </li> <?php } ?> </ul>
Il faut ensuite mettre en forme cette liste avec du CSS. Je ne pense pas qu’il faille beaucoup d’explications pour cette partie là.
/* style global de la liste non ordonné */ ul#list-photos{ list-style:none; height:140px; } /* style des éléments de la liste */ ul#list-photos li{ border:1px solid #ddd; padding:10px; cursor:move; height:100px; width:75px; float:left; margin-right:10px; background:#fff; color:#212326; font-size:12px; -moz-box-shadow:2px 2px 5px #ccc; } /* style de l'élément fantome, qui apparait losque que l'on bouge un élément */ ul#list-photos li.highlight{ background:#f2f2f2; border:1px dashed #212326; }
Ensuite vient la partie qui nous intéresse vraiment, le code JQuery. On initialise Sortable avec l’id de la liste et on met en Callback l’appel Ajax au fichier PHP qui va procéder à l’enregistrement dans la base données :
$(document).ready( function(){ // quand la page a fini de se charger $("#list-photos").sortable({ // initialisation de Sortable sur #list-photos placeholder: 'highlight', // classe à ajouter à l'élément fantome update: function() { // callback quand l'ordre de la liste est changé var order = $('#list-photos').sortable('serialize'); // récupération des données à envoyer $.post('ajax.php',order); // appel ajax au fichier ajax.php avec l'ordre des photos } }); $("#list-photos").disableSelection(); // on désactive la possibilité au navigateur de faire des sélections });
Et voici enfin le contenu du fichier ajax.php qui enregistre les positions des éléments. On récupère un $_POST de la forme : photo[] = id_photo. Il suffit de boucler sur ce tableau ($_POST['photo']) et on récupère les id des photos dans l’ordre :
<?php //connexion à la base de données define('DB_NAME', 'nom_de_la_base'); define('DB_USER', 'nom_utilisateur'); define('DB_PASSWORD', 'mot_de_passe'); define('DB_HOST', 'localhost'); $link = mysql_connect( DB_HOST , DB_USER , DB_PASSWORD ); mysql_select_db( DB_NAME , $link ); // changement de l'ordre des photos dans la base de données, photo par photo foreach( $_POST['photo'] as $order => $id_photo ) { mysql_query( 'UPDATE demo_photo SET position = \'' . safe( $order ) . '\' WHERE id = \'' . safe( $id_photo ) . '\'' , $link ) or die( mysql_error() ); } /***** fonctions *****/ function safe($var) { $var = mysql_real_escape_string($var); $var = addcslashes($var, '%_'); $var = trim($var); $var = htmlspecialchars($var); return $var; } ?>
J’espère que tutoriel est clair et compréhensible. Il faut, certes, un minimum de connaissances en html, javascript et php mais je pense que ça vaut quand même le coup !
Pas encore de billet sur le même sujet !












Hello,
Je découvre tes tutos et ce n’est que du bonheur.
Je bosse normalement en html+CSS+php mais il est temps pour moi de passer a quelque chose de plus. (suis ancien codeur AS2 en fait).
Je suis sur un projet open source http.//openardilla.org qui est à la base juste un ptit gestionnaire perso de bookmarks. Comme on m’en a souvent demander les sources, je l’ai passé sous GPL2 et ai ajouté un gestion simpliste de flux et de notes (anciennement cave à vin aussi)
Je cherchais exactement ce genre de tutos pour faire évoluer mon projet.
.
Salut !
Très bon tuto, simple clair et efficace !
Merci pour le partage, ce tuto m’a été bien utile pour un de mes projets.
Je reviendrai voir le reste qui me semble plutôt bien fourni
Bonjour Arnaud,
Tout d’abord merci beaucoup pour le temps passé à faire ce tuto… c’est grâce à des gens comme toi que des personnes comme moi, autodidacte, peuvent apprendre jour après jour.
Jusqu’ici je bossais sur de l’AS2 et depuis quelques semaines je me mets peu à peu à l’HTML, PHP, Jquery etc… pour faire le site internet d’un ami photographe.
J’ai essayé tant que possible d’appliquer ton tuto… celui-ci fonctionne parfaitement bien… mais il y a un problème que je n’arrive pas à résoudre malgré les recherches multiples que j’ai pu faire…
Voilà lorsque je drag and drop mes fichiers, ceux-ci changent bien de place par contre dès que je recharge ma page, malheureusement ils reprennent leur place initiale.
Comment puis-je faire (où qu’ai-je fais de travers) pour que mes modifications d’ordre s’enregistre sur ma base de donnée Mysql?
Voilà le code que j’ai pour le moment sur ma page html : (j’ai juste enlevé mes identifiants)
————————————————
Untitled Document
/************
STYLE DE LA LISTE A TRIER
************/
ul#list-photos{
list-style:none;
height:140px;
}
ul#list-photos li{
border:1px solid #ddd;
padding:10px;
cursor:move;
height:100px;
width:75px;
float:left;
margin-right:10px;
background:#fff;
color:#212326;
font-size:12px;
-moz-box-shadow:2px 2px 5px #ccc;
}
ul#list-photos li.highlight{
background:#f2f2f2;
border:1px dashed #212326;
}
/************
DEBUT DU SCRIPT POUR LE DRAG’N'DROP
************/
$(document).ready( function(){ // quand la page a fini de se charger
$(« #list-photos »).sortable({ // initialisation de Sortable sur #list-photos
placeholder: ‘highlight’, // classe à ajouter à l’élément fantome
update: function() { // callback quand l’ordre de la liste est changé
var order = $(‘#list-photos’).sortable(‘serialize’); // récupération des données à envoyer
$.post(‘ajax.php’,order); // appel ajax au fichier ajax.php avec l’ordre des photos
}
});
$(« #list-photos »).disableSelection(); // on désactive la possibilité au navigateur de faire des sélections
});
<li id="photo_ »>
———————————————————————————————–
Voilà celui de ma page ajax.php
$id_photo )
{
mysql_query( ‘UPDATE Dynamic SET position = \ » . safe( $order ) . ‘\’ WHERE id = \ » . safe( $id_photo ) . ‘\ » , $link ) or die( mysql_error() );
}
/*****
fonctions
*****/
function safe($var)
{
$var = mysql_real_escape_string($var);
$var = addcslashes($var, ‘%_’);
$var = trim($var);
$var = htmlspecialchars($var);
return $var;
}
?>
———————————–
Ma base de donnée se présente ainsi :
id / TitreAlbum/ OrdreAlbum
——————————–
J’espère vraiment que tu pourras m’aider, car j’ai longtemps cherché toute seule avant de te contacter.
Merci encore pour tout
Maxence
Résolu : ma classe order n’était pas en clé « index » et c’est pour cela que ça ne fonctionnait pas !
Bonjour ,
Un très grand merci pour ce module drag and drop.
Est- il adapatble sur un tableau j’ai essayé sans succes
merci de votre aide
Très bonne idée, dommage que ça fonctionne pas sur IE9 l’exemple .
Quelqu’un a une soluce?
Et bien je suis étonnée que ça ne fonctionne pas sur IE9 car ça fonctionne sur IE8 sans soucis…
Pour la compatibilité IE9, il faudrait essayer en mettant à jour JQuery UI vers la dernière version. Dans l’exemple c’est la version 1.8.5 et on en est à la 1.8.10.
Ça peut être une bonne piste !
Sympa ce tuto. Perso ça ne me servira pas mais je peux comprendre que ça plaise à pas mal de monde.
En tout cas je t’encourage à poursuivre.
Bonne journée
Super pour ce tuto, simple et bien expliqué, ça marche nickel ! Dans la meme idée, y a t’il moyen de pouvoir intervertir deux photos par exemple la une et la trois sans que les autres ne bougent.
La trois viendrait prendre la place de la une et vice versa, les autres photos conservent leur position.
Bonjour,
Super tuto très clair.
Ici il y a échange de code html. Comment faire pour qu’entre un composant Jquery UI et le code php ne s’échange que des données formatées par exemple en XML ? Ceci pour isoler la couche de présentation de la logique de code.
Merci
Bonjour,
oui un très bon tuto.
Par contre quand on y couple une pagination, là l’ordre des photos devient complètement chaotique. Et en cas de galerie photos, la pagination est inévitable.
Si quelqu’un a une solution.
Merci
c’est sympa comme tuto,
par contre j’ai un petit souci quand je veux passer une autre variable en POST.
En fait quand on passe order en POST on obtient une array pour les positions avec les valeurs 0,1,2,3 etc…
Mais si vous y incluez une autre variable :
var order = $(‘#list-photos’).sortable(‘serialize’);
var toto = ‘toto’;
var donnees = « order= »+order+ »&toto= »+toto;
$.post(‘ajax.php’,donnees); // appel ajax au fichier ajax.php avec l’ordre des photos
l’array de position donne 0,0,1,2,3,4,etc….
Donc 2 positions à 0.
L’auteur ou un internaute saurait il pourquoi ?
Merci à tous
Super merci pour ce tutorial.
Moi qui suis un quiche en ajax et qui cherchai justement à trier des photos après upload, je te dis un immense merci pour ton script qui est aussi clair qu’efficasse!
Chapeau l’artiste!
Un grand merci Arnaud, vous m’avez sauvez la vie. Respect MAN
Bonjour, je me permet d’ajouter un petit complément pour optimiser la requête dans ajax.php
En effet tel qu’il est écrit dans le tuto il effectue autant de requête qu’il y a de photos à trier.
Je vous propose une solution qui permet de faire l’opération en une seule requête afin de moins solliciter le serveur dans le cas où il y aurait beaucoup de photo à trier:
$id_photo){
$requete .= 'WHEN '.safe($id_photo).' THEN '.safe($order).' ';
}
$requete .= 'ELSE position END';
mysql_query($requete , $link ) or die( mysql_error() );
/*****
fonctions
*****/
function safe($var)
{
$var = mysql_real_escape_string($var);
$var = addcslashes($var, '%_');
$var = trim($var);
$var = htmlspecialchars($var);
return $var;
}
?>
petite erreur d’affichage dans la balise code que j’ai mis dans le com et qui ma supprimer le début… revoila le code :
//connexion à la base de données
define(‘DB_NAME’, ‘nom_de_la_base’);
define(‘DB_USER’, ‘nom_utilisateur’);
define(‘DB_PASSWORD’, ‘mot_de_passe’);
define(‘DB_HOST’, ‘localhost’);
$link = mysql_connect( DB_HOST , DB_USER , DB_PASSWORD );
mysql_select_db( DB_NAME , $link );
// changement de l’ordre des photos dans la base de données, photo par photo
$requete = ‘ UPDATE demo_photo SET position = CASE demo_photo.id ‘;
foreach ($_POST['photo'] as $order =>$id_photo){
$requete .= ‘WHEN ‘.safe($id_photo).’ THEN ‘.safe($order).’ ‘;
}
$requete .= ‘ELSE position END’;
mysql_query($requete , $link ) or die( mysql_error() );
/*****
fonctions
*****/
function safe($var)
{
$var = mysql_real_escape_string($var);
$var = addcslashes($var, ‘%_’);
$var = trim($var);
$var = htmlspecialchars($var);
return $var;
}
Ta fonction ‘safe’ ici est inutile.
Tu récupère 2 entiers ‘id_photo’ et ‘order’, tu as juste besoin de mettre un (int) devant tes variables.
Tu fais une grosse économie de performance.
Bonjour,
Tout d’abord merci pour ce tuto ( c’est exactement ce que je cherchais pour créer un gestionnaire de tâches.)
Je suis en pleine implémentation et j’ai remarqué une toute petite coquille dans le code.
<li id="photo_ »>
<img src="photos_NY/ » alt= »Photos NY – Arnaud-k » />
par Arnaud-k
Cette ligne :
doit être :
/>
Il manque juste le chevron pour fermer le code PHP.
Encore merci pour ce tuto comme pour le site !
Cordialement Anthony
Bonjour,
Tout d’abord merci pour ce tuto ( c’est exactement ce que je cherchais pour créer un gestionnaire de tâches.)
Je suis en pleine implémentation et j’ai remarqué une toute petite coquille dans le code.
<li id="photo_">
<img src="photos_NY//>" alt="Photos NY - Arnaud-k" />
par Arnaud-k
Cette ligne :
doit être :
/>Il manque juste le chevron pour fermer le code PHP.
Encore merci pour ce tuto comme pour le site !
(désolé pour le double poste, je n’avais pas mis les balises pour le code)
Cordialement Anthony
Je découvre les nombreuses ressources pour JQuery de ton blog.. C’est génial ! Bravo !
Ma question est : comment ajouter de nouveaux éléments a cette liste, en utilisant le dragNdrop ??
Merci de votre aide
Ne fonctionne pas sous IE 9