2 // Copyright 2008 Grégory Burri
4 // This file is part of Euphorik.
6 // Euphorik is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // Euphorik is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Euphorik. If not, see <http://www.gnu.org/licenses/>.
19 // Regroupe la partie communication JSON client -> serveur de euphorik.
20 // Voir : http://dev.euphorik.ch/wiki/euk/Protocole
23 * Les fonctions debutReq et finReq servent, par exemple, à afficher à l'utilisateur
24 * qu'une communication est en cours.
25 * @param funError un fonction executée lors d'un réponse 'error' de la part du serveur, peut être redéfinit pour une requête.
26 * @param funDebutReq fonction appelée au début d'une requête (facultatif)
27 * @param funFinReq fonction appelée à la fin d'une requête (facultatif)
29 euphorik
.Communication = function(funError
, funDebutReq
, funFinReq
) {
30 this.funError
= funError
;
31 this.funDebutReq
= funDebutReq
;
32 this.funFinReq
= funFinReq
;
36 * Charge un fichier depuis une url et retourne son contenu.
38 euphorik
.Communication
.prototype.load = function(url
) {
39 if (this.funDebutReq
) {
43 $.ajax({async: false, url: url
, success : function(page
) { contenu
+= page
; }});
51 * Effectue une requête JSON auprès du serveur.
52 * @param action une chaine spécifiant l'action, par exemple "put_message"
53 * @param json les données à envoyer associé à l'action, par exemple {"cookie" : "LKJDLAKSJBFLKASN", "nick" : "Paul", "content" : "Bonjour", "answer_to" : [] }
54 * @param funOk la fonction exécuté après réception des données du serveur
55 * @param funError la fonction exécuté si une erreur arrive (facultatif)
56 * @param asynchrone true pour une communication asychrone (facultatif, truepar défaut)
57 * @param paramsSupp un objet contenant des paramètres supplémentaire pour la fonction ajax de jQuery (facultatif)
59 euphorik
.Communication
.prototype.requete = function(action
, json
, funOk
, funError
, asynchrone
, paramsSupp
) {
60 var thisCommunication
= this;
61 if (asynchrone
=== undefined) {
62 asynchrone
= true; // asynchrone par défaut
65 var mess
= this.getBase(action
);
66 objectEach(json
, function(name
, val
) {
70 if (this.funDebutReq
) {
79 data: { action : JSON
.stringify(mess
) },
82 if (thisCommunication
.funFinReq
) {
83 thisCommunication
.funFinReq();
85 if (data
.reply
=== "error") {
88 } else if (thisCommunication
.funError
) {
89 thisCommunication
.funError(data
);
97 if (thisCommunication
.funFinReq
) {
98 thisCommunication
.funFinReq();
104 objectEach(paramsSupp
, function(name
, val
) {
105 paramsAjax
[name
] = val
;
109 jQuery
.ajax(paramsAjax
);
112 euphorik
.Communication
.prototype.createCometConnection = function(name
) {
113 return new Comet(name
, this.getBase
);
116 euphorik
.Communication
.prototype.getBase = function(action
) {
118 "header" : { "action" : action
, "version" : euphorik
.conf
.versionProtocole
}
123 * Permet de gérer les événements (push serveur).
124 * Principe de fonctionnement :
125 * - La page courante créer un objet euphorik.Comet en indiquant le nom de la page et la version du protocole.
126 * - La page courante attend un événement en appelant 'waitEvent' (non-bloquant) et en donnant deux fonctions :
127 * - 'funsReceive' un ensemble de fonctions à appeler en fonction du "reply" du serveur, par exemple {"set_nom" : function(data) { print("ok : " + data.nom); } }
128 * - 'funSend' une fonction qui renvoie l'objet à envoyer avant l'attente, par exemple {"dernierMess" : 23}
129 * ("header" et "page" sont automatiquement ajoutés à l'objet)
131 * l'information envoyée est sous la forme :
133 * "header" : {"action" : "wait_event", "version" : <v> },
137 * l'information reçue est sous la forme :
142 * <reply> et <page> sont de type chaine
144 * @page [string] la page courante pour laquelle on écoute des événements (un string)
145 * @util [int] la version
147 Comet = function(page
, getBase
) {
149 this.getBase
= getBase
;
151 // l'objet JSONHttpRequest représentant la connexion d'attente
152 this.attenteCourante
= undefined;
154 // le multhreading du pauvre, merci javascript de m'offrire autant de primitives pour la gestion de la concurrence...
159 * Arrête l'attente courante s'il y en a une.
161 Comet
.prototype.stopAttenteCourante = function() {
164 if (this.attenteCourante
) {
165 this.attenteCourante
.abort();
170 * Attend un événement lié à la page. Non-bloquant.
171 * @funsReceive est un objet comprenant les fonctions à appeler en fonction du "reply"
172 * les fonctions acceptent un paramètre correspondant au données reçues.
173 * exemple : {"new_message" : function(data){ ... }}
174 * @funSend une fonction renvoyant les données json à envoyer (optional)
176 Comet
.prototype.waitEvent = function(funsReceive
, funSend
) {
177 this.stopAttenteCourante();
179 var thisComet
= this;
181 // on doit conserver l'ordre des valeurs de l'objet JSON (le serveur les veut dans l'ordre définit dans le protocole)
182 // TODO : ya pas mieux ?
183 var dataToSend
= this.getBase("wait_event")
184 dataToSend
["page"] = this.page
;
186 if (funSend
!== undefined) {
188 objectEach(tmp
, function(k
, v
) {
193 this.attenteCourante
= jQuery
.ajax({
197 // TODO : doit disparaitre
198 timeout: 180000, // timeout de 3min. Gros HACK pas beau. FIXME problème décrit ici : http://groups.google.com/group/jquery-en/browse_thread/thread/8724e64af3333a76
199 data: { action : JSON
.stringify(dataToSend
) },
202 funsReceive
[data
.reply
](data
);
204 // rappel de la fonction dans 100 ms
205 setTimeout(function(){ thisComet
.waitEvent2(funsReceive
, funSend
); }, 100);
208 function(XMLHttpRequest
, textStatus
, errorThrown
) {
209 // console.log("Connexion perdue dans Comet.prototype.waitEvent() : \n" + textStatus);
210 setTimeout(function(){ thisComet
.waitEvent2(funsReceive
, funSend
); }, 1000);
216 * Si un stopAttenteCourante survient un peu n'importe quand il faut imédiatement arreter de boucler.
218 Comet
.prototype.waitEvent2 = function(funsReceive
, funSend
) {
222 this.waitEvent(funsReceive
, funSend
);