Envoyé par : Raphael
Date : 13/02/2007 16:27
Arf... à force de me dire ça, vous allez finir par me convaincre ^^"
C'est que pour moi qui ne suis pas développeur de formation, ma logique me disait que : Requete + Affichage des réponses eu fur et à mesure dans un listbox, c'était le plus simplement codable...
Mais je vais peut-être vraiment me pencher sur ce treeview... c'est que ça me démotive un peu : je m'étais déjà taper tout un moteur de filtre en gardant les infos en RAM et ça s'est avéré désastreux pour de grosses bases... Là, j'ai quasiment fini le recodage de ce moteur et il marche même pour de grosses bases... du coup, me plonger dans un nouveau concept d'affichage là tout de suite, je sais pas trop... peut-être pour un v 2.0 ? XD
En tous cas, merci de vos retours et de vos expériences... il semblerait bien que je sois voué à m'intéressez à Treeview pour un résultat optimal...
Freud > Sympa ta base de données... j'espère pouvoir faire la même chose pour Yugioh, afin de rendre l'ensemble des sites francophones et des applications basées sur le jeu totalement intéropérables =)
Envoyé par : o_freud_o
Date : 13/02/2007 17:34
Faut pas te démotiver pour ça ;) Je ne suis pas développeur de formation (autodidaxie power) mais c'est justement ce genre de moments qui me font aimer mon métier : évaluer, évoluer, se remettre en cause, s'arracher les cheveux sur une p*tain de boucle.
Je vais rejoindre les dires de hhf sur la première page : RDF! Si tu préfère attendre une v2, fait comme tu le sens mais quand tu voudras passer au treeview, tu ne devrais pas avoir trop de choses à changer (mais bon, je connais pas ton projet dans son ensemble).
Dans le code que tu as donné, tu ajoute tes données à un tableau. Tu auras "juste" à boucler comme tu le fais, au lieu de mettre dans un tableau, tu compléte ton fichier RDF (syntaxe XML). Ensuite une fonction comme celle-ci va te remplir directement ton treeview :
function loadTree(treeId, dsUrl) { var ZeTree = treeId; var Observer = { onBeginLoad: function(sink){ }, onInterrupt: function(sink){ }, onResume: function(sink) { }, onError: function(sink, aStatus, aErrorMsg) { if(aErrorMsg!='null') { alert("error! " + aErrorMsg); } }, onEndLoad: function(sink) { var temp_val = document.getElementById(ZeTree).view.rowCount; // On met le focus sur le premier résultat sinon on vide pour éviter d'avoir un élément vide séléctionné document.getElementById(ZeTree).currentIndex = '0'; if((temp_val>1)||((temp_val=='1')&&(document.getElementById(ZeTree).view.getCellText(document.getElementById(ZeTree).currentIndex,document.getElementById(ZeTree).columns[0])!=''))) { document.getElementById(ZeTree).currentIndex = '0'; } else { clearTree(ZeTree); } } }; try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); datasource = RDF.GetDataSource(dsUrl); if (datasource.loaded) { //alert("Datasource déjà chargé !"); } else { var sink = datasource.QueryInterface(Components.interfaces.nsIRDFXMLSink); sink.addXMLSinkObserver(Observer); } var tree = document.getElementById(treeId); var remote = datasource.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource); remote.Refresh(false); if (remote.loaded) { tree.database.AddDataSource(datasource); tree.builder.rebuild(); } else { tree.database.AddDataSource(datasource); } } catch(e) { alert(e); } }
Et pour vider ton treeview :
function clearTree(treeId) { try { var tree = document.getElementById(treeId); netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); sources = tree.database.GetDataSources(); while(sources.hasMoreElements()) { ds = sources.getNext(); tree.database.RemoveDataSource(ds); } tree.builder.rebuild(); } catch(e) { alert(e); } }
Donc tu génére un RDF du genre :
<?xml version="1.0" encoding="ISO-8859-1"?> <RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:row="http://dummy/rdf#" xmlns:NC="http://home.netscape.com/NC-rdf#"> <RDF:Bag about="urn:data:row"> <RDF:li> <RDF:Description> <row:per_id>553</row:per_id> <row:per_nom_vf>Carte 1 vf</row:per_nom_vf> <row:per_nom_vo>Carte 1 vo</row:per_nom_vo> </RDF:Description> </RDF:li> <RDF:li> <RDF:Description> <row:per_id>559</row:per_id> <row:per_nom_vf>Carte 2 vf</row:per_nom_vf> <row:per_nom_vo>Carte 2 vo</row:per_nom_vo> </RDF:Description> </RDF:li> </RDF:Bag> </RDF:RDF>
Dans "ta page" tu place ton treeview :
<tree id="treeGrid" flex="1" flags="dont-build-content" ref="urn:data:row" datasources="rdf:null" ondblclick="GoRecord('view');"> <treecols> <treecol id="id" label="Id" primary="true" flex="1" class="sortDirectionIndicator" sortActive="false" sortDirection="ascending" hidden="true" sort="rdf:http://dummy/rdf#per_id"/> <splitter class="tree-splitter"/> <treecol id="nom_vf" label="Nom VF" flex="3" class="sortDirectionIndicator" sortActive="true" sortDirection="ascending" sort="rdf:http://dummy/rdf#per_nom_vf"/> <splitter class="tree-splitter"/> <treecol id="nom_vo" label="Nom VO" flex="3" class="sortDirectionIndicator" sortActive="true" sortDirection="ascending" sort="rdf:http://dummy/rdf#per_nom_vo"/> </treecols> <template> <treechildren> <treeitem uri="rdf:*"> <treerow> <treecell label="rdf:http://dummy/rdf#per_id"/> <treecell label="rdf:http://dummy/rdf#per_nom_vf"/> <treecell label="rdf:http://dummy/rdf#per_nom_vo"/> </treerow> </treeitem> </treechildren> </template> </tree>
et enfin, sur le onload de "ta page" :
onload="loadTree('treeGrid',TaFonctionQuiGenereTonRDF());"
A partir de là, à chaque changement de filtre, tu appelle la fonction clearTree() puis loadTree().
Ben il te reste plus qu'à bookmarquer cette page pour quand tu voudras passer à la v2, ça te donnera certainement quelques pistes ;)
Sinon, question interopérabilité, il te faudra obligatoirement prévoir une fonction d'export des données (en XML... ?) car c'est justement ce qui fait défaut et en général, chacun doit se taper sa base dans son coin et ça, ça démotive vite ;)
Envoyé par : Raphael
Date : 13/02/2007 18:09
Bah justement, j'ai déjà pensé à ça =)
J'ai développé un format XYD pour XML Yugioh Deck, qui permet d'importer/exporter des decks dans des applis/sites internet.
Et le choix de SQLite3 s'est justement fait notamment pour ces critères :
Car c'est justement pour éviter à tous les sites et applications de faire leur petite base incomplète dans leur coin, avec leur MAJ décalé, leur taux d'exactitude variable, etc...
A partir de cette base de données SQLite3, n'importe qui peut construire un site ou une application propulsé par des données de qualité et totalement libre : Même si le mainteneur arrête, n'importe qui peut continuer à MAJ grâce à un logiciel adapté =)
Là, je développe une appli. de Deck Manager, pour gérer ses decks, imprimer des proxys ou ses decklists de tournois... mais j'ai déjà en tête un jeu Online basé sur Jabber ! J'ai déjà lu beaucoup de très beaux projets liant XMPP à XUL, c'est vraiment épatant !
A terme, je compte créer tout un écosystème de logiciels basés sur cette base et j'espère bien que d'autres développeurs s'y attèleront aussi.
Enfin bref,... je m'emballe ^^.
En tous cas, je te remercie effectivement beaucoup pour tes infos qui vont très certainement énormément me servir quand je me plongerai dans les Treeview =)
Envoyé par : Raphael
Date : 16/02/2007 09:30
Finalement, je ne suis pas si satisfait que ça des performances de mon filtre. En effet, lorsqu'il y a à chaque fois 100 réponses... le textbox du "nom de la carte" qui est filtré en temps réel n'est pas totalement fluide et saccade un peu...
Je vais donc me pencher sur le Treeview, mais j'ai quelques questions :
Bon, je vais commencer à tatonner à droite à gauche... =)
Envoyé par : teddyber
Date : 16/02/2007 13:38
bon, alors je dois l'avouer, à la lecture de ce topic et l'enthousiasme pour le treeview, j'ai craqué. je suis passé au treeview. Et c'est monstrueusement rapide comme il a déjà été dit!
il y a deux fonctions à réellement implémenter : rowCount
et getCellText
(une troisième intéressante est cycleHeader pour gérer le tri sur un clic colonne).
perso getCelltext(row, column)
ressemble à ça chez moi :
si le cache n'est pas rempli on requête (la requête est construite avec la clause WHERE et le ORDER by voulu) on rempli un tableau (le cache) à deux dimensions on renvoi la case demandée
rowCount
renvoie la valeur de SELECT count(*) FROM (la requête de ci-dessus)
bref le treeview, c'est bon, mangez-en!
Envoyé par : Raphael
Date : 16/02/2007 15:31
Mais qu'est-ce que le Treeview exactement, j'ai du mal à saisir... Ca marche aussi avec du RDF non ? Quelle différence avec un tree rempli par un template RDF généré ? Je comprends pas trop... ? Et est-ce asynchrone ? Est-ce que l'interface se fige un peu le temps de remplir le tree ou pas ?
Envoyé par : David Marteau
Date : 16/02/2007 15:49
Je pense qu'il y a eu une petite confusion sur le terme 'treeview' :
Le treeview est un objet (js ou autre) implémentant l'interface nsITreeView. Il est affecté a l'élément DOM associé au <tree>:
montree.view = monTreeview.
Il gère les propriétés des éléments de l'arbre. Le tree doit être declaré avec flag="dont-build-content" et c'est une manière complètement programmatique de générer le contenu de l'arbre.
Il existe plusieurs manière de peupler un arbre 1 - Directement via le DOM 2 - Template (RDF) 3 - Implémenter un nsITreeView.
cf : Treeview simple
L'exemple qui à été donné dans ce fil, n'est pas un "treeview" mais une manière de manipuler le contenu l'arbre en manipulant la datasource RDF directement, l'arbre ayant définie par un template dans le document Xul.
La méthode la plus rapide est la méthode 3.
Envoyé par : Paul Rouget
Date : 16/02/2007 17:16
Qu'est ce que vous êtes bavards :)
Envoyé par : Raphael
Date : 16/02/2007 18:12
Oulala... c'est compliqué tout ça...
Si j'ai bien tout suivi, la 3° méthode "implémenter un nsITreeView" est la plus performante, et les exemples données sur ce topic sont en fait simplement des templates RDF ?
En fait, si je comprends bien - corrigez-moi si je me trompe - pour la 3° méthode, il faut remplir une variable "array" qui contienne les valeurs à afficher, puis je créé un objet qui contienne les méthodes "getCellText" et autres puis je l'affecte à un tree ? L'idée serait donc de générer un tableau à chaque filtrage et "recharger" mon tree ensuite ? Ainsi, j'aurais les meilleures performances possibles ?
Bah dis-donc, en lisant les tutos et le wiki depuis quelques mois, je n'avais vraiment pas compris qu'il existait 3 méthode pour remplir un tree... Si jamais, j'arrive à cerner un peu mieux le problème, j'essaierai d'éclaircir certains points sur le Wiki...
En tous cas, merci pour ces précisions très utiles David. =)
PS : Et oui M. Rouget, nous sommes bavards... c'est que j'adore XUL et j'ai soif de connaissance ^^
EDIT : Après quelques lectures plus approfondies et plus ciblées sur cette fameuse 3° méthode, il semblerait bien que ce soit à peu près ce que j'ai dit non ? En fait, je mets mes données dans un tableau JS et à partir de là, je crée un objet "theview" pour communiquer avec le tree ? Pour qu'il sache quoi faire et quoi chercher ? Faut définir des méthodes pour afficher le texte, ou l'image c'est ça ? J'ai pas encore totalement compris cette étape de compréhension entre "theview" et le fait que le tree afficher les bonnes données mais je vais continuer d'étudier ça car en plus, ça me parait plus "compréhensible" que des templates RDF ^^"
RE-EDIT : Cette méthode est vraiment géniale ! Plus je la découvre et plus je la trouve simple ! Encore plus que du DOM ou du Template RDF... Je pense pouvoir l'implémenter sans trop de problèmes, mais je me pose juste une question : Une fois mon tree affiché, comment puis-je accéder aux éléments sélectionnés ? Comme d'habitude genre "getSelectedItem" ou "CurrentIndex" ?
Envoyé par : Raphael
Date : 16/02/2007 22:08
Bon, j'ai essayé de coder ça, et a priori, ça marche du tonnerre ! mon filtrage est instantannée même avec une frappe rapide sur des milliers d'enregistrements !
<tree flags="dont-build-content" flex="1" id="cardlist"> <treecols> <treecol id="ref" label="Réf." primary="true" flex="1" /> <treecol id="name" label="Nom" flex="1"/> </treecols> <treechildren /> </tree>
En variable globale :
var cardlistview = { rowCount : 0, getCellText : function(row,column){ if (column.id == "ref") return cards[row].Ref; else return cards[row].Name; }, setTree: function(treebox){ this.treebox = treebox; }, isContainer: function(row){ return false; }, isSeparator: function(row){ return false; }, isSorted: function(row){ return false; }, getLevel: function(row){ return 0; }, getImageSrc: function(row,col){ return null; }, getRowProperties: function(row,props){}, getCellProperties: function(row,col,props){}, getColumnProperties: function(colid,col,props){} };
A chaque frappe de touche, je filtre en remplissant mon tableau cards :
cards = new Array(); /* Boucle SQL pour remplir mon tableau cards */ cardlistview.rowCount= cards.length; $("cardlist").view = cardlistview;
Voilà... maintenant, j'ai dernier point à régler :
Quelqu'un pourrait-il m'aiguiller ? Merci d'avance =)
Il n'est plus possible de poster des messages dans ce forum.
Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.
Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™
sont des marques de la fondation Mozilla.