From 05c47dab31a7591207a73ee7026b85fd2fc43cf7 Mon Sep 17 00:00:00 2001
From: Cerdic <cedric@yterium.com>
Date: Sun, 9 Jan 2011 17:51:12 +0000
Subject: [PATCH] Extension de l'argument ajax de #INCLURE <INCLURE> et #MODELE
 : INCLURE{fond=xxx,ajax=yyy} pose une etiquette 'yyy' sur le bloc ajax
 concerne. Plusieurs blocs ajax peuvent partager une meme etiquette.

La fonction javascript ajaxRefreshBloc('yyy') permet de declencher le rechargement de tous les blocs ajax avec l'etiquette yyy.
Cette fonctionnalite permet par exemple de forcer la mise a jour distante d'un morceau de page apres soumission d'un formulaire.
Seul l'etiquette des blocs ajax a besoin d'etre connue, pas la structure html de la page.

La syntaxe anonyme existante :
INCLURE{fond=xxx,ajax}
continue de fonctionner a l'identique, mais ne permet pas de cibler le bloc pour forcer sa mise a jour.
---
 ecrire/inc/filtres.php           | 32 ++++++++++----
 ecrire/inc/utils.php             |  6 +--
 ecrire/public/balises.php        |  9 ++--
 ecrire/public/compiler.php       |  6 ++-
 prive/javascript/ajaxCallback.js | 72 ++++++++++++++++++++++----------
 5 files changed, 88 insertions(+), 37 deletions(-)

diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index cc8235eab0..f2e15a1bbc 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -2108,11 +2108,24 @@ function puce_changement_statut($id_objet, $statut, $id_rubrique, $type, $ajax=f
 	return $puce_statut($id_objet, $statut, $id_rubrique, $type, $ajax=false);
 }
 
-// Encoder un contexte pour l'ajax, le signer avec une cle, le crypter
-// avec le secret du site, le gziper si possible...
-// l'entree peut etre serialisee (le #ENV** des fonds ajax et ajax_stat)
-// http://doc.spip.org/@encoder_contexte_ajax
-function encoder_contexte_ajax($c,$form='', $emboite=NULL) {
+/**
+ * Encoder un contexte pour l'ajax, le signer avec une cle, le crypter
+ * avec le secret du site, le gziper si possible...
+ * l'entree peut etre serialisee (le #ENV** des fonds ajax et ajax_stat)
+ *
+ * http://doc.spip.org/@encoder_contexte_ajax
+ *
+ * @param string|array $c
+ *   contexte, peut etre un tableau serialize
+ * @param string $form
+ *   nom du formulaire eventuel
+ * @param string $emboite
+ *   contenu a emboiter dans le conteneur ajax
+ * @param string $ajaxid
+ *   ajaxid pour cibler le bloc et forcer sa mise a jour
+ * @return string
+ */
+function encoder_contexte_ajax($c,$form='', $emboite=NULL, $ajaxid='') {
 	if (is_string($c)
 	AND !is_null(@unserialize($c)))
 		$c = unserialize($c);
@@ -2143,8 +2156,13 @@ function encoder_contexte_ajax($c,$form='', $emboite=NULL) {
 	}
 	
 	if ($emboite === NULL) return $c;
-	return !trim($emboite) ? '' :  
-	"<div class='ajaxbloc env-$c'>\n$emboite</div><!-- ajaxbloc -->\n";
+	if (!trim($emboite)) return "";
+	$r = "";
+	if ($ajaxid AND is_string($ajaxid)){
+		$c .= ' ajax-id-'.$ajaxid;
+	  $r = ' data-url="'.self().'"';
+	}
+	return "<div class='ajaxbloc env-$c'$r>\n$emboite</div><!-- ajaxbloc -->\n";
 }
 
 // la procedure inverse de encoder_contexte_ajax()
diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php
index 28fe29f888..62b544e348 100644
--- a/ecrire/inc/utils.php
+++ b/ecrire/inc/utils.php
@@ -1817,10 +1817,10 @@ function recuperer_fond($fond, $contexte=array(), $options = array(), $connect='
 			$a = array('fichier'=>$fond);
 			erreur_squelette(_T('info_erreur_squelette2', $a), $c);
 		}
-					 
-		if (isset($options['ajax'])AND $options['ajax']){
+
+		if (isset($options['ajax']) AND $options['ajax']){
 			include_spip('inc/filtres');
-			$page['texte'] = encoder_contexte_ajax(array_merge($contexte,array('fond'=>$f)),'',$page['texte']);
+			$page['texte'] = encoder_contexte_ajax(array_merge($contexte,array('fond'=>$f)),'',$page['texte'], $options['ajax']);
 		}
 
 		$page = pipeline('recuperer_fond',array(
diff --git a/ecrire/public/balises.php b/ecrire/public/balises.php
index 491285b5b4..93e4c1ea56 100644
--- a/ecrire/public/balises.php
+++ b/ecrire/public/balises.php
@@ -954,7 +954,7 @@ function balise_INCLURE_dist($p) {
 
 		$_options = array();
 		if (isset($_contexte['ajax'])) {
-			$_options[] = "'ajax'=>true";
+			$_options[] = preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
 			unset($_contexte['ajax']);
 		}
 		if ($p->etoile) $_options[] = "'etoile'=>true";
@@ -1011,8 +1011,11 @@ function balise_MODELE_dist($p) {
 			$connect = $p->boucles[$p->id_boucle]->sql_serveur;
 
 		$_options = memoriser_contexte_compil($p);
-		$_options = "'compil'=>array($_options), 'trim'=>true"
-		  . (isset($_contexte['ajax'])?", 'ajax'=>true":'');
+		$_options = "'compil'=>array($_options), 'trim'=>true";
+	  if (isset($_contexte['ajax'])){
+		  $_options .= ", ".preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
+			unset($_contexte['ajax']);
+	  }
 
 		$page = sprintf(CODE_RECUPERER_FOND, $nom, 'array(' . join(',', $_contexte) .')', $_options, _q($connect));
 
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index c3d57a2807..dfdf28fa8d 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -156,8 +156,10 @@ function calculer_inclure($p, &$boucles, $id_boucle) {
 			$_contexte['doublons'] = "\\'doublons\\' => '.var_export(\$doublons,true).'";
 		}
 
-		if ($ajax = isset($_contexte['ajax']))
+		if ($ajax = isset($_contexte['ajax'])){
+			$ajax = preg_replace(",=>(.*)$,ims",'=> ($v=(\\1))?$v:true',$_contexte['ajax']);
 			unset($_contexte['ajax']);
+		}
 
 		$_contexte = join(",\n\t", $_contexte);
 	}
@@ -181,7 +183,7 @@ function calculer_inclure($p, &$boucles, $id_boucle) {
 	} else 	{
 		$_options[] = "\"compil\"=>array($compil)";
 		if ($ajax)
-			$_options[] = "\"ajax\"=>true";
+			$_options[] = $ajax;
 		$code = " ' . argumenter_squelette($code) . '"; 
 		$code = "echo " . sprintf(CODE_RECUPERER_FOND, $code, $contexte, implode(',',$_options), "_request(\"connect\")") . ';';
 	}
diff --git a/prive/javascript/ajaxCallback.js b/prive/javascript/ajaxCallback.js
index 0b3654d8d7..d3de644cbd 100644
--- a/prive/javascript/ajaxCallback.js
+++ b/prive/javascript/ajaxCallback.js
@@ -82,9 +82,9 @@ jQuery.fn.positionner = function(force) {
 	var h = jQuery(window).height();
 	var scroll=0;
 
-	if (force || offset['top'] - 5 <= scrolltop)
+	if (force || (offset && offset['top'] - 5 <= scrolltop))
 		scroll = offset['top'] - 5;
-	else if (offset['top'] + hauteur - h + 5 > scrolltop)
+	else if (offset && offset['top'] + hauteur - h + 5 > scrolltop)
 		scroll = Math.min(offset['top'] - 5, offset['top'] + hauteur - h + 15);
 	if (scroll)
 		jQuery('html,body')
@@ -224,10 +224,12 @@ jQuery.fn.ajaxbloc = function() {
 	  jQuery('div.ajaxbloc',this).ajaxbloc(); // traiter les enfants d'abord
 		var blocfrag = jQuery(this);
 
-		var on_pagination = function(c) {
+		var on_pagination = function(c,u) {
 			jQuery(blocfrag)
 			.html(c)
 			.removeClass('loading');
+			if (typeof u != undefined)
+				jQuery(blocfrag).attr('data-url',u);
 			var a = jQuery('a:first',jQuery(blocfrag)).eq(0);
 			if (a.length
 			  && a.is('a[name=ajax_ancre]')
@@ -257,13 +259,44 @@ jQuery.fn.ajaxbloc = function() {
 		if (ajaxbloc_selecteur==undefined)
 			ajaxbloc_selecteur = '.pagination a,a.ajax';
 
-		jQuery(ajaxbloc_selecteur,this).not('.noajax').each(function(){
-			var url = this.href.split('#');
+	  var makeAjaxUrl = function(href){
+		  var url = href.split('#');
 			url[0] += (url[0].indexOf("?")>0 ? '&':'?')+'var_ajax=1&var_ajax_env='+encodeURIComponent(ajax_env);
 			if (url[1])
 				url[0] += "&var_ajax_ancre="+url[1];
-			if (jQuery(this).is('.preload') && !preloaded_urls[url[0]]) {
-				jQuery.ajax({"url":url[0],"success":function(r){preloaded_urls[url[0]]=r;}});
+		  return url[0];
+	  }
+
+	  var loadAjax = function(url, href, force){
+		  jQuery(blocfrag)
+		  .animeajax()
+		  .addClass('loading').positionner(false);
+		  if (preloaded_urls[url] && !force) {
+			  on_pagination(preloaded_urls[url],href);
+			  triggerAjaxLoad(document);
+		  } else {
+			  jQuery.ajax({
+				  url: url,
+				  success: function(c){
+					  on_pagination(c,href);
+					  preloaded_urls[url] = c;
+				  }
+			  });
+		  }
+	  }
+	  jQuery(this).not('.reloaded').bind('reload',function(){
+			var href = $(this).attr('data-url');
+		  if (href && typeof href != undefined){
+			  var url = makeAjaxUrl(href);
+			  loadAjax(url, href, true);
+		  }
+	  }).addClass('reloaded');
+
+		jQuery(ajaxbloc_selecteur,this).not('.noajax').each(function(){
+			var href = this.href;
+			var url = makeAjaxUrl(href);
+			if (jQuery(this).is('.preload') && !preloaded_urls[url]) {
+				jQuery.ajax({"url":url,"success":function(r){preloaded_urls[url]=r;}});
 			}
 			jQuery(this).click(function(){
 				if (!ajax_confirm) {
@@ -274,21 +307,7 @@ jQuery.fn.ajaxbloc = function() {
 					if ((d.getTime()-ajax_confirm_date)<=2)
 						return false;
 				}
-				jQuery(blocfrag)
-				.animeajax()
-				.addClass('loading').positionner(false);
-				if (preloaded_urls[url[0]]) {
-					on_pagination(preloaded_urls[url[0]]);
-					triggerAjaxLoad(document);
-				} else {
-					jQuery.ajax({
-						url: url[0],
-						success: function(c){
-							on_pagination(c);
-							preloaded_urls[url[0]] = c;
-						}
-					});
-				}
+				loadAjax(url, href, jQuery(this).is('.nocache'));
 				return false;
 			});
 		}).addClass('noajax'); // previent qu'on ajax pas deux fois le meme lien
@@ -318,6 +337,15 @@ jQuery.fn.ajaxbloc = function() {
   });
 };
 
+/**
+ * Recharger un bloc ajax pour le mettre a jour
+ * ajaxid est l'id passe en argument de INCLURE{ajax=ajaxid}
+ * @param string ajaxid
+ */
+function ajaxRefreshBloc(ajaxid){
+	jQuery('div.ajaxbloc.ajax-id-'+ajaxid).trigger('reload');
+}
+
 // Ajaxer les formulaires qui le demandent, au demarrage
 
 jQuery(function() {
-- 
GitLab