Fiche Javascript :

Objet de la fiche

État de la fiche Terminée validée


Plan de la fiche :

Avant propos

Le système de glisser/déposer permet de déplacer un élément très simplement en cliquant dessus, en maintenant le clic tout en bougeant le curseur puis relâcher le bouton à l'endroit voulu.

Grâce au HTML5, il est maintenant possible de permettre un déplacement de texte, de fichier ou d'autres éléments depuis n'importe quelle application jusqu'à votre navigateur.

Attention : L'utilisation du glisser/coller tel que décrit ci-dessous n'est pas encore supportée par les appareils mobiles. les exemples suivants s'appliquent aux navigateurs de bureau. Touefois en fin de fiche on s'interressera à ce que l'on peut réaliser d'une autre façon sur les terminaux mobiles.

Condition pour qu'un élément soit glissable (attribut draggable)

Généralités

En HTML, excepté le comportement par défaut des images, des liens et des sélections, aucun autre élément ne peut être glissé et vous ne pourrez faire qu'une sélection du contenu. Pour rendre un élément HTML glissable, il suffit d'utiliser son attribut draggable et de le mettre à true (que ce soit en HTML ou en JavaScript). À partir de là, l'élément est autorisé au glissement.

En ce qui concerne les éléments draggable par défaut si on ne désire pas autoriser le glissement il suffira de mettre l'attribut draggable à false.

Syntaxe

Exemple : <img src="toto.gif" draggable="true" alt="" />

Valeurs attributCommentaires
trueLe contenu peut être déplacé.
falseLe contenu ne peut pas être déplacé.
autoLe contenu adopte le comportement par défaut du navigateur (le texte, les liens et les images sont déplaçables, d’autres éléments ne le sont pas).

Bases de la page HTML utilisée pour illustrer les exemples de glisser/coller

Exemple de base avec son code

Remarques sur la page

1) Des images de miniatures définies de la manière ci-contre.
2) Une zone d'atterrissage symbolisée par une image de panier
3) Une zone poubelle symbolisée par une image de poubelle
4) Les CSS associés

Les évènements liés à l'objet que l'on déplace

Evènements

EvènementsActions
dragstartDébut du glissement de l’élément.
dragL'élément se déplace (évènement périodique).
dragendFin du glissement. L'élément n'est plus maintenu.

Exemple avec son code

Remarques sur le code

  • Chacun des évènements sont déclarés de façon classique.
  • On utilise la propriété target de l'évènement pour accéder au style le l'élément.
  • Un journal des évènement permettra de suivre les diverses phases du glisser/coller.
  • L'évènement drag étant périodique (toutes les 350ms) et pour ne pas polluer le journal par un flot de messages, le nombre d'évènements drag survenus durant l'action seront affichés dans l'évènement dragend.

Les évènements liés à la zone de dépot

Evènements

EvènementsActions
dragenterL'élément en cours de déplacement vient de rentrer dans une zone d'atterrissage possible. Voir aussi (*).
dragoverOn survole une zône d'atterrissage (évènement périodique). Voir aussi (*).
dragleaveOn vient de quitter une zône d'atterrissage.
drop L'élément vient d'être laché sur la zone d'atterrissage.
Pour que le drop soit autorisé on doit annuler l'évènement s'il est annulable, sans toutefois stopper sa propagation. On fait celà en appelant la méthode "event.preventDefault".

(*)La méthode "preventDefault" doit être appelée lors des évènements dragenter et dragover. Cependant, il est possible qu'on ne veuille activer cette méthode qu'uniquement dans certaines situations, par exemple, seulement si un lien est glissé.
Cette méthode doit aussi être utilisée dans l'évènement drop pour éviter que lors du drop l'application associée au fichier déplacé ne soit automatiquement activée (affichage direct de la photo par exemple).

Note : Durant ces opérations seuls les évènements spécifiques au glisser/déposer sont déclenchés, des évènements comme mousemove ne sont plus disponibles lors de cette opération.

Exemple avec son code

Remarques sur le code

  • Les 4 nouveaux évènements liés à la zone de dépot son déclarés de façon classique.
  • La variable globale flagOverDropZone est utiliser pour servir de bascule dans l'évènement dragover afin d'éviter les fux de message dans le journal, emis à chaque déplacement du curseur.
  • Important 1 : event.preventDefault() doit être exécuté en début d'évènement dragover pour autoriser le futur atterrissage (évènement drop).
  • Important 2 : event.preventDefault() doit être exécuté en début d'évènement drop pour que l'évènement soit bloqué au niveau de l'élément et ne remonte pas jusqu'au document lui-même, car dans ce cas le navigateur ouvrirait la page qui correspond à http://monwebfacile.free.fr/Tutoriaux/Images/AlphaRomeo.png si c'est l'image AlphaRomeo qui est lachée sur la zone de drop.

L'API Drag and Drop : objet dataTransfer

Généralités

Tous les événements de glissement ont une propriété appelée dataTransfer utilisée pour contenir la donnée de glissement.

L'objet dataTransfer permet de réaliser trois actions:

  • Sauvegarder une chaîne de caractères qui sera transmise à l'élément HTML qui accueillera l'élément déplacé (setData()).
  • Définir une image utilisée lors du déplacement (setDragImage()).
  • Spécifier les autorisations en fonction du type de déplacement (effectAllowed).

Syntaxe

objetevenement.dataTransfer.Propriete = "valeur";

Propriétés

PropriétésCommentaires
dropEffect

Donne une image différente du curseur en fonction des opérations.

Cette propriété doit être spécifiée pour les évènements suivants :

  • dragenter et dropover => dropEffect sera initialisé à l'action à réaliser. Ces données pourront être modifiées à la demande de l'utilisateur.

Pour les évènements drop et dragend => dropEffect sera automatiquement initialisée à la valeur qui sera la valeur qu'avait dropeffect aprés les derniers évènements dragenter ou dragover.

ValeursImages curseur
copy
move
link
noneCet élément ne sera pas droppé.

Tout autre valeur n'aura aucun effet (l'ancienne valeur sera retenue).

effectAllowed

Cette propriété peut être spécifiée pour les évènements suivants:

  • dragstart
  • dragenter
  • dragover

pour définir les actions souhaitées et autorisées pour la source et la cible. Les valeurs suivantes peuvent être affectées :

valeursActions
copyUne copie de l'élément source peut être faite à son nouvel emplacement.
moveL'élément est déplacé vers un nouvel emplacement.
linkUn lien peut être établi vers la source depuis le nouvel emplacement.
copyLink copy ou link est autorisée.
copyMovecopy ou move est autorisée.
linkMovelink ou move est autorisée.
allToutes les opérations sont autorisées.
nonel'élément ne peut être déposé.
uninitializedla valeur par défaut lorsque l'effet n'a pas été spécifié, ce qui équivaut à all.
filesCette propriété est uniquement à utiliser avec l'évènement drop.
Dans le cadre d'opérations sur des fichiers issus du système (fichiers sélectionnés avec explorer ou à partir du bureau) cette propriété contient la liste de tous les fichiers disponibles sur le transfert de données (objet [object FileList]). La liste sera vide pour des glisser/coller concernant des éléments de la page web elle même.
types Cette propriété en lecture seule retourne un tableau des formats des données (chaine de caractères) déplacées initialisées dans l'evènement dragstart. L'ordre des formats est le même que celui initialisé.

Ceci peut être utile dans les évènements dragenter et dragover pour voir quel types de données ont été créees.

Méthodes

MéthodesCommentaires
addElementNon implémenté par les navigateurs
setData Cette méthode est à spécifier au départ du glisser dans l'évènement dragstart. Elle fourni des informations sur les données à glisser.

Syntaxe : event.dataTransfer.setData(identificateur,données);
  • identificateur : peut être une chaine de caractères arbitraire. Exemple "texte", "image"..ou un type mime si on veut par exemple mettre du html dans les données transférées.
  • données : chaine de caractères correspondant aux informations à transmettre.

Exp : event.dataTransfer.setData("mon_id", event.target.id); pour avoir l'information de l'id de l'élément déplacé lorsque ce dernier aura été glissé et déposé.
Important :La méthode peut être appelée plusieurs fois avec des informations différentes.
getData Cette méthode peut être spécifier pour les évènements dragenter, dragover, dragleave, drop. Elle permet de récupérer les données initialisées par setData

Syntaxe : event.dataTransfer.getData(identificateur);
identificateur étant le même identifiant utilisé dans setData.
Exp : event.dataTransfer.getData("mon_id"); retournera le valeur data (event.target.id) de l'identifiant "mon_id") initialisé lors de l'appel de la méthode event.dataTransfer.setData("mon_id", event.target.id) dans l'évènement dragStart
clearData Cette méthode ne peut être appelée qu'uniquement dans l'évènement dragStart. En fonction d'analyses au niveau de l'objet déplacé on peut être amené à supprimer certaines informations initiées par un setData

Syntaxe : event.dataTransfer.clearData(identificateur);
identificateur étant le même identifiant utilisé dans setData.
Attention : Si on exécute cette méthode sans paramètre (event.dataTransfer.clearData()) tous les formats seront supprimés.
setDragImage Cette méthode est habituellement appelée dans l'évènement dragstart.

Durant un glissement , une image translucide (crée automatiquement) de l'objer déplacé est présentée dés le début du glissement. Cette image suit le déplacement de la souris. La méthode setDragImage permet de personnaliser cette image filigrane.

Syntaxe : event.dataTransfer.setDragImage(image, xOffset, yOffset);
Les deuxième et troisième arguments de la méthode sont les décalages de l'image par rapport au pointeur de la souris.

Exemple

Remarques sur le code

La seule différence avec l'exemple précédent consiste à utiliser les méthodes ( de l'objet dataTransfer) effectAllowed, setData, getData, et setDragImage

1) Evènement dragstart

On initialise l'action que l'on envisage pour l'élément avec effectAllowed = "copy", l'image associée au curseur dés le déplacement avec setDragImage(dragImg, 10, 10); , ainsi que les données pertinentes que l'on veut voir associées à l'élément avec la possibilité de pouvoir les récupérer à tout moment : son id, la source de l'image et le titre par l'intermédiaire de setData ou getData.

2) Evènements dragenter et Dragover

On confirme l'action que l'on envisage pour l'élément avec effectAllowed = "copy", et le symbole associé au curseur avec dropEffect = "copy".

3) Edition du journal

Pour l'édition du journal on récupère les informations de dataTransfer avec getdata pour les afficher et fournir ainsi plus d'informations.

Exploiter les éléments déposés

Généralités

Le code est construit pour être facilement compréhensible et portable et de telle façon que l'on puisse aborder le maximum de possibilités autorisées par l'API mise à notre disposition par HTML5.
Pour cela deux zones d'atterrissage ont été définies : celle du "panier" et celle de la "poubelle".
Le développeur va définir arbitrairement des autorisations ou des interdictions entre l'origine de l'élément et sa destination en fonction des règles définies dans le tableau ci-dessous :

Départ
CataloguePanierPoubelleAutres
Arrivée Cataloguenonnonnonnon
Panierouinonnonnon
Poubellenonouinonnon
Autresnonnonnonnon

A partir des directions établies dans cette table on cré une fonction qui nous renverra les directions en cours. Les résultats seront exploités pour autoriser ou interdire l'action.

Avertissement

Ce type de gestion des autorisations/Interdictions est pratique pour définir dynamiquement les actions suivant les évènements : par exemple dans dragenter ou dragover on peut ajuster dataTransfer.dropEffect ou dataTransfer.effectAllowed.

Malheureusement certains navigateurs à l'heure actuelle (chrome, opéra) ne gèrent dataTransfer.getData() qu'uniquement pour les évènements dragstart et drop ce qui nous oblige à utiliser la matrice des Autorisations/Interdictions uniquement au moment du drop.

Données dans l'évènement drop

Cet évènement est l'aboutissement final de notre action glisser/coller. Que va-t-on faire de l'objet déplacé ?

  • Autorisations/Interdictions

    On va dabord initialiser des variables booléennes qui nous servirons pour savoir ce que l'on doit faire en fonction des autorisations/interdictions définies dans les évènements drgenter et dragover.


  • Evènements clavier

    On gère les évènements clavier durant un glisser/coller. L'internaute à appuyé sur une touche particulière avant de relacher le élément sur sa zône d'atterrissage.

    Lors d'appui sur les touches clavier durant les phases glisser/coller, l'API HTML5 retoune uniquement des informations concernant les "modifier keys". Parmi ce type de touches on notera les plus communes comme Shift, Control, Alt, AltGr ..

    Les informations (true ou false) sont disponibles à partir de event.ctrlKey, event.shiftKey, event.altKey, event.altGrKey.

    L'intérêt de ces touches est de pouvoir modifier le résultat d'un drop, comme par exemple l'appui sur la touche ctrl (contrôle) pourrait permettre de faire une copie et le non appui sur cette touche seulement un déplacement.

Les traitements définis sont les suivants :

  • Appui sur Shift : L'évènement n'est pas bloqué au niveau de l'élément mais remonte tout l'arbre et affiche l'élément déplacé (event.preventDefault(); n'est pas activé).
  • Appui sur Ctrl : L'évènement est bloqué au niveau de l'élément (event.preventDefault(); est activé). L'élément sera copié et l'original supprimer : il s'agit d'un glissement.
  • Pas d'appui sur Ctrl ni sur Shift : L'évènement est bloqué au niveau de l'élément (event.preventDefault(); est activé). L'élément sera cloné et l'original conservé : il s'agit d'une copie réelle.

  • Copie de la sélection

    De base les fonctions de manipulation du DOM ne copient pas l'élément mais le déplace. Il faut utiliser ".cloneNode(true)", si on ne veut pas toucher à l'original mais créer une nouvelle copie.

    event.target.appendChild() effectue la copie réelle de l'image de départ.

    Lors du clonage tout est copié y compris l'ancien id. Comme 2 éléments ne doivent pas posséder le même id il faut donc le modifier (nodeCopy.id).

    Cloner un nœud copie tous les évènements initialisées sur ce nœud, à l'exeption des écouteurs d'évènement qui eux sont liés à l'id du nœud qui devra être nécessairement différent de celui d'origine. C'est pourquoi on exécute setDragEvents(x);


  • Style

    Lors de la mise de l'objet dans le panier, on va réduire sa taille et le positionné vers le fond du panier.

  • Edition du journal

    On a essayé d'utiliser un maximum de sources d'informations (dataTransfer, getdata, target), afin d'être le plus complet possible.

La gestion du panier pourrait être affinée en comptabilisant dans un tableau les éléments mis dans le panier et ceux sorties vers la poubelle afin d'avoir une vue plus précise du contenu du panier et ainsi pouvoir l'exploiter ailleur dans l"application. De même pour la Poubelle.


Exemple complet et son code


Glisser/coller de fichiers systèmes

Généralités

Cette partie basée elle aussi sur les évènements drag and drop, permet de glisser des fichiers systèmes (bureau ou explorateur) de types images ou textes vers une zone particulière en vue d'être exportés vers un serveur. Notre exemple simulera l'envoi au serveur.

On utilise ici les API file, reader.readAsText(), reader.readAsDataURL() pour afficher les images sélectionnées.

Exemple complet et son code

Remarques sur le code

Il n'y a rien de spécial à dire sur le code. Les évènements de glissement on été vus précédemment, la partie reader a été vue dans la fiche HTML5 Balises et API < ICI >


Glisser/coller d'éléments quelconques

Généralités

Cette partie basée sur une démonstration minimaliste des évènements glisser/coller, permet de mettre en évidence les possibilités de glisser/coller n'importe quel élément d'une page web.

Exemple complet et son code

Remarques sur le code

Rien de particulier si ce n'est le positionnement de draggable="true" pour l'élément p qui ne l'est pas de base.


Glisser/Coller sur appareils à écran tactile

Le but de cette partie est de reproduire l'exemple précédent pour un écran tactile.

Javascript met pour celà à notre disposition un ensemble d'évènements liés à l'appui sur l"écran tactile.

Ces évènements ne se limitent pas uniquement à du glisser/coller et peuvent être utilisés dans un grand nombre de fonctionnalités.

Les évènements tactiles

Evènements

EvènementsCommentaires
touchstartle doigt est placé sur un élément.
touchmovele doigt est déplacé sur un élément.
touchendle doigt est retiré d'un élément.
touchcancelTrés peu utilisé dans le cadre de cette fiche. Cet évènement apparait si l'internaute bouge son doig hors de l'interface du navigateur ce qui peut être par xemple, dans une fenêtre modale (type alert).

Note : event.preventDefault(); obligatoire dans touchstart

Syntaxe

Objets liés aux évènements tactiles

Objets

Chaque évènement tactile inclu trois objets liés aux touches :

L'utilisateur pouvant utiliser plusieurs doigts pour toucher simultanément la même surface, les objets liés aux touche sont accessibles via une liste.

ObjetsCommentaires
touches[]une liste de tous les doigts actuellement sur l'écran.
targetTouches[]une liste des doigts sur l'élement du DOM actuel.
changedTouches[]une liste des doigts impliqués dans l'évènement courant. Par exemple, sur un évènement touchend, il s'agira du doigt qui a été retiré.

Syntaxe

touchobj = event.changedTouches[0];

  • event => objet évènement relatif à l'objet l'ayant déclenché.
  • changedTouches ou targetTouches ou touches => objet lié à la touche.
  • [x] => Indicateur de la touche.

Méthodes des objets liés aux touches

Méthodes des Objets

MéthodesDescriptions
identifiernuméro qui identifie de façon unique le doigt courant dans la session tactile.
targetl'élément DOM qui est ciblé par l'action, même si la touche s'est déplacée à l"extérieur de l'élément.
screenXcoordonnées horizontales relatives à l'écran
screenYcoordonnées verticales relatives à l'écran
clientXcoordonnées horizontales du point relatives à la page utile, hors le scroll offset.
clientYcoordonnées verticales du point relatives à la page utile, hors le scroll offset.
pageXcoordonnées horizontales du point relatives à la page web, incluant le scroll offset
pageYcoordonnées verticales du point relatives à la page web, incluant le scroll offset

Syntaxes

Exemple avec les touches : event.changedTouches[0].pageX

Exemple avec target : event.target.[Attribut]. Attribut pouvant êre id pour identificateur, src s'il s'agit d'une image, href pour un lien etc.

Déterminer si on a à faire à un écran tactile

Attention DocumentTouch tend vers l'obsolescence, mais c'est la meilleure solution pour détecter un fonctionnement sur écran tactile.

Contraintes

  • Étant donné que l'appel de la méthode preventDefault() sur l'événement touchstart ou le premier événement touchmove de la série empêche la saisie d'événements en provenance de la souris, on appelle souvent preventDefault() sur touchmove plutôt que sur touchstart. Ainsi, les événements de la souris peuvent continuer à se déclencher et le reste du site fonctionnera de manière habituelle. Mais bon la gestion de ce type de configuration apparait encore aléatoire suivant les navigateurs.
  • L'objet dataTransfer n'est pas exploitable avec les évènements tactiles.
  • Il n'y a pas l'équivalent de l'évènement drop. Les traitements finaux doivent être regroupés dans les évènements touchend ou touchcancel

Gestion du résultat dans touchmove

Cet évènement nous sert à maintenir la position de l'objet durant tout le déplacement. De plus comme on ne dispose pas de l'évènement touchenter on va se le fabriquer nous même dans cet évènement en faisant appel à la fonction isdropzone.

Cette fonction reçoit les coordonnées courantes de l'objet qui se déplace ainsi que l'id de la zone à tester et les compare aux coordonnées des zones de drop autorisées.

Gestion du résultat dans touchend ou touchcancel

Rien de spécial, on laisse l'imagination au développeur pour l'esthétique, la gestion du panier etc.

Exemple complet et son code


De bonnes pratiques

  • Le drag and drop doit avoir une réelle utilité, pas un gadget de présentation.
  • La zone de réception doit être clairement identifiable même avant que l'utilisateur ait débuté le glissement
  • Modifier l'image du curseur au survol de l'objet déplaçable pour faire comprendre que cet élément est déplaçable. Vous pouvez aussi prévoir une bulle d'aide.
  • Modifier l'aspect de l'emplacement de départ dès que le glisser commence
  • Modifier l'aspect de la zone de réception lorsque l'objet à glisser commence à survoler cette zone.
  • En cours de déplacement présentez l'objet déplacé différemment : miniature, transparence.
  • Prévoir des tailles de zones de réception résonnable vis à vis des objets à recevoir.
  • Les distances entre les objets à glisser et la zone de réception devront être au plus prés. Eviter d'avoir à traverser tout l'écran pour glisser l'objet
  • Ne pas utiliser à tord et à travers, pensez aux problèmes d'accessibilité.
  • Attention avec l'utilisation sur écran tactile : prévoir une possibilité de commandes classiques types boutons, liste de choix etc .

Application au projet de site web

Retrouvez la solution

Correction


Respectons la propriété intellectuelle