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. Mattia

    Funziona correttamente. Manca solo e.preventDefault(); per evitare il “rimbalzo” al click sul pulsante Load More.
    Grazie

    1. Matteo Feduzi

      Grazie mille Mattia, è sempre ben accetta un’osservazione e/o consiglio!

      Un saluto,
      Matteo.

    2. Pietro

      @Mattia posso chiederti dove metteresti e.preventDefault() ? che dove l’ho scritto io non mi corregge l’errore. Grazie!

    3. Matteo Feduzi

      Ciao Pietro,

      l’ho appena aggiunto nel codice, sull’articolo! 😉

      Un saluto,
      Matteo.

  2. Vic

    non capisco il riferimento “admin_url(“admin-ajax.php”)” a cosa si riferisce, non ne fai menzione in nessuna parte del codice.
    Grazie

    1. Matteo Feduzi

      Ciao Vittorio,

      è una parte essenziale dell’infinite scroll che va a richiamare il file admin-ajax.php, essenziale per il funzionamento di questo codice 🙂

      Un saluto,
      Matteo.

  3. Roberto

    Davvero utile, grazie mille!

    1. Matteo Feduzi

      Prego!

      Un abbraccio,
      Matteo.

  4. Marco

    Impossibile copiare e incollare il codice, tra testo sballato e la dicitura del copyright.

    1. Matteo Feduzi

      Ciao Marco, purtroppo hai proprio ragione, provvedo subito a risolvere il problema.

      Grazie della tua recensione, per me è molto importante.

      Un abbraccio,
      Matteo.

    2. Matteo Feduzi

      Ti confermo che il problema è appena stato risolto.

      Per ulteriori problemi non esitare a contattarci anche tramite la nostra chat di assistenza gratuita!

      Un abbraccio,
      Matteo.

  5. Marco

    Grazie Matteo! Mi hai salvato la vita! Ho provato a seguire tantissime guide ma nessuna di queste funzionava! La tua sono funziona perfettamente. Grazie ancora!

    1. Matteo Feduzi

      Prego Marco, sono molto contento che la guida ti sia servita!

      Un abbraccio,
      Matteo.

Lascia un commento

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