"Бесконечная" прокрутка страниц в блоге была в свое время создана под влиянием интерфейса таких социальных медиа, как Facebook and Twitter. Чтобы прочесть старые посты, в такой системе перелистывания достаточно прокрутить страницу вниз.
С одной стороны, такая система перелистывания страниц существенно улучшает опыт использования сайта, но при неправильной настройке она может испортить впечатление посетителей вашего сайта. Так что если вы собираетесь внедрить "бесконечную" прокрутку, убедитесь, что в нижней части страницы в текущем дизайне нет никаких важных навигационных ссылок. Потому что при бесконечном прокручивании страницы попытка кликнуть на одну из таких ссылок будет приводить к появлению новых постов, а сама ссылка будет "убегать" от пользователя. Для того, чтобы избежать таких негативных последствий, важные ссылки придется перенести в боковую панель либо зафиксировать расположение футера в вашем блоге. Итак, приступим к настройке.
| Скачать исходники |
Шаг 1. Планируем деление на страницы при новой прокрутке
Важно спланировать деление блога настраницы перед тем, как настроить новый тип прокрутки и навигации. Обычно деление на страницы происходит путем перечисления номеров страниц в нижней части главной страницы. Но теперь при условии, что прокрутка будет динамической, вам такая нумерация и разбивка на номера не понадобится.
Наша бесконечная прокрутка использует функциональность jQuery и ajax для обработки запросов к странице и постам, которые отображаются для пользователя, как только он достигает видимого "дна" страницы. В этом пользовательском руководстве я расскажу вам, как настроить динамическую прокрутку на примере темы Twenty Ten.
Шаг 2. Создаем функцию Ajax
Мы воспользуемся функцией WordPress ajax, чтобы создать процедуру обработки вызова новых постов при разбивке на страницы с эффектом "бесконечной" прокрутки. Сначала надо задать основную функцию для нашего деления на страницы, для этого следующий код понадобится добавить в functions.php
function wp_infinitepaginate(){ $loopFile = $_POST['loop_file']; $paged = $_POST['page_no']; $posts_per_page = get_option('posts_per_page'); # Load the posts query_posts(array('paged' => $paged )); get_template_part( $loopFile ); exit; }
Эта функция будет использоваться для вызова нашей процедуры деления на страницы, и обычно у нас тут происходит отправка двух переменных при помощи ajax: одна задает номер страницы, а другая - файл шаблона, который использует такую новую прокрутку. Чтобы включить эту функцию и использовать ее совместно при помощи WordPress ajax, нам понадобится следующий код:
add_action('wp_ajax_infinite_scroll', 'wp_infinitepaginate'); // for logged in user add_action('wp_ajax_nopriv_infinite_scroll', 'wp_infinitepaginate'); // if user not logged in
Действие по умолчанию для WordPress ajax будет wp_ajax_(our action name), поскольку имя infinite_scroll используется в коде темы, которая служит примером в данном посте. Нам надо добавить 2 действия: одно — для авторизованных пользователей сайта, а другое - для тех, кто не авторизован на сайте.
Далее нам надо создать ajax-функцию, которая будет отправлять 2 переменных, необходимых для нашей процедуры деления на страницы. Вы можете использовать следующие примеры кода WordPress для вставки jQuery ajax-функции либо же напрямую добавить этот код в файл header.php вашей темы:
<script type="text/javascript"> function loadArticle(pageNumber) { $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } </script>
Перед нами — основной вызов ajax, который будет осуществляться, и мы используем "infinite_scroll" как имя производимого действия. WordPress будет автоматический вызывать функцию wp_infinitepaginate(); потому что мы задали ее в нашем файле functions.php.
Шаг 3. Определяем действие в момент, когда пользователь достигает "дна" страницы
Чтобы включить "бесконечную прокрутку", нам надо определить тот момент, в который пользователь достигает видимого "дна" страницы. Добиться этого можно при помощи jQuery, используя следующий код:
<script type="text/javascript"> $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ // run our call for pagination } }); </script>
Теперь мы можем узнать, когда пользователь достигнет прокруткой видимой нижней границы на странице. Далее надо вызвать функцию loadArticle в рамках функции прокрутки. Для этого я добавляю счетчик, который определяет номер страницы для дальнейшего вызова функции:
<script type="text/javascript"> var count = 2; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ loadArticle(count); count++; } }); function loadArticle(pageNumber){ $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } </script>
Каждый раз, когда пользователь прокручивает страницу до нижней границы, значение счетчика возрастает и включает передачу номера страницы в функцию wp_infinitepage() в рамках файла functions.php из нашей темы оформления. При помощи функций scroll и loadArticle мы можем осуществить вызов функции ajax в нашей теме для WordPress; но результат не отобразится, если мы не поместили файл цикла в папке с нашей темой оформления.
Шаг 4. Настраиваем тему оформления
Наиболее важный этап: нам надо настроить значение div, которое содержит новый контент, запрашиваемый функцией ajax. В теме оформления Twenty Ten уже есть div, который мы можем использовать. Этот div имеет значение id="content", поэтому мы укажем div id в нашей функции ajax. Если вы для оформления используете другие темы, которые не оформляют цикл в div, вы просто можете оформить функцию цикла так, как это сделано в приведенном фрагменте кода, чтобы получить аналогичный результат:
<div id="content"> loop content </div>
Далее нам понадобится файл цикла. В теме Twenty Ten уже есть файл цикла, вот одна из причин, почему я и взял эту тему для нашего сегодняшнего урока. Если у вас в теме нет файла loop.php, просто создайте новый файл цикла и скопируйте функцию цикла в рамках файла index.php в ваш новый файл, а затем новый файл цикла загрузите в папку с темой.
Для всех, кто использует тему Twenty Ten, можно еще "закомментировать" деление на страницы в рамках файла, потому что нам оно больше не понадобится (изучите исходный файл руководства для того, чтобы узнать, как это правильно сделать).
Шаг 5. Добавляем загрузчик Ajax
Это действие — необязательное, чтобы просто "украсить" нашу бесконечную прокрутку страниц. Для этого мы добавим образ загрузчика ajax к нижней границе нашей страницы. Для этого просто вставьте следующий фрагмент кода в ваш файл footer.php:
<a id="inifiniteLoader">Loading... <img src="<?php bloginfo('template_directory'); ?>/images/ajax-loader.gif" /></a>
а затем вставьте следующий CSS-код в лист стилей темы:
a#inifiniteLoader{ position: fixed; z-index: 2; bottom: 15px; right: 10px; display:none; }
Далее надо дописать пару строк кода в нашу функцию jQuery, чтобы показать и скрыть элемент загрузчика ajax:
<script type="text/javascript"> jQuery(document).ready(function($) { var count = 2; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ loadArticle(count); count++; } }); function loadArticle(pageNumber){ $('a#inifiniteLoader').show('fast'); $.ajax({ url: "<?php bloginfo('wpurl') ?>/wp-admin/admin-ajax.php", type:'POST', data: "action=infinite_scroll&page_no="+ pageNumber + '&loop_file=loop', success: function(html){ $('a#inifiniteLoader').hide('1000'); $("#content").append(html); // This will be the div where our content will be loaded } }); return false; } }); </script>
Загрузчик ajax будет отображаться сразу, как только пользователь достигнет нижней границы на странице, и сразу скроется, как только завершится ajax-запрос на показ новой порции постов.
Шаг 6. Дополнительные ограничения для улучшения бесконечного механизма прокрутки
Мы написали вполне рабочий механизм бесконечной прокрутки, но кое-чего ему не хватает. Эта функция будет срабатывать каждый раз, как только пользователь достигает "дна" страницы, даже если постов уже больше нет. А вот такого эффекта нам совсем не надо. Потому мы добавим настройку, которая будет контролировать режим отображения постов, и если постов уже больше не осталось, то действие "бесконечной" прокрутки будет прекращаться:
<script type="text/javascript"> var count = 2; var total = <?php echo $wp_query->max_num_pages; ?>; $(window).scroll(function(){ if ($(window).scrollTop() == $(document).height() - $(window).height()){ if (count > total){ return false; }else{ loadArticle(count); } count++; } }); </script>
Мы дописали var total в функцию: она возвращает суммарное число страниц, доступных для просмотра на нашем сайте. Таким образом каждый раз перед срабатыванием функции бесконечной прокрутки будет производиться проверка, не исчерпался ли лимит постов и не достигнуто ли максимальное число страниц на данном сайте.
Еще нам надо добавить ограничение, которое указывает, где именно применяется данная функция: на главной странице, на страницах архива или может в поиске — но не в рамках 1 поста или отдельно взятой страницы блога. Потому нам понадобится довольно простой PHP-параметр функции if else в коде jQuery:
if (!is_single() || !is_page()): // our jQuery function here endif;
Вот и все, что вам понадобится, чтобы создать эффект бесконечной прокрутки на вашем сайте. Пожалуйста, пользуйтесь данным руководством, а также файлами-исходниками и примерами кода из данного поста для того, чтобы создать свое оформление такого рода. Все файлы и примеры в этом посте приведены на основе темы Twenty Ten для WordPress.
Комментарии к записи: 36
Спасибо за статью. Хорошо и интересно расписана, не для бездумного копипаста. Только один момент: даже если хочешь скопировать фрагмент кода, то Ваш SyntaxHighlighter любезно подсовывает в буфер нумерацию строк, что не очень удобно. Что я делаю не так?)
При наведении курсора на код справа появляется 3 кнопочки, если нажать на первую — откроется чистый код в новом окне без нумерации и форматирования, специально чтобы можно было сразу копировать.
А ларчик просто открывался :) Спасибо :)
Не думаю, что это очень удобно, т.к. я например, просматривая страница сайта и намереваясь туда вернуться, запоминаю, на какой странице остановился. А так при бесконечной прокрутке как найти то же самое место…?
Мой любимый способ — контрл+ф :) Но да, сама идея бесконечной прокрутки не всегда оправдывает себя, не нужно ее лепить везде :)
Я сделал чтобы у меня на главной выводились анонсы с первыми картинками и под ними социальные кнопки=) весь этот цикл кинул в луп все как надо вставил,но посты не подгружаются,а вместо них под первой картинкой по новой загружаются соц кнопки=)И что ставить в настройках чтения?
Убрал соц кнопки и теперь когда скролл на дне под первым анонсом пустая область прибавляется=( Помогите плз=)
На localhost все работает,но на хостинге нет:( подскажите плиз в чем может быть проблема:) заранее благодарен:)
Возможно, в ограничениях хостинг провайдера, попробуйте протестировать на другом хостинге.
Сегодня вдруг подгрузка начала работать:) Спасибо вам за отличную статью и за оперативность:)
Похоже я рано радовался=( на одном браузере она не работает и еще при подгрузке после новых постов за ними опять подгружаются старые=(
Извиняюсь=) я просто лох невнимательный=)
Отличный пост.Подскаэите как сделать ,чтобы подгрузка примерно за 250 пикселей до низа срабатывала?
Добрый вечер. У меня вопрос возник. Я сделал бесконечную прокрутку, все отлично работает. Только я не могу сделать вот это:
if (!is_single() || !is_page()):
// our jQuery function here
endif;
куда и как это записать, просьба ответить подробно. Заранее спасибо.
Это дополнительная функция проверки, которая вызывает скрипт функцию в том случае, если вы сейчас находитесь на любой Записи, или Странице. Внутри функции проверки должен быть сам
jQuery код. Разместить эту проверку можно в файле footer.php
Добрый день, спасибо, что ответили. Если честно, то у меня не получилось так реализовать, скорее надо было сделать что-то типа if (!is_single() || !is_page()):
echo(«our jQuery function here»);
endif;
Но для уменьшения нагрузки на сервер, я сделал просто кнопочку внизу страницы, которая просто подгружает контент с помощью jQuery.
Спасибо еще раз за ответ.
Здравствуйте, настроил тему, все работает, только вот он выводит просто все записи со всех категорий при подгрузке.. задавая любую сортировку она сбивается после подгрузки
А где это нужно прописать
function wp_infinitepaginate(){
2 $loopFile = $_POST[‘loop_file’];
3 $paged = $_POST[‘page_no’];
4 $posts_per_page = get_option(‘posts_per_page’);
5
6 # Load the posts
7 query_posts(array(‘paged’ => $paged ));
8 get_template_part( $loopFile );
9 exit;
10}
В самом конце файла темы functions.php
ДОбрый день, а как сделать все тоже самое, только с кнопкой, ПОКАЗАТЬ ЕЩЕ ЗАПИСИ. и если они заканчиваются, записей больше нет…
Это вопрос отдельной статьи, т.к. алгоритм отработки там будет другой.
Доброго дня. При спуске ко дну страницы после постов просто появляется «0» без выдачи новых постов и так каждый раз при достижении низа. Не подскажете, в чем причина?
Очень сложно так ответить, возможно настройки вашего хостера что-то блокируют.
Здравствуйте. Интегрировала все в код темы TwentyEleven. Создала отдельный loop для категории «Портфолио», функция работает, однако есть баг и я не пойму то ли это к функции относится, то ли к вордпрессу. В категории всего 3 записи, я ставлю вывод по 1ой — все ок, ставлю вывод по 2, выводит первых две записи из Портфолио и следующих 2 записи, одна из Портфолио, вторая — следующий пост из другой категории.
Есть мысли как это можно решить?
Заранее спасибо
Честно говоря, с такой проблемой не сталкивались.
Маленькое дополнение к статье.
Нормально не сработал ваш вариант javascript кода автоматического запрос новых записей при достижения конца страницы.
На Stack Overflow нашел более лучший вариант чем у вас + дополнил его с учетом, если у сайта есть футер(надо учитывать и его высоту).
var footer_height = $(‘footer’).height();
if ($(window).scrollTop() >= ($(document).height() — $(window).height()-1) — $(‘footer’).height() ) {
…
}
Так же, при динамической загрузке записей, надо блокировать повторный запрос новых данных, иначе у нас могут быть несколько неожиданных вариантов поведения:
1. Несколько запросов могут отправить и получить одни и те же данные.
2. Несколько запросов будут параллельно добавлять данные и получится мусор.
3. При выше приведенном варианте скрипта может несколько запросов отправить и получить данные последовательно.
И для того чтобы отображать или скрывать картинку ajax загрузки можно воспользоваться следующим кодом.
$.ajaxSetup({
beforeSend:function(){
$(«#[id элемента]»).show();
},
complete:function(){
$(«#[id элемента]»).hide();
}
});
Спасибо за дополнение! Думаю, это будет многим интересно.
у вас в демке не работает скрипт
а есть решение для дозагрузки страници, а не записей, у меня просто страница на сайте, ну ооочень длинная и грузится долго
Вот пытаюсь решить ту же проблему. А это вариант тоже можно преобразовать как решение. Но у меня есть подозрения, что описанные здесь приемы для ранних версий WP раз демка не работает. Но нужно пробовать
Максим, нужна помощь в вопросе? Я смотрю на сайте у тебя по прежнему тормоза.
ну как разобрался, поставил модуль для дозагрузки изображений при прокрутке, вроде быстрее стало грузится
Можгл расширить статью для «бездумного копипаста» ? То что вставлять в функтион пхп, понятно, футер тоже. А что такое Джквери ? Где его взять ? И куда вставлять вот это :
ту функцию и использовать ее совместно при помощи WordPress ajax, нам понадобится следующий код:
1
2add_action(‘wp_ajax_infinite_scroll’, ‘wp_infinitepaginate’); // for logged in user
add_action(‘wp_ajax_nopriv_infinite_scroll’, ‘wp_infinitepaginate’); // if user not logged in
Спасибо за ответ!
Спасибо автору за статью!
И в дополнение для тех, кто выводит статьи в категориях. При данном подходе пагинация «ломается». Пришлось немного повозиться, и нашёл одно решение…
В аякс запросе необходимо передавать id текущей категории в поле дата.
Например, для категории 1 это будет выглядеть так:
Т.е. data:»action=infinite_scroll&page_no=»+ pageNumber + «&loop_file=loop&cat=1»
Вот функция для определения текущей категории, её надо просто впихнуть в файл functions.php
function getCurrentCatID(){
global $wp_query;
if(is_category() || is_search()){
$cat_ID = get_query_var(‘cat’);
}
return $cat_ID;
}
Далее, сделаем динамику, и сможем получать id категории автоматом:
Т.е. data:»action=infinite_scroll&page_no=»+ pageNumber + «&loop_file=loop&cat=»
А в самом файле functions.php всё будет выглядеть так:
function wp_infinitepaginate(){
$cat = $_POST[‘cat’];
$loopFile = $_POST[‘loop_file’];
$paged = $_POST[‘page_no’];
$posts_per_page = get_option(‘posts_per_page’);
query_posts(array(‘cat’ => $cat, ‘paged’ => $paged, ‘post_status’ => ‘publish’));
get_template_part($loopFile);
exit;
}
add_action(‘wp_ajax_infinite_scroll’, ‘wp_infinitepaginate’); // for logged in user
add_action(‘wp_ajax_nopriv_infinite_scroll’, ‘wp_infinitepaginate’); // if user not logged in
Вполне рабочее решение. Испытано на себе)
Антон, можешь помочь, за вознаграждение конечно. Я на одной странице хочу прикрутить два цикла, каждый из них выводит новости с определенных категорий. Задача сделать для каждого цикла пагинацию, при чем в аджаксе, чтобы при нажатии на ссылку подгружалось еще несколько статей и только в том блоке где нажал.
Здравствуйте.
До какой версии поддерживается этот скрипт?
у меня стоит кастомная версия на базе WP2.9 как я понял там проблема в файле admin-ajax.php
когда страница пытается подгрузить новые данные вместо них идут 0000000000…
Можно что то с этим сделать или нужна более новая версия WP ?