Factorises promo selection.
[platal.git] / htdocs / javascript / xorg.js
CommitLineData
0337d704 1/***************************************************************************
5e1513f6 2 * Copyright (C) 2003-2011 Polytechnique.org *
0337d704 3 * http://opensource.polytechnique.org/ *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, Inc., *
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19 ***************************************************************************/
20
0337d704 21// {{{ function getNow()
80dcbd9a
FB
22var days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
23var months = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet',
34cc65fd 24 'août', 'septembre', 'octobre', 'novembre', 'décembre'];
0337d704 25
0337d704 26function getNow() {
80dcbd9a
FB
27 var dt = new Date();
28 var dy = dt.getDay();
29 var mh = dt.getMonth();
30 var wd = dt.getDate();
31 var yr = dt.getYear();
80dcbd9a
FB
32 var hr = dt.getHours();
33 var mi = dt.getMinutes();
34cc65fd
FB
34 var se = dt.getSeconds();
35
36 if (yr<1000) {
37 yr += 1900;
38 }
80dcbd9a
FB
39 if (mi < 10) {
40 mi = '0' + mi;
41 }
80dcbd9a
FB
42 if (se < 10) {
43 se = '0' + se;
44 }
9f449375 45
80dcbd9a
FB
46 $(".date-heure").html(days[dy] + ' ' + wd + ' ' + months[mh] + ' ' + yr + '<br />'
47 + hr + ':' + mi + ':' + se);
9f449375 48}
49
50// }}}
a27c6df8 51// {{{ Search Engine
52
53function canAddSearchEngine()
54{
34cc65fd
FB
55 if (((typeof window.sidebar === "object") && $.isFunction(window.sidebar.addSearchEngine))
56 || ((typeof window.external === "object") && $.isFunction(window.external.AddSearchProvider))) {
350ba5ac
FB
57 return true;
58 }
59 return false;
a27c6df8 60}
39fd8f50 61
b09e5dea 62function addSearchEngine()
63{
350ba5ac 64 var searchURI = "http://www.polytechnique.org/xorg.opensearch.xml";
34cc65fd 65 if ((typeof window.sidebar === "object") && $.isFunction(window.sidebar.addSearchEngine)) {
350ba5ac
FB
66 window.sidebar.addSearchEngine(
67 searchURI,
68 "http://www.polytechnique.org/images/xorg.png",
69 "Annuaire Polytechnique.org",
70 "Academic");
71 } else {
72 try {
73 window.external.AddSearchProvider(searchURI);
74 } catch(e) {
75 alert("Impossible d'installer la barre de recherche");
76 }
b09e5dea 77 }
39fd8f50 78}
79
39fd8f50 80// }}}
0337d704 81
82/***************************************************************************
83 * POPUP THINGS
84 */
85
769dc7d5
VZ
86// {{{ function goodiesPopup()
87
048c44a3
FB
88(function($) {
89 var goodies = {
90 ical: {
91 default_title: 'Calendrier iCal',
92 sites: [
93 {url_prefix: '',
94 img: 'images/icons/calendar_view_day.gif',
95 title: 'Calendrier iCal'},
96 {url_prefix: 'http://www.google.com/calendar/render?cid=',
97 img: 'images/goodies/add-google-calendar.gif',
98 title: 'Ajouter à Google Calendar'},
99 {url_prefix: 'https://www.google.com/calendar/hosted/polytechnique.org/render?cid=',
100 img: 'images/goodies/add-google-calendar.gif',
101 title: 'Ajouter à Google Apps / Calendar'}
102 ]
103 },
104
105 rss: {
106 default_title: 'Fils RSS',
107 sites: [
108 {url_prefix: '',
109 img: 'images/icons/feed.gif',
110 title: 'Fil rss'},
111 {url_prefix: 'http://fusion.google.com/add?feedurl=',
112 img: 'images/goodies/add-google.gif',
113 alt: 'Add to Google',
114 title: 'Ajouter à iGoogle/Google Reader'},
115 {url_prefix: 'http://www.netvibes.com/subscribe.php?url=',
116 img: 'images/goodies/add-netvibes.gif',
117 title: 'Ajouter à Netvibes'},
118 {url_prefix: 'http://add.my.yahoo.com/content?.intl=fr&url=',
119 img: 'images/goodies/add-yahoo.gif',
120 alt: 'Add to My Yahoo!',
121 title: 'Ajouter à My Yahoo!'}
122 ]
123 }
124 };
125
126 $.fn.extend({
127 goodiesPopup: function goodiesPopup(type) {
128 var text = '<div style="text-align: center; line-height: 2.2">';
34cc65fd
FB
129 var site;
130 var entry;
131 var s_alt;
132 var s_img;
133 var s_title;
134 var s_url;
b3d92c8e 135 var href = this.attr('href');
34cc65fd
FB
136
137 for (site in goodies[type].sites) {
138 entry = goodies[type].sites[site];
139 s_alt = entry.alt || "";
140 s_img = entry.img;
141 s_title = entry.title || "";
b3d92c8e 142 s_url = entry.url_prefix.length > 0 ? entry.url_prefix + escape(href) : href;
048c44a3
FB
143
144 text += '<a href="' + s_url + '"><img src="' + s_img + '" title="' + s_title + '" alt="' + s_alt + '"></a><br />';
b3d92c8e 145 }
048c44a3 146 text += '<a href="https://www.polytechnique.org/Xorg/Goodies">Plus de bonus</a> ...</div>';
769dc7d5 147
048c44a3
FB
148 return this.overlib({
149 text: text,
34cc65fd 150 caption: this.attr('title') || goodies.default_title,
048c44a3
FB
151 close_text: 'Fermer',
152 delay: 800,
153 sticky: true,
154 width: 150
155 });
156 }
157 });
158}(jQuery));
769dc7d5
VZ
159
160// }}}
0337d704 161// {{{ function auto_links()
162
0337d704 163function auto_links() {
80dcbd9a
FB
164 var url = document.URL;
165 var fqdn = url.replace(/^https?:\/\/([^\/]*)\/.*$/,'$1');
63c89179
FB
166 var light = url.indexOf('display=light') > url.indexOf('?');
167 var resource_page = url.contains('rss') || url.contains('ical');
e83d83e8 168
b804b882
FB
169 $("a,link").each(function(i) {
170 var node = $(this);
171 var href = this.href;
63c89179
FB
172 var matches;
173 var rss;
174 var ical;
175
b804b882 176 if(!href || node.hasClass('xdx')
63c89179 177 || href.startsWith('mailto:') || href.startsWith('javascript:')) {
b804b882
FB
178 return;
179 }
63c89179 180 if ((!href.contains(fqdn) && !this.className.contains('popup')) || node.hasClass('popup')) {
b804b882 181 node.click(function () {
7ffe1c54 182 window.open(this.href);
b804b882
FB
183 return false;
184 });
185 }
63c89179 186 if (href.contains(fqdn) && light) {
b804b882
FB
187 href = href.replace(/([^\#\?]*)\??([^\#]*)(\#.*)?/, "$1?display=light&$2$3");
188 this.href = href;
189 }
63c89179
FB
190 rss = href.contains('rss');
191 ical = href.contains('ical');
b804b882 192 if (rss || ical) {
63c89179 193 if (!href.startsWith('http')) {
b804b882 194 href = 'http://' + fqdn + '/' + href;
e83d83e8 195 }
b804b882 196 }
34cc65fd 197 if (this.nodeName.toLowerCase() === 'a' && !resource_page) {
63c89179 198 if (rss && !href.contains('prefs/rss') && (href.contains('xml') || href.contains('hash'))) {
048c44a3 199 node.goodiesPopup('rss');
b804b882 200 } else if (ical) {
048c44a3 201 node.goodiesPopup('ical');
769dc7d5 202 }
3def38d5 203 }
34cc65fd
FB
204 matches = /^popup_([0-9]*)x([0-9]*)$/.exec(this.className);
205 if (matches) {
206 node.popWin(matches[1], matches[2]);
b804b882
FB
207 }
208 });
209 $('.popup2').popWin(840, 600);
210 $('.popup3').popWin(640, 800);
0337d704 211}
212
e83d83e8 213
0337d704 214// }}}
215
7143ad2b
FB
216/***************************************************************************
217 * Password check
218 */
219
220// {{{ function checkPassword
221
5ff39ae1
FB
222/* {{{ SHA1 Implementation */
223
224/*
225 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
226 * in FIPS PUB 180-1
227 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
228 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
229 * Distributed under the BSD License
230 * See http://pajhome.org.uk/crypt/md5 for details.
231 */
232
233/*
234 * Configurable variables. You may need to tweak these to be compatible with
235 * the server-side, but the defaults work in most cases.
236 */
237var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
238var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
239var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
240
241/*
242 * These are the functions you'll usually want to call
243 * They take string arguments and return either hex or base-64 encoded strings
244 */
245function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
246function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
247function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
248function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
249function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
250function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
251
252/*
253 * Perform a simple self-test to see if the VM is working
254 */
255function sha1_vm_test()
256{
34cc65fd 257 return hex_sha1("abc") === "a9993e364706816aba3e25717850c26c9cd0d89d";
5ff39ae1
FB
258}
259
260/*
261 * Calculate the SHA-1 of an array of big-endian words, and a bit length
262 */
263function core_sha1(x, len)
264{
34cc65fd
FB
265 var w, a, b, c, d, e;
266 var olda, oldb, oldc, oldd, olde;
267 var i, j, t;
268
5ff39ae1
FB
269 /* append padding */
270 x[len >> 5] |= 0x80 << (24 - len % 32);
271 x[((len + 64 >> 9) << 4) + 15] = len;
272
34cc65fd
FB
273 w = Array(80);
274 a = 1732584193;
275 b = -271733879;
276 c = -1732584194;
277 d = 271733878;
278 e = -1009589776;
5ff39ae1 279
34cc65fd 280 for(i = 0; i < x.length; i += 16)
5ff39ae1 281 {
34cc65fd
FB
282 olda = a;
283 oldb = b;
284 oldc = c;
285 oldd = d;
286 olde = e;
5ff39ae1 287
34cc65fd 288 for(j = 0; j < 80; j++)
5ff39ae1
FB
289 {
290 if(j < 16) w[j] = x[i + j];
291 else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
34cc65fd 292 t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
5ff39ae1
FB
293 safe_add(safe_add(e, w[j]), sha1_kt(j)));
294 e = d;
295 d = c;
296 c = rol(b, 30);
297 b = a;
298 a = t;
299 }
300
301 a = safe_add(a, olda);
302 b = safe_add(b, oldb);
303 c = safe_add(c, oldc);
304 d = safe_add(d, oldd);
305 e = safe_add(e, olde);
306 }
307 return Array(a, b, c, d, e);
308
309}
310
311/*
312 * Perform the appropriate triplet combination function for the current
313 * iteration
314 */
315function sha1_ft(t, b, c, d)
316{
317 if(t < 20) return (b & c) | ((~b) & d);
318 if(t < 40) return b ^ c ^ d;
319 if(t < 60) return (b & c) | (b & d) | (c & d);
320 return b ^ c ^ d;
321}
322
323/*
324 * Determine the appropriate additive constant for the current iteration
325 */
326function sha1_kt(t)
327{
328 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
329 (t < 60) ? -1894007588 : -899497514;
330}
331
332/*
333 * Calculate the HMAC-SHA1 of a key and some data
334 */
335function core_hmac_sha1(key, data)
336{
337 var bkey = str2binb(key);
34cc65fd
FB
338 var i, ipad, opad;
339 var hash;
340
5ff39ae1
FB
341 if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
342
34cc65fd
FB
343 ipad = Array(16);
344 opad = Array(16);
345 for(i = 0; i < 16; i++)
5ff39ae1
FB
346 {
347 ipad[i] = bkey[i] ^ 0x36363636;
348 opad[i] = bkey[i] ^ 0x5C5C5C5C;
349 }
350
34cc65fd 351 hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
5ff39ae1
FB
352 return core_sha1(opad.concat(hash), 512 + 160);
353}
354
355/*
356 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
357 * to work around bugs in some JS interpreters.
358 */
359function safe_add(x, y)
360{
361 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
362 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
363 return (msw << 16) | (lsw & 0xFFFF);
364}
365
366/*
367 * Bitwise rotate a 32-bit number to the left.
368 */
369function rol(num, cnt)
370{
371 return (num << cnt) | (num >>> (32 - cnt));
372}
373
374/*
375 * Convert an 8-bit or 16-bit string to an array of big-endian words
376 * In 8-bit function, characters >255 have their hi-byte silently ignored.
377 */
378function str2binb(str)
379{
380 var bin = Array();
381 var mask = (1 << chrsz) - 1;
34cc65fd
FB
382 var i;
383 for(i = 0; i < str.length * chrsz; i += chrsz)
5ff39ae1
FB
384 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
385 return bin;
386}
387
388/*
389 * Convert an array of big-endian words to a string
390 */
391function binb2str(bin)
392{
393 var str = "";
394 var mask = (1 << chrsz) - 1;
34cc65fd
FB
395 var i;
396 for(i = 0; i < bin.length * 32; i += chrsz)
5ff39ae1
FB
397 str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
398 return str;
399}
400
401/*
402 * Convert an array of big-endian words to a hex string.
403 */
404function binb2hex(binarray)
405{
406 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
407 var str = "";
34cc65fd
FB
408 var i;
409 for(i = 0; i < binarray.length * 4; i++)
5ff39ae1
FB
410 {
411 str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
412 hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
413 }
414 return str;
415}
416
417/*
418 * Convert an array of big-endian words to a base-64 string
419 */
420function binb2b64(binarray)
421{
422 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
423 var str = "";
34cc65fd
FB
424 var i, j, triplet;
425 for(i = 0; i < binarray.length * 4; i += 3)
5ff39ae1 426 {
34cc65fd 427 triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
5ff39ae1
FB
428 | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
429 | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
34cc65fd 430 for(j = 0; j < 4; j++)
5ff39ae1
FB
431 {
432 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
433 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
434 }
435 }
436 return str;
437}
438
439/* }}} */
440
441function hash_encrypt(a) {
442 return hex_sha1(a);
443}
444
445var hexa_h = "0123456789abcdef";
446
447function dechex(a) {
448 return hexa_h.charAt(a);
449}
450
451function hexdec(a) {
452 return hexa_h.indexOf(a);
453}
454
455function hash_xor(a, b) {
34cc65fd 456 var c,i,j,k,d;
5ff39ae1
FB
457 c = "";
458 i = a.length;
459 j = b.length;
460 if (i < j) {
5ff39ae1
FB
461 d = a; a = b; b = d;
462 k = i; i = j; j = k;
463 }
34cc65fd 464 for (k = 0; k < j; k++) {
5ff39ae1 465 c += dechex(hexdec(a.charAt(k)) ^ hexdec(b.charAt(k)));
34cc65fd
FB
466 }
467 for (; k < i; k++) {
5ff39ae1 468 c += a.charAt(k);
34cc65fd 469 }
5ff39ae1
FB
470 return c;
471}
472
0ba43ee4
VZ
473function getType(c) {
474 if (c >= 'a' && c <= 'z') {
7143ad2b 475 return 1;
0ba43ee4 476 } else if (c >= 'A' && c <= 'Z') {
7143ad2b 477 return 2;
0ba43ee4 478 } else if (c >= '0' && c <= '9') {
7143ad2b
FB
479 return 3;
480 } else {
481 return 4;
482 }
483}
484
4baa7323 485function differentTypes(password) {
7143ad2b 486 var prev = 0;
34cc65fd 487 var type;
4baa7323
SJ
488
489 for (i = 0 ; i < password.length ; ++i) {
34cc65fd
FB
490 type = getType(password.charAt(i));
491 if (prev !== 0 && prev !== type) {
4baa7323
SJ
492 return true;
493 }
494 prev = type;
495 }
496 return false;
497}
498
499function passwordStrength(password) {
7143ad2b 500 var prop = 0;
4baa7323 501 var prev = 0;
eaa3f284 502 var firstType = true;
4baa7323 503 var types = Array(0, 0, 0, 0, 0);
34cc65fd 504 var type;
4baa7323
SJ
505
506 for (i = 0 ; i < password.length ; ++i) {
34cc65fd
FB
507 type = getType(password.charAt(i));
508 if (prev !== 0 && prev !== type) {
7143ad2b 509 prop += 5;
4baa7323 510 firstType = false;
7143ad2b 511 }
eaa3f284 512 prop += i;
34cc65fd 513 if (types[type] === 0 && !firstType) {
eaa3f284 514 prop += 15;
7143ad2b
FB
515 }
516 types[type]++;
517 prev = type;
518 }
4baa7323
SJ
519 if (password.length < 6) {
520 prop *= 0.75;
521 }
522 if (firstType) {
aca1582e 523 prop *= 0.75;
eaa3f284 524 }
7143ad2b
FB
525 if (prop > 100) {
526 prop = 100;
527 } else if (prop < 0) {
528 prop = 0;
529 }
4baa7323
SJ
530
531 return prop;
532}
533
534function checkPassword(box, okLabel) {
535 var password = box.value;
536 var prop = passwordStrength(password);
34cc65fd 537 var submitButton;
4baa7323 538
de99248c 539 if (prop >= 60) {
00681970
FB
540 color = "#4f4";
541 bgcolor = "#050";
de99248c 542 ok = true;
23f6d4cc 543 } else if (prop >= 35) {
de99248c 544 color = "#ff4";
00681970 545 bgcolor = "#750";
b19839fd 546 ok = true;
de99248c
FB
547 } else {
548 color = "#f20";
00681970 549 bgcolor = "#700";
de99248c
FB
550 ok = false;
551 }
552 $("#passwords_measure")
00681970
FB
553 .stop()
554 .animate({ width: prop + "%",
555 backgroundColor: color
556 }, 750)
557 .parent().stop()
558 .animate({ backgroundColor: bgcolor }, 750);
34cc65fd 559 submitButton = $(":submit[name='" + passwordprompt_submit + "']");
4baa7323 560 if (ok && password.length >= 6 && differentTypes(password)) {
7b7d0970 561 submitButton.attr("value", okLabel);
de99248c 562 submitButton.removeAttr("disabled");
7143ad2b 563 } else {
7b7d0970 564 submitButton.attr("value", "Mot de passe trop faible");
de99248c 565 submitButton.attr("disabled", "disabled");
7143ad2b
FB
566 }
567}
568
30439e34 569function hashResponse(password1, password2, hasConfirmation, doAuth) {
34cc65fd
FB
570 var pw1 = $('[name=' + password1 + ']').val();
571 var pw2;
5ff39ae1
FB
572
573 if (hasConfirmation) {
574 pw2 = $('[name=' + password2 + ']').val();
34cc65fd 575 if (pw1 !== pw2) {
5ff39ae1
FB
576 alert("\nErreur : les deux champs ne sont pas identiques !");
577 return false;
578 }
579 $('[name=' + password2 + ']').val('');
34cc65fd 580 } else if (pw1 === '********') {
5ff39ae1
FB
581 return true;
582 }
583
584 if (pw1.length < 6) {
585 alert("\nErreur : le nouveau mot de passe doit faire au moins 6 caractères !");
586 return false;
587 }
588 if (!differentTypes(pw1)) {
589 alert ("\nErreur : le nouveau mot de passe doit comporter au moins deux types de caractères parmi les suivants : lettres minuscules, lettres majuscules, chiffres, caractères spéciaux.");
590 return false;
591 }
592
b80cbf0d 593 alert("Le mot de passe va être chiffré avant de nous parvenir par Internet ! Ainsi il ne circulera pas en clair.");
5ff39ae1
FB
594 $('[name=' + password1 + ']').val('');
595 $('[name=pwhash]').val(hash_encrypt(pw1));
30439e34
SJ
596
597 if (doAuth) {
598 $('[name=password]').val(pw1);
599 doChallengeResponse();
600 }
601
5ff39ae1
FB
602 return true;
603}
604
605function correctUserName() {
606 var u = document.forms.login.username;
34cc65fd
FB
607 var mots;
608
5ff39ae1 609 // login with no space
460098c8 610 if (!u.value.contains(' ')) {
34cc65fd
FB
611 return true;
612 }
613 mots = u.value.split(' ');
5ff39ae1 614 // jean paul.du pont -> jean-paul.du-pont
460098c8 615 if (u.value.contains('.')) {
34cc65fd
FB
616 u.value = mots.join('-');
617 return true;
618 }
5ff39ae1 619 // jean dupont -> jean.dupont
34cc65fd
FB
620 if (mots.length === 2) {
621 u.value = mots[0] + "." + mots[1];
622 return true;
623 }
5ff39ae1 624 // jean dupont 2001 -> jean.dupont.2001
34cc65fd
FB
625 if (mots.length === 3 && mots[2] > 1920 && mots[2] < 3000) {
626 u.value = mots.join('.');
627 return true;
628 }
5ff39ae1 629 // jean de la vallee -> jean.de-la-vallee
34cc65fd
FB
630 if (mots[1].toUpperCase() === 'DE') {
631 u.value = mots[0] + "." + mots.join('-').substr(mots[0].length+1);
632 return true;
633 }
5ff39ae1 634 // jean paul dupont -> jean-paul.dupont
34cc65fd
FB
635 if (mots.length === 3 && mots[0].toUpperCase() === 'JEAN') {
636 u.value = mots[0] + "-" + mots[1] + "." + mots[2];
637 return true;
638 }
5ff39ae1
FB
639
640 alert('Ton email ne doit pas contenir de blanc.\nLe format standard est\n\nprenom.nom.promotion\n\nSi ton nom ou ton prenom est composé,\nsépare les mots par des -');
641
642 return false;
643}
644
645function doChallengeResponse() {
34cc65fd 646 var new_pass, old_pass, str;
5ff39ae1 647
34cc65fd
FB
648 if (!correctUserName()) {
649 return false;
650 }
5ff39ae1 651
34cc65fd
FB
652 new_pass = hash_encrypt(document.forms.login.password.value);
653 old_pass = hash_encrypt(document.forms.login.password.value.substr(0, 10));
5ff39ae1
FB
654
655 str = document.forms.login.username.value + ":" +
656 new_pass + ":" +
657 document.forms.loginsub.challenge.value;
658
659 document.forms.loginsub.response.value = hash_encrypt(str);
34cc65fd 660 if (new_pass !== old_pass) {
5ff39ae1
FB
661 document.forms.loginsub.xorpass.value = hash_xor(new_pass, old_pass);
662 }
663 document.forms.loginsub.username.value = document.forms.login.username.value;
664 document.forms.loginsub.remember.value = document.forms.login.remember.checked;
665 document.forms.loginsub.domain.value = document.forms.login.domain.value;
666 document.forms.login.password.value = "";
667 document.forms.loginsub.submit();
668}
669
670function doChallengeResponseLogged() {
34cc65fd 671 var str = document.forms.loginsub.username.value + ":" +
5ff39ae1
FB
672 hash_encrypt(document.forms.login.password.value) + ":" +
673 document.forms.loginsub.challenge.value;
674
675 document.forms.loginsub.response.value = hash_encrypt(str);
676 document.forms.loginsub.remember.value = document.forms.login.remember.checked;
677 document.forms.login.password.value = "";
678 document.forms.loginsub.submit();
679}
680
7143ad2b 681// }}}
b0e935d6
FB
682// {{{ send test email
683
684function sendTestEmail(token, hruid)
685{
686 var url = 'emails/test';
687 var msg = "Un email a été envoyé avec succès";
34cc65fd 688 if (hruid) {
b0e935d6
FB
689 url += '/' + hruid;
690 msg += " sur l'adresse de " + hruid + ".";
691 } else {
692 msg += " sur ton addresse.";
693 }
fd4ec421 694 $('#mail_sent').successMessage(url + '?token=' + token, msg);
b0e935d6
FB
695 return false;
696}
697
698// }}}
6a686adb
FB
699// {{{ jQuery object extension
700
701(function($) {
102f3fc2
FB
702 /* Add new functions to jQuery namesapce */
703 $.extend({
063410c8
FB
704 /* The goal of the following functions is to provide an AJAX API that
705 * take a different callback in case of HTTP success code (2XX) and in
706 * other cases.
707 */
708
102f3fc2
FB
709 xajax: function(source, method, data, onSuccess, onError, type) {
710 /* Shift argument */
711 if ($.isFunction(data)) {
712 type = type || onError;
713 onError = onSuccess;
714 onSuccess = data;
715 data = null;
6a686adb 716 }
102f3fc2
FB
717 if (onError != null && !$.isFunction(onError)) {
718 type = type || onError;
719 onError = null;
6a686adb 720 }
6a686adb 721
102f3fc2
FB
722 function ajaxHandler(data, textStatus, xhr) {
723 if (textStatus == 'success') {
724 if (onSuccess) {
725 onSuccess(data, textStatus, xhr);
726 }
727 } else if (textStatus == 'error') {
728 if (onError) {
729 onError(data, textStatus, xhr);
730 } else {
731 alert("Une error s'est produite lors du traitement de la requête.\n"
732 + "Ta session a peut-être expiré");
733 }
734 }
735 }
736 return $.ajax({
737 url: source,
738 type: method,
739 success: ajaxHandler,
740 data : data,
741 dataType: type
742 });
743 },
744
745 xget: function(source, data, onSuccess, onError, type) {
746 return $.xajax(source, 'GET', data, onSuccess, onError, type);
747 },
748
749 xgetJSON: function(source, data, onSuccess, onError) {
750 return $.xget(source, data, onSuccess, onError, 'json');
751 },
752
753 xgetScript: function(source, onSuccess, onError) {
754 return $.xget(source, null, onSuccess, onError, 'script');
755 },
756
063410c8
FB
757 xgetText: function(source, data, onSuccess, onError) {
758 return $.xget(source, data, onSuccess, onError, 'text');
759 },
760
102f3fc2
FB
761 xpost: function(source, data, onSuccess, onError, type) {
762 return $.xajax(source, 'POST', data, onSuccess, onError, type);
6a686adb 763 }
102f3fc2
FB
764 });
765
766 /* Add new functions to jQuery objects */
767 $.fn.extend({
768 tmpMessage: function(message, success) {
769 if (success) {
770 this.html("<img src='images/icons/wand.gif' alt='' /> " + message)
771 .css('color', 'green');
772 } else {
773 this.html("<img src='images/icons/error.gif' alt='' /> " + message)
774 .css('color', 'red');
775 }
776 return this.css('fontWeight', 'bold')
777 .show()
778 .delay(1000)
779 .fadeOut(500);
780 },
781
782 updateHtml: function(source, callback) {
783 var elements = this;
784 function handler(data) {
785 elements.html(data);
786 if (callback) {
787 callback(data);
788 }
789 }
790 $.xget(source, handler, 'text');
791 return this;
792 },
793
794 successMessage: function(source, message) {
795 var elements = this;
796 $.xget(source, function() {
797 elements.tmpMessage(message, true);
798 });
799 return this;
800 },
801
802 wiki: function(text, withTitle) {
803 if (text == '') {
804 return this.html('');
805 }
806 var url = 'wiki_preview';
807 if (!withTitle) {
808 url += '/notitile';
809 }
810 var $this = this;
811 $.post(url, { text: text },
812 function (data) {
813 $this.html(data);
814 }, 'text');
815 return this;
063410c8
FB
816 },
817
818 popWin: function(w, h) {
819 return this.click(function() {
820 window.open(this.href, '_blank',
821 'toolbar=0,location=0,directories=0,status=0,'
822 +'menubar=0,scrollbars=1,resizable=1,'
823 +'width='+w+',height='+h);
824 return false;
825 });
6a686adb 826 }
102f3fc2 827 });
6a686adb
FB
828})(jQuery);
829
830// }}}
831// {{{ preview wiki
832
833function previewWiki(idFrom, idTo, withTitle, idShow)
834{
835 $('#' + idTo).wiki($('#' + idFrom).val(), withTitle);
836 if (idShow != null) {
837 $('#' + idShow).show();
838 }
839}
840
841// }}}
9f4004f3
SJ
842// {{{ updatepromofields
843
844function updatepromofields(egal1, egal2, promo2) {
845 var comparator = egal1.val();
846
847 if (comparator == '=') {
848 egal2.attr('disabled', 'disabled');
849 promo2.attr('disabled', 'disabled');
850 } else if (comparator == '<=' || comparator == '>=') {
851 egal2.removeAttr('disabled');
852 promo2.removeAttr('disabled');
853 if (comparator == '<=') {
854 egal2.val('>=');
855 } else {
856 egal2.val('<=');
857 }
858 }
859}
860
861// }}}
7143ad2b 862
aaffb7b2
FB
863/***************************************************************************
864 * Quick search
865 */
866
60a4e0b3 867/* quick search {{{ */
aaffb7b2
FB
868(function($) {
869 function findPos(obj) {
870 var curleft = obj.offsetLeft || 0;
871 var curtop = obj.offsetTop || 0;
872 while (obj = obj.offsetParent) {
873 curleft += obj.offsetLeft
874 curtop += obj.offsetTop
875 }
876 return {x:curleft,y:curtop};
877 }
878
879 $.template('quickMinifiche',
0b2c582e 880 '<div class="contact grayed" style="clear: both">' +
aaffb7b2
FB
881 '<div class="identity">' +
882 '<div class="photo"><img src="photo/${hrpid}" alt="${directory_name}" /></div>' +
883 '<div class="nom">' +
0f8ca11e 884 '{{if is_female}}&bull;{{/if}}<a>${directory_name}</a>' +
aaffb7b2
FB
885 '</div>' +
886 '<div class="edu">${promo}</div>' +
887 '</div>' +
888 '<div class="noprint bits"></div>' +
889 '<div class="long"></div>' +
890 '</div>');
891
60a4e0b3 892
b1ae686e 893 function buildPopup(input, destination, linkBindFunction)
60a4e0b3 894 {
b1ae686e 895 var $popup = destination;
60a4e0b3 896 var selected = null;
c145766b 897 var hovered = 0;
60a4e0b3
FB
898
899 function updateSelection()
900 {
901 var sel = $popup.children('.contact').addClass('grayed');
902 if (selected !== null) {
903 while (selected < 0) {
904 selected += sel.length;
905 }
906 if (selected >= sel.length) {
907 selected -= sel.length;
908 }
909 sel.eq(selected).removeClass('grayed');
910 }
911 }
912
913 function formatProfile(i, profile) {
914 var data = $.tmpl('quickMinifiche', profile)
c145766b 915 .css('cursor', 'pointer')
60a4e0b3
FB
916 .hover(function() {
917 selected = i;
918 updateSelection();
c145766b 919 hovered++;
60a4e0b3
FB
920 }, function() {
921 if (selected === i) {
922 selected = null;
923 updateSelection();
924 }
c145766b 925 hovered--;
60a4e0b3 926 }).mouseup(function() {
8ca09823 927 var sel = $(this).find('a');
c145766b 928 if (!sel.attr('hovered')) {
8ca09823 929 sel.click();
60a4e0b3
FB
930 }
931 });
c145766b
FB
932 data.find('a').hover(function() { $(this).attr('hovered', true) },
933 function() { $(this).attr('hovered', false) });
60a4e0b3
FB
934 return data;
935 }
936
b1ae686e
FB
937 if (!$popup) {
938 $popup = $('<div>').hide()
939 .addClass('contact-list')
940 .css({
941 position: 'absolute',
942 width: '300px',
943 top: input.css('bottom'),
b1ae686e
FB
944 clear: 'both',
945 'text-align': 'left'
946 });
947 input.after($popup);
948 }
60a4e0b3
FB
949
950 return {
951 hide: function(ignoreIfHover) {
c145766b 952 if (ignoreIfHover && hovered !== 0) {
60a4e0b3
FB
953 return true;
954 }
955 selected = null;
956 updateSelection();
957 $popup.hide();
958 return true;
959 },
960
961 show: function() {
974c4947
FB
962 var pos = findPos(input.get(0));
963 $popup.css('left', pos.x - 300 + input.width()).show();
60a4e0b3
FB
964 return true;
965 },
966
967 selected: function() {
968 return selected !== null;
969 },
970
971 unselect: function() {
972 selected = null;
973 updateSelection();
974 },
975
976 selectNext: function() {
977 if (selected === null) {
978 selected = 0;
979 } else {
980 selected++;
981 }
982 updateSelection();
983 return true;
984 },
985
986 selectPrev: function() {
987 if (selected === null) {
988 selected = -1;
989 } else {
990 selected--;
991 }
992 updateSelection();
993 return true;
994 },
995
996 activeCurrent: function() {
997 var sel = $popup.children('.contact');
998 if (selected !== null) {
999 sel.eq(selected).find('a').click();
1000 return false;
1001 }
1002 return true;
1003 },
1004
0f8ca11e 1005 updateContent: function(profiles, extra) {
60a4e0b3 1006 var profile;
0f8ca11e 1007 var $this;
60a4e0b3
FB
1008 $popup.empty();
1009 for (var i = 0, len = profiles.length; i < len; i++) {
0f8ca11e
FB
1010 (function(elt) {
1011 var profile = formatProfile(i, elt);
1012 profile.find('a').each(function() {
1013 linkBindFunction.call(this, elt, $this, extra);
1014 });
1015 profile.appendTo($popup);
1016 }(profiles[i]));
60a4e0b3
FB
1017 }
1018 if (len === 1) {
1019 selected = 0;
1020 } else {
1021 selected = null;
1022 }
1023 updateSelection();
1024 if (len > 0) {
1025 this.show();
1026 } else {
1027 this.hide();
1028 }
1029 return true;
1030 }
1031 };
1032 }
1033
aaffb7b2 1034 $.fn.extend({
c2c5ac82 1035 quickSearch: function(options) {
8ca09823
FB
1036 return this.each(function() {
1037 var $this = $(this);
1038 var $input = this;
aaffb7b2 1039 var $popup;
b1ae686e 1040 var previous = null;
599ff0d3 1041 var pending = false;
aaffb7b2
FB
1042 var disabled = false;
1043 var updatePopup;
aaffb7b2 1044
c2c5ac82 1045 options = options || { };
b1ae686e
FB
1046 options = $.extend({
1047 destination: null,
1048 minChars: 3,
1049 shortChars: 5,
1050 shortTimeout: 300,
1051 longTimeout: 100,
1052 queryParams: {
1053 offset: 0,
1054 count: 10,
2b13c66c 1055 allow_special: true
b1ae686e
FB
1056 },
1057 loadingClassLeft: 'ac_loading',
1058 loadingClassRight: 'ac_loading_left',
0f8ca11e
FB
1059 selectAction: function(profile, popup, extra) {
1060 var type = extra.link_type || 'profile';
1061 switch (type) {
1062 case 'profile':
1063 $(this).attr('href', 'profile/' + profile.hrpid)
1064 .popWin(840, 600)
241ba494 1065 .click(function() { $popup.hide(); return false; });
0f8ca11e
FB
1066 break;
1067 case 'admin':
1068 $(this).attr('href', 'admin/user/' + profile.hrpid)
1069 .click(function() { window.open($(this).attr('href')); return false });
1070 break;
1071 }
b1ae686e
FB
1072 }
1073 }, options);
b1ae686e
FB
1074 options.loadingClass = $this.css('text-align') === 'right' ? options.loadingClassRight
1075 : options.loadingClassLeft;
c8985ea9 1076 $this.attr('autocomplete', 'off');
0f8ca11e 1077 $popup = buildPopup($this, options.destination, options.selectAction);
aaffb7b2
FB
1078
1079 function markPending() {
1080 pending = true;
1081 }
1082
599ff0d3 1083 function performUpdate(quick)
aaffb7b2 1084 {
599ff0d3 1085 if (updatePopup === markPending) {
aaffb7b2
FB
1086 return true;
1087 }
599ff0d3 1088 updatePopup = markPending;
c2c5ac82
FB
1089 $this.addClass(options.loadingClass);
1090 $.xapi('search', $.extend({ 'quick': quick }, options.queryParams), function(data) {
b1ae686e 1091 if (data.profile_count > options.queryParams.count || data.profile_count < 0) {
599ff0d3 1092 return $popup.hide();
aaffb7b2 1093 }
0f8ca11e 1094 $popup.updateContent(data.profiles, data);
aaffb7b2 1095 previous = quick;
c54829c1
FB
1096 }, function(data, text) {
1097 if (text !== 'abort') {
1098 disabled = true;
1099 }
599ff0d3 1100 }).complete(function() {
c2c5ac82 1101 $this.removeClass(options.loadingClass);
aaffb7b2
FB
1102 updatePopup = doUpdatePopup;
1103 if (pending) {
c2c5ac82 1104 updatePopup();
aaffb7b2 1105 }
599ff0d3 1106 });
aaffb7b2
FB
1107 return true;
1108 }
0b2c582e 1109
599ff0d3
FB
1110 function doUpdatePopup(dontDelay)
1111 {
c2c5ac82 1112 var quick = $this.val();
599ff0d3 1113 if ($.isFunction(quick.trim)) {
599ff0d3
FB
1114 quick = quick.trim();
1115 }
1116 pending = false;
b1ae686e 1117 if (disabled || quick.length < options.minChars) {
599ff0d3
FB
1118 previous = quick;
1119 return $popup.hide();
1120 } else if (!dontDelay) {
b1ae686e 1121 var timeout = quick.length < options.shortChars ? options.shortTimeout : options.longTimeout;
599ff0d3 1122 setTimeout(function() {
c2c5ac82 1123 updatePopup(true);
599ff0d3
FB
1124 }, timeout);
1125 return true;
1126 } else if (previous === quick) {
1127 return $popup.show();
1128 }
c2c5ac82 1129 return performUpdate(quick);
599ff0d3
FB
1130 }
1131
aaffb7b2
FB
1132 updatePopup = doUpdatePopup;
1133
8ca09823 1134 return $this.keyup(function(e) {
0b2c582e
FB
1135 if (e.keyCode !== 27 /* escape */ && e.keyCode !== 13 /* enter */
1136 && e.keyCode !== 9 /* tab */ && e.keyCode !== 38 /* up */
1137 && e.keyCode !== 40 /* down */) {
c2c5ac82 1138 return updatePopup();
aaffb7b2
FB
1139 }
1140 return true;
1141 })
1142 .keydown(function(e) {
0b2c582e
FB
1143 switch (e.keyCode) {
1144 case 9: /* Tab */
1145 case 40: /* Down */
60a4e0b3 1146 $popup.selectNext();
0b2c582e
FB
1147 return false;
1148
1149 case 38:
60a4e0b3 1150 $popup.selectPrev();
0b2c582e
FB
1151 return false;
1152
1153 case 13: /* Return */
60a4e0b3 1154 return $popup.activeCurrent();
0b2c582e
FB
1155
1156 case 27: /* Escape */
60a4e0b3
FB
1157 if ($popup.selected()) {
1158 $popup.unselect();
1159 } else {
1160 $popup.hide();
1161 }
1162 return true;
aaffb7b2
FB
1163 }
1164 return true;
1165 })
1166 .blur(function() {
60a4e0b3 1167 return $popup.hide(true);
aaffb7b2 1168 })
8ca09823 1169 .focus(updatePopup);});
aaffb7b2
FB
1170 }
1171 });
1172}(jQuery));
7143ad2b 1173
0337d704 1174/***************************************************************************
048c44a3
FB
1175 * Overlib made simple
1176 */
1177
1178(function($) {
1179 $.fn.extend({
1180 overlib: function(text, width, height) {
1181 var args = [ ];
34cc65fd
FB
1182 var key;
1183
1184 if (typeof text === 'string') {
048c44a3 1185 args.push(text);
34cc65fd 1186 if (width) {
c8985ea9 1187 args.push(WIDTH, width);
34cc65fd
FB
1188 }
1189 if (height) {
c8985ea9 1190 args.push(HEIGHT, height);
34cc65fd 1191 }
048c44a3 1192 } else {
34cc65fd 1193 for (key in text) {
048c44a3
FB
1194 switch (key) {
1195 case 'text':
1196 args.unshift(text[key]);
1197 break;
1198 case 'caption':
1199 args.push(CAPTION, text[key]);
1200 break;
1201 case 'close_text':
1202 args.push(CLOSETEXT, text[key]);
1203 break;
1204 case 'delay':
1205 args.push(DELAY, text[key]);
1206 break;
1207 case 'sticky':
1208 if (text[key]) {
1209 args.push(STICKY);
1210 }
1211 break;
1212 case 'width':
1213 args.push(WIDTH, text[key]);
1214 break;
1215 case 'height':
1216 args.push(HEIGHT, text[key]);
1217 break;
1218 }
1219 }
1220 }
1221 return this
1222 .mouseover(function () {
1223 return overlib.apply(null, args);
1224 })
1225 .mouseout(nd);
1226 }
1227 });
1228}(jQuery));
60a4e0b3 1229/* }}} */
048c44a3
FB
1230
1231/***************************************************************************
0337d704 1232 * The real OnLoad
1233 */
1234
4171c0bf 1235$(function() {
80dcbd9a
FB
1236 auto_links();
1237 getNow();
1238 setInterval(getNow, 1000);
1239 $("#quick")
1240 .focus(function() {
1241 if ($(this).val() === 'Recherche dans l\'annuaire') {
1242 $(this).val('');
1243 }
1244 $("#quick_button").show();
1245 })
1246 .blur(function() {
1247 $("#quick_button").hide();
aaffb7b2
FB
1248 })
1249 .quickSearch();
80dcbd9a
FB
1250 $("#quick_button").click(function() {
1251 if ($("#quick").val() === 'Recherche dans l\'annuaire'
1252 || $("#quick").val() === '') {
1253 return false;
1254 }
1255 return true;
1256 });
1257});
0337d704 1258
a14159bf 1259// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: