[SPIP] +2.1.12
[velocampus/web/www.git] / www / prive / javascript / layer.js
1 var memo_obj = new Array();
2 var url_chargee = new Array();
3 var xhr_actifs = {};
4
5 function findObj_test_forcer(n, forcer) {
6 var p,i,x;
7
8 // Voir si on n'a pas deja memorise cet element
9 if (memo_obj[n] && !forcer) {
10 return memo_obj[n];
11 }
12
13 var d = document;
14 if((p = n.indexOf("?"))>0 && parent.frames.length) {
15 d = parent.frames[n.substring(p+1)].document;
16 n = n.substring(0,p);
17 }
18 if(!(x = d[n]) && d.all) {
19 x = d.all[n];
20 }
21 for (i = 0; !x && i<d.forms.length; i++) {
22 if (d.forms[i][n]){
23 if (d.forms[i][n].id==n)
24 x = d.forms[i][n];
25 }
26 }
27 for(i=0; !x && d.layers && i<d.layers.length; i++) x = findObj(n,d.layers[i].document);
28 if(!x && document.getElementById) x = document.getElementById(n);
29
30 // Memoriser l'element
31 if (!forcer) memo_obj[n] = x;
32 return x;
33 }
34
35 function findObj(n) {
36 return findObj_test_forcer(n, false);
37 }
38 // findObj sans memorisation de l'objet - avec Ajax, les elements se deplacent dans DOM
39 function findObj_forcer(n) {
40 return findObj_test_forcer(n, true);
41 }
42
43 function hide_obj(obj) {
44 var element;
45 if (element = findObj(obj)){
46 jQuery(element).css("visibility","hidden");
47 }
48 }
49
50 // deplier un ou plusieurs blocs
51 jQuery.fn.showother = function(cible) {
52 var me = this;
53 if (me.is('.replie')) {
54 me.addClass('deplie').removeClass('replie');
55 jQuery(cible)
56 .slideDown('fast',
57 function(){
58 jQuery(me)
59 .addClass('blocdeplie')
60 .removeClass('blocreplie')
61 .removeClass('togglewait');
62 }
63 ).trigger('deplie');
64 }
65 return this;
66 }
67
68 // replier un ou plusieurs blocs
69 jQuery.fn.hideother = function(cible) {
70 var me = this;
71 if (!me.is('.replie')){
72 me.addClass('replie').removeClass('deplie');
73 jQuery(cible)
74 .slideUp('fast',
75 function(){
76 jQuery(me)
77 .addClass('blocreplie')
78 .removeClass('blocdeplie')
79 .removeClass('togglewait');
80 }
81 ).trigger('replie');
82 }
83 return this;
84 }
85
86 // pour le bouton qui deplie/replie un ou plusieurs blocs
87 jQuery.fn.toggleother = function(cible) {
88 if (this.is('.deplie'))
89 return this.hideother(cible);
90 else
91 return this.showother(cible);
92 }
93
94 // deplier/replier en hover
95 // on le fait subtilement : on attend 400ms avant de deplier, periode
96 // durant laquelle, si la souris sort du controle, on annule le depliement
97 // le repliement ne fonctionne qu'au clic
98 // Cette fonction est appelee a chaque hover d'un bloc depliable
99 // la premiere fois, elle initialise le fonctionnement du bloc ; ensuite
100 // elle ne fait plus rien
101 jQuery.fn.depliant = function(cible) {
102 // premier passage
103 if (!this.is('.depliant')) {
104 var time = 400;
105
106 var me = this;
107 this
108 .addClass('depliant');
109
110 // effectuer le premier hover
111 if (!me.is('.deplie')) {
112 me.addClass('hover')
113 .addClass('togglewait');
114 var t = setTimeout(function(){
115 me.toggleother(cible);
116 t = null;
117 }, time);
118 }
119
120 me
121 // programmer les futurs hover
122 .hover(function(e){
123 me
124 .addClass('hover');
125 if (!me.is('.deplie')) {
126 me.addClass('togglewait');
127 if (t) { clearTimeout(t); t = null; }
128 t = setTimeout(function(){
129 me.toggleother(cible);
130 t = null;
131 }, time);
132 }
133 }
134 , function(e){
135 if (t) { clearTimeout(t); t = null; }
136 me
137 .removeClass('hover');
138 })
139
140 // gerer le triangle clicable
141 /*.find("a.titremancre")
142 .click(function(){
143 if (me.is('.togglewait') || t) return false;
144 me
145 .toggleother(cible);
146 return false;
147 })*/
148 .end();
149
150 }
151 return this;
152 }
153 jQuery.fn.depliant_clicancre = function(cible) {
154 var me = this.parent();
155 // gerer le triangle clicable
156 if (me.is('.togglewait')) return false;
157 me.toggleother(cible);
158 return false;
159 }
160
161
162 //
163 // Fonctions pour mini_nav
164 //
165
166 function slide_horizontal (couche, slide, align, depart, etape ) {
167
168 var obj = findObj_forcer(couche);
169
170 if (!obj) return;
171 if (!etape) {
172 if (align == 'left') depart = obj.scrollLeft;
173 else depart = obj.firstChild.offsetWidth - obj.scrollLeft;
174 etape = 0;
175 }
176 etape = Math.round(etape) + 1;
177 pos = Math.round(depart) + Math.round(((slide - depart) / 10) * etape);
178
179 if (align == 'left') obj.scrollLeft = pos;
180 else obj.scrollLeft = obj.firstChild.offsetWidth - pos;
181 if (etape < 10) setTimeout("slide_horizontal('"+couche+"', '"+slide+"', '"+align+"', '"+depart+"', '"+etape+"')", 60);
182 //else obj.scrollLeft = slide;
183 }
184
185 function changerhighlight (couche) {
186 jQuery(couche)
187 .removeClass('off')
188 .siblings()
189 .not(couche)
190 .addClass('off');
191 }
192
193 function aff_selection (arg, idom, url, event) {
194 noeud = findObj_forcer(idom);
195 if (noeud) {
196 noeud.style.display = "none";
197 charger_node_url(url+arg, noeud, '','',event);
198 }
199 return false;
200 }
201
202 // selecteur de rubrique et affichage de son titre dans le bandeau
203
204 function aff_selection_titre(titre, id, idom, nid)
205 {
206 t = findObj_forcer('titreparent');
207 t.value= titre;
208 t=findObj_forcer(nid);
209 t.value=id;
210 jQuery(t).trigger('change'); // declencher le onchange
211 t=findObj_forcer(idom);
212 t.style.display='none';
213 p = $(t).parents('form');
214 if (p.is('.submit_plongeur')) p.get(p.length-1).submit();
215 }
216
217 function admin_tech_selection_titre(titre, id, idom, nid)
218 {
219 nom = titre.replace(/\W+/g, '_');
220 findObj_forcer("znom_sauvegarde").value=nom;
221 findObj_forcer("nom_sauvegarde").value=nom;
222 aff_selection_titre(titre, id, idom, nid);
223 }
224
225 function aff_selection_provisoire(id, racine, url, col, sens,informer,event)
226 {
227 charger_id_url(url.href,
228 racine + '_col_' + (col+1),
229 function() {
230 slide_horizontal(racine + '_principal', ((col-1)*150), sens);
231 aff_selection (id, racine + "_selection", informer);
232 },
233 event);
234 // empecher le chargement non Ajax
235 return false;
236 }
237
238 // Lanche une requete Ajax a chaque frappe au clavier dans une balise de saisie.
239 // Si l'entree redevient vide, rappeler l'URL initiale si dispo.
240 // Sinon, controler au retour si le resultat est unique,
241 // auquel cas forcer la selection.
242
243 function onkey_rechercher(valeur, rac, url, img, nid, init) {
244 var Field = findObj_forcer(rac);
245 if (!valeur.length) {
246 init = findObj_forcer(init);
247 if (init && init.href) { charger_node_url(init.href, Field);}
248 } else {
249 charger_node_url(url+valeur,
250 Field,
251 function () {
252 var n = Field.childNodes.length - 1;
253 // Safari = 0 & Firefox = 1 !
254 // et gare aux negatifs en cas d'abort
255 if ((n == 1)) {
256 noeud = Field.childNodes[n].firstChild;
257 if (noeud.title)
258 // cas de la rubrique, pas des auteurs
259 aff_selection_titre(noeud.firstChild.nodeValue, noeud.title, rac, nid);
260 }
261 },
262 img);
263 }
264 return false;
265 }
266
267
268 // Recupere tous les formulaires de la page
269 // (ou du fragment qu'on vient de recharger en ajax)
270 // et leur applique les comportements js souhaites
271 // ici :
272 // * retailler les input
273 // * utiliser ctrl-s, F8 etc comme touches de sauvegarde
274 var verifForm_clicked=false;
275 function verifForm(racine) {
276
277 // Clavier pour sauver (cf. crayons)
278 // cf http://www.quirksmode.org/js/keys.html
279 if (!jQuery.browser.msie)
280 // keypress renvoie le charcode correspondant au caractere frappe (ici s)
281 jQuery('form', racine||document)
282 .keypress(function(e){
283 if (
284 ((e.ctrlKey && (
285 /* ctrl-s ou ctrl-maj-S, firefox */
286 (((e.charCode||e.keyCode) == 115) || ((e.charCode||e.keyCode) == 83))
287 /* ctrl-s, safari */
288 || (e.charCode==19 && e.keyCode==19)
289 )
290 ) /* ctrl-s, Opera Mac */
291 || (e.keyCode==19 && jQuery.browser.opera))
292 && !verifForm_clicked
293 ) {
294 verifForm_clicked = true;
295 jQuery(this).find('input[type=submit]')
296 .click();
297 return false;
298 }
299 });
300 else
301 // keydown renvoie le keycode correspondant a la touche pressee (ici F8)
302 jQuery('form', racine||document)
303 .keydown(function(e){
304 //jQuery('#ps').after("<div>ctrl:"+e.ctrlKey+"<br />charcode:"+e.charCode+"<br />keycode:"+e.keyCode+"<hr /></div>");
305 if (!e.charCode && e.keyCode == 119 /* F8, windows */ && !verifForm_clicked){
306 verifForm_clicked = true;
307 jQuery(this).find('input[type=submit]')
308 .click();
309 return false;
310 }
311 });
312
313 }
314
315 // Si Ajax est disponible, cette fonction l'utilise pour envoyer la requete.
316 // Si le premier argument n'est pas une url, ce doit etre un formulaire.
317 // Le deuxieme argument doit etre l'ID d'un noeud qu'on animera pendant Ajax.
318 // Le troisieme, optionnel, est la fonction traitant la reponse.
319 // La fonction par defaut affecte le noeud ci-dessus avec la reponse Ajax.
320 // En cas de formulaire, AjaxSqueeze retourne False pour empecher son envoi
321 // Le cas True ne devrait pas se produire car le cookie spip_accepte_ajax
322 // a du anticiper la situation.
323 // Toutefois il y toujours un coup de retard dans la pose d'un cookie:
324 // eviter de se loger avec redirection vers un telle page
325
326 function AjaxSqueeze(trig, id, callback, event)
327 {
328 var target = jQuery('#'+id);
329
330 // position du demandeur dans le DOM (le donner direct serait mieux)
331 if (!target.size()) {return true;}
332
333 return !AjaxSqueezeNode(trig, target, callback, event);
334 }
335
336 // La fonction qui fait vraiment le travail decrit ci-dessus.
337 // Son premier argument est deja le noeud du DOM
338 // et son resultat booleen est inverse ce qui lui permet de retourner
339 // le gestionnaire Ajax comme valeur non fausse
340
341 function AjaxSqueezeNode(trig, target, f, event)
342 {
343 var i, callback;
344
345 // retour std si pas precise: affecter ce noeud avec ce retour
346 if (!f) {
347 callback = function() { verifForm(this);}
348 }
349 else {
350 callback = function(res,status) {
351 f.apply(this,[res,status]);
352 verifForm(this);
353 }
354 }
355
356 valid = false;
357 if (typeof(window['_OUTILS_DEVELOPPEURS']) != 'undefined'){
358 if (!(navigator.userAgent.toLowerCase().indexOf("firefox/1.0")))
359 valid = (typeof event == 'object') && (event.altKey || event.metaKey);
360 }
361
362 if (typeof(trig) == 'string') {
363 // laisser le choix de la touche enfoncee au moment du clic
364 // car beaucoup de systemes en prenne une a leur usage
365 if (valid) {
366 window.open(trig+'&transformer_xml=valider_xml');
367 } else {
368 jQuery(target).animeajax();
369 }
370 res = jQuery.ajax({
371 "url":trig,
372 "complete": function(r,s) {
373 AjaxRet(r,s,target, callback);
374 }
375 });
376 return res;
377
378 }
379
380 if(valid) {
381 //open a blank window
382 var doc = window.open("","valider").document;
383 //create a document to enable receiving the result of the ajax post
384 doc.open();
385 doc.close();
386 //set the element receiving the ajax post
387 target = doc.body;
388 }
389 else {
390 jQuery(target).animeajax();
391 }
392
393 jQuery(trig).ajaxSubmit({
394 "target": target,
395 "success": function(res,status) {
396 if(status=='error') return this.html('Erreur HTTP');
397 callback.apply(this,[res,status]);
398 },
399 "beforeSubmit":function (vars) {
400 if (valid)
401 vars.push({"name":"transformer_xml","value":"valider_xml"});
402 return true;
403 }
404 });
405 return true;
406 }
407
408 // Les Submit avec attribut name ne sont pas transmis par JQuery
409 // Cette fonction clone le bouton de soumission en hidden
410 // Voir l'utilisation dans ajax_action_post dans inc/actions
411
412 function AjaxNamedSubmit(input) {
413 jQuery('<input type="hidden" />')
414 .attr('name', input.name)
415 .attr('value', input.value)
416 .insertAfter(input);
417 return true;
418 }
419
420 function AjaxRet(res,status, target, callback) {
421 if (res.aborted) return;
422 if (status=='error') return jQuery(target).html('HTTP Error');
423
424 // Inject the HTML into all the matched elements
425 jQuery(target)
426 .html(res.responseText)
427 // Execute callback
428 .each(callback, [res.responseText, status]);
429 }
430
431
432 // Comme AjaxSqueeze,
433 // mais avec un cache sur le noeud et un cache sur la reponse
434 // et une memorisation des greffes en attente afin de les abandonner
435 // (utile surtout a la frappe interactive au clavier)
436 // De plus, la fonction optionnelle n'a pas besoin de greffer la reponse.
437
438 function charger_id_url(myUrl, myField, jjscript, event)
439 {
440 var Field = findObj_forcer(myField);
441 if (!Field) return true;
442
443 if (!myUrl) {
444 jQuery(Field).empty();
445 retour_id_url(Field, jjscript);
446 return true; // url vide, c'est un self complet
447 } else return charger_node_url(myUrl, Field, jjscript, findObj_forcer('img_' + myField), event);
448 }
449
450 // La suite
451
452 function charger_node_url(myUrl, Field, jjscript, img, event)
453 {
454 // disponible en cache ?
455 if (url_chargee[myUrl]) {
456 var el = jQuery(Field).html(url_chargee[myUrl])[0];
457 retour_id_url(el, jjscript);
458 triggerAjaxLoad(el);
459 return false;
460 } else {
461 if (img) img.style.visibility = "visible";
462 if (xhr_actifs[Field]) { xhr_actifs[Field].aborted = true;xhr_actifs[Field].abort(); }
463 xhr_actifs[Field] = AjaxSqueezeNode(myUrl,
464 Field,
465 function (r) {
466 xhr_actifs[Field] = undefined;
467 if (img) img.style.visibility = "hidden";
468 url_chargee[myUrl] = r;
469 retour_id_url(Field, jjscript);
470 slide_horizontal($(Field).children().attr("id")+'_principal', $(Field).width() , $(Field).css("text-align"));
471 },
472 event);
473 return false;
474 }
475 }
476
477 function retour_id_url(Field, jjscript)
478 {
479 jQuery(Field).css({'visibility':'visible','display':'block'});
480 if (jjscript) jjscript();
481 }
482
483 function charger_node_url_si_vide(url, noeud, gifanime, jjscript,event) {
484
485 if (noeud.style.display !='none') {
486 noeud.style.display='none';}
487 else {
488 if (noeud.innerHTML != "") {
489 noeud.style.visibility = "visible";
490 noeud.style.display = "block";
491 } else {
492 charger_node_url(url, noeud,'',gifanime,event);
493 }
494 }
495 return false;
496 }
497
498 function charger_id_url_si_vide (myUrl, myField, jjscript, event) {
499 var Field = findObj_forcer(myField); // selects the given element
500 if (!Field) return;
501
502 if (Field.innerHTML == "") {
503 charger_id_url(myUrl, myField, jjscript, event)
504 }
505 else {
506 Field.style.visibility = "visible";
507 Field.style.display = "block";
508 }
509 }
510