CLIQUER-GLISSER

illus

script : dragOn v2.1
langage : javascript
catégorie : module
usage : Déplacez les éléments html à la souris, par effet de "drag and drop"
tags : ergonomie

Concept

Un petit élément d'ergonomie bien pratique : le glisser-déposer, aussi connu sous le nom de drag & drop.

Démo

Les trois blocs suivants ne demandent qu'à être déplacés :

une dragBox standard.

cette boîte-ci change de style quand on la déplace.

dragBox 3

cette boîte-ci doit être saisie par son titre

cette boîte-ci ne bouge qu'à la verticale.

cette boîte-ci ne peut pas être sortie de la zone en pointillés.

Cliquez ici pour remettre les blocs à leur position initiale.
Remarquez que lorsque vous déplacez un bloc, il passe au premier plan.

Intégration

Permièrement, charger le script, en insérant le code suivant entre les balises <head> et </head> de la page :

<script type="text/javascript" src="dragOn.min.js"></script>

Ensuite, placer une (ou des) <div> (ou tout autre élément se comporant comme un bloc) dans la page :
(Pour retrouver facilement notre élément en javascript, on va lui attibuer un id.)

<div id="ma_div">salut !</div>

Et puis à la fin du code html, juste avant le balise </body>, on peut maintenant déclarer les comportements des blocs. On les placera entre des balises <script type="text/javascript"> et </script>  :

Pour rendre déplaçable une <div>, on procède simplement comme ceci :

dragOn.apply( document.getElementById( "ma_div" ) );

Options

Le script propose aussi plusieurs options.
On les passera comme deuxième argument de la fonction, compilées dans un tableau associatif :

var draggable = document.getElementById('ma_div');
var options =  {
	handle : document.getElementById('handle'),
	movingClass : 'isMoving',
	cssPosition : 'fixed'
};
dragOn.apply( draggable, options );

Les options disponibles sont les suivantes :

options type description par défaut
handle HTMLElement
L'élément html qui servira de poignée.
(voir l'exemple rouge de la démo ci-dessus.)
l'élément déplaçable lui-même, tout entier.
movingClass String
Nom de classe css à donner à target quand on le déplace.
(voir l'exemple verte de la démo ci-dessus.)
null
cssPosition Boolean
Indique la position css initiale de l'élément déplaçable.
(utile uniquement pour les "position:fixed")
null
moveHoriz Boolean
Indique si target peut être déplacé dans le sens horizontal. true
moveVert Boolean
même chose, à la verticale !
(voir l'exemple bleu clair de la démo ci-dessus.)
true
moveArea HTMLElement
permet de restreindre la zone de déplacement à la surface de l'élément indiqué dans cette option.
(voir l'exemple jaune de la démo ci-dessus.)
null

Téléchargement

Vous trouverez dans ce zip une version minifiée du script (3Ko), et une autre commentée, ainsi que la feuille de styles utilisée dans la démo de cette page.

compatibilité :
Internet Explorer (6+) Firefox Safari Opera Google Chrome
(autres navigateurs non testés)

Notez que ce module embarque deux fragments de code présentés sur ce site : getPos, qui permet de connaître la position d'un élément html dans la page, et mousePos, qui nous renseigne sur la position de la souris.

Commentaires

  • Publier un nouveau commentaire
  • gravatar
    ça manque d'info :

    "dragOn.apply(document.getElementById('ma_div')); // super compliqué, hein !" visiblement, plus que vous ne le prétendez ;-)

    l'Objet "dragOn" où et comment est-il déclaré?
  • gravatar
    Oui, j'admets que ma petite exclamation présuppose quand même une connaissance de base du javascript.

    Sinon, pour répondre à ta question, l'objet "dragOn" est déclaré dans le fichier dragOn.js, qui est chargé grâce à la balise <script>.
    Tu n'as donc pas à te sourcier de sa déclaration, à moins bien sûr de vouloir apporter des modifications au script.
  • gravatar
    ça ne fonctionne pas
  • gravatar
    "ça ne fonctionne pas " => plus précis tu peux pas. X)
  • gravatar
    moi ca me dit "b is undefined" ...
  • gravatar
    Mise à jour

    Salut. Je mets en ligne aujourd'hui une nouvelle version script :
    Elle corrige les quelques bugs qu'on m'a signalés (merci), et intègre de nouvelles options (qui permettent de restreindre les déplacements).
  • gravatar
    Hello, merci, mais les 2 dernières boites bougent où je veux sous Firefox :D
  • gravatar
    On peux pas éditer -_-
    Sorry, ça fonctionne, faut vider le cache du navigateur avant de tester ^^
  • gravatar
    Fantastique ! Je cherchais un code de ce genre depuis très longtemps (ceux que j'avais testé ne fonctionnaient pas ou étaient très mal expliqué pour quelqu'un avec un aussi faible niveau que moi en javascript ).
    J'aurai juste deux petites questions et là ça serait nickel pour moi :
    - Pour le : moveArea : document.getElementById('area'), comment peut -on définir la taille de restriction de l'élément draggable ?
    Avec un div css ? ou directement dans le code ?
    Je suis un peu perdue sur ce coup la.
    - Y'a t'il une fonction qui permettrait avec un simple clique sur un bouton d'enregistrer les éléments draggés dans leur position finale ?
    Je vous demande cela car j'ai actuellement un jeu en ligne où j'aimerai vraiment créer une "pièce personnage" où les joueurs pourraient déplacer des objets sans sortir de la limite du cadre (d'où la première question) et ensuite enregistrer la façon dont ils ont aménagé les objets avec un simple clique sur un bouton (question 2).

    En tout cas merci beaucoup pour le code est les explications claires et précises ;-)
  • gravatar
    Salut Jess.

    Question 1 : Pour l'option redimArea, c'est effectivement avec une div (ou autre élément) que tu pourras déterminer la zone. Sers-toi des css pour définir sa taille.

    Question 2 : Tu auras du mal à trouver un script tout prêt qui te permette de faire ce que tu désires. Il va falloir coder.
    La prochaine évolution de dragOn devrait te faciliter ce travail, mais je ne sais pas encore quand j'aurai le temps de m'y consacrer. Dans tous les cas, le javascript ne te permettra pas à lui seul d'enregistrer des données. Il faudra le coupler avec un langage côté serveur, et peut-être une base de données.
  • gravatar
    Merci beaucoup pour les réponses ;-)
    Pour la première question j'ai fais comme tu m'as conseiller et ça marche très bien pour la deuxième je vais essayer de voir au niveau de ma base de données pour y enregistrer la position des DIV.
    Bonne fin de journée.
  • gravatar
    Bonjour,

    Je viens de tester l'animation sur un div pour que celle-ci ne soit modifiable que en horizontal. J'ai utilisé "moveVert : false" pour éviter le mouvement vertical mais j'ai un problème. A chaque fois que je clique sur la div que je veut déplacer, celle-ci fais d'abord un petit décalage en haut et à droite de 8px.

    Merci d'avance.
  • gravatar
    Est-ce que ta div a une propriété css "margin" ? Il vaut mieux garder les marges à 0 pour les éléments déplaçables.
    Et si tu as vraiment besoin de marges, on peut trouver plein de ruses pour ne pas les appliquer directement à la cible de dragOn.
  • gravatar
    Mon div ne contient aucun margin.
    Voici les attributs que mon div possède:
        width:980px;
        height:83px;
        float:left;
        cursor:move;

    Du coup le problème est d'autant plus embêtant car je dois le faire valide pour IE6 et à cause des top et left la div ce met en tout en haut.

    Mon div ce trouve dans un autre div donc voici ces propriété:
        width:980px;
        height:315px;
        position:relative;

    Mais je ne pense pas que cela est un rapport.
  • gravatar
    Pas facile de t'aider à résoudre ton problème sans voir ta page. Tu as un lien à me fournir ?
    (Tu peux me le transmettre par email, pour plus de discrétion.)
  • gravatar
    Je viens de t'envoyer un mail merci pour l'aide.
  • gravatar
    salut, merci pour le script
    mais ça fonctionne pas pour moi
    Est ce que tu peux fournir un exemple de page html avec tout le script.
    Celle de ta démo par exemple . Merci
  • gravatar
    Salut ,

    Excellent site, désign agréable , scripts de qualité.
    Je suis étudiant en informatique , et j'utilise tes scripts sur un gros projet ;)
    Je te recontacterais une fois que ce projet sera terminé ,
    Bon courage pour la suite !
  • gravatar
    Fonctionnalité pour pouvoir appliquer une grille magnétique sur les déplacements :


    --- dragOn.src.js 2010-08-12 22:37:50.000000000 0200
    dragOn.src.js 2010-09-14 11:21:27.000000000 0200
    @@ -332,6 332,7 @@
    options.cssPosition = options.cssPosition ? options.cssPosition : target.style.position ;
    options.moveHoriz = options.moveHoriz===undefined ? 1 : options.moveHoriz;
    options.moveVert = options.moveVert===undefined ? 1 : options.moveVert;
    options.magneticGrid = options.magneticGrid===undefined ? {X:1, Y:1} : options.magneticGrid;

    // m%uFFFDmorisation des options
    target.dragOptions = options;
    @@ -381,7 382,7 @@
    left = mousePos.x - dragOn.decalX;
    left = opt.maxX!==undefined && opt.maxX<left elem.offsetWidth ? opt.maxX-elem.offsetWidth : left;
    left = opt.minX!==undefined && opt.minX>left ? opt.minX : left;
    - elem.style.left = left "px" ;
    elem.style.left = (left - left % opt.magneticGrid.X) "px" ;
    }

    // position verticale
    @@ -389,7 390,7 @@
    top = mousePos.y - dragOn.decalY;
    top = opt.maxY!==undefined && opt.maxY<top elem.offsetHeight ? opt.maxY-elem.offsetHeight : top;
    top = opt.minY!==undefined && opt.minY>top ? opt.minY : top;
    - elem.style.top = top "px" ;
    elem.style.top = (top - top % opt.magneticGrid.Y) "px" ;
    }
    }
    }
  • gravatar
    attention, dans mon message au dessus, ton système de blog a retiré tous les caractères 'plus'.
  • gravatar
    Salut,

    Merci pour ce script qui est très simple à mettre en place et plutôt efficace, cependant j'ai une remarque/question.
    Ce script marche à la perfection pour tout ce qui est <div> affiché à l'écran au chargement de la page, mais un problème se pose quand on souhaite déplacer un <div> à qui on applique la propriété CSS "display:none" et que l'on affiche avec :

    <a onclick="document.getElementById('fiche').style.display='block'" href="javascript:;">

    Dans cette situation, le <div> qui s'affiche est complètement déformé (en gros, le CSS ne s'applique plus).
    Y aurait-il une solution envisageable ?
  • gravatar
    C'est encore moi.

    Je précise que le problème semble, d'après mes tests, venir du "display:none".
  • gravatar
    Tu as une page d'exemple à me fournir ?
  • gravatar
    malheureusement non, car ce n'est pas un site web hébergé... pour le moment il est seulement en local sur mon ordinateur. :(
  • gravatar
    Bonjour, moi j'aimerai utiliser la DragBox 3, pouvez vous me donner ce que je dois ecrir dans ma page .html et dans le .js ?
  • gravatar
    Ok. Ca n'a pas l'air évident pour tout le monde. Voici donc un exemple complet.
    (On considère que votre fichier html et le fichier javascript sont enregistrés dans le même dossier.)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd" >
    <html lang="fr">

    <head>
    <title>essai dragOn</title>

    <!-- un peu de css pour faire une jolie boîte -->
    <style type="text/css" media="all">
    #dragBox {
    background: #fafafa;
    border: 1px solid #ccc;
    width: 150px;
    height: 150px;
    }
    #handle {
    margin: 0;
    background: #ccc;;
    }
    </style>
    </head>

    <body>

    <!-- la boîte -->
    <div id="dragBox">
    <h5 id="handle">dragBox</h5> <!-- la poignée -->
    <p>cette bo&icirc;te-ci doit &ecirc;tre saisie par son titre</p>
    </div>


    <!-- on charge le script "dragOn" -->
    <script src="dragOn.min.js" type="text/javascript"></script>

    <!-- on paramètre et on active dragOn -->
    <script type="text/javascript">
    var draggable = document.getElementById('dragBox');
    var options = {
    handle : document.getElementById('handle')
    };
    dragOn.apply( draggable, options );
    </script>
    </body>
    </html>


    Et surtout, quand vous adaptez ce qui précède à vos besoins, assurez-vous que votre code source soit bien valide.

    Voici où tester votre code :
    - pour le html : http://validator.w3.org/
    - pour les css : http://jigsaw.w3.org/css-validator/
    - pour le javascript : http://www.jslint.com/

    Bonne continuation.
  • gravatar
    Ouai merci beaucoup ! ça marche ! (bon la dragbox ressemble pas à la même que sur le site mais c'est pas grave ^^)
    Merci encore !
  • gravatar
    Très bien et bravo mais sous firefox le click initial m'envoie la div environ 1000 px à gauche et 800 px vers le bas ?
  • gravatar
    sous ie aussi d'ailleurs ...
  • gravatar
    le déplacement s'effectue quand même correctement mais avec ce décalage par rapport à la position réelle du curseur
  • gravatar
    Je suppose que le dysfonctionnement que tu décris se produit sur ton propre site, parce qu'ici ça fonctionne très bien. Il y a probablement des erreurs sur ta page. Si tu me donnes un lien je tâcherai d'y jeter un oeil.
  • gravatar
    Bonsoir, mon site est en local pour l'instant. Mais j'ai testé ton code sur une autre page et c'est vrai qu'il fonctionne parfaitement. Le problème vient du passage en absolute (par ton script) de mes div qui sont en relative. Donc pas de solution pour moi sauf repenser mon site en absolute ?
  • gravatar
    @cmmi : Normalement, il ne devrait y avoir aucun problème avec les position relatives. Il y a peut-être une interférence avec un autre script dans ta page... Difficile de savoir sans voir le code.
  • gravatar
    Hello!
    Tout d'abord, un grand merci pour ce script, et tes explications simples et efficaces.
    Je suis incapable de coder en javascript donc tu m'as rendu un fier service ;)
    J'ai juste un petit souci. Tout fonctionne correctement, j'ai appliqué le script à un div qui contient un petit paragraphe explicatif, mais lorsque le curseur survole le bloc, il ne change pas d'état (enfin sauf au dessus du texte comme d'hab) et n'affiche pas la croix multidirectionnelle qui indique que l'on peut déplacer le bloc.
    je voudrais garder un design le plus simple possible pour seulement suggérer le déplacement . c'est pourquoi le changement d'état est quasi impératif. Autrement je pense que les visiteurs n'auraient même pas l'idée d'essayer le déplacement.
    quelle peut en être la raison? puisque je ne sais pas, dans ce cas, quel élément provoque le changement d'état, je ne sais pas vraiment comment corriger le problème.
    Merci d'avance.
  • gravatar
    @hemK: Le curseur en forme de croix ne relève pas du javascript mais des css. Pour obtenir cet effet, il faut que tu appliques la propriété suivante à l'élément qui sert de poignée : cursor: move;
  • gravatar
    Tsilves1 > Je ne sais pas si ton problème est toujours d'actualité, mais à tout hasard ...
    Je me suis penché sur ton problème, et j'ai tenté de recréer l'effet que tu recherchais (faire apparaître/disparaître un div avec un bouton), et j'ai réussi sans peine :
    http://filmoz.fr/test2/a.php (je te laisse zyeuter le code source).

    N'hésite pas si tu as des questions !

    PS : Abrab, ne t'inquiète pas, je te laisse la vedette :p
  • gravatar
    Bonjour,
    merci pour ce script simple et efficace.
    Je l'ai appliqué sur plusieurs div côte à côte (avec la propriété float). Or quand en déplace une, toutes les autres se décalent pour prendre sa place.
    Je voudrais savoir s'il existe une solution pour éviter cela ?
  • gravatar
    Merci beaucoup, ce script est tout simplement génial :)
    Il est rapide et facile à mettre en place, très léger, modulable,... top quoi ! Chapeau
  • gravatar
    Merci beaucoup pour tout ! Mon site vous doit beaucoup :D
  • gravatar
    Salut,
    d'abord merci pour ce script.
    Tout fonctionne parfaitement (ou presque), je n'ai aucun souci pour déplacer plusieurs div. Cependant j'ai un petit problème lorsque j'applique l'option moveArea. L'option fonctionne très bien quand je ne l'applique que sur une seul div mais si j'écris ceci plus rien ne fonctionne:

    <script type="text/javascript">
    options ={
             moveArea : document.getElementById('zone_affichage'),
              };          
    dragOn.apply(document.getElementById('carre1'),options);
    dragOn.apply(document.getElementById('carre2'),options);
    </script>

    ce qu'il faut noter ce que l'option fonctionne très bien quand je ne la met que sur la première ou la deuxième div. Mais j'aimerais pouvoir l'appliquer sur une dizaine...

    merci d'avance pour votre aide
  • gravatar
    Salut,

    Merci beaucoup pour ce script, extra !

    J'ai juste quelques petites questions :

    - Est-ce normal que ma div se décale vers la droite lorsque je clique dessus, et pourquoi elle grossit également ?
    Et aussi, pourquoi lorsque je clique sur ma div, malgré la fonction drag&drop, elle ne se décale pas de suite en même temps que le déplacement de mon curseur ? (je dois cliquer une première fois sur ma div, qui grossit, puis recliquer afin de la déplacer, car ça ne marche pas la première fois)

    - Deuxième chose, j'aimerais que lorsque je souhaite déplacer une de mes div, si je veux la mettre à la place de celle se trouvant par exemple en dessous, que cette dernière se décale pour laisser la place à ma première div ? En gros faire comme le problème qu'avait Sybille (voir plus haut)...

    Cordialement
  • gravatar
    Ps : J'ai mis mon code ici pour ceux qui auraient le même problème ou une solution : http://jsfiddle.net/qXwEG/5/
    (Par contre l'interaction avec le script ne se fait pas ici apparemment, il faut regarder chez soi)
  • gravatar
    Je remercie vraiment l'auteur, j'ai un projet en cours et c'est quasi exactement ce genre de script dont j'avais besoin. Je suis en train de rajouter quelques options qui manquent ici (ce n'est pas une critique :D, voir la suite), et le code source commenté est vraiment bien fichu.
    MERCI.


    Pour Ginger et Sybille, en mettant les div à côté non en float mais en absolute, ça fonctionne bien. Après s'il y a absolument besoin de float... Peut-être que créer un div invisible qui prend la place du div déplacé peut convenir ?
    Juste une question (je n'ai pas encore eu le temps de m'y pencher, mais au cas où). Est-il possible de "désapply" la fonction de drag ? En gros on appuie sur un bouton et on peut draguer les div, on rappuie dessus, on ne peut pas (si jetrouve la solution, je ne manquerai pas de l'indiquer ici).
  • gravatar
    Je suis très bête, il suffit de réappliquer des options en mettant à false moveHoriz et moveVert.
  • Navré, le formulaire de commentaires est temporairement indisponible.