Template part : une mosaique d’article avec un filtre par catégorie

La page d’entrée du site permet l’affichage de l’entièreté des posts, de les afficher avec leur image à la une, et de les filtrer grâce à leurs catégories.

Le but

Le but est d’avoir une mosaïque de toutes les productions d’un auteur ou graphiste, par date, et d’ensuite les filtrer par catégories.

Donc, ceci :

Passer par un template part

Le code aurait pu être placé directement dans le fichier home.php qui affiche l’a page d’entrée. Mais pour des raisons pratique, le choix a été fait de le placer dans un fichier séparé, placé dans le dossier "morceaux", dont il a été question dans un autre article de ce didacticiel.

Commencer par gérer la query

La première chose à faire est de forcer Wordpress à aller chercher dans la base de données les articles nécessaires à l’affichage. En effet, par défaut, la boucle cherche un certain nombre d’articles (10 par défaut) alors qu’ici il faut afficher tous les articles disponibles.

On commence par sauvegarder la requête par défaut de Wordpress au cas ou un autre bout de code en aurait besoin, puis faire une nouvelle requête dans la base de données :

<?php
// stocker la query de base
$temp_query = $wp_query;

// demander tous les posts
$args = array(
   'post_type' => 'post',
   'order' => 'ASC',
   'posts_per_page' => -1
);
// faire la demande
query_posts($args);
?>

$args comporte les arguments de la requête : des posts, en ordre ascendant, sans limite de résultats.
query_posts($args) fait la nouvelle requête et "charge" la boucle Wordpress de ses résultats. De là, on peut faire tourner la boucle pour afficher les résultats.

Faire tourner la boucle

Le code de la boucle est celui-ci :

<div class="row " id="mosaique">
       <?php while(have_posts()) : the_post(); ?>
       <div class="col-3 post mb-4 px-1" id="post-<?php the_ID(); ?>">
           <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail('vignette'); ?></a>
           <h2 class="h6 mt-3"><a class="text-secondary" href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2>
           <div class="categories small">
               <?php the_category(', '); ?>
           </div>
       </div>
       <?php endwhile; ?>
   </div>

Le code affiche donc l’image à la une, le titre, et les catégories avec le code the_category(", ") qui affiche les catégories associées à un post, séparées par une virgule.

Le système de filtre par mot-clé

Le filtrage passe par deux portions de code : le premier affiche des cases à cocher pour les mots-clés, que voici :

<div class="form-row form-inline my-3" id="filter-keywords">
       <div class="form-check-label pr-3"><b>Filter : </b></div>
       <?php
       $categories =  get_categories();
       foreach  ($categories as $category) {
           echo '<div class="form-check pr-3">';
           echo '<input type="checkbox" class="form-check-input" value="'.$category->cat_name.'" id="c'.$category->term_id.'" checked>';
           echo '<label class="form-check-label" for="c'.$category->term_id.'">'.$category->cat_name.'</label>';
           echo '</div>';
       }
       ?>
   </div>

Le code, mélange de html et de php, affiche donc des cases à cocher, en passant en revue les catégories utilisées, fournies par la fonction get_categories(). Ça donne donc ceci :

La deuxième partie est un code en jquery, qui à chaque fois qu’une des cases est cochée, passe en revue les éléments affichés pour voir s’ils comporte au moins une des catégories cochées. Si un des éléments ne comporte pas au moins une des catégories, alors il est caché.
Voici ce code :

<script>
   // ce code filtre les mots clés sur clic
   jQuery('#filter-keywords input').change(function(){
       // constituer la liste des mots à filtrer
       var liste=[];
       jQuery("#filter-keywords input:checked").each(function(){
           liste.push(jQuery(this).val());
       });

       jQuery("#mosaique .post").each(function(){
           var affiche=false;
           var texte=jQuery(this).find(".categories").html();

           liste.forEach(function(mot){
               if(texte.indexOf(mot) != -1) {
                   affiche=true;
               }  
           });
           if(affiche == true) {
               jQuery(this).fadeIn();
           } else {
               jQuery(this).fadeOut();
           }
       });
   });
</script>

Le code complet du template_part

Le voici donc :

<?php
// stocker la query de base
$temp_query = $wp_query;

// demander tous les posts
$args = array(
   'post_type' => 'post',
   'order' => 'ASC',
   'posts_per_page' => -1
);
// faire la demande
query_posts($args);
?>

<?php if(have_posts()) : ?>
<div id="mosaique-container" class="container px-4">

   <!-- barre de filtrage -->
   <div class="form-row form-inline my-3" id="filter-keywords">
       <div class="form-check-label pr-3"><b>Filter : </b></div>
       <?php
       $categories =  get_categories();
       foreach  ($categories as $category) {
           echo '<div class="form-check pr-3">';
           echo '<input type="checkbox" class="form-check-input" value="'.$category->cat_name.'" id="c'.$category->term_id.'" checked>';
           echo '<label class="form-check-label" for="c'.$category->term_id.'">'.$category->cat_name.'</label>';
           echo '</div>';
       }
       ?>
   </div>

   <!-- la mosaique -->
   <div class="row " id="mosaique">
       <?php while(have_posts()) : the_post(); ?>
       <div class="col-3 post mb-4 px-1" id="post-<?php the_ID(); ?>">
           <a href="<?php the_permalink(); ?>"><?php the_post_thumbnail('vignette'); ?></a>
           <h2 class="h6 mt-3"><a class="text-secondary" href="<?php the_permalink(); ?>" title="<?php the_title(); ?>"><?php the_title(); ?></a></h2>
           <div class="categories small">
               <?php the_category(', '); ?>
           </div>
       </div>
       <?php endwhile; ?>
   </div>
</div>

<script>
   // ce code filtre les mots clés sur clic
   jQuery('#filter-keywords input').change(function(){
       // constituer la liste des mots à filtrer
       var liste=[];
       jQuery("#filter-keywords input:checked").each(function(){
           liste.push(jQuery(this).val());
       });

       jQuery("#mosaique .post").each(function(){
           var affiche=false;
           var texte=jQuery(this).find(".categories").html();

           liste.forEach(function(mot){
               if(texte.indexOf(mot) != -1) {
                   affiche=true;
               }  
           });
           if(affiche == true) {
               jQuery(this).fadeIn();
           } else {
               jQuery(this).fadeOut();
           }
       });
   });
</script>
<?php endif; ?>

<?php
// on remet en place la requete initiale
$wp_query = $temp_query; ?>