MOD french -> english (3)
[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 * Object that represents the user.
23 * It carries all the user data like
24 * - ID
25 * - Nick
26 * - E-Mail
27 * - etc..
28 * It can access directly to the DOM if needed. Some examples :
29 * - Changes the menu if the user is logged or not
30 * - Changes the logo if the user is an ek master
31 * - etc..
32 * @util See util.js.
33 * @communication See communication.js.
34 */
35 euphorik.Client = function(util, communication) {
36 this.util = util;
37 this.communication = communication;
38
39 this.cookie = null;
40 this.regexCookie = /cookie=([^;]*)/;
41
42 this.resetPersonalData();
43
44 this.setStatus(euphorik.Client.statusType.disconnected);
45
46 // If true then each data change is flushed to the server.
47 // Active only for opera which doesn't support the unload event.
48 this.autoflush = $.browser.opera;
49 };
50
51 // The three status of a client.
52 euphorik.Client.statusType = {
53 // authentified and registered : The user can post messages and can modify his profile
54 auth_registered : 0,
55 // authentified but not registered : The user can only post messages
56 auth_not_registered : 1,
57 // disconnected (the initial state) : The user cannot post message
58 disconnected : 2
59 };
60
61 euphorik.Client.prototype.resetPersonalData = function() {
62 this.id = 0;
63 this.nick = euphorik.conf.defaultNick;
64 this.login = "";
65 this.password = "";
66 this.email = "";
67 this.css = $("link#mainCss").attr("href");
68 this.chatOrder = "reverse";
69 this.nickFormat = "nick";
70 this.viewTimes = true;
71 this.viewTooltips = true;
72 this.cookie = undefined;
73
74 this.mainConversationPage = 1;
75 this.ekMaster = false;
76 this.ostentatiousMaster = "light";
77
78 // les conversations, une conversation est un objet possédant les propriétés suivantes :
79 // - root (entier)
80 // - page (entier)
81 // - reduit (bool)
82 this.conversations = [];
83 };
84
85 euphorik.Client.prototype.setCss = function(css) {
86 if (this.css === css || !css) {
87 return;
88 }
89
90 this.css = css;
91 $("link#mainCss").attr("href", this.css);
92 if (this.autoflush) {
93 this.flush(true);
94 }
95 };
96
97 euphorik.Client.prototype.pageSuivante = function(numConv) {
98 if (numConv < 0 && this.mainConversationPage > 1) {
99 this.mainConversationPage -= 1;
100 } else if (this.conversations[numConv].page > 1) {
101 this.conversations[numConv].page -= 1;
102 }
103 };
104
105 euphorik.Client.prototype.pagePrecedente = function(numConv) {
106 if (numConv < 0) {
107 this.mainConversationPage += 1;
108 } else {
109 this.conversations[numConv].page += 1;
110 }
111 };
112
113 /**
114 * Définit la première page pour la conversation donnée.
115 * @return true si la page a changé sinon false
116 */
117 euphorik.Client.prototype.goPremierePage = function(numConv)
118 {
119 if (numConv < 0) {
120 if (this.mainConversationPage === 1) {
121 return false;
122 }
123 this.mainConversationPage = 1;
124 } else {
125 if (this.conversations[numConv].page === 1) {
126 return false;
127 }
128 this.conversations[numConv].page = 1;
129 }
130 return true;
131 };
132
133 /**
134 * Ajoute une conversation à la vue de l'utilisateur.
135 * Le profile de l'utilisateur est directement sauvegardé sur le serveur.
136 * @param racines la racine de la conversation (integer)
137 * @return true si la conversation a été créée sinon false (par exemple si la conv existe déjà)
138 */
139 euphorik.Client.prototype.ajouterConversation = function(racine) {
140 // vérification s'il elle n'existe pas déjà
141 var existe = false;
142 this.conversations.each(function(i, conv) {
143 if (conv.root === racine) {
144 existe = true;
145 }
146 });
147 if (existe) {
148 return false;
149 }
150
151 this.conversations.push({root : racine, page : 1, reduit : false});
152 if (this.autoflush) {
153 this.flush(true);
154 }
155
156 return true;
157 };
158
159 euphorik.Client.prototype.supprimerConversation = function(num) {
160 if (num < 0 || num >= this.conversations.length) {
161 return;
162 }
163
164 // décalage TODO : supprimer le dernier élément
165 for (var i = num; i < this.conversations.length - 1; i++) {
166 this.conversations[i] = this.conversations[i+1];
167 }
168 this.conversations.pop();
169
170 if (this.autoflush) {
171 this.flush(true);
172 }
173 };
174
175 euphorik.Client.prototype.getJSONConversations = function() {
176 var conversations = [];
177 this.conversations.each(function(i, conv) {
178 conversations.push({ "root" : conv.root, "minimized" : conv.reduit });
179 });
180 return conversations;
181 };
182
183 euphorik.Client.prototype.getJSONProfile = function() {
184 return {
185 "cookie" : this.cookie,
186 "login" : this.login,
187 "password" : this.password,
188 "profile" : this.getJSONProfileInfos()
189 };
190 };
191
192 euphorik.Client.prototype.getJSONProfileInfos = function() {
193 return {
194 "nick" : this.nick,
195 "email" : this.email,
196 "css" : this.css,
197 "chat_order" : this.chatOrder,
198 "nick_format" : this.nickFormat,
199 "view_times" : this.viewTimes,
200 "view_tooltips" : this.viewTooltips,
201 "conversations" : this.getJSONConversations(),
202 "ostentatious_master" : this.ostentatiousMaster
203 };
204 };
205
206 /**
207 * .
208 */
209 euphorik.Client.prototype.getCookie = function() {
210 var cookie = this.regexCookie.exec(document.cookie);
211 if (cookie) {
212 this.cookie = cookie[1];
213 } else {
214 this.cookie = undefined;
215 }
216 };
217
218 euphorik.Client.prototype.delCookie = function() {
219 document.cookie = "cookie=; max-age=0";
220 this.cookie = undefined;
221 };
222
223 euphorik.Client.prototype.setCookie = function() {
224 if (!this.cookie) {
225 return;
226 }
227
228 // doesn't work under IE....
229 /*document.cookie = "cookie=" + this.cookie + "; max-age=" + (60 * 60 * 24 * 365) */
230
231 document.cookie =
232 "cookie="+this.cookie+"; expires=" + new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365).toUTCString();
233 };
234
235 euphorik.Client.prototype.authentifie = function() {
236 return this.statut === euphorik.Client.statusType.auth_registered || this.statut === euphorik.Client.statusType.auth_not_registered;
237 };
238
239 euphorik.Client.prototype.setStatus = function(statut)
240 {
241 // conversation en "enum" si en "string"
242 if (typeof(statut) === "string") {
243 statut =
244 statut === "auth_registered" ?
245 euphorik.Client.statusType.auth_registered :
246 (statut === "auth_not_registered" ? euphorik.Client.statusType.auth_not_registered : euphorik.Client.statusType.disconnected);
247 }
248
249 if (statut === this.statut) {
250 return;
251 }
252
253 this.statut = statut;
254
255 this.majMenu();
256 this.majLogo();
257 };
258
259 /**
260 * Try to authentify the client with the cookie information.
261 * Do nothing if there is no cookie.
262 */
263 euphorik.Client.prototype.connectionCookie = function() {
264 this.getCookie();
265 if (!this.cookie) {
266 return false;
267 }
268 return this.connexion("authentification", { "cookie" : this.cookie });
269 };
270
271 euphorik.Client.prototype.connexionLogin = function(login, password) {
272 return this.connexion("authentification", {"login" : login, "password" : password });
273 };
274
275 euphorik.Client.prototype.enregistrement = function(login, password) {
276 if (this.authentifie()) {
277 this.login = login;
278 this.password = password;
279 if(this.flush()) {
280 this.setStatus(euphorik.Client.statusType.auth_registered);
281 return true;
282 }
283 return false;
284 } else {
285 return this.connexion("register", this.getJSONEnregistrement(login, password));
286 }
287 };
288
289 /**
290 * le couple (login, password) est facultatif. S'il n'est pas fournit alors il ne sera pas possible
291 * de s'autentifier avec (login, password).
292 */
293 euphorik.Client.prototype.getJSONEnregistrement = function(login, password) {
294 var mess = {};
295
296 if (login && password) {
297 mess.login = login;
298 mess.password = password;
299 }
300
301 mess.profile = this.getJSONProfileInfos();
302
303 return mess;
304 };
305
306 /**
307 * Connexion. Réalisé de manière synchrone.
308 */
309 euphorik.Client.prototype.connexion = function(action, messageJson) {
310 var thisClient = this;
311
312 this.communication.requete(
313 action,
314 messageJson,
315 function(data) {
316 thisClient.chargerDonnees(data);
317 },
318 function(data) {
319 thisClient.util.messageDialog(data.error_message);
320 thisClient.delCookie(); // suppression du cookie actuel, cas où le cookie du client ne permet pas une authentification
321 },
322 false
323 );
324 return this.authentifie();
325 };
326
327 euphorik.Client.prototype.disconnect = function() {
328 this.flush(true);
329 this.delCookie();
330 this.resetPersonalData();
331 this.setStatus(euphorik.Client.statusType.disconnected);
332 };
333
334 euphorik.Client.prototype.chargerDonnees = function(data) {
335 // la modification du statut qui suit met à jour le menu, le menu dépend (page admin)
336 // de l'état ekMaster
337 this.ekMaster = data.ek_master ? data.ek_master : false;
338
339 this.setStatus(data.status);
340
341 if (this.authentifie()) {
342 this.cookie = data.cookie;
343 this.setCookie();
344
345 this.id = data.id;
346 this.login = data.login;
347 this.nick = data.profile.nick;
348 this.email = data.profile.email;
349 this.setCss(data.profile.css);
350 this.chatOrder = data.profile.chat_order;
351 this.nickFormat = data.profile.nick_format;
352 this.viewTimes = data.profile.view_times;
353 this.viewTooltips = data.profile.view_tooltips;
354 this.ostentatiousMaster = data.profile.ostentatious_master;
355
356 // la page de la conversation principale
357 this.mainConversationPage = 1;
358
359 // les conversations
360 this.conversations = data.profile.conversations;
361 this.conversations.map(function(conv) {
362 return { root : conv.root, page : 1, reduit : conv.minimized };
363 });
364
365 this.majBulle();
366 this.majCssSelectionee();
367 }
368 };
369
370 /**
371 * Met à jour les données personne sur serveur.
372 * @param async de manière asynchrone ? défaut = true
373 * @return false si le flush n'a pas pû se faire sinon true
374 */
375 euphorik.Client.prototype.flush = function(async) {
376 async = async || false;
377
378 if (!this.authentifie()) {
379 return false;
380 }
381
382 var thisClient = this;
383 var ok = true;
384
385 this.communication.requete(
386 "set_profile",
387 this.getJSONProfile(),
388 function(data) {
389 thisClient.majBulle();
390 },
391 function(data) {
392 thisClient.util.messageDialog(data.error_message);
393 ok = false;
394 },
395 async
396 );
397
398 return ok;
399 };
400
401 euphorik.Client.prototype.majMenu = function() {
402 var displayType = "block";
403
404 $("#menu .admin").css("display", this.ekMaster ? displayType : "none");
405
406 // met à jour le menu
407 if (this.statut === euphorik.Client.statusType.auth_registered) {
408 $("#menu .profile").css("display", displayType).text("profile");
409 $("#menu .logout").css("display", displayType);
410 $("#menu .register").css("display", "none");
411 } else if (this.statut === euphorik.Client.statusType.auth_not_registered) {
412 $("#menu .profile").css("display", "none");
413 $("#menu .logout").css("display", displayType);
414 $("#menu .register").css("display", displayType);
415 } else {
416 $("#menu .profile").css("display", displayType).text("login");
417 $("#menu .logout").css("display", "none");
418 $("#menu .register").css("display", displayType);
419 }
420 };
421
422 /**
423 * Met à jour l'affichage ou non des infos bulles en fonction du profile.
424 */
425 euphorik.Client.prototype.majBulle = function() {
426 this.util.bulleActive = this.viewTooltips;
427 };
428
429 /**
430 * Met à jour la css sélectionnée, lors du chargement des données.
431 */
432 euphorik.Client.prototype.majCssSelectionee = function() {
433 // extraction du numéro de la css courante
434 var numCssCourante = this.css.match(/^.*?\/(\d)\/.*$/);
435 if (numCssCourante && numCssCourante[1]) {
436 $("#menuCss option").removeAttr("selected");
437 $("#menuCss option[value=" + numCssCourante[1]+ "]").attr("selected", "selected");
438 }
439 };
440
441 /**
442 * Change la "class" du logo en fonction du statut de ekMaster.
443 */
444 euphorik.Client.prototype.majLogo = function() {
445 if (this.ekMaster) {
446 $("#logo").addClass("ekMaster");
447 } else {
448 $("#logo").removeClass("ekMaster");
449 }
450 };
451
452 euphorik.Client.prototype.slap = function(userId, raison) {
453 var thisClient = this;
454 this.communication.requete("slap", { "cookie" : thisClient.cookie, "user_id" : userId, "reason" : raison });
455 };
456
457 euphorik.Client.prototype.ban = function(userId, raison, minutes) {
458 var thisClient = this;
459
460 // par défaut un ban correspond à 3 jours
461 minutes = minutes || euphorik.conf.tempsBan;
462 this.communication.requete("ban", { "cookie" : thisClient.cookie, "duration" : minutes, "user_id" : userId, "reason" : raison });
463 };
464
465 euphorik.Client.prototype.kick = function(userId, raison) {
466 this.ban(userId, raison, euphorik.conf.tempsKick);
467 };