Fix url in goodies popup.
[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
FB
181 node.click(function () {
182 window.open(href);
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
5ff39ae1 569function hashResponse(password1, password2, hasConfirmation) {
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
593 alert("Le mot de passe que tu as rentré va être chiffré avant de nous parvenir par Internet ! Ainsi il ne circulera pas en clair.");
594 $('[name=' + password1 + ']').val('');
595 $('[name=pwhash]').val(hash_encrypt(pw1));
596 return true;
597}
598
599function correctUserName() {
600 var u = document.forms.login.username;
34cc65fd
FB
601 var mots;
602
5ff39ae1 603 // login with no space
460098c8 604 if (!u.value.contains(' ')) {
34cc65fd
FB
605 return true;
606 }
607 mots = u.value.split(' ');
5ff39ae1 608 // jean paul.du pont -> jean-paul.du-pont
460098c8 609 if (u.value.contains('.')) {
34cc65fd
FB
610 u.value = mots.join('-');
611 return true;
612 }
5ff39ae1 613 // jean dupont -> jean.dupont
34cc65fd
FB
614 if (mots.length === 2) {
615 u.value = mots[0] + "." + mots[1];
616 return true;
617 }
5ff39ae1 618 // jean dupont 2001 -> jean.dupont.2001
34cc65fd
FB
619 if (mots.length === 3 && mots[2] > 1920 && mots[2] < 3000) {
620 u.value = mots.join('.');
621 return true;
622 }
5ff39ae1 623 // jean de la vallee -> jean.de-la-vallee
34cc65fd
FB
624 if (mots[1].toUpperCase() === 'DE') {
625 u.value = mots[0] + "." + mots.join('-').substr(mots[0].length+1);
626 return true;
627 }
5ff39ae1 628 // jean paul dupont -> jean-paul.dupont
34cc65fd
FB
629 if (mots.length === 3 && mots[0].toUpperCase() === 'JEAN') {
630 u.value = mots[0] + "-" + mots[1] + "." + mots[2];
631 return true;
632 }
5ff39ae1
FB
633
634 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 -');
635
636 return false;
637}
638
639function doChallengeResponse() {
34cc65fd 640 var new_pass, old_pass, str;
5ff39ae1 641
34cc65fd
FB
642 if (!correctUserName()) {
643 return false;
644 }
5ff39ae1 645
34cc65fd
FB
646 new_pass = hash_encrypt(document.forms.login.password.value);
647 old_pass = hash_encrypt(document.forms.login.password.value.substr(0, 10));
5ff39ae1
FB
648
649 str = document.forms.login.username.value + ":" +
650 new_pass + ":" +
651 document.forms.loginsub.challenge.value;
652
653 document.forms.loginsub.response.value = hash_encrypt(str);
34cc65fd 654 if (new_pass !== old_pass) {
5ff39ae1
FB
655 document.forms.loginsub.xorpass.value = hash_xor(new_pass, old_pass);
656 }
657 document.forms.loginsub.username.value = document.forms.login.username.value;
658 document.forms.loginsub.remember.value = document.forms.login.remember.checked;
659 document.forms.loginsub.domain.value = document.forms.login.domain.value;
660 document.forms.login.password.value = "";
661 document.forms.loginsub.submit();
662}
663
664function doChallengeResponseLogged() {
34cc65fd 665 var str = document.forms.loginsub.username.value + ":" +
5ff39ae1
FB
666 hash_encrypt(document.forms.login.password.value) + ":" +
667 document.forms.loginsub.challenge.value;
668
669 document.forms.loginsub.response.value = hash_encrypt(str);
670 document.forms.loginsub.remember.value = document.forms.login.remember.checked;
671 document.forms.login.password.value = "";
672 document.forms.loginsub.submit();
673}
674
7143ad2b 675// }}}
b0e935d6
FB
676// {{{ send test email
677
678function sendTestEmail(token, hruid)
679{
680 var url = 'emails/test';
681 var msg = "Un email a été envoyé avec succès";
34cc65fd 682 if (hruid) {
b0e935d6
FB
683 url += '/' + hruid;
684 msg += " sur l'adresse de " + hruid + ".";
685 } else {
686 msg += " sur ton addresse.";
687 }
688 $('#mail_sent').successMessage($url + '?token=' + token, msg);
689 return false;
690}
691
692// }}}
6a686adb
FB
693// {{{ jQuery object extension
694
695(function($) {
102f3fc2
FB
696 /* Add new functions to jQuery namesapce */
697 $.extend({
063410c8
FB
698 /* The goal of the following functions is to provide an AJAX API that
699 * take a different callback in case of HTTP success code (2XX) and in
700 * other cases.
701 */
702
102f3fc2
FB
703 xajax: function(source, method, data, onSuccess, onError, type) {
704 /* Shift argument */
705 if ($.isFunction(data)) {
706 type = type || onError;
707 onError = onSuccess;
708 onSuccess = data;
709 data = null;
6a686adb 710 }
102f3fc2
FB
711 if (onError != null && !$.isFunction(onError)) {
712 type = type || onError;
713 onError = null;
6a686adb 714 }
6a686adb 715
102f3fc2
FB
716 function ajaxHandler(data, textStatus, xhr) {
717 if (textStatus == 'success') {
718 if (onSuccess) {
719 onSuccess(data, textStatus, xhr);
720 }
721 } else if (textStatus == 'error') {
722 if (onError) {
723 onError(data, textStatus, xhr);
724 } else {
725 alert("Une error s'est produite lors du traitement de la requête.\n"
726 + "Ta session a peut-être expiré");
727 }
728 }
729 }
730 return $.ajax({
731 url: source,
732 type: method,
733 success: ajaxHandler,
734 data : data,
735 dataType: type
736 });
737 },
738
739 xget: function(source, data, onSuccess, onError, type) {
740 return $.xajax(source, 'GET', data, onSuccess, onError, type);
741 },
742
743 xgetJSON: function(source, data, onSuccess, onError) {
744 return $.xget(source, data, onSuccess, onError, 'json');
745 },
746
747 xgetScript: function(source, onSuccess, onError) {
748 return $.xget(source, null, onSuccess, onError, 'script');
749 },
750
063410c8
FB
751 xgetText: function(source, data, onSuccess, onError) {
752 return $.xget(source, data, onSuccess, onError, 'text');
753 },
754
102f3fc2
FB
755 xpost: function(source, data, onSuccess, onError, type) {
756 return $.xajax(source, 'POST', data, onSuccess, onError, type);
6a686adb 757 }
102f3fc2
FB
758 });
759
760 /* Add new functions to jQuery objects */
761 $.fn.extend({
762 tmpMessage: function(message, success) {
763 if (success) {
764 this.html("<img src='images/icons/wand.gif' alt='' /> " + message)
765 .css('color', 'green');
766 } else {
767 this.html("<img src='images/icons/error.gif' alt='' /> " + message)
768 .css('color', 'red');
769 }
770 return this.css('fontWeight', 'bold')
771 .show()
772 .delay(1000)
773 .fadeOut(500);
774 },
775
776 updateHtml: function(source, callback) {
777 var elements = this;
778 function handler(data) {
779 elements.html(data);
780 if (callback) {
781 callback(data);
782 }
783 }
784 $.xget(source, handler, 'text');
785 return this;
786 },
787
788 successMessage: function(source, message) {
789 var elements = this;
790 $.xget(source, function() {
791 elements.tmpMessage(message, true);
792 });
793 return this;
794 },
795
796 wiki: function(text, withTitle) {
797 if (text == '') {
798 return this.html('');
799 }
800 var url = 'wiki_preview';
801 if (!withTitle) {
802 url += '/notitile';
803 }
804 var $this = this;
805 $.post(url, { text: text },
806 function (data) {
807 $this.html(data);
808 }, 'text');
809 return this;
063410c8
FB
810 },
811
812 popWin: function(w, h) {
813 return this.click(function() {
814 window.open(this.href, '_blank',
815 'toolbar=0,location=0,directories=0,status=0,'
816 +'menubar=0,scrollbars=1,resizable=1,'
817 +'width='+w+',height='+h);
818 return false;
819 });
6a686adb 820 }
102f3fc2 821 });
6a686adb
FB
822})(jQuery);
823
824// }}}
825// {{{ preview wiki
826
827function previewWiki(idFrom, idTo, withTitle, idShow)
828{
829 $('#' + idTo).wiki($('#' + idFrom).val(), withTitle);
830 if (idShow != null) {
831 $('#' + idShow).show();
832 }
833}
834
835// }}}
836// {{{ send test email
837
838function sendTestEmail(token, hruid)
839{
840 var url = 'emails/test';
841 var msg = "Un email a été envoyé avec succès";
842 if (hruid != null) {
843 url += '/' + hruid;
844 msg += " sur l'adresse de " + hruid + ".";
845 } else {
846 msg += " sur ton addresse.";
847 }
848 $('#mail_sent').successMessage($url + '?token=' + token, msg);
849 return false;
850}
851
852// }}}
7143ad2b 853
aaffb7b2
FB
854/***************************************************************************
855 * Quick search
856 */
857
60a4e0b3 858/* quick search {{{ */
aaffb7b2
FB
859(function($) {
860 function findPos(obj) {
861 var curleft = obj.offsetLeft || 0;
862 var curtop = obj.offsetTop || 0;
863 while (obj = obj.offsetParent) {
864 curleft += obj.offsetLeft
865 curtop += obj.offsetTop
866 }
867 return {x:curleft,y:curtop};
868 }
869
870 $.template('quickMinifiche',
0b2c582e 871 '<div class="contact grayed" style="clear: both">' +
aaffb7b2
FB
872 '<div class="identity">' +
873 '<div class="photo"><img src="photo/${hrpid}" alt="${directory_name}" /></div>' +
874 '<div class="nom">' +
0f8ca11e 875 '{{if is_female}}&bull;{{/if}}<a>${directory_name}</a>' +
aaffb7b2
FB
876 '</div>' +
877 '<div class="edu">${promo}</div>' +
878 '</div>' +
879 '<div class="noprint bits"></div>' +
880 '<div class="long"></div>' +
881 '</div>');
882
60a4e0b3 883
b1ae686e 884 function buildPopup(input, destination, linkBindFunction)
60a4e0b3 885 {
b1ae686e 886 var $popup = destination;
60a4e0b3 887 var selected = null;
c145766b 888 var hovered = 0;
60a4e0b3
FB
889
890 function updateSelection()
891 {
892 var sel = $popup.children('.contact').addClass('grayed');
893 if (selected !== null) {
894 while (selected < 0) {
895 selected += sel.length;
896 }
897 if (selected >= sel.length) {
898 selected -= sel.length;
899 }
900 sel.eq(selected).removeClass('grayed');
901 }
902 }
903
904 function formatProfile(i, profile) {
905 var data = $.tmpl('quickMinifiche', profile)
c145766b 906 .css('cursor', 'pointer')
60a4e0b3
FB
907 .hover(function() {
908 selected = i;
909 updateSelection();
c145766b 910 hovered++;
60a4e0b3
FB
911 }, function() {
912 if (selected === i) {
913 selected = null;
914 updateSelection();
915 }
c145766b 916 hovered--;
60a4e0b3 917 }).mouseup(function() {
8ca09823 918 var sel = $(this).find('a');
c145766b 919 if (!sel.attr('hovered')) {
8ca09823 920 sel.click();
60a4e0b3
FB
921 }
922 });
c145766b
FB
923 data.find('a').hover(function() { $(this).attr('hovered', true) },
924 function() { $(this).attr('hovered', false) });
60a4e0b3
FB
925 return data;
926 }
927
b1ae686e
FB
928 if (!$popup) {
929 $popup = $('<div>').hide()
930 .addClass('contact-list')
931 .css({
932 position: 'absolute',
933 width: '300px',
934 top: input.css('bottom'),
b1ae686e
FB
935 clear: 'both',
936 'text-align': 'left'
937 });
938 input.after($popup);
939 }
60a4e0b3
FB
940
941 return {
942 hide: function(ignoreIfHover) {
c145766b 943 if (ignoreIfHover && hovered !== 0) {
60a4e0b3
FB
944 return true;
945 }
946 selected = null;
947 updateSelection();
948 $popup.hide();
949 return true;
950 },
951
952 show: function() {
974c4947
FB
953 var pos = findPos(input.get(0));
954 $popup.css('left', pos.x - 300 + input.width()).show();
60a4e0b3
FB
955 return true;
956 },
957
958 selected: function() {
959 return selected !== null;
960 },
961
962 unselect: function() {
963 selected = null;
964 updateSelection();
965 },
966
967 selectNext: function() {
968 if (selected === null) {
969 selected = 0;
970 } else {
971 selected++;
972 }
973 updateSelection();
974 return true;
975 },
976
977 selectPrev: function() {
978 if (selected === null) {
979 selected = -1;
980 } else {
981 selected--;
982 }
983 updateSelection();
984 return true;
985 },
986
987 activeCurrent: function() {
988 var sel = $popup.children('.contact');
989 if (selected !== null) {
990 sel.eq(selected).find('a').click();
991 return false;
992 }
993 return true;
994 },
995
0f8ca11e 996 updateContent: function(profiles, extra) {
60a4e0b3 997 var profile;
0f8ca11e 998 var $this;
60a4e0b3
FB
999 $popup.empty();
1000 for (var i = 0, len = profiles.length; i < len; i++) {
0f8ca11e
FB
1001 (function(elt) {
1002 var profile = formatProfile(i, elt);
1003 profile.find('a').each(function() {
1004 linkBindFunction.call(this, elt, $this, extra);
1005 });
1006 profile.appendTo($popup);
1007 }(profiles[i]));
60a4e0b3
FB
1008 }
1009 if (len === 1) {
1010 selected = 0;
1011 } else {
1012 selected = null;
1013 }
1014 updateSelection();
1015 if (len > 0) {
1016 this.show();
1017 } else {
1018 this.hide();
1019 }
1020 return true;
1021 }
1022 };
1023 }
1024
aaffb7b2 1025 $.fn.extend({
c2c5ac82 1026 quickSearch: function(options) {
8ca09823
FB
1027 return this.each(function() {
1028 var $this = $(this);
1029 var $input = this;
aaffb7b2 1030 var $popup;
b1ae686e 1031 var previous = null;
599ff0d3 1032 var pending = false;
aaffb7b2
FB
1033 var disabled = false;
1034 var updatePopup;
aaffb7b2 1035
c2c5ac82 1036 options = options || { };
b1ae686e
FB
1037 options = $.extend({
1038 destination: null,
1039 minChars: 3,
1040 shortChars: 5,
1041 shortTimeout: 300,
1042 longTimeout: 100,
1043 queryParams: {
1044 offset: 0,
1045 count: 10,
0f8ca11e 1046 allow_special: true,
b1ae686e
FB
1047 },
1048 loadingClassLeft: 'ac_loading',
1049 loadingClassRight: 'ac_loading_left',
0f8ca11e
FB
1050 selectAction: function(profile, popup, extra) {
1051 var type = extra.link_type || 'profile';
1052 switch (type) {
1053 case 'profile':
1054 $(this).attr('href', 'profile/' + profile.hrpid)
1055 .popWin(840, 600)
241ba494 1056 .click(function() { $popup.hide(); return false; });
0f8ca11e
FB
1057 break;
1058 case 'admin':
1059 $(this).attr('href', 'admin/user/' + profile.hrpid)
1060 .click(function() { window.open($(this).attr('href')); return false });
1061 break;
1062 }
b1ae686e
FB
1063 }
1064 }, options);
b1ae686e
FB
1065 options.loadingClass = $this.css('text-align') === 'right' ? options.loadingClassRight
1066 : options.loadingClassLeft;
c8985ea9 1067 $this.attr('autocomplete', 'off');
0f8ca11e 1068 $popup = buildPopup($this, options.destination, options.selectAction);
aaffb7b2
FB
1069
1070 function markPending() {
1071 pending = true;
1072 }
1073
599ff0d3 1074 function performUpdate(quick)
aaffb7b2 1075 {
599ff0d3 1076 if (updatePopup === markPending) {
aaffb7b2
FB
1077 return true;
1078 }
599ff0d3 1079 updatePopup = markPending;
c2c5ac82
FB
1080 $this.addClass(options.loadingClass);
1081 $.xapi('search', $.extend({ 'quick': quick }, options.queryParams), function(data) {
b1ae686e 1082 if (data.profile_count > options.queryParams.count || data.profile_count < 0) {
599ff0d3 1083 return $popup.hide();
aaffb7b2 1084 }
0f8ca11e 1085 $popup.updateContent(data.profiles, data);
aaffb7b2 1086 previous = quick;
c54829c1
FB
1087 }, function(data, text) {
1088 if (text !== 'abort') {
1089 disabled = true;
1090 }
599ff0d3 1091 }).complete(function() {
c2c5ac82 1092 $this.removeClass(options.loadingClass);
aaffb7b2
FB
1093 updatePopup = doUpdatePopup;
1094 if (pending) {
c2c5ac82 1095 updatePopup();
aaffb7b2 1096 }
599ff0d3 1097 });
aaffb7b2
FB
1098 return true;
1099 }
0b2c582e 1100
599ff0d3
FB
1101 function doUpdatePopup(dontDelay)
1102 {
c2c5ac82 1103 var quick = $this.val();
599ff0d3 1104 if ($.isFunction(quick.trim)) {
599ff0d3
FB
1105 quick = quick.trim();
1106 }
1107 pending = false;
b1ae686e 1108 if (disabled || quick.length < options.minChars) {
599ff0d3
FB
1109 previous = quick;
1110 return $popup.hide();
1111 } else if (!dontDelay) {
b1ae686e 1112 var timeout = quick.length < options.shortChars ? options.shortTimeout : options.longTimeout;
599ff0d3 1113 setTimeout(function() {
c2c5ac82 1114 updatePopup(true);
599ff0d3
FB
1115 }, timeout);
1116 return true;
1117 } else if (previous === quick) {
1118 return $popup.show();
1119 }
c2c5ac82 1120 return performUpdate(quick);
599ff0d3
FB
1121 }
1122
aaffb7b2
FB
1123 updatePopup = doUpdatePopup;
1124
8ca09823 1125 return $this.keyup(function(e) {
0b2c582e
FB
1126 if (e.keyCode !== 27 /* escape */ && e.keyCode !== 13 /* enter */
1127 && e.keyCode !== 9 /* tab */ && e.keyCode !== 38 /* up */
1128 && e.keyCode !== 40 /* down */) {
c2c5ac82 1129 return updatePopup();
aaffb7b2
FB
1130 }
1131 return true;
1132 })
1133 .keydown(function(e) {
0b2c582e
FB
1134 switch (e.keyCode) {
1135 case 9: /* Tab */
1136 case 40: /* Down */
60a4e0b3 1137 $popup.selectNext();
0b2c582e
FB
1138 return false;
1139
1140 case 38:
60a4e0b3 1141 $popup.selectPrev();
0b2c582e
FB
1142 return false;
1143
1144 case 13: /* Return */
60a4e0b3 1145 return $popup.activeCurrent();
0b2c582e
FB
1146
1147 case 27: /* Escape */
60a4e0b3
FB
1148 if ($popup.selected()) {
1149 $popup.unselect();
1150 } else {
1151 $popup.hide();
1152 }
1153 return true;
aaffb7b2
FB
1154 }
1155 return true;
1156 })
1157 .blur(function() {
60a4e0b3 1158 return $popup.hide(true);
aaffb7b2 1159 })
8ca09823 1160 .focus(updatePopup);});
aaffb7b2
FB
1161 }
1162 });
1163}(jQuery));
7143ad2b 1164
0337d704 1165/***************************************************************************
048c44a3
FB
1166 * Overlib made simple
1167 */
1168
1169(function($) {
1170 $.fn.extend({
1171 overlib: function(text, width, height) {
1172 var args = [ ];
34cc65fd
FB
1173 var key;
1174
1175 if (typeof text === 'string') {
048c44a3 1176 args.push(text);
34cc65fd 1177 if (width) {
c8985ea9 1178 args.push(WIDTH, width);
34cc65fd
FB
1179 }
1180 if (height) {
c8985ea9 1181 args.push(HEIGHT, height);
34cc65fd 1182 }
048c44a3 1183 } else {
34cc65fd 1184 for (key in text) {
048c44a3
FB
1185 switch (key) {
1186 case 'text':
1187 args.unshift(text[key]);
1188 break;
1189 case 'caption':
1190 args.push(CAPTION, text[key]);
1191 break;
1192 case 'close_text':
1193 args.push(CLOSETEXT, text[key]);
1194 break;
1195 case 'delay':
1196 args.push(DELAY, text[key]);
1197 break;
1198 case 'sticky':
1199 if (text[key]) {
1200 args.push(STICKY);
1201 }
1202 break;
1203 case 'width':
1204 args.push(WIDTH, text[key]);
1205 break;
1206 case 'height':
1207 args.push(HEIGHT, text[key]);
1208 break;
1209 }
1210 }
1211 }
1212 return this
1213 .mouseover(function () {
1214 return overlib.apply(null, args);
1215 })
1216 .mouseout(nd);
1217 }
1218 });
1219}(jQuery));
60a4e0b3 1220/* }}} */
048c44a3
FB
1221
1222/***************************************************************************
0337d704 1223 * The real OnLoad
1224 */
1225
4171c0bf 1226$(function() {
80dcbd9a
FB
1227 auto_links();
1228 getNow();
1229 setInterval(getNow, 1000);
1230 $("#quick")
1231 .focus(function() {
1232 if ($(this).val() === 'Recherche dans l\'annuaire') {
1233 $(this).val('');
1234 }
1235 $("#quick_button").show();
1236 })
1237 .blur(function() {
1238 $("#quick_button").hide();
aaffb7b2
FB
1239 })
1240 .quickSearch();
80dcbd9a
FB
1241 $("#quick_button").click(function() {
1242 if ($("#quick").val() === 'Recherche dans l\'annuaire'
1243 || $("#quick").val() === '') {
1244 return false;
1245 }
1246 return true;
1247 });
1248});
0337d704 1249
a14159bf 1250// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: