Un drag and Drop Dojo modifié

Le drag and drop proposé par le framework Dojo est particulièrement bien fait et efficace.
Le comportement de base est que lorsqu'un objet est dropé il s'insère et décale les objets suivants.
Nous allons voir ici comment modifier ce comportement afin pouvoir intervertir des éléments. C'est à dire que l'objet dropé prendra la place de l'objet ciblé et vice-versa.

Avant tout chose je vous conseil de lire la documentation concernant Dojo et plus particulièrement celle concernant le drag and drop

Le css

Les css n'ont pas d'influence sur le comportement du drag and drop ils permettent juste de rendre certain évènement plus évidents.

css
.target {border: 1px dotted gray; width: 300px; height: 300px;padding: 5px; 
              -moz-border-radius:8pt 8pt;radius:8pt;}
	ul {border: 1px dotted skyblue;
               -moz-border-radius:8pt 8pt;radius:8pt; overflow:auto;}
    ul li {float:left; padding:10px; border:1px solid #F00;}
	.dojoDndItemOver {background: #feb;border: 1px dotted gray; }
	.dojoDndItemBefore {border-left: 2px dotted gray; }
	.dojoDndItemAfter {border-right: 2px dotted gray; }
	.target .dojoDndItemAnchor {border:1px solid gray;}
	.dojoDndAvatar {font-size: 75%; color: black;}
	.dojoDndAvatar td {padding-left: 20px; padding-right: 4px;height:20px}
	.dojoDndAvatarHeader {background: #ccc; background-repeat: no-repeat;}
	.dojoDndAvatarItem {background: #eee;}
	.dojoDndMove .dojoDndAvatarHeader {background-image: url(images/dndNoMove.png);}
	.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader {background-image: 
                url(images/dndMove.png);}

Le javascript

javascript
 dojo.require("dojo.dnd.Source"); // capital-S Source in 1.0
 
		function init()	{			
			//recupere la valeur de l'img dropee
			dojo.subscribe("/dnd/drop", function(source,nodes,iscopy){
				var target = dojo.dnd.manager().target	
 
				//le noeud dropé
				dropedNode=nodes[0];
				dropedNodeData=dropedNode.getAttribute("dndData");
 
				//le noeud cible
				targetNode=target.current;
                                if (!targetNode) 
					return false;
				targetNodeData=targetNode.getAttribute("dndData");
 
				//le conteneur
				sourceNode=source.node;
 
				//on oblige le noeudDrope a se placer derriere le noeudCible
 
 
				//on deplace le noeud cible
				AfterId="pos"+(parseInt(dropedNode.getAttribute("dndData"))+1);
				if (AfterId!=targetNode.id)
					sourceNode.insertBefore(targetNode,dojo.byId(AfterId));
				else 
					sourceNode.insertBefore(targetNode,dropedNode);
 
				//on met à jour les id et les dndData
				dropedNode.id=targetNode.id;								
				targetNode.id="pos"+parseInt(dropedNode.getAttribute("dndData"));
				targetNode.setAttribute("dndData",dropedNodeData);
				dropedNode.setAttribute("dndData",targetNodeData);		
			});
		}
 
		dojo.addOnLoad( init );

Ici on créé une fonction qui sera appelée au moment du drop de l'objet.
Le principe est simplement de repérer le noeud dropé et le noeud cible et de déplacer les noeuds en conséquence.
On remet à jour ensuite les id et les dndData afin qu'il n'y ai pas de bug lors d'un prochain mouvement.

Le code HTML

html4strict
<ul dojoType="dojo.dnd.Source" jsId="s1" class="source" accept="li">
	<li class="dojoDndItem" dndType="li" dndData="1" id="pos1" ><img src="01_01arthur.jpg" alt="one" height="150px"/></li>
	<li class="dojoDndItem" dndType="li" dndData="2" id="pos2"><img src="01_a1.jpg" alt="two" height="150px"/></li>
 
	<li class="dojoDndItem" dndType="li" dndData="3" id="pos3"><img src="01_a.jpg" alt="three" height="150px"/></li>
	<li class="dojoDndItem" dndType="li" dndData="4" id="pos4"><img src="01_b.jpg" alt="four" height="150px"/></li>
</ul>

Ici on créé une liste UL qui sera définie comme source de notre drag and drop (c'est à dire le lieu ou peuvent être dropés les éléments)
Chaque Li est donc dragable.
Les id et les dndData nous permette de repérer chaque Li. Ils seront mis à jour au fur et à mesure des déplacements.

Le code complet

html4strict
<html>
<head>
<title>Modifier la position des images</title>
<style type="text/css">
        .target {border: 1px dotted gray; width: 300px; height: 300px;padding: 5px; 
              -moz-border-radius:8pt 8pt;radius:8pt;}
	ul {border: 1px dotted skyblue;
               -moz-border-radius:8pt 8pt;radius:8pt; overflow:auto;}
    ul li {float:left; padding:10px; border:1px solid #F00;}
	.dojoDndItemOver {background: #feb;border: 1px dotted gray; }
	.dojoDndItemBefore {border-left: 2px dotted gray; }
	.dojoDndItemAfter {border-right: 2px dotted gray; }
	.target .dojoDndItemAnchor {border:1px solid gray;}
	.dojoDndAvatar {font-size: 75%; color: black;}
	.dojoDndAvatar td {padding-left: 20px; padding-right: 4px;height:20px}
	.dojoDndAvatarHeader {background: #ccc; background-repeat: no-repeat;}
	.dojoDndAvatarItem {background: #eee;}
	.dojoDndMove .dojoDndAvatarHeader {background-image: url(images/dndNoMove.png);}
	.dojoDndMove .dojoDndAvatarCanDrop .dojoDndAvatarHeader {background-image: 
                url(images/dndMove.png);}
</style>
<script type="text/javascript" src="../script/dojoroot/dojo/dojo.js" djConfig="parseOnLoad: true">
</script>
<script type="text/javascript"> 
        dojo.require("dojo.dnd.Source"); // capital-S Source in 1.0
 
		function init()	{			
			//recupere la valeur de l'img dropee
			dojo.subscribe("/dnd/drop", function(source,nodes,iscopy){
				var target = dojo.dnd.manager().target	
 
				//le noeud dropé
				dropedNode=nodes[0];
				dropedNodeData=dropedNode.getAttribute("dndData");
 
				//le noeud cible
				targetNode=target.current;
				targetNodeData=targetNode.getAttribute("dndData");
 
				//le conteneur
				sourceNode=source.node;		
 
				//on deplace le noeud cible
				AfterId="pos"+(parseInt(dropedNode.getAttribute("dndData"))+1);
				if (AfterId!=targetNode.id)
					sourceNode.insertBefore(targetNode,dojo.byId(AfterId));
				else 
					sourceNode.insertBefore(targetNode,dropedNode);
 
				//on met à jour les id et les dndData
				dropedNode.id=targetNode.id;								
				targetNode.id="pos"+parseInt(dropedNode.getAttribute("dndData"));
				targetNode.setAttribute("dndData",dropedNodeData);
				dropedNode.setAttribute("dndData",targetNodeData);		
			});
		}
 
		dojo.addOnLoad( init );	
</script>
</head>
<body>
<ul dojoType="dojo.dnd.Source" jsId="s1" class="source" accept="li">
	<li class="dojoDndItem" dndType="li" dndData="1" id="pos1" >one</li>
	<li class="dojoDndItem" dndType="li" dndData="2" id="pos2">two</li>
 
	<li class="dojoDndItem" dndType="li" dndData="3" id="pos3">three</li>
	<li class="dojoDndItem" dndType="li" dndData="4" id="pos4">four</li>
</ul>
</body>

Demo

dojo-dnd.html


08/04/2008 12:12 -

ManiT4c
Gérant et chef de projet de l'agence web Op'art, je suis également webmaster freelance. Retrouvez moi également sur twitter.