In de praktijk
Het principe is dat het toepassen van AJAX zich terugbetaalt, want het heeft een verborgen compexiteit:
Je hebt een deel van de pagina dat links naar dezelfde pagina bevat die uitsluitend veranderingen in dat deel van de pagina veroorzaken:
- je plaatst dat deel van de pagina in een apart skelet;
- je voorziet de betroffen links van een class ajax:
<a href='mijnlink' class='ajax'>...</a>
- je neemt het skelet op in de hoofdpagina met
<INCLURE{fond=mijnskelet}{ajax}{env}>
of#INCLURE{fond=mijnskelet}{ajax}{env}
.
En dat is alles!
Toch nog enkele specificaties:
- test je skelet eerst zonder de toevoeging
{ajax}
; - de toevoeging
{ajax}
moet altijd begeleid worden door{env}
om het risico van URL-injecties in de cache van SPIP te vermijden; - standaard bevatten
a
tags met een classpagination
ook de ajax functionaliteit; - het is mogelijk andere links te gebruiken door middel van jquery
var ajaxbloc_selecteur = 'a.eenandereclass';
- je moet er voor zorgen dat een
#INSERT_HEAD
in de heading van het skelet van de pagina is opgenomen en dat JavaScript is geactiveerd in de browser van de gebruiker.
In detail
Syntax voor het aanroepen:
-
<INCLURE{fond=mijnskelet}{ajax}{env}>
-
[(#INCLURE{fond=mijnskelet}{ajax}{env})]
Deze aanroep van het skelet mijnskelet
zorgt automatisch voor de toepassing van ajax bij alle gekozen links door de JavaScript variabele ajaxbloc_selecteur
.
Een <div ..></div>
blok wordt automatisch rond het betroffen deel van het skelet opgenomen voor het beheer van de ajax functionaliteit.
Dit wordt standaard opgeroepen door ’.pagination a,a.ajax’. Met andere woorden: in de skeletten moet staan:
- ofwel het standaard systeem van SPIP voor de indeling in pagina’s. Dit houdt dus in dat het baken
#PAGINATION
is opgenomen wat in een classpagination
resulteert. Bijvoorbeeld:<p>#PAGINATION</p>
- ofwel dat de hyperlinks een class
ajax
hebben (<a class="ajax" href=...>
).
Het aantreffen van ajax herstart automatisch de herberekening van uitsluitend het opgeroepen skelet door het terugzetten van zijn #ENV
met de toevoeging van de parameters in de URL van de link.
Tijdens het herladen van het deel verandert de opaciteit naar 50 % en krijgt het de class loading
wat een afwijkende styling mogelijk maakt.
Enkele interessante punten:
- De
ajax
links worden in de cache van de browser geplaatst wanneer er voor het eerst op wordt geklikt. Het blok wordt dus slechts eenmaal geladen, zelfs als de bezoeker meerdere keren op dezelfde link klikt. - Bepaalde links kunnen vooraf worden geladen door ze te voorzien van een aanvullende class
preload
.
Enkele voorbeelden
Gebruik van ajax links
Neem het skelet inc-links.html
.
Het wal worden opgeroepen in het omvattende skelet door
[(#INCLURE{fond=inc-links}{ajax}{env})]
En bevat
<BOUCLE_lijst(AUTEURS) >
<a class="ajax" href="[(#SELF|parametre_url{id_auteur,#ID_AUTEUR})]">
#NOM #ID_AUTEUR
</a>
</BOUCLE_lijst>
[(#ENV{id_auteur}|oui)
#ENV{id_auteur}
]
Indeling in meerdere pagina’s
Voor het indelen in meerdere pagina’s nemen we een voorbeeld uit squelettes-dist/sommaire.html
.
In een skelet inc-recent.html
zetten we een lus die recente artikelen weergeeft:
<B_articles_recents>
<div class="menu articles">
[(#ANCRE_PAGINATION)]
<h2><:derniers_articles:></h2>
<ul>
<BOUCLE_articles_recents(ARTICLES) {par date}{inverse} {pagination 5}>
<li class="hentry">
[(#LOGO_ARTICLE_RUBRIQUE|#URL_ARTICLE|image_reduire{150,100})]
<h3 class="entry-title"><a href="#URL_ARTICLE" rel="bookmark">#TITRE</a></h3>
<small><abbr class="published"[ title="(#DATE|date_iso)"]>[(#DATE|affdate_jourcourt)]</abbr>[, <:par_auteur:> (#LESAUTEURS)]</small>
[<div class="#EDIT{intro} introduction entry-content">(#INTRODUCTION)</div>]
</li>
</BOUCLE_articles_recents>
</ul>
[<p class="pagination">(#PAGINATION)</p>]
</div>
</B_articles_recents>
Het volstaat om in sommaire.html</cite> in de plaats van die lus het volgende op te nemen: <code><INCLURE{fond=inc-recent}{env}{ajax}>
.
Beperkingen en bijzondere gevallen
Dit hele mechanisme van automatisch toepassen van ajax berust op een hypothese: de ajax link mag niets anders aanpassen dan het blok waarin het is opgenomen, door de aangepaste versie op dezelfde plaats op te nemen. Toch is het mogelijk om door vanuit een blok een ander blok te "triggeren" door gebruik te maken van een hieronder omschreven reload techniek.
Het is belangrijk te realiseren dat de (her)berekening van het opgeroepen skelet uitsluitend mag gebeuren op basis van de parameters die via #ENV
opvraagbaar zijn.
Feitelijk gebeurt de herberekening van een ajax blok ook individueel, buiten het skelet dat het oproept. Uitsluitend de variabelen in #ENV
worden hersteld.
Zo is het dus niet mogelijk om te refereren aan globale PHP-variabelen: die worden niet hersteld bij het berekenen van een ajax blok.
Wil je toch persé globale PHP-variabelen gebruiken, dan moet je die bij de oproep opnemen in de #ENV
:
<INCLURE{fond=mijnskelet}{ajax}{env}{parameter=#EVAL{$GLOBALS['toto']}}>
Aanvullingen
SPIP3.0 levert ajax nieuws:
- De .ajax links beschadigen niet langer de navigatiegeschiedenis van browsers die de API HTML5 History ondersteunen (onder andere Firefox, Safari en Chrome). Dat wil zeggen dat wanneer een gebruiker op een ajax link klikt wat een gedeeltelijk herladen van de pagina veroorzaakt, de URL van deze update wordt opgeslagen in de browser en de bezoeker dus op "Vorige pagina" kan klikken om terug te gaan.
- Speciale "classes" op ajax links:
-
.nohistory
geeft aan dat deze link de navigatiehistorie niet mag beïnvloeden wanneer erop wordt geklikt; -
.preload
geeft SPIP aan dat de inhoud van de link moet worden geladen op het moment dat de pagina wordt ingelezen. Het resultaat is dat een klik op de link tot onmiddellijk resultaat leidt; -
.nocache
geeft SPIP aan dat de inhoud van de ajax link niet in de cache mag worden gezet. Dus meerdere kliks op dezelfde link betekenen steeds het opnieuw inladen van het blok vanaf de server (terwijl dit normaal slecht bij de eerste keer gebeurt).
- de #BOUTON_ACTION
bakens kunnen het herladen van een blok dat ajax bevat activeren.
- Reload van een ajax blok: De .ajax links zorgen standaard voor het herladen van het blok waarin ze zijn opgenomen, maar het is soms nodig om ook een ander blok op de pagina opnieuw te laden.
Daarvoor is het mogelijk om de ajax blokken te benoemen op het moment van hun insluiting: <INCLURE{fond=...,ajax=bloknaam} />
. Het aldus genoemde ajax blok kan vervolgens worden herladen via de oproep ajaxReload('nomdubloc')
.
Aan de lijst van opties kan een tweede argument worden toegevoegd:
-
callback
: deze functie kan worden aangeroepen na het laden van een ajax blok
-
args
: een lijst van argumenten die worden doorgegeven aan de URL op het moment van laden van het blok (dit laat toe de #ENV van het aangepaste blok te veranderen);
-
history
: wat aangeeft of de browsergeschiedenis moet worden aangepast (normaal niet). Voorbeeld:ajaxReload('bloknaam', { callback:function(){alert('einde');}, args:{id_article:3}, history:false });
ajaxReload kan ook worden toegepast op een jQuery selector in welk geval hij het herladen forceert van het kleinste ajax blok dat het betroffen element bevat. Het kan dus slechts één van de mogelijke argumenten bevatten (de tabel van opties):
$('#contenu').ajaxReload({args:{id_article:3}})
Een stukje geschiedenis
In SPIP 1.9.2 werd een eerste (niet gedocumenteerde) poging tot ajax gedaan door dit op de inhoud van een lus toe te passen zonder het skelet in twee aparte delen op te splitsen.
Het bleek niet te voldoen, want:
- de entiteit lus is niet noodzakelijk pertinent -> hij kan bestaan uit een lijst warvan de
tags over meerdere lussen zijn opgebouwd
- het betekent dat de gehele pagina opnieuw moet worden berekend, omdat de begincontext niet bekend is -> de server moet dus nagenoeg de gehele pagina opnieuw berekenen omwille van een klein deel, dus waar zit de winst...
De nieuwe oplossing heeft als voordeel dat:
- de ontwerper van het skelet het concept voor ogen heeft, de juiste splitsing maakt en die in een op te roepen skelet plaatst;
- de ontwerper dus bepaald welk onafhankelijk deel separaat kan worden herberekend;
- de ontwerper de context defineert door bepaalde extra parameters door te geven;
- de server uitsluitend de relevante data herberekend.