Paginacja w WordPressie, wczytywanie postów w tle (nieskończone przewijanie – infinite scroll)
W poprzednim artykule dotyczącym paginacji dla szablonów WordPress’a opisałem proces tworzenia „paginacji numerycznej” opartej o wyświetlanie poszczególnych numerów stron z naszymi wpisami. Rozwiązanie to dobrze się spisuje na blogach, gdzie czytelnik może mieć potrzebę szybkiego przeskakiwania pomiędzy artykułami opublikowanymi z dużym odstępem czasowym. Czasami jednak taka funkcjonalność nie jest w ogóle potrzebna, a pracując nad motywem możemy pozwolić sobie na nieco bardziej „wyrafinowane” rozwiązania.
Paginacja ładująca nowe strony wpisów „w tle” czyli tak zwane nieskończone przewijanie, wiąże ze sobą konieczność obsługi skryptów po stronie klienta (Ajax, JavaScript, jQuery) na co programiści nie mają wpływu oraz należy pamiętać o tym, że pozbywamy się w ten sposób dostępu do tradycyjnej stopki, w której być może zapisane są ważne informacje. Jeżeli jednak pogodziliśmy się z tymi niedogodnościami to pora przejść do najprzyjemniejszej części tego wpisu czyli kodowania.
Wszystkie czynności będziemy wykonywać na bazie motywu Tewnety Fifteen.
Na początek odszukujemy plik index.php
(katalog główny szablonu) i usuwamy z niego pętlę odpowiedzialną za wyświetlanie artykułów. Zamiast tego kodu wstawimy zwykły blok div
:
<?php /** * The main template file * * This is the most generic template file in a WordPress theme * and one of the two required files for a theme (the other being style.css). * It is used to display a page when nothing more specific matches a query. * e.g., it puts together the home page when no home.php file exists. * * Learn more: {@link https://codex.wordpress.org/Template_Hierarchy} * * @package WordPress * @subpackage Twenty_Fifteen * @since Twenty Fifteen 1.0 */ get_header(); ?> <div id="primary" class="content-area"> <main id="main" class="site-main" role="main"> <?php if ( have_posts() ) : ?> <?php if ( is_home() && ! is_front_page() ) : ?> <header> <h1 class="page-title screen-reader-text"><?php single_post_title(); ?></h1> </header> <?php endif; ?> <?php // Start the loop. //while ( have_posts() ) : the_post(); /* * Include the Post-Format-specific template for the content. * If you want to override this in a child theme, then include a file * called content-___.php (where ___ is the Post Format name) and that will be used instead. */ //get_template_part( 'content', get_post_format() ); //End the loop. //endwhile; // Previous/next page navigation. //the_posts_pagination( array( // 'prev_text' => __( 'Previous page', 'twentyfifteen' ), // 'next_text' => __( 'Next page', 'twentyfifteen' ), // 'before_page_number' => '<span class="meta-nav screen-reader-text">' . __( 'Page', 'twentyfifteen' ) . ' </span>', //) ); //... cd. skryptu
Zakomentowany fragment kodu możemy skasować, a w jego miejsce wstawiamy:
<div id="articles"></div>
Następnie przechodzimy do folderu js
i tworzymy dwa nowe pliki o nazwie load-post.php
(plik php) i load.js
(plik javascript).
Otwieramy plik load-post.php w dowolnym edytorze tekstu i wklejamy poniższy kod:
<?php define('WP_USE_THEMES', false); require_once('../../../../wp-load.php'); $posts = 0; $page = 0; if (isset($_GET['posts'])) { $posts = $_GET['posts']; } if ( isset($_GET['page']) ) { $page = $_GET['page']; } query_posts( array( 'posts_per_page' => $posts, 'paged' => $page ) ); if ( have_posts() ) { while ( have_posts() ) { the_post(); get_template_part( 'content', get_post_format() ); } } wp_reset_query(); ?>
Jest to kod PHP, który będzie pobierał z bazy danych odpowiednie artykuły.
Następnie przechodzimy do pliku load.js
i wklejamy ten kod:
$(function() { pageNumber = 1; load = true; loadPosts = function() { $.ajax({ url: templateURL + '/js/loop-ajax.php', type: 'GET', dataType: 'html', data: { posts : countPosts, page : pageNumber }, beforeSend: function() { $( '#articles' ).append('<span id="loading"><img src="' + templateURL + '/img/ajax-loader.gif"></span>'); load = false; }, success: function(data) { $( '#articles' ).append(data); $( '#loading' ).remove(); load = true; }, error: function() { alert('Coś poszło nie tak...'); } }); }; $(window).scroll(function() { if ( load && $(window).scrollTop() == $(document).height() - $(window).height() ) { pageNumber++; loadPosts(); }; }); loadPosts(); });
Teraz musimy „podpiąć” nasze skrypty do szablonu. W tym celu otwieramy plik header.php
(katalog główny) i w sekcji head
wklejamy poniższy kod:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> var countPosts = "<?php echo get_option( 'posts_per_page' ); ?>"; var templateURL = "<?php echo get_template_directory_uri(); ?>"; </script> <script src="<?php echo get_template_directory_uri(); ?>/js/load.js"></script>
Teraz pozostało stworzyć folder img
(w katalogu głównym szablonu) i wrzucić tam animację gif symulującą ładowanie postów (obrazek taki możecie wygenerować w odpowiednim generatorem online: Ajax loading gif generator):
Wpisy na stronie głównej od teraz będą ładowane w tle. Pamiętajcie, że nie będzie dostępu do stopki (chyba, że wszystkie posty zostaną załadowane).
Brak możliwości ładowania plików przez AJAX na localhost
Jeżeli tak jak ja, natknęliście się przy próbie uruchomienia powyższego skryptu z poziomu lokalnego serwera na poniższy błąd:
XMLHttpRequest cannot load http://127.0.0.1 Origin http://localhost is not allowed by Access-Control-Allow-Origin.
To aby się go pozbyć musicie w pliku konfiguracyjnym serwera Apache (httpd.conf
) dopisać poniższy kod:
<Directory /> Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Headers "Content-Type" Header set Access-Control-Allow-Methods "GET, PUT, OPTIONS, DELETE, POST" </Directory>
Przeczytaj również: Nieskończone przewijanie (infinite scroll), a SEO….
Nie lepiej wykorzystać infinitescroll.js? Wtedy przy wyłączonym JS wyświetla się tradycyjna paginacja.
To jest całkowicie inne rozwiązanie niż to które przedstawiłem, ale przyjrzę się jak to działa i myślę, że w przyszłości na ten temat też coś napiszę ;)
Jak to możliwe, że nie chce mi zadziałać? Głowię się z tym już od dwóch godzin, wszystko robię według instrukcji i nic. Jedynie co udało mi się osiągnąć to to, że wyświetlił mi się animowany gif i komunikat „coś poszło nie tak”.
A na konsoli są jakieś błędy? Ciężko mi tak pomóc nie widząc strony, skrypt na pewno działa
Żadnych błędów nie zauważyłem prócz tego komunikatu.
Nie za bardzo rozumiem do którego momentu w index.php powinienem usunąć za komentowany kod, ponieważ w artykule nie został on podany w całości.
Tylko ten fragment, który jest zakomentowany w artykule (nic więcej).