Infinite scroll per WordPress senza plugin

Infinite scroll per WordPress senza plugin

Stai cercando il modo di mostrare i tuoi articoli quando l’utente scrolla la pagina o quando seleziona un bottone senza l’ausilio di ulteriori plugin che potrebbero rallentare solamente il tuo sito? Allora continua a leggere questo articolo, sei nel posto giusto!

Pubblicato il Scritto da Matteo Feduzi Sito Web, WordPress 30 commenti

Per realizzare un infinte scroll o un bottone che carichi il contenuto successivo è necessario utilizzare AJAX.

Proprio per questo credo sia molto importante dare una breve introduzione a questo argomento.

Cos’è AJAX?

Ajax, acronimo di Asynchronous JavaScript and XML si basa su uno scambio di dati in background fra web browser e server.

Esso consente quindi l’aggiornamento dinamico di una pagina web senza un ricaricamento da parte dell’utente.

Perché utilizzarlo?

Facciamo subito un esempio pratico e immaginiamo di essere nella pagina blog del nostro sito.

Esso, con molta probabilità e se configurato correttamente avrà più pagine, solitamente nominate in questo modo: https://example.com/blog/page/1.

Passare alla seconda pagina del nostro blog comporterà un nuovo caricamento degli stili, degli script e dell’HTML stesso.

Invece, eseguendo una richiesta AJAX, non verranno ricaricati nuovamente tutti questi file ma solamente gli articoli successivi.

In quest’ultimo caso l’utente non sarà costretto ad aspettare il caricamento completo di una nuova pagina e tutto ciò si tradurrà in una miglior esperienza utente.

Infinite scroll e bottone load more

Ora che ti ho illustrato una breve introduzione sull’argomento AJAX sei pronto per costruire il tuo scroll infinito o alternativamente un bottone per caricare il contenuto successivo.

Creare uno shortcode WordPress

La prima cosa da fare è creare uno shortcode WordPress da utilizzare nella pagina in questione, nel mio caso la pagina del blog.

Per fare ciò dobbiamo creare una funzione di callback che verrà eseguita ogni volta che viene utilizzato il codice.

Prima di creare lo shortcode aggiungiamo la funzione che visualizzerà i primi articoli.

Aggiungiamo quindi il seguente codice nel file functions.php.

Puoi trovare questo file al seguente percorso: /wp-content/themes/temaattivo/functions.php.

function script_load_more($args = array()) {
    echo '<div id="ajax-primary" class="content-area">';
        echo '<div id="ajax-content" class="content-area">';
            ajax_script_load_more($args);
        echo '</div>';
        echo '<a href="#" id="loadMore"  data-page="1" data-url="'.admin_url("admin-ajax.php").'" >Load More</a>';
    echo '</div>';
}

Ora creiamo il nostro shortcode il quale richiamerà la funzione script_load_more.

Inseriscilo sempre nel file functions.php.

add_shortcode('ajax_posts', 'script_load_more');

Crea la richiesta AJAX

Adesso dobbiamo creare la funzione che richiamerà gli articoli successivi, cioè ajax_script_load_more chiamato all’interno della funzione script_load_more.

Aggiungiamo perciò la seguente funzione nel file functions.php.

function ajax_script_load_more($args) {
    //Init ajax
    $ajax = false;
    //Controlla la chiamata AJAX
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
        strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        $ajax = true;
    }
    //Numero degli articoli da caricare
    $num =3;
    //Numero della pagina
    $paged = $_POST['page'] + 1;
    //Args
    $args = array(
        'post_type' => 'post',
        'post_status' => 'publish',
        'posts_per_page' =>$num,
        'paged'=>$paged
    );
    //Query
    $query = new WP_Query($args);
    //Controllo
    if ($query->have_posts()):
        //loop articales
        while ($query->have_posts()): $query->the_post();
            //include articles template
            include 'contenuto-ajax.php';
        endwhile;
    else:
        echo 0;
    endif;
    //Ripristina post
    wp_reset_postdata();
    //Controlla la chiamata AJAX
    if($ajax) die();
}

Con questa funzione verranno caricati 3 articoli alla volta.

Se vuoi caricarne di più o di meno modifica il valore $num.

Crea il template dell’articolo

Ora crea il file contenuto-ajax.php che verrà utilizzato nella funzione ajax_script_load_more.

Questo è il file che conterrà il template dell’articolo.

Inserisci questo file al seguente percorso /wp-content/themes/temaattivo/contenuto-ajax.php.

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
	
	<div class="box-articolo">
		
		<div class="img-articolo">
			<a class="img-thumbnail" href="<?php the_permalink() ?>"><?php the_post_thumbnail(); ?></a>
		</div>
		
		<div class="container-articolo">
			<h3 class="titolo-articolo"><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></h3>
			<div class="meta-articolo">
				<p class="data">Pubblicato il <time><?php the_time('j F, Y'); ?></time></p>
				<span class="divisore">/</span>
				<a class="autore" href="<?php the_author_link(); ?>"><?php the_author(); ?> </a>
				<span class="divisore">/</span>
				<?php $parentscategory ="";
				foreach((get_the_category()) as $category) {
					if ($category->category_parent == 0) {
						$parentscategory .= ' <a class="categoria" href="' . get_category_link($category->cat_ID) . '" title="' . $category->name . '">' . $category->name . '</a>, ';
					}
				}
				echo substr($parentscategory,0,-2); ?>
			</div>
			
			<div class="excerpt">
				<?php the_excerpt(); ?>
			</div>
			
			<div class="btn-altro">
				<a class="leggi-altro" href="<?php the_permalink() ?>">Leggi altro</a>
			</div>
			
		</div>
		
	</div>
	
</article>

Crea un action hook AJAX

Ora dobbiamo creare un action hook AJAX per richiamare la funzione ajax_script_load_more.

Per farlo aggiungi il seguente codice nel file functions.php.

add_action('wp_ajax_nopriv_ajax_script_load_more', 'ajax_script_load_more');
add_action('wp_ajax_ajax_script_load_more', 'ajax_script_load_more');

Crea il file script per lo scroll infinito o per il bottone load more

Ora creiamo il file scripts_ajax.js all’interno della directory js del tema attivo.

Dovresti trovarla al seguente percorso: /wp-content/themes/temaattivo/js/scripts_ajax.js.

Dopodiché creiamo una funzione nel file functions.php che richiami questo script nel footer del nostro sito.

add_action( 'wp_enqueue_scripts', 'ajax_enqueue_script' );
function ajax_enqueue_script() {
    wp_enqueue_script( 'scripts_ajax', get_theme_file_uri( '/js/scripts_ajax.js' ), array( 'jquery' ), '1.0', true );
}

Ora hai due possibilità, scegli una delle due e inserisci il codice apposito.

1) Caricare gli articoli successivi quando l’utente seleziona il bottone carica altro.

jQuery.noConflict($);
/* Funzioni AJAX */
jQuery(document).ready(function($) {
    //Esegue la funzione quando avviene il click
    $("#loadMore").on('click', function(e) {
        e.preventDefault();
        //Init
        var that = $(this);
        var page = $(this).data('page');
        var newPage = page + 1;
        var ajaxurl = that.data('url');
        //Chiamata AJAX
        $.ajax({
            url: ajaxurl,
            type: 'post',
            data: {
                page: page,
                action: 'ajax_script_load_more'

            },
            error: function(response) {
                console.log(response);
            },
            success: function(response) {
                //Controllo
                if (response == 0) {
                    $('#ajax-content').append('<div class="text-center"><h3>Non sono presenti altri articoli!</h3></div>');
                    $('#loadMore').hide();
                } else {
                    that.data('page', newPage);
                    $('#ajax-content').append(response);
                }
            }
        });
    });
});

2) Caricare gli articoli quando l’utente scrolla la pagina.

jQuery.noConflict($);
/* Funzioni AJAX */
jQuery(document).ready(function($) {
    //Trova la posizione dello scroll
    $(window).scroll(function() {
        //Init
        var that = $('#loadMore');
        var page = $('#loadMore').data('page');
        var newPage = page + 1;
        var ajaxurl = $('#loadMore').data('url');
        //Controllo
        if ($(window).scrollTop() == $(document).height() - $(window).height()) {

            //Chiamata AJAX
            $.ajax({
                url: ajaxurl,
                type: 'post',
                data: {
                    page: page,
                    action: 'ajax_script_load_more'
                },
                error: function(response) {
                    console.log(response);
                },
                success: function(response) {
                    //Controllo
                    if (response == 0) {
                        //Controllo
                        if ($("#no-more").length == 0) {
                            $('#ajax-content').append('<div id="no-more" class="text-center"><h3>Non sono presenti altri articoli!</h3></div>');
                        }
                        $('#loadMore').hide();
                    } else {
                        $('#loadMore').data('page', newPage);
                        $('#ajax-content').append(response);
                    }
                }
            });
        }
    });
});

Utilizzando questo codice verranno caricati altri articoli solamente quando arriverai a toccare la fine della pagina.

Se vuoi che gli articoli successivi vengano caricati prima di toccare la fine della pagina utilizza questo codice:

jQuery.noConflict($);
/* Funzioni AJAX */
jQuery(document).ready(function($) {

var eseguito = false;

//Trova la posizione dello scroll
$(window).scroll(function() {
		
        //Init
        var that = $('#loadMore');
        var page = $('#loadMore').data('page');
        var newPage = page + 1;
        var ajaxurl = $('#loadMore').data('url');
		
	if (eseguito) {
		//if ($(window).scrollTop() <= ($(document).height() - $(window).height())*0.8){
		if ($(window).scrollTop() <= (($(document).height() - $(window).height())- $("footer").height())-200) {
			eseguito = false;
		} else {
			return false;
		}
	}
		
	if (!eseguito) {
		
        //Controllo
        //if ($(window).scrollTop() >= ($(document).height() - $(window).height())*0.8){
        if ($(window).scrollTop() >= (($(document).height() - $(window).height())- $("footer").height())-200) {
			
	eseguito = true;
			
        //Chiamata AJAX
        $.ajax({
        	url: ajaxurl,
                type: 'post',
                data: {
                    	page: page,
                    	action: 'ajax_script_load_more'
                },
                error: function(response) {
                    	console.log(response);
                },
                success: function(response) {
                    	//Controllo
                    	if (response == 0) {
                        	//Controllo
                        	if ($("#no-more").length == 0) {
                            		$('#ajax-content').append('<div id="no-more" class="text-center"><h3>You reached the end of the line!</h3><p>No more posts to load.</p></div>');
                        	}
                        	$('#loadMore').hide();
                    	} else {
                        	$('#loadMore').data('page', newPage);
                        	$('#ajax-content').append(response);
                    	}
                }
            });
        }
	}
    });
});

Come puoi vedere viene dichiarata una variabile eseguito che indica se la chiamata AJAX è già stata eseguita.

Questo perché utilizzando esclusivamente il valore > nella selezione verrebbero eseguite più chiamate del singolo oggetto restituendo così gli stessi 3 articoli più volte.

Inoltre è presente un’altra possibile selezione sotto commento che ti permette di caricare altri post quando si arriva all’80% della pagina.

Aggiungere shortcode per visualizzare gli articoli

Ora non ti resta altro che aggiungere il seguente shortcode nella pagina del blog per ottenere il risultato sperato.

<?php echo do_shortcode('[[ajax_posts]]'); ?>

Come utilizzare AJAX “infinite scroll” o “load more” nelle pagine categorie e tag

Mi sono accorto che mano a mano che aumentava la popolarità di questo post, aumentavano anche le richieste di come poter applicare questa tipologia di codice alle pagine categoria e tag.

Molti per cercare di far funzionare il codice da me riportato hanno provato ad utilizzare il seguente filtro:

$categoria_corrente = get_queried_object();
$ID_categoria_corrente = $categoria_corrente->term_id;
$args = array(
   'post_type' => 'post',
   'post_status' => 'publish',
   'cat' => $ID_categoria_corrente,
   'posts_per_page' =>$num,
   'paged'=>$paged
);

Purtroppo però questo codice funziona solo nel primo richiamo, dopodiché non riuscirà più a trovare la pagina da cui viene effettuata la richiesta, perché il codice partirà dal file JavaScript.

Così ho subito deciso di creare una versione funzionante con solo qualche piccola modifica. Di seguito il codice JavaScript:

jQuery.noConflict($);
jQuery(document).ready(function($) {

  var eseguito = false;

  //find scroll position
  $(window).scroll(function() {

    //init
    var that = $('#loadMore');
    // L'aggiornamento parte da qui
    var classBody = document.getElementsByTagName("body")[0].className;
    var cat = classBody.replace( /^\D+/g, '');
    // L'aggiornamento finisce qui
    var page = $('#loadMore').data('page');
    var newPage = page + 1;
    var ajaxurl = $('#loadMore').data('url');

    if (eseguito) {
  		if ($(window).scrollTop() &lt;= (($(document).height() - $(window).height())- $("footer").height())-200) {
  		       eseguito = false;
  		} else {
  			return false;
  		}
  	}

    if (!eseguito) {

      //check
      if ($(window).scrollTop() >= (($(document).height() - $(window).height())- $("footer").height())-200) {
        eseguito = true;

        /*ajax call*/
        $.ajax({
          url: ajaxurl,
          type: 'post',
          data: {
            cat : cat, // Qui viene passata l'intera classe con l'ID categoria
            page: page,
            action: 'ajax_script_load_more_category'
          },
          error: function(response) {
            console.log(response);
          },
          success: function(response) {
            //check
            if (response == 0) {
              //check
              if ($("#no-more").length == 0) {
                $('#ajax-content').append('&lt;div id="no-more" class="text-center">&lt;h3>Non sono presenti altri articoli!&lt;/h3>&lt;/div>');
              }
              $('#loadMore').hide();
              } else {
                $('#loadMore').data('page', newPage);
                $('#ajax-content').append(response);
              }
            }
          });
        }
      }
  });
});

Mentre il codice da inserire sul functions.php è il seguente:

//INFINITY SCROLL
function script_load_more_category($args = array()) {
    echo '<div id="ajax-primary" class="content-area">';
    echo '<div id="ajax-content" class="content-area">';
            ajax_script_load_more_category($args);
    echo '</div>';
    echo '<a href="#" id="loadMore"  data-page="1" data-url="'.admin_url("admin-ajax.php").'" >Load More</a>';
    echo '</div>';
}
add_shortcode('ajax_posts_category', 'script_load_more_category');
function ajax_script_load_more_category($args) {
    //Init ajax
    $ajax = false;
    //Controlla la chiamata AJAX
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
        strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
        $ajax = true;
    }
    //Numero degli articoli da caricare
    $num =3;
    //Numero della pagina
    $paged = $_POST['page'] + 1;
        // L'aggiornamento parte qui
	$cat = $_POST['cat'];
	if(!$cat){
		$categoria_corrente = get_queried_object();
    	    $cat = $categoria_corrente->term_id;
	}
        // L'aggiornamento finisce qui
    //Args
    //$categoria_corrente = get_queried_object();
    //$ID_categoria_corrente = $categoria_corrente->term_id;
	//error_log($ID_categoria_corrente);
    $args = array(
        'post_type' => 'post',
        'post_status' => 'publish',
        'cat' => $cat, // Qui viene inserito l'ID categoria che filtra i risultati
        'posts_per_page' =>$num,
        'paged'=>$paged
    );
    //Query
    $query = new WP_Query($args);
    //Controllo
    if ($query->have_posts()):
        //loop articales
        while ($query->have_posts()): $query->the_post();
            //include articles template
            include 'ajax-content.php';
        endwhile;
    else:
        echo 0;
    endif;
    //Ripristina post
    wp_reset_postdata();
    //Controlla la chiamata AJAX
    if($ajax) die();
}
add_action('wp_ajax_nopriv_ajax_script_load_more_category', 'ajax_script_load_more_category');
add_action('wp_ajax_ajax_script_load_more_category', 'ajax_script_load_more_category');

Conclusioni

Oggi abbiamo visto come creare uno scroll infinito e un bottone carica altro tramite delle chiamate AJAX permettendoci di migliorare e di molto l’esperienza dell’utente nel nostro sito.

Ah giusto… sapevi che puoi personalizzare le pagine archivio come più preferisci? Ho creato una guida anche per questo! 😉

Hai avuto problemi nella riproduzione del codice? Fammelo sapere nei commenti!

Un abbraccio,

Matteo.

30Commenti
Lascia un commento
  1. Lala

    Salve. é possibile farlo in DIVI theme?

    1. Matteo Feduzi

      Ciao, dipende, dici scrivendo codice o come funzione nativa del tema? 😉

  2. Gabriele

    Ciao Matteo,
    grazie mille per questa guida molto chiare e utile.
    Se volessi aggiungere il Load More per un nuovo Custom Post Type con nome “xyz”, dovrei modificare solo il post_type della WP_Query o serve altro?

    Grazie 😉

    1. Matteo Feduzi

      Ciao Gabriele, esatto, basterebbe aggiornare il valore post_type 😉

  3. Carla

    Ciao,

    grazie per gli snippet! Ho una domanda, se volessi scriverli in file al di fuori del functions.php?

    1. Matteo Feduzi

      Ciao Carla,

      perché vorresti scriverli al di fuori del file functions.php?

      Un saluto,
      Matteo.

    2. Carla

      Ciao Matteo, mi piacerebbe richiamare il codice da un plugin custom e non dal tema

    3. Matteo Feduzi

      Ciao Carla,

      dipende molto dalla struttura custom che sta seguendo il tuo plugin. Utilizzi il boilerplate di questo sito wppb.me?

      Un saluto,
      Matteo.

    4. Carla

      Sì, l’idea è quella di usare un plugin starter da cui richiamare le funzioni, evitando di chiamarle dal tema

    5. Matteo Feduzi

      Capito, penso che esistano già plugin del genere. Ti consiglio di utilizzare quelli se la realizzazione è troppo complessa, se invece vuoi proprio crearne uno ti consiglio di leggere la documentazione riguardo lo sviluppo di plugin su WordPress.org.

      Un saluto,
      Matteo.

    6. Carla

      Grazie mille, seguirò la guida!

  4. Marco

    Ciao Matteo grazie per questo code molto molto chiaro.
    Volendolo inserire in una categoria come faccio a filtrare i risultati per categoria?

    1. Matteo Feduzi

      Ciao Marco,

      basta inserire nell’$args del loop la categoria in questione che può essere ripresa direttamente con il seguente codice:

      $categoria_corrente = get_queried_object();
      $ID_categoria_corrente = $categoria_corrente->term_id;

      All’interno dell’array della variabile $args dovrai poi inserire:

      'cat' => $ID_categoria_corrente,

      Un saluto,
      Matteo.

    2. Marco

      Ciao Matteo,
      ho fatto come mi hai detto ed effettivamente la query filtra i risultati per Id categoria.
      L’unica cosa che funziona solo per i primi 3 che è il mio $num.
      Dopo che comincia a caricare gli altri post è come se saltasse l’ID categoria dalla query e ne carica anche altri di altre categorie.
      Il mio codice:
      //Args
      $categoria_corrente = get_queried_object();
      $ID_categoria_corrente = $categoria_corrente->term_id;
      $args = array(
      ‘post_type’ => ‘post’,
      ‘post_status’ => ‘publish’,
      ‘cat’ => $ID_categoria_corrente,
      ‘posts_per_page’ =>$num,
      ‘paged’=>$paged
      );
      //Query
      $query = new WP_Query($args);

    3. Matteo Feduzi

      Ciao Marco,

      non mi sembra di vedere niente di anomalo.

      Stai eseguendo questo codice sulle pagine archivio di categoria, giusto?

      Un saluto,
      Matteo.

    4. Marco

      Si certo pagine di categoria, ma è come se salta la query dopo i primi 3 e carica tutti i post

    5. Matteo Feduzi

      Prova a scrivermi in chat e mandami il codice che stai utilizzando nella pagina di categoria utilizzando un programma come il seguente: https://pastebin.com/

      Grazie!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *