1jQuery.spip=jQuery.spip || {}; 2jQuery.spip.log = function(){ 3 if (jQuery.spip.debug && window.console && window.console.log) 4 window.console.log.apply(this,arguments); 5} 6// A plugin that wraps all ajax calls introducing a fixed callback function on ajax complete 7if(!jQuery.spip.load_handlers) { 8 jQuery.spip.load_handlers = new Array(); 9 10 /** 11 * OnAjaxLoad allow to 12 * add a function to the list of those 13 * to be executed on ajax load complete 14 * 15 * most of time function f is applied on the loaded data 16 * if not known, the whole document is targetted 17 * 18 * @param function f 19 */ 20 function onAjaxLoad(f) { 21 jQuery.spip.load_handlers.push(f); 22 }; 23 24 /** 25 * Call the functions that have been added to onAjaxLoad 26 * @param root 27 */ 28 jQuery.spip.triggerAjaxLoad = function (root) { 29 jQuery.spip.log('triggerAjaxLoad'); 30 jQuery.spip.log(root); 31 for ( var i = 0; i < jQuery.spip.load_handlers.length; i++ ) 32 jQuery.spip.load_handlers[i].apply( root ); 33 }; 34 35 jQuery.spip.intercepted={}; 36 37 // intercept jQuery.fn.load 38 jQuery.spip.intercepted.load = jQuery.fn.load; 39 jQuery.fn.load = function( url, params, callback ) { 40 41 callback = callback || function(){}; 42 43 // If the second parameter was provided 44 if ( params ) { 45 // If it's a function 46 if ( params.constructor == Function ) { 47 // We assume that it's the callback 48 callback = params; 49 params = null; 50 } 51 } 52 var callback2 = function() {jQuery.spip.log('jQuery.load');jQuery.spip.triggerAjaxLoad(this);callback.apply(this,arguments);}; 53 return jQuery.spip.intercepted.load.apply(this,[url, params, callback2]); 54 }; 55 56 // intercept jQuery.fn.ajaxSubmit 57 jQuery.spip.intercepted.ajaxSubmit = jQuery.fn.ajaxSubmit; 58 jQuery.fn.ajaxSubmit = function(options){ 59 // find the first parent that will not be removed by formulaire_dyn_ajax 60 // or take the whole document 61 options = options || {}; 62 if (typeof options.onAjaxLoad=="undefined" || options.onAjaxLoad!=false) { 63 var me=jQuery(this).parents('div.ajax'); 64 if (me.length) 65 me=me.parent(); 66 else 67 me = document; 68 if (typeof options=='function') 69 options = { success: options }; 70 var callback = options.success || function(){}; 71 options.success = function(){callback.apply(this,arguments);jQuery.spip.log('jQuery.ajaxSubmit');jQuery.spip.triggerAjaxLoad(me);} 72 } 73 return jQuery.spip.intercepted.ajaxSubmit.apply(this,[options]); 74 } 75 76 // intercept jQuery.ajax 77 jQuery.spip.intercepted.ajax = jQuery.ajax; 78 jQuery.ajax = function(type) { 79 var s = jQuery.extend(true, {}, jQuery.ajaxSettings, type); 80 var callbackContext = s.context || s; 81 try { 82 if (jQuery.ajax.caller==jQuery.spip.intercepted.load || jQuery.ajax.caller==jQuery.spip.intercepted.ajaxSubmit) 83 return jQuery.spip.intercepted.ajax(type); 84 } 85 catch (err){} 86 var orig_complete = s.complete || function() {}; 87 type.complete = function(res,status) { 88 // Do not fire OnAjaxLoad if the dataType is not html 89 var dataType = type.dataType; 90 var ct = (res && (typeof res.getResponseHeader == 'function')) 91 ? res.getResponseHeader("content-type"): ''; 92 var xml = !dataType && ct && ct.indexOf("xml") >= 0; 93 orig_complete.call( callbackContext, res, status); 94 if(!dataType && !xml || dataType == "html") { 95 jQuery.spip.log('jQuery.ajax'); 96 if (typeof s.onAjaxLoad=="undefined" || s.onAjaxLoad!=false) 97 jQuery.spip.triggerAjaxLoad(s.ajaxTarget?s.ajaxTarget:document); 98 } 99 }; 100 return jQuery.spip.intercepted.ajax(type); 101 }; 102 103} 104 105/** 106 * if not fully visible, scroll the page to position 107 * target block at the top of page 108 * if force = true, allways scroll 109 * 110 * @param bool force 111 */ 112jQuery.fn.positionner = function(force, setfocus) { 113 var offset = jQuery(this).offset(); 114 var hauteur = parseInt(jQuery(this).css('height')); 115 var scrolltop = self['pageYOffset'] || 116 jQuery.boxModel && document.documentElement[ 'scrollTop' ] || 117 document.body[ 'scrollTop' ]; 118 var h = jQuery(window).height(); 119 var scroll=0; 120 121 if (force || (offset && offset['top'] - 5 <= scrolltop)) 122 scroll = offset['top'] - 5; 123 else if (offset && offset['top'] + hauteur - h + 5 > scrolltop) 124 scroll = Math.min(offset['top'] - 5, offset['top'] + hauteur - h + 15); 125 if (scroll) 126 jQuery('html,body') 127 .animate({scrollTop: scroll}, 300); 128 129 // positionner le curseur dans la premiere zone de saisie 130 if (setfocus!==false) 131 jQuery(jQuery('*', this).filter('input[type=text],textarea')[0]).focus(); 132 return this; // don't break the chain 133} 134 135// deux fonctions pour rendre l'ajax compatible Jaws 136jQuery.spip.virtualbuffer_id='spip_virtualbufferupdate'; 137jQuery.spip.initReaderBuffer = function(){
138 if (jQuery('#'+jQuery.spip.virtualbuffer_id).length) return; 139 jQuery('body').append('<p style="float:left;width:0;height:0;position:absolute;left:-5000px;top:-5000px;"><input type="hidden" name="'+jQuery.spip.virtualbuffer_id+'" id="'+jQuery.spip.virtualbuffer_id+'" value="0" /></p>'); 140} 141jQuery.spip.updateReaderBuffer = function(){ 142 var i = jQuery('#'+jQuery.spip.virtualbuffer_id); 143 if (!i.length) return; 144 // incrementons l'input hidden, ce qui a pour effet de forcer le rafraichissement du 145 // buffer du lecteur d'ecran (au moins dans Jaws) 146 i.attr('value',parseInt(i.attr('value'))+1); 147} 148 149jQuery.fn.formulaire_setARIA = function(){ 150 if (!this.closest('.ariaformprop').length){ 151 // eviter une double execution du js au moment de sa reinsertion dans le DOM par wrap() 152 // cf http://bugs.jquery.com/ticket/7447 153 this.find('script').remove(); 154 this.wrap('<div class="ariaformprop" aria-live="polite" aria-atomic="true" aria-relevant="additions"></div>'); 155 // dans un formulaire, le screen reader relit tout a chaque saisie d'un caractere si on est en aria-live 156 jQuery('form',this).not('[aria-live]').attr('aria-live','off'); 157 } 158 return this; 159} 160/** 161 * rechargement ajax d'un formulaire dynamique implemente par formulaires/xxx.html 162 * @param target 163 */ 164jQuery.fn.formulaire_dyn_ajax = function(target) { 165 if (this.length) 166 jQuery.spip.initReaderBuffer(); 167 return this.each(function() { 168 var scrollwhensubmit = !jQuery(this).is('.noscroll'); 169 var cible = target || this; 170 jQuery(cible).formulaire_setARIA(); 171 jQuery('form:not(.noajax):not(.bouton_action_post)', this).each(function(){ 172 var leform = this; 173 var leclk,leclk_x,leclk_y; 174 jQuery(this).prepend("<input type='hidden' name='var_ajax' value='form' />") 175 .ajaxForm({ 176 beforeSubmit: function(){ 177 // memoriser le bouton clique, en cas de repost non ajax 178 leclk = leform.clk; 179 if (leclk) { 180 var n = leclk.name; 181 if (n && !leclk.disabled && leclk.type == "image") { 182 leclk_x = leform.clk_x; 183 leclk_y = leform.clk_y; 184 } 185 } 186 jQuery(cible).wrap('<div />'); 187 cible = jQuery(cible).parent(); 188 jQuery(cible).closest('.ariaformprop').animateLoading(); 189 if (scrollwhensubmit) 190 jQuery(cible).positionner(false,false); 191 }, 192 success: function(c){ 193 if (c=='noajax'){ 194 // le serveur ne veut pas traiter ce formulaire en ajax 195 // on resubmit sans ajax 196 jQuery("input[name=var_ajax]",leform).remove(); 197 // si on a memorise le nom et la valeur du bouton clique 198 // les reinjecter dans le dom sous forme de input hidden 199 // pour que le serveur les recoive 200 if (leclk){ 201 var n = leclk.name; 202 if (n && !leclk.disabled) { 203 jQuery(leform).prepend("<input type='hidden' name='"+n+"' value='"+leclk.value+"' />"); 204 if (leclk.type == "image") { 205 jQuery(leform).prepend("<input type='hidden' name='"+n+".x' value='"+leform.clk_x+"' />"); 206 jQuery(leform).prepend("<input type='hidden' name='"+n+".y' value='"+leform.clk_y+"' />"); 207 } 208 } 209 }
210 jQuery(leform).ajaxFormUnbind().submit(); 211 } 212 else { 213 // commencons par vider le cache des urls, si jamais un js au retour 214 // essaye tout de suite de suivre un lien en cache 215 // dans le doute sur la validite du cache il vaut mieux l'invalider 216 var preloaded = jQuery.spip.preloaded_urls; 217 jQuery.spip.preloaded_urls = {}; 218 jQuery(cible).html(c); 219 var a = jQuery('a:first',cible).eq(0); 220 var d = jQuery('div.ajax',cible); 221 if (!d.length){ 222 // si pas .ajax dans le form, remettre la classe sur le div que l'on a insere 223 jQuery(cible).addClass('ajax'); 224 if (!scrollwhensubmit) 225 jQuery(cible).addClass('noscroll'); 226 } 227 else { 228 // sinon nettoyer les br ajaxie 229 d.siblings('br.bugajaxie').remove(); 230 // desemboiter d'un niveau pour manger le div que l'on a insere 231 cible = jQuery(":first",cible); 232 cible.unwrap(); 233 } 234 // chercher une ancre en debut de html pour positionner la page 235 if (a.length 236 && a.is('a[name=ajax_ancre]') 237 && jQuery(a.attr('href'),cible).length){ 238 a = a.attr('href'); 239 if (jQuery(a,cible).length) 240 setTimeout(function(){ 241 jQuery(a,cible).positionner(false); 242 //a = a.split('#'); 243 //window.location.hash = a[1]; 244 },10); 245 jQuery(cible).closest('.ariaformprop').endLoading(true); 246 } 247 else{ 248 //jQuery(cible).positionner(false); 249 if (a.length && a.is('a[name=ajax_redirect]')){ 250 a = a.get(0).href; 251 setTimeout(function(){ 252 var cur = window.location.href.split('#'); 253 document.location.replace(a); 254 // regarder si c'est juste un changement d'ancre : dans ce cas il faut reload 255 // (le faire systematiquement provoque des bugs) 256 if (cur[0]==a.split('#')[0]){ 257 window.location.reload(); 258 } 259 },10); 260 // ne pas arreter l'etat loading, puisqu'on redirige ! 261 // mais le relancer car l'image loading a pu disparaitre 262 jQuery(cible).closest('.ariaformprop').animateLoading(); 263 } 264 else { 265 jQuery(cible).closest('.ariaformprop').endLoading(true); 266 } 267 } 268 // si jamais le formulaire n'a pas un retour OK, retablissons le cache 269 // car a priori on a pas fait d'operation en base de donnee 270 if (!jQuery('.reponse_formulaire_ok',cible).length) 271 jQuery.spip.preloaded_urls = preloaded; 272 // mettre a jour le buffer du navigateur pour aider jaws et autres readers 273 // a supprimer ? 274 jQuery.spip.updateReaderBuffer(); 275 } 276 }, 277 iframe: jQuery.browser.msie 278 }) 279 // previent qu'on n'ajaxera pas deux fois le meme formulaire en cas de ajaxload 280 // mais le marquer comme ayant l'ajax au cas ou on reinjecte du contenu ajax dedans 281 .addClass('noajax hasajax') 282 ; 283 }); 284 }); 285} 286 287jQuery.fn.formulaire_verifier = function(callback, champ){ 288 var erreurs = {'message_erreur':'form non ajax'}; 289 var me=this; 290 // si on est aussi en train de submit pour de vrai, abandonner 291 if (jQuery(me).closest('.ariaformprop').attr('aria-busy')!='true') { 292 if (jQuery(me).is('form.hasajax')){ 293 jQuery(me).ajaxSubmit({ 294 dataType:"json", 295 data:{formulaire_action_verifier_json:true}, 296 success:function(errs){ 297 var args = [errs, champ] 298 // si on est aussi en train de submit pour de vrai, abandonner 299 if (jQuery(me).closest('.ariaformprop').attr('aria-busy')!='true') 300 callback.apply(me,args); 301 } 302 }); 303 } 304 else 305 callback.apply(me,[erreurs, champ]); 306 } 307 return this; 308} 309 310jQuery.fn.formulaire_activer_verif_auto = function(callback){ 311 callback = callback || formulaire_actualiser_erreurs; 312 var me = jQuery(this).closest('.ariaformprop'); 313 var check = function(){ 314 var name=jQuery(this).attr('name'); 315 // declencher apres 50ms pour ne pas double submit sur sequence saisie+submit 316 setTimeout(function(){me.find('form').formulaire_verifier(callback,name);},50); 317 } 318 var activer = function(){ 319 if (me.find('form').attr('data-verifjson')!='on'){ 320 me 321 .find('form') 322 .attr('data-verifjson','on') 323 .find('input,select,textarea') 324 .bind('change',check); 325 } 326 } 327 jQuery(activer); 328 onAjaxLoad(function(){setTimeout(activer,150);}); 329} 330 331function formulaire_actualiser_erreurs(erreurs){ 332 var parent = jQuery(this).closest('.formulaire_spip'); 333 if (!parent.length) return; 334 // d'abord effacer tous les messages d'erreurs 335 parent.find('.reponse_formulaire,.erreur_message').fadeOut().remove(); 336 parent.find('.erreur').removeClass('erreur'); 337 // ensuite afficher les nouveaux messages d'erreur 338 if (erreurs['message_ok']) 339 parent.find('form').before('<p class="reponse_formulaire reponse_formulaire_ok">'+erreurs['message_ok']+'</p>'); 340 if (erreurs['message_erreur']) 341 parent.find('form').before('<p class="reponse_formulaire reponse_formulaire_erreur">'+erreurs['message_erreur']+'</p>'); 342 for (var k in erreurs){ 343 var saisie = parent.find('.editer_'+k); 344 if (saisie.length) { 345 saisie.addClass('erreur'); 346 saisie.find('label').after('<span class="erreur_message">'+erreurs[k]+'</span>'); 347 } 348 } 349} 350 351 352// permettre d'utiliser onclick='return confirm('etes vous sur?');' sur un lien ajax 353var ajax_confirm=true; 354var ajax_confirm_date=0; 355var spip_confirm = window.confirm; 356function _confirm(message){ 357 ajax_confirm = spip_confirm(message); 358 if (!ajax_confirm) { 359 var d = new Date(); 360 ajax_confirm_date = d.getTime(); 361 } 362 return ajax_confirm; 363} 364window.confirm = _confirm; 365 366/**
367 * rechargement ajax d'une noisette implementee par {ajax} 368 * selecteur personalise, sera defini par defaut a '.pagination a,a.ajax' 369 */ 370var ajaxbloc_selecteur; 371 372/** 373 * mise en cache des url. Il suffit de vider cete variable pour vider le cache 374 */ 375jQuery.spip.preloaded_urls = {}; 376 377/** 378 * Afficher dans la page 379 * le html d'un bloc ajax charge 380 * @param object blocfrag 381 * @param string c 382 * @param string href 383 * @param bool history 384 */ 385jQuery.spip.on_ajax_loaded = function(blocfrag,c,href,history) { 386 history = history || (history==null); 387 if (typeof href == undefined || href==null) 388 history = false; 389 if (history) 390 jQuery.spip.setHistoryState(blocfrag); 391 392 if (jQuery(blocfrag).attr('data-loaded-callback')){ 393 var callback = eval(jQuery(blocfrag).attr('data-loaded-callback')); 394 callback.call(blocfrag, c, href, history); 395 } 396 else { 397 jQuery(blocfrag) 398 .html(c) 399 .endLoading(); 400 } 401 402 if (typeof href != undefined) 403 jQuery(blocfrag).attr('data-url',href); 404 if (history) { 405 jQuery.spip.pushHistoryState(href); 406 jQuery.spip.setHistoryState(blocfrag); 407 } 408 409 var a = jQuery('a:first',jQuery(blocfrag)).eq(0); 410 if (a.length 411 && a.is('a[name=ajax_ancre]') 412 && jQuery(a.attr('href'),blocfrag).length){ 413 a = a.attr('href'); 414 jQuery(a,blocfrag).positionner(false); 415 } 416 jQuery.spip.log('on_ajax_loaded'); 417 jQuery.spip.triggerAjaxLoad(blocfrag); 418 // si le fragment ajax est dans un form ajax, 419 // il faut remettre a jour les evenements attaches 420 // car le fragment peut comporter des submit ou button 421 a = jQuery(blocfrag).parents('form.hasajax') 422 if (a.length) 423 a.eq(0).removeClass('noajax').parents('div.ajax').formulaire_dyn_ajax(); 424 jQuery.spip.updateReaderBuffer(); 425} 426 427jQuery.spip.stateId=0; 428jQuery.spip.setHistoryState = function(blocfrag){ 429 if (!window.history.replaceState) return; 430 // attribuer un id au bloc si il n'en a pas 431 if (!blocfrag.attr('id')){ 432 while (jQuery('#ghsid'+jQuery.spip.stateId).length) 433 jQuery.spip.stateId++; 434 blocfrag.attr('id','ghsid'+jQuery.spip.stateId); 435 } 436 var href= blocfrag.attr('data-url') || blocfrag.attr('data-origin'); 437 href = jQuery("<"+"a href='"+href+"'></a>").get(0).href; 438 var state={ 439 id:blocfrag.attr('id'), 440 href: href 441 }; 442 var ajaxid = blocfrag.attr('class').match(/\bajax-id-[\w-]+\b/); 443 if (ajaxid && ajaxid.length) 444 state["ajaxid"] = ajaxid[0]; 445 // on remplace la variable qui decrit l'etat courant 446 // initialement vide 447 // -> elle servira a revenir dans l'etat courant 448 window.history.replaceState(state,window.document.title, window.document.location); 449} 450 451jQuery.spip.pushHistoryState = function(href, title){ 452 if (!window.history.pushState) 453 return false; 454 window.history.pushState({}, title, href); 455} 456 457window.onpopstate = function(popState){ 458 if (popState.state && popState.state.href){ 459 var blocfrag=false; 460 if (popState.state.id){ 461 blocfrag=jQuery('#'+popState.state.id); 462 } 463 if ((!blocfrag || !blocfrag.length) && popState.state.ajaxid){ 464 blocfrag=jQuery('.ajaxbloc.'+popState.state.ajaxid); 465 } 466 if (blocfrag && blocfrag.length==1) { 467 jQuery.spip.ajaxClick(blocfrag,popState.state.href,{history:false}); 468 return true; 469 } 470 // si on revient apres avoir rompu la chaine ajax, on a pu perdre l'id #ghsidxx ajoute en JS 471 // dans ce cas on redirige hors ajax 472 else { 473 window.location.href = popState.state.href; 474 } 475 } 476} 477 478/** 479 * Charger un bloc ajax represente par l'objet jQuery blocajax qui le pointe 480 * avec la requete ajax url, qui represente le lien href 481 * @param object blocfrag 482 * bloc cible 483 * @param string url 484 * url pour la requete ajax 485 * @param string href 486 * url du lien clique 487 * @param object options 488 * bool force : pour forcer la requete sans utiliser le cache 489 * function callback : callback au retour du chargement 490 * bool history : prendre en charge l'histrisation dans l'url 491 */ 492jQuery.spip.loadAjax = function(blocfrag,url, href, options){ 493 var force = options.force || false; 494 if (jQuery(blocfrag).attr('data-loading-callback')){ 495 var callback = eval(jQuery(blocfrag).attr('data-loading-callback')); 496 callback.call(blocfrag,url,href,options); 497 } 498 else { 499 jQuery(blocfrag).animateLoading(); 500 } 501 if (jQuery.spip.preloaded_urls[url] && !force) { 502 // si on est deja en train de charger ce fragment, revenir plus tard 503 if (jQuery.spip.preloaded_urls[url]=="<!--loading-->"){ 504 setTimeout(function(){jQuery.spip.loadAjax(blocfrag,url,href,options);},100); 505 return; 506 } 507 jQuery.spip.on_ajax_loaded(blocfrag,jQuery.spip.preloaded_urls[url],href,options.history); 508 } else { 509 var d = new Date(); 510 jQuery.spip.preloaded_urls[url] = "<!--loading-->"; 511 jQuery.ajax({ 512 url: parametre_url(url,'var_t',d.getTime()), 513 onAjaxLoad:false, 514 success: function(c){ 515 jQuery.spip.on_ajax_loaded(blocfrag,c,href,options.history); 516 jQuery.spip.preloaded_urls[url] = c; 517 if (options.callback && typeof options.callback == "function") 518 options.callback.apply(blocfrag); 519 }, 520 error: function(){ 521 jQuery.spip.preloaded_urls[url]=''; 522 } 523 }); 524 } 525} 526 527/** 528 * Calculer l'url ajax a partir de l'url du lien 529 * et de la variable d'environnement du bloc ajax 530 * passe aussi l'ancre eventuelle sous forme d'une variable 531 * pour que le serveur puisse la prendre en compte 532 * et la propager jusqu'a la reponse 533 * sous la forme d'un lien cache 534 * 535 * @param string href 536 * @param string ajax_env 537 */ 538jQuery.spip.makeAjaxUrl = function(href,ajax_env,origin){ 539 var url = href.split('#'); 540 url[0] = parametre_url(url[0],'var_ajax',1); 541 url[0] = parametre_url(url[0],'var_ajax_env',ajax_env); 542 543 // les arguments de origin qui ne sont pas dans href doivent etre explicitement fournis vides dans url 544 if (origin){ 545 var p=origin.indexOf('?'); 546 if (p!==-1){ 547 // recuperer la base 548 var args = origin.substring(p+1).split('&'); 549 var val; 550 var arg; 551 for(var n=0;n<args.length;n++){ 552 arg = args[n].split('='); 553 arg = arg[0]; 554 p = arg.indexOf('['); 555 if (p!==-1) 556 arg = arg.substring(0,p); 557 val = parametre_url(href,arg); 558 if (typeof val=="undefined")
559 url[0] = url[0] + '&' + arg + '='; 560 } 561 } 562 } 563 564 if (url[1]) 565 url[0] = parametre_url(url[0],'var_ajax_ancre',url[1]); 566 return url[0]; 567} 568 569/** 570 * fonction appelee sur l'evenement ajaxReload d'un bloc ajax 571 * que l'on declenche quand on veut forcer sa mise a jour 572 * 573 * @param object blocfrag 574 * @param object options 575 * callback : fonction appelee apres le rechargement 576 * href : url to load instead of origin url 577 * args : arguments passes a l'url rechargee (permet une modif du contexte) 578 * history : bool to specify if navigation history is modified by reload or not (false if not provided) 579 */ 580jQuery.spip.ajaxReload = function(blocfrag, options){ 581 var ajax_env = blocfrag.attr('data-ajax-env'); 582 if (!ajax_env || ajax_env==undefined) return; 583 var href = options.href || blocfrag.attr('data-url') || blocfrag.attr('data-origin'); 584 if (href && typeof href != undefined){ 585 options == options || {}; 586 var callback=options.callback || null; 587 var history=options.history || false; 588 var args = options.args || {}; 589 for (var key in args) 590 href = parametre_url(href,key,args[key]==undefined?'':args[key],'&',args[key]==undefined?false:true); 591 var url = jQuery.spip.makeAjaxUrl(href,ajax_env,blocfrag.attr('data-origin')); 592 // recharger sans historisation dans l'url 593 jQuery.spip.loadAjax(blocfrag, url, href, {force:true, callback:callback, history:history}); 594 return true; 595 } 596} 597 598/** 599 * fonction appelee sur l'evenement click d'un lien ajax 600 * 601 * @param object blocfrag 602 * objet jQuery qui cible le bloc ajax contenant 603 * @param string href 604 * url du lien a suivre 605 * @param object options 606 * force : pour interdire l'utilisation du cache 607 * history : pour interdire la mise en historique 608 */ 609jQuery.spip.ajaxClick = function(blocfrag, href, options){ 610 var ajax_env = blocfrag.attr('data-ajax-env'); 611 if (!ajax_env || ajax_env==undefined) return; 612 if (!ajax_confirm) { 613 // on rearme pour le prochain clic 614 ajax_confirm=true; 615 var d = new Date(); 616 // seule une annulation par confirm() dans les 2 secondes precedentes est prise en compte 617 if ((d.getTime()-ajax_confirm_date)<=2) 618 return false; 619 } 620 var url = jQuery.spip.makeAjaxUrl(href,ajax_env,blocfrag.attr('data-origin')); 621 jQuery.spip.loadAjax(blocfrag, url, href, options); 622 return false; 623} 624 625/** 626 * Implementer le comportemant des liens ajax 627 * et boutons post ajax qui se comportent 628 * comme un lien ajax 629 */ 630jQuery.fn.ajaxbloc = function() { 631 // hack accessibilite vieille version de JAWS 632 // a supprimer ? 633 if (this.length) 634 jQuery.spip.initReaderBuffer(); 635 if (ajaxbloc_selecteur==undefined) 636 ajaxbloc_selecteur = '.pagination a,a.ajax'; 637 638 return this.each(function() { 639 // traiter les enfants d'abord : 640 // un lien ajax provoque le rechargement 641 // du plus petit bloc ajax le contenant 642 jQuery('div.ajaxbloc',this).ajaxbloc(); 643 var blocfrag = jQuery(this); 644 645 var ajax_env = blocfrag.attr('data-ajax-env'); 646 if (!ajax_env || ajax_env==undefined) return; 647 648 blocfrag.not('.bind-ajaxReload').bind('ajaxReload',function(event, options){ 649 if (jQuery.spip.ajaxReload(blocfrag,options)) 650 // don't trig reload of parent blocks 651 event.stopPropagation(); 652 }).addClass('bind-ajaxReload') 653 .attr('aria-live','polite').attr('aria-atomic','true'); 654 655 // dans un formulaire, le screen reader relit tout a chaque saisie d'un caractere si on est en aria-live 656 // mettre un aria-live="off" sur les forms inclus dans ce bloc aria-live="polite" 657 jQuery('form',this).not('[aria-live]').attr('aria-live','off'); 658 659 jQuery(ajaxbloc_selecteur,this).not('.noajax,.bind-ajax') 660 .click(function(){return jQuery.spip.ajaxClick(blocfrag,this.href,{force:jQuery(this).is('.nocache'),history:!(jQuery(this).is('.nohistory')||jQuery(this).closest('.box_modalbox').length)});}) 661 .addClass('bind-ajax') 662 .filter('.preload').each(function(){ 663 var href = this.href; 664 var url = jQuery.spip.makeAjaxUrl(href,ajax_env,blocfrag.attr('data-origin')); 665 if (!jQuery.spip.preloaded_urls[url]) { 666 jQuery.spip.preloaded_urls[url] = '<!--loading-->'; 667 jQuery.ajax({url:url,onAjaxLoad:false,success:function(r){jQuery.spip.preloaded_urls[url]=r;},error:function(){jQuery.spip.preloaded_urls[url]='';}}); 668 } 669 }); // previent qu'on ajax pas deux fois le meme lien 670 671 // ajaxer les boutons actions qui sont techniquement des form minimaux
672 // mais se comportent comme des liens 673 jQuery('form.bouton_action_post.ajax', this).not('.noajax,.bind-ajax').each(function(){ 674 var leform = this; 675 var url = jQuery(this).attr('action').split('#'); 676 jQuery(this) 677 .prepend("<input type='hidden' name='var_ajax' value='1' /><input type='hidden' name='var_ajax_env' value='"+(ajax_env)+"' />"+(url[1]?"<input type='hidden' name='var_ajax_ancre' value='"+url[1]+"' />":"")) 678 .ajaxForm({ 679 beforeSubmit: function(){ 680 jQuery(blocfrag).animateLoading().positionner(false); 681 }, 682 onAjaxLoad:false, 683 success: function(c){ 684 jQuery.spip.on_ajax_loaded(blocfrag,c); 685 jQuery.spip.preloaded_urls = {}; // on vide le cache des urls car on a fait une action en bdd 686 }, 687 iframe: jQuery.browser.msie 688 }) 689 .addClass('bind-ajax') // previent qu'on n'ajaxera pas deux fois le meme formulaire en cas de ajaxload 690 ; 691 }); 692 }); 693}; 694 695/** 696 * Suivre un lien en simulant le click sur le lien 697 * Si le lien est ajax, on se contente de declencher l'evenement click() 698 * Si le lien est non ajax, on finit en remplacant l'url de la page 699 */ 700jQuery.fn.followLink = function(){ 701 $(this).click(); 702 if (!$(this).is('.bind-ajax')) 703 window.location.href = $(this).get(0).href; 704 return this; 705} 706/** 707 * Recharger un bloc ajax pour le mettre a jour 708 * ajaxid est l'id passe en argument de INCLURE{ajax=ajaxid} 709 * options permet de definir une callbackk ou de passer des arguments a l'url 710 * au rechargement 711 * ajaxReload peut s'utiliser en passant un id : 712 * ajaxReload('xx'); 713 * ou sur un objet jQuery 714 * jQuery(this).ajaxReload(); 715 * Dans ce dernier cas, le plus petit conteneur ajax est recharge 716 * 717 * @param string ajaxid 718 * @param object options 719 * callback : callback after reloading 720 * href : url to load instead of origin url 721 * args : {arg:value,...} to pass tu the url 722 * history : bool to specify if navigation history is modified by reload or not (false if not provided) 723 */ 724function ajaxReload(ajaxid, options){ 725 jQuery('div.ajaxbloc.ajax-id-'+ajaxid).ajaxReload(options); 726} 727 728/** 729 * Variante jQuery de ajaxReload pour la syntaxe 730 * jQuery(..).ajaxReload(); 731 * cf doc ci-dessus 732 * @param options 733 */ 734jQuery.fn.ajaxReload = function(options){ 735 options = options||{}; 736 // just trigg the event, as it will bubble up the DOM 737 jQuery(this).trigger('ajaxReload', [options]); 738 return this; // don't break the chain 739} 740 741/** 742 * animation du bloc cible pour faire patienter 743 * 744 */ 745jQuery.fn.animateLoading = function() { 746 this.attr('aria-busy','true').addClass('loading').children().css('opacity', 0.5); 747 if (typeof ajax_image_searching != 'undefined'){ 748 var i = (this).find('.image_loading'); 749 if (i.length) i.eq(0).html(ajax_image_searching); 750 else this.prepend('<span class="image_loading">'+ajax_image_searching+'</span>'); 751 } 752 return this; // don't break the chain 753} 754// compatibilite avec ancien nommage 755jQuery.fn.animeajax = jQuery.fn.animateLoading; 756 757/** 758 * Fin de l'animation 759 * l'argument permet de forcer le raz du contenu si il est inchange 760 * @param hard 761 */ 762jQuery.fn.endLoading = function(hard) { 763 hard = hard || false; 764 this.attr('aria-busy','false').removeClass('loading'); 765 if (hard){ 766 this.children().css('opacity', ''); 767 this.find('.image_loading').html(''); 768 } 769 return this; // don't break the chain 770} 771 772/** 773 * animation d'un item que l'on supprime : 774 * ajout de la classe remove avec un background tire de cette classe 775 * puis fading vers opacity 0 776 * quand l'element est masque, on retire les classes et css inline 777 * 778 * @param function callback 779 * 780 */ 781jQuery.fn.animateRemove = function(callback){ 782 if (this.length){ 783 var me=this; 784 var color = $("<div class='remove'></div>").css('background-color'); 785 var sel=$(this); 786 // if target is a tr, include td childrens cause background color on tr doesn't works in a lot of browsers 787 if (sel.is('tr')) 788 sel = sel.add('>td',sel); 789 sel.addClass('remove').css({backgroundColor: color}).animate({opacity: "0.0"}, 'fast',function(){ 790 sel.removeClass('remove').css({backgroundColor: ''}); 791 if (callback) 792 callback.apply(me); 793 }); 794 } 795 return this; // don't break the chain 796} 797 798/** 799 * animation d'un item que l'on ajoute : 800 * ajout de la classe append 801 * fading vers opacity 1 avec background herite de la classe append, 802 * puis suppression progressive du background pour revenir a la valeur heritee 803 * 804 * @param function callback 805 */ 806jQuery.fn.animateAppend = function(callback){ 807 if (this.length){ 808 var me=this; 809 // recuperer la couleur portee par la classe append (permet une personalisation) 810 var color = $("<div class='append'></div>").css('background-color'); 811 var origin = $(this).css('background-color') || '#ffffff'; 812 // pis aller 813 if (origin=='transparent') origin='#ffffff'; 814 var sel=$(this); 815 // if target is a tr, include td childrens cause background color on tr doesn't works in a lot of browsers 816 if (sel.is('tr')) 817 sel = sel.add('>td',sel); 818 sel.css('opacity','0.0').addClass('append').css({backgroundColor: color}).animate({opacity: "1.0"}, 1000,function(){ 819 sel.animate({backgroundColor: origin}, 3000,function(){ 820 sel.removeClass('append').css({backgroundColor: ''}); 821 if (callback) 822 callback.apply(me); 823 }); 824 }); 825 } 826 return this; // don't break the chain 827} 828 829/** 830 * Equivalent js de parametre_url php de spip 831 * 832 * Exemples : 833 * parametre_url(url,suite,18) (ajout) 834 * parametre_url(url,suite,'') (supprime) 835 * parametre_url(url,suite) (lit la valeur suite) 836 * parametre_url(url,suite[],1) (tableau valeurs multiples) 837 * @param url 838 * url 839 * @param c 840 * champ 841 * @param v 842 * valeur 843 * @param sep 844 * separateur '&' par defaut 845 * @param force_vide 846 * si true et v='' insere &k= dans l'url au lieu de supprimer le k (false par defaut) 847 * permet de vider une valeur dans une requete ajax (dans un reload) 848 */ 849function parametre_url(url,c,v,sep,force_vide){ 850 // Si l'URL n'est pas une chaine, on ne peut pas travailler dessus et on quitte 851 if (typeof(url) == 'undefined'){ 852 url = ''; 853 } 854 855 var p; 856 // lever l'#ancre 857 var ancre=''; 858 var a='./'; 859 var args=[]; 860 p = url.indexOf('#'); 861 if (p!=-1) { 862 ancre=url.substring(p); 863 url = url.substring(0,p); 864 } 865 866 // eclater 867 p=url.indexOf('?'); 868 if (p!==-1){ 869 // recuperer la base 870 if (p>0) a=url.substring(0,p); 871 args = url.substring(p+1).split('&'); 872 } 873 else 874 a=url; 875 var regexp = new RegExp('^(' + c.replace('[]','\\[\\]') + '\\[?\\]?)(=.*)?$'); 876 var ajouts = []; 877 var u = (typeof(v)!=='object')?encodeURIComponent(v):v; 878 var na = []; 879 // lire les variables et agir 880 for(var n=0;n<args.length;n++){ 881 var val = args[n]; 882 try { 883 val = decodeURIComponent(val); 884 } catch(e) {} 885 var r=val.match(regexp); 886 if (r && r.length){ 887 if (v==null){ 888 return (r.length>2 && typeof r[2]!=='undefined')?r[2].substring(1):''; 889 } 890 // suppression 891 else if (!v.length) { 892 } 893 // Ajout. Pour une variable, remplacer au meme endroit, 894 // pour un tableau ce sera fait dans la prochaine boucle 895 else if (r[1].substring(-2) != '[]') { 896 na.push(r[1]+'='+u); 897 ajouts.push(r[1]); 898 } 899 else na.push(args[n]); 900 } 901 else 902 na.push(args[n]); 903 } 904 905 if (v==null) return v; // rien de trouve 906 // traiter les parametres pas encore trouves 907 if (v || v.length || force_vide) { 908 ajouts = "="+ajouts.join("=")+"="; 909 var all=c.split('|'); 910 for (n=0;n<all.length;n++){ 911 if (ajouts.search("="+all[n]+"=")==-1){ 912 if (typeof(v)!=='object'){ 913 na.push(all[n] +'='+ u); 914 } 915 else { 916 var id = ((all[n].substring(-2)=='[]')?all[n]:all[n]+"[]"); 917 for(p=0;p<v.length;p++) 918 na.push(id +'='+ encodeURIComponent(v[p])); 919 } 920 } 921 } 922 } 923 924 // recomposer l'adresse 925 if (na.length){ 926 if (!sep) sep='&'; 927 a = a+"?"+na.join(sep); 928 } 929 930 return a + ancre; 931} 932 933 934 935// Ajaxer les formulaires qui le demandent, au demarrage 936if (!window.var_zajax_content) 937 window.var_zajax_content = 'contenu'; 938jQuery(function() { 939 jQuery('form:not(.bouton_action_post)').parents('div.ajax') 940 .formulaire_dyn_ajax();
941 jQuery('div.ajaxbloc').ajaxbloc(); 942 jQuery("input[placeholder]:text").placeholderLabel(); 943 jQuery('a.popin').click(function(){if (jQuery.modalbox) jQuery.modalbox(parametre_url(this.href,"var_zajax",jQuery(this).attr('data-var_zajax')?jQuery(this).attr('data-var_zajax'):var_zajax_content));return false;}); 944}); 945 946// ... et a chaque fois que le DOM change 947onAjaxLoad(function() { 948 if (jQuery){ 949 jQuery('form:not(.bouton_action_post)', this).parents('div.ajax') 950 .formulaire_dyn_ajax(); 951 if (jQuery(this).is('div.ajaxbloc')) 952 jQuery(this).ajaxbloc(); 953 else if (jQuery(this).closest('div.ajaxbloc').length) 954 jQuery(this).closest('div.ajaxbloc').ajaxbloc(); 955 else 956 jQuery('div.ajaxbloc', this).ajaxbloc(); 957 jQuery("input[placeholder]:text",this).placeholderLabel(); 958 jQuery('a.popin',this).click(function(){if (jQuery.modalbox) jQuery.modalbox(parametre_url(this.href,"var_zajax",jQuery(this).attr('data-var_zajax')?jQuery(this).attr('data-var_zajax'):var_zajax_content));return false;}); 959 } 960}); 961
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.