[spip-dev] Noisettes AJAX

Avec mise en cache js des morceaux chargés, comme oublie de le préciser le commentaire de commit,
et possibilité de precharger en ajoutant la class 'preload' sur les <a>
Le fond qui implemente l'ajax a ete mis dans un sous dossier par sécurité car il permet d'appeler n'importe quel autre fond,
et ne doit donc etre accessible que par inclusion, et non par ?page=xxx dans l'url

Cédric

Author: cedric@yterium.com
New Revision: 11289

Log:
Noisettes AJAX :
<INCLURE{fond=fond/ajax}{fond_ajax=mon_fond}{id_truc=xx}..>
inclut la noisette en ajaxant automatiquement tous les liens cibles par la variable js ajaxbloc_selecteur
par defaut celle ci cible les '.pagination a,a.ajax'
le hit ajax relance automatiquement le calcul de la noisette en restaurant son #ENV, et en y ajoutant les parametre en url
Attention, la noisette est inclue dans un div !!
le bloc recharge passe en opacite 50% et a la class loading pendant le chargement

homogeneisation avec les formulaires dynamiques ajax

Modified:
   spip/dist/formulaires/formulaire_.html
   spip/dist/javascript/ajaxCallback.js
   spip/dist/javascript/layer.js
   spip/ecrire/public/assembler.php

Details: http://trac.rezo.net/trac/spip/changeset/11289

cedric.morin@yterium.com a écrit :

Le fond qui implemente l'ajax a ete mis dans un sous dossier par sécurité

Et peut-on le voir ce fond ? ^^
Parce que "Aucun squelette 'fond/ajax' n'est disponible..."
MM.

Matthieu Marcillaud a écrit :

cedric.morin@yterium.com a écrit :

Le fond qui implemente l'ajax a ete mis dans un sous dossier par sécurité

Et peut-on le voir ce fond ? ^^
Parce que "Aucun squelette 'fond/ajax' n'est disponible..."
MM.

ça va que j'ai bon fond, je me vexe pas ... :stuck_out_tongue:
c'est dans [11292], désolé pour l'oubli
Cédric

cedric.morin@yterium.com a écrit :

Avec mise en cache js des morceaux chargés, comme oublie de le préciser le commentaire de commit,
et possibilité de precharger en ajoutant la class 'preload' sur les <a>
Le fond qui implemente l'ajax a ete mis dans un sous dossier par sécurité car il permet d'appeler n'importe quel autre fond,
et ne doit donc etre accessible que par inclusion, et non par ?page=xxx dans l'url

Belle fonctionnalité. Bon, on est obligé de passer par une noisette, mais va y avoir pas mal d'applications simplifiées grâce à ça.

Pat

cedric.morin@yterium.com a écrit :

Avec mise en cache js des morceaux chargés, comme oublie de le préciser
le commentaire de commit,
et possibilité de precharger en ajoutant la class 'preload' sur les <a>
Le fond qui implemente l'ajax a ete mis dans un sous dossier par
sécurité car il permet d'appeler n'importe quel autre fond,
et ne doit donc etre accessible que par inclusion, et non par ?page=xxx
dans l'url

Belle fonctionnalité. Bon, on est obligé de passer par une noisette,

oui mais avec le recul c'est le meilleur choix.
les defunts fragments etaient une tentative de gérer la fonctionnalité sans toucher au squelette, mais cela necessitait plein de calculs pour ressortir un bout de page et etait peu performant.

mais va y avoir pas mal d'applications simplifiées grâce à ça.

c'est le but.
Cédric

Cédric MORIN a écrit :

* JLuc tapuscrivait, le 13/03/2008 08:59:

Cédric MORIN a écrit :

mais va y avoir pas mal d'applications simplifiées grâce à ça.

c'est le but.

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)

J'avais une noisette :
[(#INCLURE{fond=inc_galerie}{id_article}{env})]
que j'ai transformée en :
[(#INCLURE{fond=inc_galerie}{ajax}{id_article}{env})]

Et du coup, j'ai cette erreur :
Warning: Unexpected character in input: '\' (ASCII=92) state=1 in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 153

Parse error: syntax error, unexpected T_STRING, expecting ')' in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 154

Du coup, j'ai relu la doc des commits pour finir par ecrire :
<INCLURE{fond=inc_galerie}{ajax}{id_article}{env}>
- qui passe sans erreur
- mais au clic sur les images de la galerie, j'ai un rechargement complet de la page, pas un rechargement de la noisette

RealET a écrit :

* JLuc tapuscrivait, le 13/03/2008 08:59:
  

Cédric MORIN a écrit :
    

mais va y avoir pas mal d'applications simplifiées grâce à ça.
        

c'est le but.
      

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
    

J'avais une noisette :
[(#INCLURE{fond=inc_galerie}{id_article}{env})]
que j'ai transformée en :
[(#INCLURE{fond=inc_galerie}{ajax}{id_article}{env})]

Et du coup, j'ai cette erreur :
Warning: Unexpected character in input: '\' (ASCII=92) state=1 in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 153
  

ah ca devrait passer pourtant, il faut que je regarde

Parse error: syntax error, unexpected T_STRING, expecting ')' in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 154

Du coup, j'ai relu la doc des commits pour finir par ecrire :
<INCLURE{fond=inc_galerie}{ajax}{id_article}{env}>
- qui passe sans erreur
- mais au clic sur les images de la galerie, j'ai un rechargement complet de la page, pas un rechargement de la noisette
  

les liens ajaxes sont cibles par '.pagination a' et 'a.ajax'
il faut donc que tu marques les liens ajaxables, car spip ne peut pas deviner ceux qui ne provoquent des changements dans la noisettes uniquement et ceux qui provoquent d'autres changements sur la page.
Cédric

JLuc a écrit :

Cédric MORIN a écrit :
  

mais va y avoir pas mal d'applications simplifiées grâce à ça.
      

c'est le but.
    
et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
  

Le principe est de rendre ajax abordable car la complexité est cachée :

J'ai un morceau de page qui contient des liens vers cette meme page et ne provoquent de changement que dans le morceau de page considére :
1/ je mets ce morceau de page dans une noisette (un squelette)
2/ je marque les liens concernés par la class ajax :
<a href='monlien' class='ajax'>...</a>
3/ j'inclus ma noisette dans la page principale avec
<INCLURE{fond=manoisette}{ajax}{mes parametres ...}>
#INCLURE devrait marcher aussi mais semble avoir un bug a cette heure

Et c'est tout
NB1 par defaut, les liens a contenus dans une classe pagination sont aussi ajaxés
NB2 il est possible de cibler d'autres liens en spécifiant le selecteur jquery :
var ajaxbloc_selecteur = 'a.uneautreclasse';

Cédric

cedric.morin@yterium.com a écrit :

JLuc a écrit :

Cédric MORIN a écrit :
  

mais va y avoir pas mal d'applications simplifiées grâce à ça.
      

c'est le but.
    

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
  

Le principe est de rendre ajax abordable car la complexité est cachée :

Merci pour ce beau cadeau,
ç'a l'air super !

J'imagine qu'il faut limiter l'usage à des noisettes
de manière à garder un référencement global
et un historique possible ?

(la perte de l'historique, c'est ce qui fait oublier à l'écureuil
ses réserves de noisettes ! :wink:
JL

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 10:46:

RealET a écrit :

* JLuc tapuscrivait, le 13/03/2008 08:59:
  

Cédric MORIN a écrit :
    

mais va y avoir pas mal d'applications simplifiées grâce à ça.
        

c'est le but.
      

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
    

J'avais une noisette :
[(#INCLURE{fond=inc_galerie}{id_article}{env})]
que j'ai transformée en :
[(#INCLURE{fond=inc_galerie}{ajax}{id_article}{env})]

Et du coup, j'ai cette erreur :
Warning: Unexpected character in input: '\' (ASCII=92) state=1 in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 153
  

ah ca devrait passer pourtant, il faut que je regarde

Parse error: syntax error, unexpected T_STRING, expecting ')' in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 154

Du coup, j'ai relu la doc des commits pour finir par ecrire :
<INCLURE{fond=inc_galerie}{ajax}{id_article}{env}>
- qui passe sans erreur
- mais au clic sur les images de la galerie, j'ai un rechargement complet de la page, pas un rechargement de la noisette
  

les liens ajaxes sont cibles par '.pagination a' et 'a.ajax'
il faut donc que tu marques les liens ajaxables, car spip ne peut pas deviner ceux qui ne provoquent des changements dans la noisettes uniquement et ceux qui provoquent d'autres changements sur la page.
Cédric

C'est bon, ça marche !
Par contre, le code xhtML n'est pas valide :
<script type='text/javascript'>
var ajaxbloc_id094885e0= function() {if (window.jQuery) jQuery('div#id094885e0').prepend('<div><input type=\'hidden\' name=\'var_ajax_env\' value=\'YTo3OntzOjQ6InBhZ2UiO3M6OToidHlwZV91cmxzIjtzOjExOiJzZXRfb3B0aW9ucyI7czo4OiJhdmFuY2VlcyI7czoxMDoiZGF0ZV9yZWRhYyI7czoxOToiMjAwOC0wMy0xMyAxMTozMzowOSI7czo0OiJkYXRlIjtzOjE5OiIyMDA4LTAzLTEzIDExOjMzOjA5IjtzOjEwOiJpZF9hcnRpY2xlIjtzOjM6IjE3OSI7czo0OiJsYW5nIjtzOjI6ImZyIjtzOjk6ImZvbmRfYWpheCI7czoxMToiaW5jX2dhbGVyaWUiO30=\' />'
+'<input type=\'hidden\' name=\'var_ajax_cle\' value=\'ab567816b3fa488a039194558970df96\' /></div>').ajaxbloc();}
jQuery('document').ready(ajaxbloc_id094885e0);
onAjaxLoad(ajaxbloc_id094885e0);

</script>

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).

ajax_cdata.patch (760 Bytes)

* RealET tapuscrivait, le 13/03/2008 11:39:

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).

Autre détail : le bloc de script ajax est inséré même si la noisette est vide...

RealET a écrit :

* RealET tapuscrivait, le 13/03/2008 11:39:
  

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).
    

Autre détail : le bloc de script ajax est inséré même si la noisette est vide...
  

Oui ça n'est pas evitable sur <INCLURE> car le fond/ajax doit rester en <INCLURE> sous peine de perdre des morceaux dynamiques.
On pourrait en revanche l'eviter sur #INCLURE en renvoyant du vide si la noisette est vide, pour ne pas perdre la propriete des tests
Cédric

RealET a écrit :

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 10:46:

RealET a écrit :

* JLuc tapuscrivait, le 13/03/2008 08:59:

Cédric MORIN a écrit :
   

mais va y avoir pas mal d'applications simplifiées grâce à ça.
        

c'est le but.
      

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
    

J'avais une noisette :
[(#INCLURE{fond=inc_galerie}{id_article}{env})]
que j'ai transformée en :
[(#INCLURE{fond=inc_galerie}{ajax}{id_article}{env})]

Et du coup, j'ai cette erreur :
Warning: Unexpected character in input: '\' (ASCII=92) state=1 in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 153
  

ah ca devrait passer pourtant, il faut que je regarde

Parse error: syntax error, unexpected T_STRING, expecting ')' in D:\wwwrootDev\_mutualisation\spipsvn\ecrire\public\composer.php(65) : eval()'d code on line 154

Du coup, j'ai relu la doc des commits pour finir par ecrire :
<INCLURE{fond=inc_galerie}{ajax}{id_article}{env}>
- qui passe sans erreur
- mais au clic sur les images de la galerie, j'ai un rechargement complet de la page, pas un rechargement de la noisette
  

les liens ajaxes sont cibles par '.pagination a' et 'a.ajax'
il faut donc que tu marques les liens ajaxables, car spip ne peut pas deviner ceux qui ne provoquent des changements dans la noisettes uniquement et ceux qui provoquent d'autres changements sur la page.
Cédric

C'est bon, ça marche !
Par contre, le code xhtML n'est pas valide :
<script type='text/javascript'>
var ajaxbloc_id094885e0= function() {if (window.jQuery) jQuery('div#id094885e0').prepend('<div><input type=\'hidden\' name=\'var_ajax_env\' value=\'YTo3OntzOjQ6InBhZ2UiO3M6OToidHlwZV91cmxzIjtzOjExOiJzZXRfb3B0aW9ucyI7czo4OiJhdmFuY2VlcyI7czoxMDoiZGF0ZV9yZWRhYyI7czoxOToiMjAwOC0wMy0xMyAxMTozMzowOSI7czo0OiJkYXRlIjtzOjE5OiIyMDA4LTAzLTEzIDExOjMzOjA5IjtzOjEwOiJpZF9hcnRpY2xlIjtzOjM6IjE3OSI7czo0OiJsYW5nIjtzOjI6ImZyIjtzOjk6ImZvbmRfYWpheCI7czoxMToiaW5jX2dhbGVyaWUiO30=\' />'
+'<input type=\'hidden\' name=\'var_ajax_cle\' value=\'ab567816b3fa488a039194558970df96\' /></div>').ajaxbloc();}
jQuery('document').ready(ajaxbloc_id094885e0);
onAjaxLoad(ajaxbloc_id094885e0);

</script>

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).

C'est dans [11298] avec la correction de #INCLURE, qui garde renvoie maintenant du vide si la noisette est vide
Cédric

JLuc a écrit :

cedric.morin@yterium.com a écrit :
  

JLuc a écrit :
    

Cédric MORIN a écrit :
  

mais va y avoir pas mal d'applications simplifiées grâce à ça.
      

c'est le but.
    

et yaura une application pionnière de démo
ou un mode d'emploi pour les non-ajaxiens ?
(parceque ajax, faut s'y faire !)
  

Le principe est de rendre ajax abordable car la complexité est cachée :
    
Merci pour ce beau cadeau,
ç'a l'air super !

J'imagine qu'il faut limiter l'usage à des noisettes
de manière à garder un référencement global
et un historique possible ?
  

si tu l'applique à toute la page, ça perd son intéret :p, le principe et l'interet de l'ajax étant de recharger un morceau de page.
la question sous jacente est de savoir commen découper des morceaux de page ?
la 1.9.2 avait entammé une tentative (non documentée car insatisfaisante) de considérer la boucle comme un morceau et de permettre une ajaxisation du contenu d'une boucle, sans avoir à faire de découpe du squelette.

Cela s'est avéré insatisfaisant car :
- l'entité boucle n'est pas forcément pertinente -> exemple d'une liste dont les li sont générés par plusieurs boucles
- cela obligeait à recalculer toute la page pour arriver à la boucle car on ne pouvait pas savoir son contexte d'entrée -> le serveur faisait presque un calcul de page complet pour en extraire le morceau, d'ou un gain faible en rapidité

La nouvelle solution à l'avantage :
- d'obliger le concepteur du squelette à faire la découpe du morceau qui sera rafraichi en le mettant dans une noisette
- de lui permettre de décider exactement ce qui forme un bloc fonctionnel indépendant du reste de la page
- d'expliciter son environnement en le passant en parametre dans le inclure
- de permettre au serveur de ne recalculer effectivement QUE ce morceau de page

Il y a toutefois une réserve, et un cas qui ne marchera pas :
si la noisette contient du php qui fait référence à des globales affectées dans un autre squelette.
on peut utiliser du php dans la noisette, mais celui ci ne doit référencer que des #ENV{...} car les globales ne seront pas connues au moment du calcul du bloc seul sur un rafraichissement ajax
Dans le cas d'utilisation de globales php, il faut faire
<INCLURE{fond=manoisette}{ajax}{parametre=#EVAL{$toto}}>
afin de réinjecter la globale dans le #ENV de la noisette, qui sera restauré au moment du calcul ajax.

Voila de quoi écrire un bout de doc sur spip.net non ?
Cédric

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 12:18:

RealET a écrit :

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).

C'est dans [11298] avec la correction de #INCLURE, qui garde renvoie maintenant du vide si la noisette est vide
Cédric

Super !
Utilisé par Connexion · GitLab

Merci :wink:

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 10:46:

les liens ajaxes sont cibles par '.pagination a' et 'a.ajax'
il faut donc que tu marques les liens ajaxables, car spip ne peut pas deviner ceux qui ne provoquent des changements dans la noisettes uniquement et ceux qui provoquent d'autres changements sur la page.

Et dans le cas d'un formulaire ?
Par exemple : Agenda - EcoloTech Philosophie - Écologie - Technologie
Si je clique sur OK, la page est ré affichée, mais cette fois-ci, avec l'année entière.

RealET a écrit :

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 10:46:
  

les liens ajaxes sont cibles par '.pagination a' et 'a.ajax'
il faut donc que tu marques les liens ajaxables, car spip ne peut pas deviner ceux qui ne provoquent des changements dans la noisettes uniquement et ceux qui provoquent d'autres changements sur la page.
    

Et dans le cas d'un formulaire ?
Par exemple : Agenda - EcoloTech Philosophie - Écologie - Technologie
Si je clique sur OK, la page est ré affichée, mais cette fois-ci, avec l'année entière.

Pour les formulaires, il faut utiliser les balises dynamiques nouvelle API qui gerent elles aussi l'ajax.

Voici un début de doc :

1/ créér le squelette de son formulaire dans formulaires/, par exemple dans ton cas
annee.html
qui contient ton formulaire, avec la balise #ACTION_FORMULAIRE
un formulaire minimal serait :

[(#ENV**{editable}|?{' '})
<form action='#SELF' method='post'>
#ACTION_FORMULAIRE{#SELF}
<label>annee</label>
<input type='text' name='annee' value='#ENV{annee}' />
<input type='submit' name='ok' value='ok' />
</form>
]
<INCLURE{fond=agenda}{annee=#ENV{annee}}{ajax}>

avec ça tu peux deja afficher ton formulaire en faisant
#FORMULAIRE_ANNEE

2/ implementer le chargement des valeurs par defaut
dans formulaires/annee/charger.php :
function formulaires_annee_charger_dist(){
$valeurs = array('annee'=>date('Y'));
return $valeurs; // retourner simplement les valeurs
//return array(true,$valeurs); // forcer l'etat editable du formulaire et retourner les valeurs
//return array(false,$valeurs); // forcer l'etat non editable du formulaire et retourner les valeurs
}

spip saura alors que ton formulaire a un champ annee, et remplacera sa valeur par _request('annee') si elle est dispo
ton formulaire aura ses valeurs par defaut

3/ implementer une verification de format
dans formulaires/annee/valider.php :
function formulaires_annee_valider_dist(){
$erreurs = array();
if (!_request('annee')) $erreurs['annee'] = 'Ce champ est obligatoire';
if (_request('annee')<1900 OR _request('annee')>2100) $erreurs['annee'] = 'Soyez raisonables...';
if (count($erreurs)) $erreurs['message_erreur'] = 'Veuillez recommencer !';
return $erreurs; // si c'est vide, modifier sera appele, sinon le formulaire sera resoumis
}

et ajouter dans le formulaire :
en haut le message d'erreur general :
[<p class='formulaire_erreur'>(#ENV*{message_erreur})</p>]
sous le input, le message d'erreur lie a ce champ :
[<span class='erreur'>(#ENV**{erreurs}|table_valeur{annee})</span>]

4/ implémenter une action en bdd :
dans formulaires/annee/modifier.php :
function formulaires_annee_modifier_dist(){
// rien a faire en bdd pour ce formulaire
$message = 'merci';
//return $message; // retourner simplement un message, le formulaire ne sera pas resoumis
return array(true,$valeurs); // forcer l'etat editable du formulaire et retourner le message
}

et ajouter dans le formulaire :
[<p class="formulaire_message">(#ENV*{message_ok})</p>]

Il est possible de passer des arguments à la balise
ex :
#FORMULAIRE_ANNEE{#DATE}
il seront alors retrouvés en entrée des fonction charger/valider/modifier

Avec une telle implémentation, les formulaires dynamiques sont automatiquement ajaxes.
Il est possible de desactiver l'ajax en ajoutant la class noajax sur la balise form :
<form action='#SELF' method='post' class='noajax'>
par exemple parce que l'on veut rediriger l'internaute apres soumission : il suffit de faire un redirect dans modifier() qui est appelé avant tout affichage.

Cerise sur le gateau, tu peux ajouter ton formulaire dynamique ajax dans le texte de ton article :
<formulaire|annee> qui est equivalent à #FORMULAIRE_ANNEE dans un squelette
et passer aussi un argument :
<formulaire|annee|date=13/03/2008>
qui sera recupere dans les fonctions charger/valider/modifier

Si tu veux ecrire un article avec ça et le code testé et documenté, n'hésite pas :stuck_out_tongue:

Cédric

RealET a écrit :

* cedric.morin@yterium.com tapuscrivait, le 13/03/2008 12:18:

RealET a écrit :

Est-ce que tu pourrais mettre le tout dans un CDATA ?
Voici le patch (vérifié en local).

C'est dans [11298] avec la correction de #INCLURE, qui garde renvoie maintenant du vide si la noisette est vide
Cédric

Hum... j'ai toujours un chose qui n'est pas si vide que ça visiblement :
J'appelle l'inclure comme montré après. Si j'enleve {ajax} rien n'est affiché (je n'ai pas de site) mais si je le mets, il m'affiche le contenu avant/après le [avant (#INCLURE) après]

En fait, c'est le |trim qui ne semble pas pris en compte, si je l'enlève, les deux syntaxes (avec et sans {ajax}) affichent toutes deux le avant / après car j'ai des espaces qui sont créés dans la noisette appelée (d'où le |trim)

MM.

[
  <h1 class="blue"><:nouveautes_web:></h1>
  (#INCLURE{fond=noisettes/site/inc/dernieres_syndications_colonne}{ajax}{env}
    >trim
  )
]

Le probleme est que le trim s'applique sur la noisette enveloppée par les marmottes et du coup meme si y a de l'air dans le papier, il y a quand meme le papier...
on pourrait faire un trim sur la noisette avant de mettre le papier eventuel, mais du coup une noisette qui renvoie rien ou un espace ne marcherait plus
Su tu veux ne rien avoir, il faut que la noisette ne renvoie rien...