ADD avancement dans tool.rb
[euphorik.git] / js / client.js
1 // coding: utf-8
2 // Copyright 2008 Grégory Burri
3 //
4 // This file is part of Euphorik.
5 //
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.
10 //
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.
15 //
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/>.
18
19 /*jslint laxbreak:true */
20
21 /**
22 * Représente l'utilisateur du site.
23 */
24 euphorik.Client = function(util) {
25 this.util = util;
26
27 this.cookie = null;
28 this.regexCookie = /^cookie=([^;]*)/;
29
30 // données personnels
31 this.resetDonneesPersonnelles();
32
33 this.setStatut(euphorik.Client.statutType.deconnected);
34
35 // si true alors chaque modification du client est mémorisé sur le serveur
36 this.autoflush = $.browser.opera;
37 };
38
39 // les statuts possibes du client
40 euphorik.Client.statutType = {
41 // mode enregistré, peut poster des messages et modifier son profile
42 auth_registered : 0,
43 // mode identifié, peut poster des messages mais n'a pas accès au profile
44 auth_not_registered : 1,
45 // mode déconnecté, ne peut pas poster de message
46 deconnected : 2
47 };
48
49 euphorik.Client.prototype.resetDonneesPersonnelles = function() {
50 this.id = 0;
51 this.pseudo = euphorik.conf.pseudoDefaut;
52 this.login = "";
53 this.password = "";
54 this.email = "";
55 this.css = $("link#cssPrincipale").attr("href");
56 this.chatOrder = "reverse";
57 this.nickFormat = "nick";
58 this.viewTimes = true;
59 this.viewTooltips = true;
60 this.cookie = undefined;
61
62 this.pagePrincipale = 1;
63 this.ekMaster = false;
64 this.ostentatiousMaster = "light";
65
66 // les conversations, une conversation est un objet possédant les propriétés suivantes :
67 // - root (entier)
68 // - page (entier)
69 // - reduit (bool)
70 this.conversations = [];
71 };
72
73 euphorik.Client.prototype.setCss = function(css) {
74 if (this.css === css || !css) {
75 return;
76 }
77
78 this.css = css;
79 $("link#cssPrincipale").attr("href", this.css);
80 if (this.autoflush) {
81 this.flush(true);
82 }
83 };
84
85 euphorik.Client.prototype.pageSuivante = function(numConv) {
86 if (numConv < 0 && this.pagePrincipale > 1) {
87 this.pagePrincipale -= 1;
88 } else if (this.conversations[numConv].page > 1) {
89 this.conversations[numConv].page -= 1;
90 }
91 };
92
93 euphorik.Client.prototype.pagePrecedente = function(numConv) {
94 if (numConv < 0) {
95 this.pagePrincipale += 1;
96 } else {
97 this.conversations[numConv].page += 1;
98 }
99 };
100
101 /**
102 * Définit la première page pour la conversation donnée.
103 * @return true si la page a changé sinon false
104 */
105 euphorik.Client.prototype.goPremierePage = function(numConv)
106 {
107 if (numConv < 0) {
108 if (this.pagePrincipale === 1) {
109 return false;
110 }
111 this.pagePrincipale = 1;
112 } else {
113 if (this.conversations[numConv].page === 1) {
114 return false;
115 }
116 this.conversations[numConv].page = 1;
117 }
118 return true;
119 };
120
121 /**
122 * Ajoute une conversation à la vue de l'utilisateur.
123 * Le profile de l'utilisateur est directement sauvegardé sur le serveur.
124 * @param racines la racine de la conversation (integer)
125 * @return true si la conversation a été créée sinon false (par exemple si la conv existe déjà)
126 */
127 euphorik.Client.prototype.ajouterConversation = function(racine) {
128 // vérification s'il elle n'existe pas déjà
129 var existe = false;
130 this.conversations.each(function(i, conv) {
131 if (conv.root === racine) {
132 existe = true;
133 }
134 });
135 if (existe) {
136 return false;
137 }
138
139 this.conversations.push({root : racine, page : 1, reduit : false});
140 if (this.autoflush) {
141 this.flush(true);
142 }
143
144 return true;
145 };
146
147 euphorik.Client.prototype.supprimerConversation = function(num) {
148 if (num < 0 || num >= this.conversations.length) {
149 return;
150 }
151
152 // décalage TODO : supprimer le dernier élément
153 for (var i = num; i < this.conversations.length - 1; i++) {
154 this.conversations[i] = this.conversations[i+1];
155 }
156 this.conversations.pop();
157
158 if (this.autoflush) {
159 this.flush(true);
160 }
161 };
162
163 euphorik.Client.prototype.getJSONLogin = function(login, password) {
164 return {
165 "header" : { "action" : "authentification", "version" : euphorik.conf.versionProtocole },
166 "login" : login,
167 "password" : password
168 };
169 };
170
171 euphorik.Client.prototype.getJSONLoginCookie = function() {
172 return {
173 "header" : { "action" : "authentification", "version" : euphorik.conf.versionProtocole },
174 "cookie" : this.cookie
175 };
176 };
177
178 /**
179 * le couple (login, password) est facultatif. S'il n'est pas fournit alors il ne sera pas possible
180 * de s'autentifier avec (login, password).
181 */
182 euphorik.Client.prototype.getJSONEnregistrement = function(login, password) {
183 var mess = {
184 "header" : { "action" : "register","version" : euphorik.conf.versionProtocole }
185 };
186
187 if (login && password) {
188 mess.login = login;
189 mess.password = password;
190 }
191
192 mess.profile = this.getJSONProfileInfos();
193
194 return mess;
195 };
196
197 euphorik.Client.prototype.getJSONConversations = function() {
198 var conversations = [];
199 this.conversations.each(function(i, conv) {
200 conversations.push({ "root" : conv.root, "minimized" : conv.reduit });
201 });
202 return conversations;
203 };
204
205 euphorik.Client.prototype.getJSONProfile = function() {
206 return {
207 "header" : { "action" : "set_profile", "version" : euphorik.conf.versionProtocole },
208 "cookie" : this.cookie,
209 "login" : this.login,
210 "password" : this.password,
211 "profile" : this.getJSONProfileInfos()
212 };
213 };
214
215 euphorik.Client.prototype.getJSONProfileInfos = function() {
216 return {
217 "nick" : this.pseudo,
218 "email" : this.email,
219 "css" : this.css,
220 "chat_order" : this.chatOrder,
221 "nick_format" : this.nickFormat,
222 "view_times" : this.viewTimes,
223 "view_tooltips" : this.viewTooltips,
224 "conversations" : this.getJSONConversations(),
225 "ostentatious_master" : this.ostentatiousMaster
226 };
227 };
228
229 /**
230 * .
231 */
232 euphorik.Client.prototype.getCookie = function() {
233 var cookie = this.regexCookie.exec(document.cookie);
234 if (cookie) {
235 this.cookie = cookie[1];
236 } else {
237 this.cookie = undefined;
238 }
239 };
240
241 euphorik.Client.prototype.delCookie = function() {
242 document.cookie = "cookie=; max-age=0";
243 this.cookie = undefined;
244 };
245
246 euphorik.Client.prototype.setCookie = function() {
247 if (!this.cookie) {
248 return;
249 }
250
251 // ne fonctionne pas sous IE....
252 /*document.cookie = "cookie=" + this.cookie + "; max-age=" + (60 * 60 * 24 * 365) */
253
254 document.cookie =
255 "cookie="+this.cookie+"; expires=" + new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365).toUTCString();
256 };
257
258 euphorik.Client.prototype.authentifie = function() {
259 return this.statut === euphorik.Client.statutType.auth_registered || this.statut === euphorik.Client.statutType.auth_not_registered;
260 };
261
262 euphorik.Client.prototype.setStatut = function(statut)
263 {
264 // conversation en "enum" si en "string"
265 if (typeof(statut) === "string") {
266 statut =
267 statut === "auth_registered" ?
268 euphorik.Client.statutType.auth_registered :
269 (statut === "auth_not_registered" ? euphorik.Client.statutType.auth_not_registered : euphorik.Client.statutType.deconnected);
270 }
271
272 if (statut === this.statut) {
273 return;
274 }
275
276 this.statut = statut;
277
278 this.majMenu();
279 this.majLogo();
280 };
281
282 /**
283 * Effectue la connexion vers le serveur.
284 * Cette fonction est bloquante tant que la connexion n'a pas été établie.
285 * S'il existe un cookie en local on s'authentifie directement avec lui.
286 * Si il n'est pas possible de s'authentifier alors on affiche un captcha anti-bot.
287 */
288 euphorik.Client.prototype.connexionCookie = function() {
289 this.getCookie();
290 if (!this.cookie) {
291 return false;
292 }
293 return this.connexion(this.getJSONLoginCookie());
294 };
295
296 euphorik.Client.prototype.connexionLogin = function(login, password) {
297 return this.connexion(this.getJSONLogin(login, password));
298 };
299
300 euphorik.Client.prototype.enregistrement = function(login, password) {
301 if (this.authentifie()) {
302 this.login = login;
303 this.password = password;
304 if(this.flush()) {
305 this.setStatut(euphorik.Client.statutType.auth_registered);
306 return true;
307 }
308 return false;
309 } else {
310 return this.connexion(this.getJSONEnregistrement(login, password));
311 }
312 };
313
314 /**
315 * Connexion. Réalisée de manière synchrone.
316 */
317 euphorik.Client.prototype.connexion = function(messageJson) {
318 var thisClient = this;
319 jQuery.ajax({
320 async: false,
321 type: "POST",
322 url: "request",
323 dataType: "json",
324 data: this.util.jsonVersAction(messageJson),
325 success:
326 function(data){
327 if (data.reply === "error") {
328 thisClient.util.messageDialogue(data.error_message);
329 // suppression du cookie actuel, cas où le cookie du client ne permet pas une authentification
330 thisClient.delCookie();
331 } else {
332 thisClient.chargerDonnees(data);
333 }
334 }
335 });
336 return this.authentifie();
337 };
338
339 euphorik.Client.prototype.deconnexion = function() {
340 this.flush(true);
341 this.delCookie();
342 this.resetDonneesPersonnelles();
343 this.setStatut(euphorik.Client.statutType.deconnected); // deconnexion
344 };
345
346 euphorik.Client.prototype.chargerDonnees = function(data) {
347 // la modification du statut qui suit met à jour le menu, le menu dépend (page admin)
348 // de l'état ekMaster
349 this.ekMaster = data.ek_master ? data.ek_master : false;
350
351 this.setStatut(data.status);
352
353 if (this.authentifie()) {
354 this.cookie = data.cookie;
355 this.setCookie();
356
357 this.id = data.id;
358 this.login = data.login;
359 this.pseudo = data.profile.nick;
360 this.email = data.profile.email;
361 this.setCss(data.profile.css);
362 this.chatOrder = data.profile.chat_order;
363 this.nickFormat = data.profile.nick_format;
364 this.viewTimes = data.profile.view_times;
365 this.viewTooltips = data.profile.view_tooltips;
366 this.ostentatiousMaster = data.profile.ostentatious_master;
367
368 // la page de la conversation principale
369 this.pagePrincipale = 1;
370
371 // les conversations
372 this.conversations = data.profile.conversations;
373 this.conversations.map(function(conv) {
374 return { root : conv.root, page : 1, reduit : conv.minimized };
375 });
376
377 this.majBulle();
378 this.majCssSelectionee();
379 }
380 };
381
382 /**
383 * Met à jour les données personne sur serveur.
384 * @param async de manière asynchrone ? défaut = true
385 * @return false si le flush n'a pas pû se faire sinon true
386 */
387 euphorik.Client.prototype.flush = function(async) {
388 async = async || false;
389
390 if (!this.authentifie()) {
391 return false;
392 }
393
394 var thisClient = this;
395 var ok = true;
396 jQuery.ajax({
397 async: async,
398 type: "POST",
399 url: "request",
400 dataType: "json",
401 data: this.util.jsonVersAction(this.getJSONProfile()),
402 success:
403 function(data) {
404 if (data.reply === "error") {
405 thisClient.util.messageDialogue(data.error_message);
406 ok = false;
407 } else {
408 thisClient.majBulle();
409 }
410 }
411 });
412
413 return ok;
414 };
415
416 euphorik.Client.prototype.majMenu = function() {
417 var displayType = "block";
418
419 $("#menu .admin").css("display", this.ekMaster ? displayType : "none");
420
421 // met à jour le menu
422 if (this.statut === euphorik.Client.statutType.auth_registered) {
423 $("#menu .profile").css("display", displayType).text("profile");
424 $("#menu .logout").css("display", displayType);
425 $("#menu .register").css("display", "none");
426 } else if (this.statut === euphorik.Client.statutType.auth_not_registered) {
427 $("#menu .profile").css("display", "none");
428 $("#menu .logout").css("display", displayType);
429 $("#menu .register").css("display", displayType);
430 } else {
431 $("#menu .profile").css("display", displayType).text("login");
432 $("#menu .logout").css("display", "none");
433 $("#menu .register").css("display", displayType);
434 }
435 };
436
437 /**
438 * Met à jour l'affichage ou non des infos bulles en fonction du profile.
439 */
440 euphorik.Client.prototype.majBulle = function() {
441 this.util.bulleActive = this.viewTooltips;
442 };
443
444 /**
445 * Met à jour la css sélectionnée, lors du chargement des données.
446 */
447 euphorik.Client.prototype.majCssSelectionee = function() {
448 // extraction du numéro de la css courante
449 var numCssCourante = this.css.match(/^.*?\/(\d)\/.*$/);
450 if (numCssCourante && numCssCourante[1]) {
451 $("#menuCss option").removeAttr("selected");
452 $("#menuCss option[value=" + numCssCourante[1]+ "]").attr("selected", "selected");
453 }
454 };
455
456 /**
457 * Change la "class" du logo en fonction du statut de ekMaster.
458 */
459 euphorik.Client.prototype.majLogo = function() {
460 if (this.ekMaster) {
461 $("#logo").addClass("ekMaster");
462 } else {
463 $("#logo").removeClass("ekMaster");
464 }
465 };
466
467 euphorik.Client.prototype.slap = function(userId, raison) {
468 var thisClient = this;
469
470 jQuery.ajax({
471 type: "POST",
472 url: "request",
473 dataType: "json",
474 data: this.util.jsonVersAction({
475 "header" : { "action" : "slap", "version" : euphorik.conf.versionProtocole },
476 "cookie" : thisClient.cookie,
477 "user_id" : userId,
478 "reason" : raison
479 }),
480 success:
481 function(data) {
482 if (data.reply === "error") {
483 thisClient.util.messageDialogue(data.error_message);
484 }
485 }
486 });
487 };
488
489 euphorik.Client.prototype.ban = function(userId, raison, minutes)
490 {
491 var thisClient = this;
492
493 // par défaut un ban correspond à 3 jours
494 minutes = minutes || euphorik.conf.tempsBan;
495
496 jQuery.ajax({
497 type: "POST",
498 url: "request",
499 dataType: "json",
500 data: this.util.jsonVersAction({
501 "header" : { "action" : "ban", "version" : euphorik.conf.versionProtocole },
502 "cookie" : thisClient.cookie,
503 "duration" : minutes,
504 "user_id" : userId,
505 "reason" : raison
506 }),
507 success:
508 function(data) {
509 if (data.reply === "error") {
510 thisClient.util.messageDialogue(data.error_message);
511 }
512 }
513 });
514 };
515
516 euphorik.Client.prototype.kick = function(userId, raison) {
517 this.ban(userId, raison, euphorik.conf.tempsKick);
518 };