Écrit par Neil Deakin.
Traduit par Adrien Montoille (07/09/2004).
Page originale :
http://www.xulplanet.com/tutorials/xultu/rdfscript.html
Cette section explique comment manipuler RDF avec un script.
Les gabarits peuvent être utilisés pour extraire les données d'une source RDF et construire du contenu à partir de celles-ci. Cependant les sources de données peuvent aussi être parcourues à partir d'un script. Vous pouvez obtenir la source de données d'un élément construit à partir d'un gabarit et en sélectionner des ressources. Cela vous permet aussi de modifier la source de données.
Le composant XPCOM pour RDF propose un certain nombre d'interfaces. Sont listées ci-aprés certaines de ces interfaces :
Seq
, Bag
et Alt
.Dans la fenêtre de recherche de fichiers, nous pouvons implémenter la possibilité de stocker les éléments les plus récemment recherchés. Le champs de saisie de recherche peut-être remplacé par une liste déroulante éditable qui contient une énumération des termes qui ont été récemment recherchés. Nous allons maintenant ajouter cette fonctionnalité.
Cela ne fonctionnera réellement que si la fenêtre a accés à un espace sur le disque
où la liste des éléments récemments recherchés peut-être enregistrée. Les endroits les plus
suceptibles de permettre ceci sont le répertoire de profil de l'utilisateur ou un répertoire
choisi par l'utilisateur lui-même. Bien que nous n'allons pas l'utiliser ici, le répertoire
du profil de l'utilisateur peut être trouvé en utilisant le composant
@mozilla.org/file/directory_service;1
. Pour simplifier l'exemple, nous allons juste
mettre un chemin de fichier quelconque dans un attribut
datasources
.
Nous pourrions enregistrer la liste des recherches récentes dans un fichier texte simple. Cependant, nous pouvons utiliser RDF qui a déjà la capacité de lire et d'écrire ses données et de mettre à jour un composant graphique généré automatiquement à partir d'un gabarit.
Premièrement, les changements dans le fichier XUL. Nous allons remplacer le champs de saisie
par une liste
déroulante éditable. Changez la valeur de l'attribut datasources
par un chemin approprié. (Le fichier doit déjà exister.)
<menulist id="find-text" flex="1" style="min-width: 15em;"
editable="true"
datasources="file:///mozilla/recents.rdf"
ref="http://www.xulplanet.com/rdf/recent/all">
<template>
<menupopup>
<menuitem label="rdf:http://www.xulplanet.com/rdf/recent#Label" uri="rdf:*"/>
</menupopup>
</template>
</menulist>
Tous les éléments XUL qui ont leur fils générés par un gabarit ont une propriété database
qui se référe à un objet nsIRDFDataSource
. Cet objet peut ensuite
être utilisé pour lire et modifier la source de données utilisée. La propriété
database
est placée sur l'élément qui porte l'attribut datasources
.
Cela va typiquement être un élément tree
, ou comme c'est le cas ici, un élément
menulist
.
La propriété database
contient une liste (en fait un
nsISimpleEnumerator
)
de chacune des sources de données qui ont été spécifiées dans l'attribut datasources
. Cela signifie que nous avons besoin de réitérer chaque élément,
même s'il n'y en a qu'un seul. L'exemple suivant montre comment réaliser ceci en supposant qu'il
n'existe qu'une source de données :
var dsource;
var menulist=document.getElementById("find-text");
var sources=menulist.database.GetDataSources();
if (sources.hasMoreElements()){
dsource=sources.getNext();
}
dsource=dsource.QueryInterface(Components.interfaces.nsIRDFDataSource);
Tout d'abord, nous obtenons une référence sur un menulist
, qui ici porte l'identifiant
find-text (attribut id
). Ensuite nous obtenons la liste des
sources de données à partir de l'élément menulist
. L'interface
nsISimpleEnumerator
a deux méthodes (pareillement à l'interface d'énumération java). Nous bouclons sur les éléments de
l'énumération et, parce que nous supposons qu'il n'y a en a qu'un, nous allons juste l'obtenir
par la méthode getNext
. Finalement nous appellons QueryInterface
pour
s'assurer qu'il s'agit d'un nsIRDFDataSource
.
Nous allons utiliser un code similaire pour créer la liste des recherches récentes. D'abord,
initialisons les composants que nous voulons utiliser. Nous aurons besoin de trois composants.
L'interface nsIRDFService
va être utilisée pour créer les objets de ressource, l'interface
nsIRDFContainer
va servir à ajouter des ressources à la source de données et nous
utiliserons la troisième interface, nsIRDFContainerUtils
, uniquement lorsque la liste
est employée la première fois, pour créer le noeud racine. Ajoutez le code suivant au début d'un
fichier de script (findfile.js).
Il va être exécuté quand la fenêtre de recherche de fichiers est chargée.
const RDFC = '@mozilla.org/rdf/container;1';
RDFC = Components.classes[RDFC].createInstance(Components.interfaces.nsIRDFContainer);
const RDFCUtils = '@mozilla.org/rdf/container-utils;1';
RDFCUtils = Components.classes[RDFCUtils].getService(Components.interfaces.nsIRDFContainerUtils);
const RDF = '@mozilla.org/rdf/rdf-service;1';
RDF = Components.classes[RDF].getService(Components.interfaces.nsIRDFService);
Cette portion de code va créer les trois services dont nous avons besoin. La syntaxe est similaire
à celle utilisée pour les autres créations d'objets XPCOM. Les trois premières lignes prennent une
référence à un objet nsIRDFContainer
. Puis nous exécutons une opération semblable
pour obtenir l'objet nsIRDFContainerUtils
. Enfin nous la faisons de nouveau pour l'objet
nsIRDFService
.
Ensuite, nous créons une fonction d'initialisation que nous allons appeler dans l'événement onload
de la fenêtre. Elle va être exécutée quand la fenêtre va être
affichée. Dans ce source, nous allons ajouter le code pour initialiser les objets RDF que
nous avons créé plus haut.
findfile.xul :<window onload="initSearchList()" ... >
findfile.js :var dsource; function initSearchList() { var recentlist=document.getElementById("find-text"); var sources=recentlist.database.GetDataSources(); var rootnode=RDF.GetResource("http://www.xulplanet.com/rdf/recent/all"); while (sources.hasMoreElements()){ try { dsource=sources.getNext(); dsource=dsource.QueryInterface(Components.interfaces.nsIRDFDataSource); RDFC.Init(dsource,rootnode); } catch (e) { RDFCUtils.MakeSeq(dsource,rootnode); RDFC.Init(dsource,rootnode); } } }
Décomposons la fonction initSearchList
:
var recentlist=document.getElementById("find-text");
var sources=recentlist.database.GetDataSources();
menulist
sur lequel est attachée la source de données.
Elle a une propriété database
qui contient les sources de données qui
sont présentes. Nous obtenons une référence sur les sources de données disponibles et nous
l'assignons à la variable sources
.
var rootnode=RDF.GetResource("http://www.xulplanet.com/rdf/recent/all");
Seq
qui
contient une liste de ressources, une pour chaque objet présent dans la liste des recherches
récentes. Cette fonction ne retire rien de la source de données, elle convertit juste une URI en
un identifiant de ressource. Au lieu d'inscrire l'URI dans le code, nous pourrions aussi
l'obtenir à partir de l'attribut ref
.
while (sources.hasMoreElements()){
try {
dsource=sources.getNext();
dsource=dsource.QueryInterface(Components.interfaces.nsIRDFDataSource);
RDFC.Init(dsource,rootnode);
} catch (e){
RDFCUtils.MakeSeq(dsource,rootnode);
RDFC.Init(dsource,rootnode);
}
MakeSeq
de l'interface
nsIRDFContainerUtils
. Des
fonctions similaires existent pour créer des éléments Bag
et
Alt
. (MakeBag
et MakeAlt
). On essaie ensuite
de réinitialiser le conteneur.
L'interface nsIRDFService
contient une méthode GetResource
qui crée pour
nous un objet de ressource à partir de la chaîne de caractères passée en argument.
Cette méthode ne récupére aucune valeur, mais convertit simplement une chaîne de caractères en un
objet ressource que l'on peut utiliser pour obtenir la valeur à partir de la source de données.
Les interfaces RDF n'employent pas de chaînes de caractères mais utilisent plutôt des ressources
pour se référer au contenu.
La valeur retournée par GetResource
est de type nsIRDFResource
.
Maintenant que les objets ont été initialisés, nous pouvons ajouter et enlever des informations à la source de données. Il y a deux méthodes requises selon si vous voulez ajoutez une ressource à un conteneur ou si vous voulez ajouter une liaison d'une ressource vers une autre. Ces deux cas correspondent à l'ajout d'un marque-page et à l'ajout d'une propriété comme un URL ou un titre à un marque-page.
Nous allons ajouter une nouvelle entrée à la liste des éléments recherchés quand l'utilisateur cliquera sur le bouton de recherche. Nous le simplifierons un peu à l'extrême de plusieurs manières. Tout d'abord nous ne prendrons pas la peine de vérifier les entrées doubles. Deuxièmement, nous ne nous soucierons pas de limiter la longueur de la liste.
Ajoutons une autre fonction qui est appelée à partir de la fonction doFind
:
function doFind()
{
var recentlist=document.getElementById("find-text");
var fldval=recentlist.value;
addSearchedItem(fldval);
.
.
.
Cette portion de code prend la valeur saisie dans la liste déroulante éditable et nous passons
le texte à la fonction addSearchedItem
qui va être définie plus loin.
function addSearchedItem(txt)
{
var newnode=RDF.GetResource("http://www.xulplanet.com/rdf/recent/all/item"+(RDFC.GetCount()+1));
var labelprop=RDF.GetResource("http://www.xulplanet.com/rdf/recent#Label");
var newvalue=RDF.GetLiteral(txt);
dsource.Assert(newnode,labelprop,newvalue,true);
RDFC.InsertElementAt(newnode,1,true);
dsource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush();
}
Ce code fait trois choses, il ajoute une nouvelle ressource, il ajoute un nouvel enregistrement qui contient la valeur, et ensuite il enregistre la source de données modifiée. Décomposons le code :
var newnode=RDF.GetResource("http://www.xulplanet.com/rdf/recent/all/item"+(RDFC.GetCount()+1));
GetCount
retourne le nombre de ressources déjà présentes dans le conteneur.
Cela nous permet de générer une URI unique. Nous pouvons aussi appeler
GetAnonymousResource
(à la place de GetResource
) qui ne prend
pas de paramètre et génère au hasard une URI unique.
var labelprop=RDF.GetResource("http://www.xulplanet.com/rdf/recent#Label");
Label
de la ressource le texte qui a été
récemment cherché.
Vous pouvez utiliser n'importe quel nom de propriété pourvu qu'il soit conforme. Vous noterez
qu'il a la même valeur que l'attribut label
de l'élément
menuitem
ajouté précédemment au fichier XUL.
var newvalue=RDF.GetLiteral(txt);
GetLiteral
génére un objet RDF de type chaîne qui va contenir le texte que
l'utilisateur a recherché et passé à travers l'argument txt
.
Nous n'utilisons pas la fonction GetResource
ici car nous assignons une valeur à
une ressource.
dsource.Assert(newnode,labelprop,newvalue,true);
GetCount
.
Cependant, ce n'est que la moitié de ce qu'il faut faire. Nous devons encore
dire que la ressource est une des recherches récentes.
RDFC.InsertElementAt(newnode,1,true);
AppendElement
à la place pour l'ajouter à la fin. Le gabarit menulist va
maintenant détecter la nouvelle ressource, et ajoutera une rangée suplémentaire dans la
liste.
dsource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush();
Flush
.
Cette fonction ne fait pas partie de l'interface nsIRDFDataSource
, donc nous
devons d'abord appeller QueryInterface
pour convertir la source de données vers la bonne
interface, nsIRDFRemoteDataSource
.
Toutes les sources de données ne peuvent pas être modifiées. Toutes les sources de données chargées à partir de fichiers et d'URLs de ressource peuvent être écrites aussi bien que des sources de données internes.
Si vous ouvrez la fenêtre de recherche de fichiers, que vous entrez du texte puis pressez "Recherche", vous constaterez que le texte apparait en tant qu'un des choix dans la liste déroulante. Même si vous quittez puis redémarrez, le texte restera dans la liste déroulante.
Pour vérifier les entrées dupliquées, nous pouvons vérifier les ressources existantes, en utilisant
les fonctions hasAssertion
ou GetAllRessources
de l'interface nsIRDFDataSource
.
Exemple de recherche de fichier : Source Voir
Nous allons voir maintenant comment accéder au presse-papier du système pour les opérations copier et coller.