Souhait
Nous souhaitons afficher tous les événements (publiés) du site sous forme calendaire, en proposant d’abord un affichage par mois, avec possibilité de basculer en affichage par semaine ou par jour.
Pré-requis
- SPIP 3.2.x, en ayant conservé l’organiseur dans plugins-dist.
- Plugin Agenda 3.6.11 minimum.
- Compréhension de la mécanique des squelettes de SPIP.
- Quelques évènements à afficher.
Vous n’avez pas besoin d’installer la librairire FullCalendar : elle est livrée avec SPIP.
Principe de base
Pour afficher notre agenda nous allons :
- créer un squelette agenda.html, avec un
div
dont l’attributid
estagenda
. - appeler dans le squelette le script
fullcalendar
et ses feuilles de styles. - utiliser ce script pour afficher l’agenda dans dans la
div#agenda
. - créer un squelette
agenda.json.html
fournissant au script les données à afficher dans l’agenda.
Fichiers manipulés
Dans cet article nous manipulons deux fichiers squelettes :
-
agenda.html
(qui contient le code nécessaire à l’affichage du calendrier). -
agenda.json.html
(qui nous permet de générer une liste d’événements compatible avec le script fullcalendar).
Si l’un de ces squelette existe déjà, je vous invite à utiliser le mécanisme de surcharge de SPIP.
Création du squelette
Il nous faut créer un squelette agenda.html
complet (à savoir une page SPIP classique avec les balises <head><body>
etc), dans lequel nous mettons un div
dont l’attribut id
est agenda
à l’endroit où nous souhaitons que l’agenda s’affiche.
Au dessus de ce div, nous allons appeler :
- plusieurs scripts javascript, dans leurs versions compressées :
moment-with-locales
, nécessaire au fonctionnement defullcalendar
[1] ;fullcalendar
, qui gère l’affichage proprement dit du calendrierlocale-all
, qui contient les traductions des informations de calendriers pourfullcalendar
;
- les styles CSS associés à
fullcalendar
.
Pour ce faire, nous utilisons la balise #CHEMIN
:
<link rel='stylesheet' type='text/css' href='#CHEMIN{lib/fullcalendar/fullcalendar.min.css}' />
<script type='text/javascript' src='#CHEMIN{lib/moment/moment-with-locales.min.js}'></script>
<script type='text/javascript' src='#CHEMIN{lib/fullcalendar/fullcalendar.min.js}'></script>
<script type='text/javascript' src='#CHEMIN{lib/fullcalendar/locale-all.js}'></script>
<div id="agenda">
</div>
Appel à l’agenda
Nous allons maintenant ajouter les fonctions javascript qui permettent d’afficher l’agenda. Pour ce faire, nous allons mettre au dessus du div (cela pourrait être dedans ou en dessous, cela importe peu) le code suivant, que je vais commenter :
<script type="text/javascript">/*<![CDATA[*/
jQuery(function($) {
$('#agenda').fullCalendar({
locale : '[(#LANG|strtolower)]',
editable: false,
navLinks: true,
eventLimit: true,
events: "[(#URL_PAGE{agenda.json})]",
header: {
left: [(#LANG_DIR|=={ltr}|?{"'prevYear,prev,next,nextYear,today'","'listMonth,month,agendaWeek,agendaDay'"})],
center: 'title',
right: [(#LANG_DIR|=={ltr}|?{"'agendaDay,agendaWeek,month,listMonth'","'today nextYear,next,prev,prevYear'"})]
},
fixedWeekCount: false,
allDayHtml:'<:organiseur:cal_jour_entier|textebrut:>',
loading: function(bool) {
if (bool) $('#calendrier-loading').show();
else $('#calendrier-loading').hide();
},
})
});
/*]]>*/</script>
- l. 2
jQuery(function($)
signifie que le navigateur va exécuter la fonction dans les accolades qui suivent. - l. 3
$('#agenda').fullCalendar
signifie que nous allons demander à javascript de modifier lediv
dont l’id est égale àagenda
pour y mettre à la place… l’agenda. - Le code entre parenthèse puis accolade correspond aux options passées à l’agenda (l. 4-21) :
- l. 4 : on passe le nom de la langue courante comme paramètre de langue à
fullcalendar
, ceci permet notamment d’avoir les bons noms de jours et de mois, et de déterminer automatiquement le premier jour de la semaine [2]. - l. 5 : on ne peut pas éditer les évènements depuis l’agenda.
- l. 6 : rend cliquable les numéros de jours / les noms de jours pour basculer sur une vue par jour.
- l. 7 : limite le nombre d’évènements affichés par jour à la hauteur de la cellule. Les évènements supplémentaires seront affichables via un clique supplémentaire.
- l. 8 : on récuperera la liste des évènements via un squelette
agenda.json.html
, nous détaillerons ce squelette dans la partie suivante - l. 9-13 : qu’affiche-t-on dans l’entête de l’agenda ? :
- l. 10 : à gauche, on met les boutons de navigation par mois/semaines/jours (selon le type de calendrier) et par années (dans tout les cas).
- l. 11 : au centre, on affiche le titre de l’agenda, correspondant à la période affichée (par ex. « Août 2012 »).
- l. 12 : à droite, on affiche la bascule vers l’agenda en mode mois, semaine ou jour.
- À noter l. 10 et l. 12 le test sur la direction de la langue, qui permet d’inverser les boutons de gauche et de droite si l’on est dans écriture de droite à gauche.
- l. 14 : afficher 4, 5 ou 6 semaines par mois en fonction du mois, et non pas systématiquement 6.
- l. 15 : changer la chaîne de langue pour « toute la journée », chaîne de langue définie par SPIP.
- l. 16-19 : pendant le temps du chargement, afficher l’élément HTML dont l’id est
calendrier-loading
. Nous reviendrons dessus plus bas.
- l. 4 : on passe le nom de la langue courante comme paramètre de langue à
D’autres options sont bien sûr possibles : on se reportera à la documentation de FullCalendar, malheureusement en anglais uniquement.
Sélection des évènements à afficher
Pour pouvoir afficher les évènements, il va falloir nous fabriquer un squelette agenda.json.html
(cf. l. 7) qui retournera les évènements qui nous intéreressent sous forme de données JSON.
La page spip.php?page=agenda.json
sera automatiquement appelée par FullCalendar, qui lui passera deux arguments, variant selon la période demandée :
-
start
, correspondant à l’ISO-8601 de la date de début. -
end
, correspondant à ISO-8601 de la date de fin [3].
Dans le squelette agenda.json.html
correspondant à cette page, nous pourrons récuperer ces informations via : #ENV{start}
et #ENV{end}
(voir mon article sur la balise #ENV
). On pourrait éventuellement passer d’autres arguments, en appliquant le filtre |parametre_url
sur #URL_PAGE{agenda.json}
.
Voilà un squelette agenda.json.html
basique :
#HTTP_HEADER{Content-Type: application/json; charset=#CHARSET}
#SET{start,#ENV{start}|strtotime}
#SET{end,#ENV{end}|strtotime}
[<BOUCLE_evenements(EVENEMENTS){', '}{par date_debut}
{!evenement_passe #ENV{start}}{!evenement_a_venir #ENV{end}}
>
[(#ARRAY{
id,#ID_EVENEMENT,
title,[(#TITRE|html2unicode|unicode2charset)],
allDay,[(#HORAIRE|=={non}|?{#EVAL{true},#EVAL{false}})],
start,#DATE_DEBUT,
end,#DATE_FIN,
url,#URL_ARTICLE,
description,[(#DESCRIPTIF|html2unicode|unicode2charset)]
}|json_encode)]
</BOUCLE_evenements>]
Je commente rapidement ce squelette :
- l. 1. On demande à SPIP de :
- Ne pas insérer de boutons d’administration.
- Dire au navigateur que la page retournée est du json, et fournir le charset.
- l. 2-3 : nous convertissons les dates de début et de fin de l’ISO-8601 au timestamp, et nous stockons dans les variables
start
etend
, homonymes aux variables d’environnement reçues. - l. 4 et l .18, les crochets servent à indiquer que nous retournons plusieurs objets JSON, chacun correspondant à un évènements.
- l. 4 nous bouclons sur les évènements. Entre chaque élément de la boucle, nous affichons une virgule (
{", "}
). Nous trions par date de début : ceci servira plus loin lors de l’affichage des données sans Javascript. - l. 5-7 pour sélectionner les évènements, nous utilisons les critères
evenement_passe
etevenement_a_venir
. Les options de ces critère nous permette de sélectionner tous les évènements à cheval sur la période considérée :-
{!evenement_passe #ENV{start}}
: pour sélectionner les événements en cours ou pas encore commencés à la date#ENV{start}
. -
{!evenement_a_venir #ENV{end}}
: pour sélectionner les événements finis ou en cours à la date #ENVend. - la combinaison de ces 2 critères va sélectionner les évènements entre les 2 dates [4]
-
- l. 9-17 : nous remplissons un tableau SPIP via
#ARRAY
, puis nous le transformons en objet JSON, via le filtre|json_encode
. Ce tableau comprend les entrées suivantes :-
id
: identifiant unique pour FullCalendar. Ca tombe bien, SPIP attribut un identifiant à chaque évenement :#ID_EVENEMENT
-
title
: le titre. On transforme les entité HTML en caractère unicode (|html2unicode
) puis on s’assure de proposer des données avec le bon charset (|unicode2charset
). -
allDay
: on précise si l’évènement dure toute la journée. Utiliséepour l’affichage par jour. Pour préciser cela, on s’appuie sur le champ#HORAIRE
qui contient justement cette information. On utilise#EVAL
pour indiquer qu’on insére une valeur booléenne et non pas textuelle. -
start
: date de début. On garde le format SQL. -
end
: date de fin. On garde le format SQL. -
url
: lien. Pour le coup, on renvoie vers l’article. -
description
: description de l’évènement. Là encore, on converti en Unicode, puis dans le charset correct.
-
À noter que l’on pourrait définir d’autres données pour chaque évènement : on se référera à la documentation de l’objet Event de FullCalendar. Par exemple, on pourrait indiquer des classes HTML en fonction de la rubrique.
Il vous faut également créer un fichier agenda.json_fonctions.php
contenant les lignes suivantes :
<?php
include_spip('inc/json');
?>
Ceci assurera que le filtre json_encode
est bien chargé [5].
Et pour les personnes sans Javascript ?
Et oui, tout le monde n’a pas de Javascript. Comment on fait alors ? La solution consiste à afficher un calendrier sous forme de liste dans un div
dont l’id est calendrier-loading
. Si Javascript est activé, FullCalendar va masquer ce div
.
Comme on a déjà fabriqué une boucle dans le squelette agenda.json.html
, nous allons nous en resservir, afin d’éviter de dupliquer les critères. Pour ce faire, nous allons utiliser la boucle DATA de SPIP 3.
Nous mettons donc dans le squelette agenda.html
:
<B_agenda>
<div id="calendrier-loading">
<p class="pagination">#PAGINATION</p>
<BOUCLE_agenda(DATA){source json, #PRODUIRE{fond=agenda.json, start=0,end=2147483647,_=#REM|time}|url_absolue}{pagination 15}>
<dl>
[<dt><:agenda:evenement_titre:></dt>
<dd><a href="#VALEUR{url}">(#VALEUR{title})</a></dd>]
[<dt><:agenda:evenement_date:></dt>
<dd>(#VALEUR{start}|Agenda_affdate_debut_fin{#VALEUR{end},#VALEUR{allDay}|=={true}|?{non,oui}})</dd>]
[<dt><:agenda:evenement_descriptif:></dt>
<dd>(#VALEUR{description})</dd>]
</dl>
</BOUCLE_agenda>
<p class="pagination">#PAGINATION</p>
</div>
</B_agenda>
- l. 1-3 : partie optionnelle avant de la boucle, avec la pagination éventuelle.
- l. 4 : code de la boucle. Nous bouclons sur des données (
(DATA)
) au format json ({source json
) extrait du fichier produit (#PRODUIRE
) par le squeletteagenda.json.html
avec la valeur destart
égale à 0, c’est à dire au 1 janvier 1970 à minuit, et la valeurend
égale à 2147483647, c’est à dire à la date maximale gérée par les ordinateurs actuel, le 19 janvier 2038, 3h14m7s [6]. Ainsi, nous sommes sûr de récuperer tout les évènements de l’agenda. L’option_=#REM|time
permet de s’assurer de ne pas avoir de cache, puisque nous passons comme argument le moment d’appel (|time
). Nous passons au chemin du fichier produit le filtre|url_absolue
pour obtenir l’url du fichier [7]. Nous paginons de 15 en 15. - l. 5-14 : nous affichons les données pour chaque évènement, via
#VALEUR{donnée}
. Ces données sont tirées du JSON. - l. 16 et suivante : partie optionelle arrière de la boucle.
On obtient alors un agenda, certes sommaire, mais au moins existant sans Javascript :
Conclusion
Vous voilà maintenant prêt à avoir un agenda avec FullCalendar. Bien sûr, il y aurait beaucoup de chose à améliorer, cependant cet article aborde déjà beaucoup de notions :
- produire du JSON avec SPIP.
- le formatage de FullCalendar.
- les boucles DATA.
Discussions par date d’activité
Une discussion
Bonjour, mon hébergeur vient de faire évoluer la version de mon site (c’est un hébergeur célèbre dans le milieu Spip qui fournit du Spip clé en main) et depuis le passage à la version Spip 4.2, mon calendrier ne s’affiche plus.
Or, je n’ai pas la main sur le core, je ne sais pas si les librairie FullCalendar sont toujours installées par défaut.
Qu’est-ce qui ferait que ce code pour afficher un calendrier, qui fonctionnait parfaitement avec Spip 3.2, ne fonctionne plus avec Spip 4.2 ?
Éric LM
Les librairies n’étaient pas fournies avec le core de spip mais avec le plugin-dist « organiseur ». Ce plugin n’est plus installé par défaut avec SPIP, mais il doit pouvoir s’installer/s’activer manuellement.
Merci Maieul, je regarde si je peux faire quelque chose.
Bonjour Maieul et tous, je viens de récupérer le site et je l’ai installé sur mon serveur local.
Effectivement, le plugin Organiseur n’est plus dans « plugins-dist ». Il est bien installé dans « plugins », Mais le contenu est très différent de Organiseur version Spip 3.2 : il n’y a plus les scripts pour l’affichage du calendrier, il n’y a plus les feuilles de style.
Pour info, j’ai activé le plugin jquery-ui qui, manifestement, était nécessaire à l’affichage du calendrier.
Ma question est surtout que dans le nouveau plugin Organiseur, on ne trouve plus les fichiers scripts pour l’affichage du fullcalendar
Bonne soirée !
Répondre à ce message
Ajouter un commentaire
Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :
Merci d’avance pour les personnes qui vous aideront !
Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.
Suivre les commentaires : |