Écrit par Neil Deakin.
Traduit par Laurent Jouanneau (11/11/2004).
Page originale :
http://www.xulplanet.com/tutorials/xultu/dragwrap.html
Cette section décrit l'utilisation d'un conteneur JavaScript pour le glisser-déposer.
Le conteneur JavaScript pour le glisser-déposer simplifie le processus en appelant toutes les interfaces XPCOM pour vous. Il fonctionne en fournissant un objet qui implémente les gestionnaires d'évènements. Tout ce que vous avez à faire est d'écrire quelques fonctions simples qui travaillent sur les données qui sont glissées.
L'interface Glisser-déposer est stockée dans le paquetage "global", dans le fichier chrome://global/content/nsDragAndDrop.js
. Vous pouvez inclure ce fichier dans votre
fichier XUL avec la balise script
de la même manière que pour
vos scripts. La bibliothèque dépend aussi d'autres scripts, que vous aurez également à inclure,
habituellement au début de votre page XUL. Vous pouvez regarder le contenu de ces fichiers pour
voir comment fonctionne le glisser-déposer au plus bas niveau.
Notez que vous ne pouvez utiliser ces bibliothèques qu'à l'intérieur de fichiers XUL chargés avec un URL chrome.
<script src="chrome://global/content/nsDragAndDrop.js"/>
<script src="chrome://global/content/nsTransferable.js"/>
Cette bibliothèque glisser-déposer crée un objet stocké dans la variable nsDragAndDrop
.
L'objet contient une série de fonctions, une pour chaque gestionnaire d'évènements (excepté
pour dragenter
où il n'y a rien de spécial à faire). Chacune de ces fonctions
prend deux arguments : le premier est l'objet event
et le deuxième est un
objet observateur que vous créez. Vous aurez plus d'explications plus tard.
L'exemple suivant est un exemple d'appel de l'objet nsDragAndDrop
:
<button label="Glissez moi" ondraggesture="nsDragAndDrop.startDrag(event,buttonObserver);" />
La fonction startDrag
sera appelée quand le glisser-déposer débutera à partir du bouton.
Le premier paramètre est l'objet event
, disponible dans tous les gestionnaires d'évènements.
Le second paramètre à cette fonction est l'observateur, que nous créerons bientôt.
Dans cet exemple, nous ne faisons rien de spécial d'autre quand débute le glisser du bouton.
Si nous voulions prendre aussi en compte les autres cas, nous pourrions appeler les autres
fonctions, comme dans l'exemple suivant :
<description value="Cliquez et glissez ce texte."
ondraggesture="nsDragAndDrop.startDrag(event,textObserver)"
ondragover="nsDragAndDrop.dragOver(event,textObserver)"
ondragexit="nsDragAndDrop.dragExit(event,textObserver)"
ondragdrop="nsDragAndDrop.drop(event,textObserver)"/>
Comme mentionné plus haut, il n'y a rien à faire de spécial pendant l'évènement
dragenter
, aussi vous pouvez l'écrire vous même.
Les fonctions sont implémentées par l'objet nsDragAndDrop
, qui est déclaré
dans le fichier nsDragAndDrop.js
, inclus par l'une des balises
script
.
Elles prennent en charge les évènements, les appels aux interfaces XPCOM, et passent une
structure de donnée simple aux fonctions de l'objet observateur.
L'observateur est un objet que vous déclarez vous-même. Dans les exemples ci-dessus, cet
observateur est stocké dans les variables buttonObserver
et textObserver
.
L'observateur est déclaré dans un script que vous devez inclure dans votre fichier XUL avec
la balise script
. Il doit avoir un certain nombre de propriétés, chacune
s'occupant d'un aspect particulier du glisser-déposer. Cinq fonctions peuvent être définies.
Vous avez juste à définir celle dont vous avez besoin.
onDragStart (event , transferData, action)
event
qui a été passé au
gestionnaire d'évènement; les données à transférer; le type d'action du glisser.
Cette fonction doit ajouter les données à transférer à l'objet transferData
.onDragOver (event, flavour, session)
event
,
le second est le type de donnée et le troisième est l'objet de session du glisser, qui fourni
plus de détails sur le glisser-déposer en cours. Vous devez définir cette fonction
pour les éléments qui autorisent la dépose de données "glissées" sur eux-même.onDragExit (event, session)
event
et la session
du glisser-déposer.onDrop (event, dropData, session)
event
et le
second est la donnée qui était glissée. Le troisième argument est la session du
glisser-déposer.getSupportedFlavours ( )
Pour un observateur lié à un élément qui peut débuter un glisser-déposer, vous
devriez définir au moins la fonction onDragStart
. Pour les éléments
qui peuvent recevoir des objets glissés, vous devriez définir onDragOver
,
onDrop
et getSupportedFlavours
(et si vous le voulez,
onDragExit
).
Le type des données pouvant être glisser-déposer, est stocké comme un ensemble de type. Souvent, un objet glissé peut être disponible dans un certain nombre de type. Ce faisant, un élément cible peut accepter le type qu'il trouve le mieux adapté. Par exemple, un fichier peut être transmis dans deux types, le fichier lui même et son nom. Si le fichier est glissé et déposé sur un répertoire, le type fichier sera utilisé. Si le fichier est glissé sur un champs de saisie, le type 'nom de fichier' sera utilisé. Le texte du nom du fichier est par conséquent utilisé quand les fichiers ne peuvent être déposés directement.
Un type d'objet a un nom, qui est formaté comme un type MIME, comme text/unicode.
À l'intérieur de la fonction onDragStart
, vous spécifiez quels types
sont disponibles pour l'item en cours de glisser-déposer. Pour faire cela, ajoutez les
données et les types à l'objet transferData
, qui est le second argument de
onDragStart
.
L'exemple ci-après devrait vous aider. La fonction onDragStart
ajoute
des données à l'objet transferData
.
var textObserver = {
onDragStart: function (evt , transferData, action){
var htmlText="<strong>Cabbage</strong>";
var plainText="Cabbage";
transferData.data=new TransferData();
transferData.data.addDataForFlavour("text/html",htmlText);
transferData.data.addDataForFlavour("text/unicode",plainText);
}
};
Ici, un observateur a été déclaré et stocké dans la variable textObserver
.
Il a une propriété appelée onDragStart
(En JavaScript, les propriétés peuvent
être déclarées avec la syntaxe nom : valeur
).
Cette propriété est une fonction qui définit les données qui seront transférées.
Une fois appelé, il commence le glisser-déposer pour la chaîne Cabbage. Bien sûr,
vous voudriez calculer cette valeur à partir de l'élément sur lequel on a cliqué.
Cet élément est disponible dans la propriété target
de l'objet event
.
Cet objet event
est passé en premier argument à onDragStart
.
Nous créons un objet transferData
qui peut être utilisé pour contenir
toutes les données à transférer. Nous ajoutons deux données à celles-ci. La première
est une chaîne de texte HTML et la seconde est une chaîne de texte brut.
Si l'utilisateur dépose sur une zone qui accepte le HTML (comme la fenêtre d'édition HTML
de Mozilla), le type HTML sera utilisé et le texte apparaîtra en gras. Sinon, la
version texte brut sera utilisée à la place.
En général vous devrez fournir une version texte de la donnée, ainsi de nombreuses applications pourront l'accepter. L'ordre dans lequel vous définissez les types devra s'établir de la meilleure correspondance vers la moins bonne. Dans le cas ci-dessus, le type HTML (text/html) vient en premier, et le type texte (text/unicode) en second.
L'exemple ci-dessous montre comment spécifier les données à transférer à partir
de l'attribut label
de l'élément. Dans ce cas, nous
fournissons la donnée dans un seul type.
var textObserver = {
onDragStart: function (evt){
var txt=evt.target.getAttribute("label");
transferData.data=new TransferData();
transferData.data.addDataForFlavour("text/unicode",txt);
}
}
Cela peut être utile lors de l'implémentation du glisser-déposer pour les cellules d'un arbre. Vous pouvez utiliser la valeur d'une cellule, ou d'une ressource du fichier RDF si l'arbre est construit à partir d'un gabarit, comme valeur pour le glisser-déposer. Si vous la stockez dans une chaîne, n'importe quel objet acceptant les chaînes pour un glisser-déposer, peut récupérer cette valeur.
Vous aurez besoin d'ajouter un observateur à chaque élément qui peuvent soit démarrer
une action glisser-déposer, soit accepter des objets glissés. Vous pouvez réutiliser
le même observateur sur plusieurs éléments. Pour un élément qui démarre un
glisser-déposer, onDragStart
est juste ce qu'il faut à implémenter.
Pour un élément sur lequel on peut déposer, l'observateur aura besoin d'implémenter
au moins les fonctions getSupportedFlavours
, onDragOver
et
onDrop
. Certains éléments pourraient être capable d'initier un glisser et
d'accepter un déposer. Dans ce cas, onDragStart
sera aussi nécessaire.
La fonction getSupportedFlavours
doit retourner une liste de type
que peut accepter pour une dépose l'élément sur lequel le glisser-déposer s'effectue.
Une vue d'un répertoire de système de fichier pourrait accepter des fichiers et peut-être du texte,
mais ne devrait pas accepter du texte HTML. Ci-dessous, nous définissons la fonction
getSupportedFlavours
. Nous n'autorisons qu'un seul type ici.
var textObserver = {
getSupportedFlavours : function () {
var flavours = new FlavourSet();
flavours.appendFlavour("text/unicode");
return flavours;
}
}
La liste de type de donnée contient un seul type, qui est text/unicode.
L'objet FlavourSet
peut être utilisé pour contenir une liste de type.
Dans certains cas, vous devez aussi fournir une interface XPCOM. Par exemple,
pour les fichiers :
var textObserver = {
getSupportedFlavours : function () {
var flavours = new FlavourSet();
flavours.appendFlavour("application/x-moz-file","nsIFile");
flavours.appendFlavour("text/unicode");
return flavours;
}
}
La fonction onDragOver
définit ce qui arrive lorsqu'un objet est
glissé au dessus. Vous pourriez alors changer l'apparence des éléments qui sont
survolés. Dans la plupart des cas, la fonction ne fait rien. Cependant elle doit être
définie pour les éléments qui acceptent des données glissées.
Ensuite, la fonction onDrop
doit être créée. Son second argument
est l'objet de transfert de données qui contient les données transférées. Avant
d'appeler onDrop
, le conteneur aura appelé getSupportedFlavours
pour déterminer le meilleur type de donnée à déposer, aussi l'objet de transfert
ne contient que les données du meilleur type déterminé.
L'objet de transfert a deux propriétés : data
qui contient la donnée
et flavour
qui contient le type de la donnée. Une fois que vous avez
la donnée, vous pouvez l'ajouter à l'élément de n'importe quelle façon. Par exemple,
vous pourriez modifier la valeur d'un champs de saisie.
var textObserver = {
onDrop : function (evt, transferData, session) {
event.target.setAttribute("value",transferData.data);
}
}
Le système de type utilisé permet à de multiples objets de types variés d'être glisser-déposer, et permet également à des formes alternatives de donnée de l'être. Le tableau suivant décrit quelques types de données que vous pourriez utiliser. Vous pouvez aussi définir votre propre type si nécessaire.
text/unicode | Text data |
text/html | données HTML |
application/x-moz-url | un URL |
application/x-moz-file | Un fichier local |
Dans la prochaine section, nous regarderons un exemple utilisant le glisser-déposer.