Wordpress infinite scroll (без jQuery и плагинов)

229
28 июля 2017, 03:36

Делаю бесконечный скрол, но не нашел ничего на pure js. Проблема возникает при отправке запроса к admin-ajax.php

HTML

<button
    class="button button--load-more"
    data-page="1"
    data-url="<?php echo admin_url('admin-ajax.php'); ?>">
    Показать еще
</button>

functions.php

if (wp_doing_ajax()) {
    add_action('wp_ajax_nopriv_dt_load_more', 'dt_load_more_callback');
    add_action('wp_ajax_dt_load_more', 'dt_load_more_callback');
}
function dt_load_more_callback() {
    $paged = $_POST['page'] + 1;
    $query = new WP_Query( array(
        'post_type' => 'post',
        'paged' => $paged, 
    ));
if ($query->have_posts()) :
    while ($query->have_posts()) : $query->the_post();
    get_template_part( 'content', get_post_format() );
    endwhile;
endif;
wp_reset_postdata();
die();}

Js

function init() {
    const loadButton = document.querySelector('.button--load-more');
    const placeToAppend = document.querySelector('.feed__main');
    function request() {
        const currentPage = this.dataset.page;
        const ajaxUrl = this.dataset.url;
        fetch(ajaxUrl, {
            method: 'POST',
            body: JSON.stringify({
                page: currentPage,
                action: 'dt_load_more',
            }),
        }).then(res => res.json())// пост => контейнер
    }
    loadButton.addEventListener('click', request);
}
if (document.readyState === 'complete' || document.readyState === 'loaded'){
    init();
} else {
    document.addEventListener('DOMContentLoaded', init);
}

Headers

Request URL:http://localhost/wordpress/wp-admin/admin-ajax.php
Request Method:POST
Status Code:200 OK
Content-Type:text/html; charset=UTF-8
Answer 1

Тут дело такое. WordPress Не отвечает, потому что хочет видеть запрос не в json, а в значениях $_REQUEST[]. Строки 27-29 /wp-admin/admin-ajax.php:

// Require an action parameter
if ( empty( $_REQUEST['action'] ) )
    die( '0' );

В связи с этим пришлось изменить функцию request:

function request() {
    const currentPage = this.dataset.page;
    const ajaxUrl = this.dataset.url;
    fetch(ajaxUrl, {
        method: 'POST',
//            headers: {
//                'Accept': 'application/json',
//                'Content-Type': 'application/json'
//            },
//            body: JSON.stringify({
//                page: currentPage,
//                action: 'dt_load_more',
//            }),
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'
        },
        body: 'action=dt_load_more&page='+currentPage,
    })
        .then((res) => res.json()
        )
        .then(function(res) {
            console.log(res.data);
            document.querySelector('#content').innerHTML += res.data;
        })
        .catch(function(error) {
            console.log(error);
        })
}

Я передаю body как строку. Кроме того, добавлены headers. Закомментированный вариант не работает.

Обратите внимание на два .then. Они выполняются последовательно. В одном .then код не работает.

В functions.php я добавил такой код:

if (wp_doing_ajax()) {
    add_action('wp_ajax_nopriv_dt_load_more', 'dt_load_more_callback');
    add_action('wp_ajax_dt_load_more', 'dt_load_more_callback');
}
function dt_load_more_callback() {
    ob_start();
    $paged = $_POST['page'] + 1;
    $query = new WP_Query( array(
        'post_type' => 'post',
        'paged' => $paged,
    ));
    if ($query->have_posts()) :
        while ($query->have_posts()) : $query->the_post();
//          get_template_part( 'content', get_post_format() );
            get_template_part( 'template-parts/post/content', get_post_format() );

        endwhile;
    endif;
    wp_reset_postdata();
    $content = ob_get_clean();
    wp_send_json_success( $content );
}

Здесь я оборачиваю вывод в ob_start() - ob_get_clean(), чтобы получить все в строке, и завершаю выполнение посредством wp_json_success(), который пакует ответ в json вида {"success":true,"data":"......."} и вызывает die().

Корректировка get_template_part носит технический характер и связана с установленной на тестовом сайте темой.

Еще в js я поставил data-page="0", поскольку сначала тестовая страница у меня пустая.

Все работает. Результат можно посмотреть здесь.

Answer 2
fetch(ajaxUrl, {
    method: 'POST',
    body: JSON.stringify({
        page: currentPage,
        action: 'dt_load_more',
    }),
}).then(res => {
    // Здесь, как я понял, вы получаете кусок html (get_template_part)
    // Всё, что вам нужно - вставить этот кусок в нужное место в DOM.
    document.querySelector('селектор контейнера ваших постов').innerHTML += res.text();
})
READ ALSO
Как проверить с помощью moment.js возраст?

Как проверить с помощью moment.js возраст?

Как проверить с помощью momentjs возраст

196
Привязка контекста объекта к внутренним фунциям метода

Привязка контекста объекта к внутренним фунциям метода

У объекта есть метод, записанный в прототип:

233
Проблема с Bootstrap 3

Проблема с Bootstrap 3

Использую bootstrapmin, при нажатии на кнопку открытия меню на мобильных разрешениях, оно открывается и тут же закрывается, не давая перейти на ссылки

366
Обработка нажатия клавиш jQuery

Обработка нажатия клавиш jQuery

У меня есть функция, которая по клику мыши выделяет элемент (добавляет класс selected)

203