[SPIP] +2.1.12
[velocampus/web/www.git] / www / prive / javascript / ajaxCallback.js
1 // A plugin that wraps all ajax calls introducing a fixed callback function on ajax complete
2 if(!jQuery.load_handlers) {
3 jQuery.load_handlers = new Array();
4 //
5 // Add a function to the list of those to be executed on ajax load complete
6 //
7 function onAjaxLoad(f) {
8 jQuery.load_handlers.push(f);
9 };
10
11 //
12 // Call the functions that have been added to onAjaxLoad
13 //
14 function triggerAjaxLoad(root) {
15 for ( var i = 0; i < jQuery.load_handlers.length; i++ )
16 jQuery.load_handlers[i].apply( root );
17 };
18
19 // jQuery uses _load, we use _ACBload
20 jQuery.fn._ACBload = jQuery.fn.load;
21
22 jQuery.fn.load = function( url, params, callback ) {
23
24 callback = callback || function(){};
25
26 // If the second parameter was provided
27 if ( params ) {
28 // If it's a function
29 if ( params.constructor == Function ) {
30 // We assume that it's the callback
31 callback = params;
32 params = null;
33 }
34 }
35 var callback2 = function(res,status) {triggerAjaxLoad(this);callback.call(this,res,status);};
36
37 return this._ACBload( url, params, callback2 );
38 };
39
40 jQuery._ACBajax = jQuery.ajax;
41
42 jQuery.ajax = function(type) {
43 var s = jQuery.extend(true, {}, jQuery.ajaxSettings, type);
44 var callbackContext = s.context || s;
45 //If called by _load exit now because the callback has already been set
46 if (jQuery.ajax.caller==jQuery.fn._load) return jQuery._ACBajax( type);
47 var orig_complete = s.complete || function() {};
48 type.complete = function(res,status) {
49 // Do not fire OnAjaxLoad if the dataType is not html
50 var dataType = type.dataType;
51 var ct = (res && (typeof res.getResponseHeader == 'function'))
52 ? res.getResponseHeader("content-type"): '';
53 var xml = !dataType && ct && ct.indexOf("xml") >= 0;
54 orig_complete.call( callbackContext, res, status);
55 if(!dataType && !xml || dataType == "html") triggerAjaxLoad(document);
56 };
57 return jQuery._ACBajax(type);
58 };
59
60 }
61
62 // animation du bloc cible pour faire patienter
63 jQuery.fn.animeajax = function(end) {
64 this.children().css('opacity', 0.5);
65 if (typeof ajax_image_searching != 'undefined'){
66 var i = (this).find('.image_loading');
67 if (i.length) i.eq(0).html(ajax_image_searching);
68 else this.prepend('<span class="image_loading">'+ajax_image_searching+'</span>');
69 }
70 return this; // don't break the chain
71 }
72
73 // s'il n'est pas totalement visible, scroller pour positionner
74 // le bloc cible en haut de l'ecran
75 // si force = true, scroller dans tous les cas
76 jQuery.fn.positionner = function(force) {
77 var offset = jQuery(this).offset();
78 var hauteur = parseInt(jQuery(this).css('height'));
79 var scrolltop = self['pageYOffset'] ||
80 jQuery.boxModel && document.documentElement[ 'scrollTop' ] ||
81 document.body[ 'scrollTop' ];
82 var h = jQuery(window).height();
83 var scroll=0;
84
85 if (force || offset['top'] - 5 <= scrolltop)
86 scroll = offset['top'] - 5;
87 else if (offset['top'] + hauteur - h + 5 > scrolltop)
88 scroll = Math.min(offset['top'] - 5, offset['top'] + hauteur - h + 15);
89 if (scroll)
90 jQuery('html,body')
91 .animate({scrollTop: scroll}, 300);
92
93 // positionner le curseur dans la premiere zone de saisie
94 jQuery(jQuery('*', this).filter('input[type=text],textarea')[0]).focus();
95 return this; // don't break the chain
96 }
97
98 // deux fonctions pour rendre l'ajax compatible Jaws
99 var virtualbuffer_id='spip_virtualbufferupdate';
100 function initReaderBuffer(){
101 if (jQuery('#'+virtualbuffer_id).length) return;
102 jQuery('body').append('<p style="float:left;width:0;height:0;position:absolute;left:-5000;top:-5000;"><input type="hidden" name="'+virtualbuffer_id+'" id="'+virtualbuffer_id+'" value="0" /></p>');
103 }
104 function updateReaderBuffer(){
105 var i = jQuery('#'+virtualbuffer_id);
106 if (!i.length) return;
107 // incrementons l'input hidden, ce qui a pour effet de forcer le rafraichissement du
108 // buffer du lecteur d'ecran (au moins dans Jaws)
109 i.attr('value',parseInt(i.attr('value'))+1);
110 }
111
112 // rechargement ajax d'un formulaire dynamique implemente par formulaires/xxx.html
113 jQuery.fn.formulaire_dyn_ajax = function(target) {
114 if (this.length)
115 initReaderBuffer();
116 return this.each(function() {
117 var cible = target || this;
118 jQuery('form:not(.noajax,.bouton_action_post)', this).each(function(){
119 var leform = this;
120 var leclk,leclk_x,leclk_y;
121 jQuery(this).prepend("<input type='hidden' name='var_ajax' value='form' />")
122 .ajaxForm({
123 beforeSubmit: function(){
124 // memoriser le bouton clique, en cas de repost non ajax
125 leclk = leform.clk;
126 if (leclk) {
127 var n = leclk.name;
128 if (n && !leclk.disabled && leclk.type == "image") {
129 leclk_x = leform.clk_x;
130 leclk_y = leform.clk_y;
131 }
132 }
133 jQuery(cible).addClass('loading').animeajax();
134 },
135 success: function(c){
136 if (c=='noajax'){
137 // le serveur ne veut pas traiter ce formulaire en ajax
138 // on resubmit sans ajax
139 jQuery("input[name=var_ajax]",leform).remove();
140 // si on a memorise le nom et la valeur du bouton clique
141 // les reinjecter dans le dom sous forme de input hidden
142 // pour que le serveur les recoive
143 if (leclk){
144 var n = leclk.name;
145 if (n && !leclk.disabled) {
146 jQuery(leform).prepend("<input type='hidden' name='"+n+"' value='"+leclk.value+"' />");
147 if (leclk.type == "image") {
148 jQuery(leform).prepend("<input type='hidden' name='"+n+".x' value='"+leform.clk_x+"' />");
149 jQuery(leform).prepend("<input type='hidden' name='"+n+".y' value='"+leform.clk_y+"' />");
150 }
151 }
152 }
153 jQuery(leform).ajaxFormUnbind().submit();
154 }
155 else {
156 var recu = jQuery('<div><\/div>').html(c);
157 var d = jQuery('div.ajax',recu);
158 if (d.length)
159 c = d.html();
160 jQuery(cible)
161 .removeClass('loading')
162 .html(c);
163 var a = jQuery('a:first',recu).eq(0);
164 if (a.length
165 && a.is('a[name=ajax_ancre]')
166 && jQuery(a.attr('href'),cible).length){
167 a = a.attr('href');
168 if (jQuery(a,cible).length)
169 setTimeout(function(){
170 jQuery(a,cible).positionner(true);
171 //a = a.split('#');
172 //window.location.hash = a[1];
173 },10);
174 }
175 else{
176 jQuery(cible).positionner(false);
177 if (a.length && a.is('a[name=ajax_redirect]')){
178 a = a.attr('href');
179 jQuery(cible).addClass('loading').animeajax();
180 setTimeout(function(){
181 document.location.replace(a);
182 },10);
183 }
184 }
185 // on le refait a la main ici car onAjaxLoad intervient sur une iframe dans IE6 et non pas sur le document
186 triggerAjaxLoad(cible);
187 // mettre a jour le buffer du navigateur pour aider jaws et autres readers
188 updateReaderBuffer();
189 }
190 },
191 iframe: jQuery.browser.msie
192 })
193 .addClass('noajax') // previent qu'on n'ajaxera pas deux fois le meme formulaire en cas de ajaxload
194 ;
195 });
196 });
197 }
198
199 // permettre d'utiliser onclick='return confirm('etes vous sur?');' sur un lien ajax
200 var ajax_confirm=true;
201 var ajax_confirm_date=0;
202 var spip_confirm = window.confirm;
203 function _confirm(message){
204 ajax_confirm = spip_confirm(message);
205 if (!ajax_confirm) {
206 var d = new Date();
207 ajax_confirm_date = d.getTime();
208 }
209 return ajax_confirm;
210 }
211 window.confirm = _confirm;
212
213 // rechargement ajax d'une noisette implementee par {ajax}
214 // avec mise en cache des url
215 var preloaded_urls = {};
216 var ajaxbloc_selecteur;
217 jQuery.fn.ajaxbloc = function() {
218 if (this.length)
219 initReaderBuffer();
220
221 return this.each(function() {
222 jQuery('div.ajaxbloc',this).ajaxbloc(); // traiter les enfants d'abord
223 var blocfrag = jQuery(this);
224
225 var on_pagination = function(c) {
226 jQuery(blocfrag)
227 .html(c)
228 .removeClass('loading');
229 var a = jQuery('a:first',jQuery(blocfrag)).eq(0);
230 if (a.length
231 && a.is('a[name=ajax_ancre]')
232 && jQuery(a.attr('href'),blocfrag).length){
233 a = a.attr('href')
234 setTimeout(function(){
235 jQuery(a,blocfrag).positionner(true);
236 //a = a.split('#');
237 //window.location.hash = a[1];
238 },10);
239 }
240 else {
241 jQuery(blocfrag).positionner(false);
242 }
243 updateReaderBuffer();
244 }
245
246 var ajax_env = (""+blocfrag.attr('class')).match(/env-([^ ]+)/);
247 if (!ajax_env || ajax_env==undefined) return;
248 ajax_env = ajax_env[1];
249 if (ajaxbloc_selecteur==undefined)
250 ajaxbloc_selecteur = '.pagination a,a.ajax';
251
252 jQuery(ajaxbloc_selecteur,this).not('.noajax').each(function(){
253 var url = this.href.split('#');
254 url[0] += (url[0].indexOf("?")>0 ? '&':'?')+'var_ajax=1&var_ajax_env='+encodeURIComponent(ajax_env);
255 if (url[1])
256 url[0] += "&var_ajax_ancre="+url[1];
257 if (jQuery(this).is('.preload') && !preloaded_urls[url[0]]) {
258 jQuery.ajax({"url":url[0],"success":function(r){preloaded_urls[url[0]]=r;}});
259 }
260 jQuery(this).click(function(){
261 if (!ajax_confirm) {
262 // on rearme pour le prochain clic
263 ajax_confirm=true;
264 var d = new Date();
265 // seule une annulation par confirm() dans les 2 secondes precedentes est prise en compte
266 if ((d.getTime()-ajax_confirm_date)<=2)
267 return false;
268 }
269 jQuery(blocfrag)
270 .animeajax()
271 .addClass('loading');
272 if (preloaded_urls[url[0]]) {
273 on_pagination(preloaded_urls[url[0]]);
274 triggerAjaxLoad(document);
275 } else {
276 jQuery.ajax({
277 url: url[0],
278 success: function(c){
279 on_pagination(c);
280 preloaded_urls[url[0]] = c;
281 }
282 });
283 }
284 return false;
285 });
286 }).addClass('noajax'); // previent qu'on ajax pas deux fois le meme lien
287 jQuery('form.bouton_action_post.ajax:not(.noajax)', this).each(function(){
288 var leform = this;
289 var url = jQuery(this).attr('action').split('#');
290 jQuery(this)
291 .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]+"' />":""))
292 .ajaxForm({
293 beforeSubmit: function(){
294 jQuery(blocfrag).addClass('loading').animeajax();
295 },
296 success: function(c){
297 on_pagination(c);
298 preloaded_urls = {}; // on vide le cache des urls car on a fait une action en bdd
299 // on le refait a la main ici car onAjaxLoad intervient sur une iframe dans IE6 et non pas sur le document
300 jQuery(blocfrag)
301 .ajaxbloc();
302 },
303 iframe: jQuery.browser.msie
304 })
305 .addClass('noajax') // previent qu'on n'ajaxera pas deux fois le meme formulaire en cas de ajaxload
306 ;
307 });
308 });
309 };
310
311 // Ajaxer les formulaires qui le demandent, au demarrage
312
313 jQuery(function() {
314 jQuery('form:not(.bouton_action_post)').parents('div.ajax')
315 .formulaire_dyn_ajax();
316 jQuery('div.ajaxbloc').ajaxbloc();
317 });
318
319 // ... et a chaque fois que le DOM change
320 onAjaxLoad(function() {
321 if (jQuery){
322 jQuery('form:not(.bouton_action_post)', this).parents('div.ajax')
323 .formulaire_dyn_ajax();
324 jQuery('div.ajaxbloc', this)
325 .ajaxbloc();
326 }
327 });