Постепенная загрузка страницы на jquery. Улучшаем «бесконечный скроллинг. Подгрузка внешних данных

Сколько я себя помню, веб-разработчики всегда обращались к старой-доброй пагинации в случае, когда им необходимо было отобразить большое количество контента. Не поймите меня неправильно, пагинация до сих пор является эффективным способом отображения контента, но в этой статье мы поговорим о другом подходе - “ленивой” прокрутке, также известной под названием “бесконечной прокрутки” и “отказом от пагинации”. С помощью этой техники подгрузка контента производится с помощью AJAX, когда пользователь прокручивает страницу до места, где загруженный контент заканчивается. Ленивая прокрутка используется некоторыми гигантами интернета, такими как Facebook и Pinterest. В этом посте мы попробуем реализовать свой плагин для ленивой загрузки на jQuery.

Преимущества и недостатки

Преимущества такого метода очевидны. Для того, чтобы получить дополнительную порцию контента вам нет необходимости переходить на другую страницу, что также сбивает ваше внимание и заставляет смотреть в другую область страницы. Добавив возможность ленивой загрузки вы удерживаете внимание пользователя на одной и той же области в процессе чтения.

Ленивая загрузка эффективна не во всех ситуациях. Например, в случаях, когда пользователь переходит по ссылке, а затем хочет вернуться на предыдущую страницу с помощью истории браузера, он теряет позицию в той части, которая была подгружена с помощью AJAX. Одним из способов решения подобной проблемы - открывать все ссылки в новом окне или вкладке.

В добавок, перед тем, как решите использовать эту технологию знайте, что поисковые системы не очень-то дружны с такими решениями. Для того, чтобы избежать проблемы видимости контента поисковикам, убедитесь, что вы можете предоставить альтернативу с пагинацией или картой сайта.

Начинаем

Начнем с наброска очень простой страницы. Самые важные части страницы показаны в коде ниже. Полные файлы можно посмотреть в исходниках.

HTML

Привет! Я - первый элемент Привет! Я - второй элемент Привет! Я - третий элемент Итак, это становится скучным... Попробуем кое-что новенькое Как насче того, чтобы загрузить еще элементов посредством AJAX Нажмите на кнопку ниже, чтобы загрузить больше элементов загрузить еще загружаю дополнительные элементы

CSS

#data-container { margin: 10px; } #data-container .data-item { background-color: #444444; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px; margin: 5px; color: #fff; } #loading-div { display: none; } #button-more{ cursor: pointer; margin: 0 auto; background-color: #aeaeae; color: #fff; width: 200px; height: 50px; line-height: 50px; }

Основные замечания

Если вы приглядитесь к документу, что мы создали, то увидите, что новые посты будут загружены при клике на кнопку “загрузить еще”. Вот пункты, которые мы будем реализовывать:

  • необходимо сделать запрос на URL, который вернет нам список элементов, которые необходимо будет вставить на странице
  • этот процесс должен повторяться каждый раз, как будет нажата кнопка, но в результате должны возвращаться новые посты
  • новые посты должны выдаваться на каждый запрос до тех пор, пока есть, что возвращать
  • когда больше не осталось постов, необходимо сообщить пользователю, что он достиг конца
Шаблоны ответа AJAX

В идеале необходимо объявить переменную, в которой мы будем хранить номер страницы, и с помощью этого номера определять URL, на который мы будем отправлять запрос. В нашем демонстрационном примере у нас будут три таких страницы: 2.html, 3.html и пустая страница 4.html.

Когда вы нажимаете на кнопку загрузки следующей порции данных, проходит некоторое время от момента отправки запроса и получения ответа. В таком случае мы будем прятать кнопку загрузки, а вместо нее будем показывать некоторый текст, говорящий о том, что идет загрузка элементов:

Добавляем полученные данные на страницу

Сначала вернем обратно те изменения, которые мы проделали, пока запрос еще выполнялся, то есть, показать кнопку “загрузить еще”, и спрятать информационный текст. Во-вторых, необходимо вставить полученные данные на страницу, после тех элементов, что уже есть на странице. Заметьте, что для упрощения в этом примере мы получаем данные HTML сразу, как результат запроса. Можно отсылать ответ в формате JSON, добавив в него дополнительные переменные, как статус или сообщение. Код ставки данных представлен ниже:

$(buttonId).show(); $(loadingId).hide(); $(response).appendTo($(container)); page += 1;

Обрабатываем вариант, когда данные закончились

Как только вы достигнете последнего поста, вам нужно показать пользователю, что больше постов нет. Сделать это можно различными способами. Можно отсылать статус в виде встроенного в ответ кода или сообщения. Так как мы напрямую используем разметку HTML в этом примере, то пустой ответ в нашем случае будет говорить о том, что данные закончились.

$.ajax({ ... success: function(response) { // Действие при пустом ответе if (response.trim() == "") { $(buttonId).fadeOut(); $(loadingId).text("No more entries to load!"); return; } // Если ответ верный }, ... });

Заключение

В данном демонстрационном примере мы привели очень базовый вариант обработки ленивой загрузки. Конечно же, можно сделать гораздо лучше, если постараться. Для начала, можно вообще избавиться от кнопки, и отправлять запрос, когда пользователь прокрутит страницу до конца. Это избавит пользователя от дополнительной необходимости нажимать кнопку, и в целом ускоряет процесс просмотра информации. Во-вторых, можно просто отсылать чистые данные в формате JSON, а разметку создавать налету, используя jQuery, например:

$.each(response.items, function(index, value) { $("", { "class" : "data-item", "text" : value }); });

И, наконец, ответ в JSON может содержать сообщение, говорящее, прошел ли запрос корректно; данные; а также информацию о том, есть ли еще посты для загрузки. В данном случае это более эффективный способ отправлять результат.

Песочница

рекрут 9 февраля 2013 в 21:42 Крути меня полностью. Адаптивный макет с бесконечной прокруткой
  • Чулан *

Не так давно столкнулся с задачей:
- Верстка адаптивного макета. При ресайзе окна, элементы на странице масштабируются до определенной ширины. Если ширина меньше минимальной, количество элементов в ряду становится меньше, в то же время заполняя весь экран по ширине. Смысл понятен - страница должна смотреться на любом мониторе, в т.ч. на мобильных устройствах.
- Подгрузка содержимого происходит при прокрутке страницы, так что выводится лишь часть контента, остальной подгружается по мере прокрутки вниз (аналог стены ВК).
- Появление элементов на странице происходит по очереди, плавным увеличением прозрачности каждого элемента. После того как первый элемент стал непрозрачным, эффект применяется к следующему элементу… и так для всех.

Готового решения не нашел, все пришлось писать с нуля. Возможно вся эта фича бесполезна, но если вдруг кому пригодится - юзаем, тестируем, наслаждаемся:

HTML . Для тестирования по-быстрому сверстал очень простой макет. Чтобы долго не заморачиваться со стилями, подключил bootstrap. Вот такая разметка:
Хеллоу ворлд! // В принципе, инициализировать класс можно и не здесь, и без параметров. Об этом далее. // контейнер, куда выводятся все элементы. // В нашем случае каждый item - отдельный элемент на странице. Их выведем много. // ... много-много item // Делаем очистку, т.к. у наших item"ов float:left

CSS . Тут все просто до безобразия. Подключил bootstrap, задал несколько стилей для контента - и вперед!
@import url("bootstrap.css"); body { background: #000; } section.container { position: absolute; top: 50px; bottom: 50px; width: 100%; overflow: auto;} section.container > section.item { position: relative; float: left; margin: 0; padding: 0; height: 140px; overflow: hidden;} section.container > section.item > img {width: 100%;}

JS . Вот тут уже интересно. Изначально писал функции по-отдельности, потом, когда все заработало обьединил их в один класс
GALLERY = { // задаем дефолтные параметры, которые можно будет переопределить при инициализации. container: "section.container", // родительский контейнер item: "section.item", // отдельный элемент галереи img: "section.item > img.hidden", // изображение, которое мы будем изначально "прятать" interval: 200, // задержка эффекта прозрачности count: 5, // количество добавляемых элементов init: function(params) { var _self = this; // Переопределение параметров (если такие переданы. Если нет - используем по умолчанию.) if(params != undefined){ for (var key in params) { _self = params; } } return _self.setUp(); }, setUp: function() { var _self = this; // Вешаем обработчики событий. В нашем случае такие нужны окну (ресайз) $(window).bind("resize", function(){ _self.adjust(); }); // ... на загрузку страницы $(document).ready(function(){ _self.adjust(); _self.play(); }); // ... на прокутку в родительском блоке $(_self.container).bind("scroll", function(){ _self.checkScroll(); }); }, // подгоняем ширину и количество элементов в ряду, зависимо от размера окна adjust: function() { var _self = this; var outWidth = $(_self.container).width(); var outHeight = $(_self.container).height(); var minWidth = 220; var cnt = Math.floor(outWidth / minWidth); var itemWidth = outWidth / cnt; $(_self.item).css({ "width" : itemWidth + "px" }); }, // Запускаем эффект постепенного появления элементов. Маленький нюанс: Класс hidden // для изображения нужен не за тем чтобы его прятать (это будет делать метод ниже), а для поиска // первого элемента при каждом обновлении контента. Цикл метода play() проходит // по всем изображениям с классом hidden (изначально такой есть у всех), после применения // эффекта fadeIn(), удаляя класс. Таким образом, при подгрузке нового контента, цикл начинается // не с первого элемента, а с первого подгруженного. // Впервые столкнулся с использованием метода queue(). play: function() { var _self = this; var items = $(_self.container).find(_self.img); $(items).each(function(i) { var cur = $(this).hide(); $(document).queue("myQueue", function(n) { cur.removeClass("hidden").fadeIn(_self.interval, n); }); }); $(document).dequeue("myQueue"); }, // Собственно подгрузка контента. Здесь все просто: отправляем запрос на сервер - получаем // новое содержимое на страницу (если такое есть) и выводим его в самом конце родительского блока load: function() { var _self = this; $.ajax({ url: "/load.php", type: "POST", data: {"count": _self.count}, dataType: "json", success: function(json) { if(json.output) { $(_self.container).children("div.clearfix").before(json.output); _self.adjust(); _self.play(); } } }); }, // Проверяем состояние прокрутки. Если вертикальная прокрутка в родительском блоке // равна максимально возможной - отправляем запрос за новым контентом. // Таким образом, подгрузка содержимого будет выполняться только если мы // докрутили страницу до конца. checkScroll: function() { var _self = this; var scrollH = $(_self.container).prop("scrollHeight"); var scrollT = $(_self.container).prop("scrollTop"); var scrollS = $(_self.container).prop("scrollTop") + $(_self.container).height(); if(scrollS == scrollH) { _self.load(); } } }

PHP . Тут все примитивно, только для тестирования.
$json = array(); $html = ""; $items_on_page = !empty($_POST["count"])? (int)$_POST["count"]: 5; for($i = 0; $i < $items_on_page; $i++) { $html .= ""; } $json["output"] = $html; echo json_encode($json);
Здесь в $_POST передается только один параметр (количество добавляемых блоков), но можно передать дополнительно точку старта, по принципу пагинации. Ее можно получить в JS при помощи:
var items = $(_self.container).find(_self.img); var start = items.length; // и передать в запросе: data: {"count": _self.count, "start": start}, // ... после чего при выборке данных указать..." LIMIT " . (int)$_POST["start"] . ", " . $items_on_page;

Вот такая получилась «пагинация без пагинации», да на резиновой страничке. Рабочий пример здесь.

Сколько я себя помню, веб-разработчики всегда обращались к старой-доброй пагинации в случае, когда им необходимо было отобразить большое количество контента. Не поймите меня неправильно, пагинация до сих пор является эффективным способом отображения контента, но в этой статье мы поговорим о другом подходе - “ленивой” прокрутке, также известной под названием “бесконечной прокрутки” и “отказом от пагинации”. С помощью этой техники подгрузка контента производится с помощью AJAX, когда пользователь прокручивает страницу до места, где загруженный контент заканчивается. Ленивая прокрутка используется некоторыми гигантами интернета, такими как Facebook и Pinterest. В этом посте мы попробуем реализовать свой плагин для ленивой загрузки на jQuery.

Преимущества и недостатки

Преимущества такого метода очевидны. Для того, чтобы получить дополнительную порцию контента вам нет необходимости переходить на другую страницу, что также сбивает ваше внимание и заставляет смотреть в другую область страницы. Добавив возможность ленивой загрузки вы удерживаете внимание пользователя на одной и той же области в процессе чтения.

Ленивая загрузка эффективна не во всех ситуациях. Например, в случаях, когда пользователь переходит по ссылке, а затем хочет вернуться на предыдущую страницу с помощью истории браузера, он теряет позицию в той части, которая была подгружена с помощью AJAX. Одним из способов решения подобной проблемы - открывать все ссылки в новом окне или вкладке.

В добавок, перед тем, как решите использовать эту технологию знайте, что поисковые системы не очень-то дружны с такими решениями. Для того, чтобы избежать проблемы видимости контента поисковикам, убедитесь, что вы можете предоставить альтернативу с пагинацией или картой сайта.

Начинаем

Начнем с наброска очень простой страницы. Самые важные части страницы показаны в коде ниже. Полные файлы можно посмотреть в исходниках.

HTML

Привет! Я - первый элемент Привет! Я - второй элемент Привет! Я - третий элемент Итак, это становится скучным... Попробуем кое-что новенькое Как насче того, чтобы загрузить еще элементов посредством AJAX Нажмите на кнопку ниже, чтобы загрузить больше элементов загрузить еще загружаю дополнительные элементы

CSS

#data-container { margin: 10px; } #data-container .data-item { background-color: #444444; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; padding: 5px; margin: 5px; color: #fff; } #loading-div { display: none; } #button-more{ cursor: pointer; margin: 0 auto; background-color: #aeaeae; color: #fff; width: 200px; height: 50px; line-height: 50px; }

Основные замечания

Если вы приглядитесь к документу, что мы создали, то увидите, что новые посты будут загружены при клике на кнопку “загрузить еще”. Вот пункты, которые мы будем реализовывать:

  • необходимо сделать запрос на URL, который вернет нам список элементов, которые необходимо будет вставить на странице
  • этот процесс должен повторяться каждый раз, как будет нажата кнопка, но в результате должны возвращаться новые посты
  • новые посты должны выдаваться на каждый запрос до тех пор, пока есть, что возвращать
  • когда больше не осталось постов, необходимо сообщить пользователю, что он достиг конца
Шаблоны ответа AJAX

В идеале необходимо объявить переменную, в которой мы будем хранить номер страницы, и с помощью этого номера определять URL, на который мы будем отправлять запрос. В нашем демонстрационном примере у нас будут три таких страницы: 2.html, 3.html и пустая страница 4.html.

Когда вы нажимаете на кнопку загрузки следующей порции данных, проходит некоторое время от момента отправки запроса и получения ответа. В таком случае мы будем прятать кнопку загрузки, а вместо нее будем показывать некоторый текст, говорящий о том, что идет загрузка элементов:

Добавляем полученные данные на страницу

Сначала вернем обратно те изменения, которые мы проделали, пока запрос еще выполнялся, то есть, показать кнопку “загрузить еще”, и спрятать информационный текст. Во-вторых, необходимо вставить полученные данные на страницу, после тех элементов, что уже есть на странице. Заметьте, что для упрощения в этом примере мы получаем данные HTML сразу, как результат запроса. Можно отсылать ответ в формате JSON, добавив в него дополнительные переменные, как статус или сообщение. Код ставки данных представлен ниже:

$(buttonId).show(); $(loadingId).hide(); $(response).appendTo($(container)); page += 1;

Обрабатываем вариант, когда данные закончились

Как только вы достигнете последнего поста, вам нужно показать пользователю, что больше постов нет. Сделать это можно различными способами. Можно отсылать статус в виде встроенного в ответ кода или сообщения. Так как мы напрямую используем разметку HTML в этом примере, то пустой ответ в нашем случае будет говорить о том, что данные закончились.

$.ajax({ ... success: function(response) { // Действие при пустом ответе if (response.trim() == "") { $(buttonId).fadeOut(); $(loadingId).text("No more entries to load!"); return; } // Если ответ верный }, ... });

Заключение

В данном демонстрационном примере мы привели очень базовый вариант обработки ленивой загрузки. Конечно же, можно сделать гораздо лучше, если постараться. Для начала, можно вообще избавиться от кнопки, и отправлять запрос, когда пользователь прокрутит страницу до конца. Это избавит пользователя от дополнительной необходимости нажимать кнопку, и в целом ускоряет процесс просмотра информации. Во-вторых, можно просто отсылать чистые данные в формате JSON, а разметку создавать налету, используя jQuery, например:

$.each(response.items, function(index, value) { $("", { "class" : "data-item", "text" : value }); });

И, наконец, ответ в JSON может содержать сообщение, говорящее, прошел ли запрос корректно; данные; а также информацию о том, есть ли еще посты для загрузки. В данном случае это более эффективный способ отправлять результат.

Что-то давненько я не публиковал никакого кода. Сегодня я исправлю ситуацию и дам несколько полезных сниппетов на jQuery, которые обязательно вам пригодятся на ваших сайтах.


Я не буду вдаваться в теорию, вся документация по jQuery есть на официальном сайте библиотеки. Я лишь напомню, что, такое jQuery.

jQuery - это библиотека JavaScript, фокусирующаяся на взаимодействии JavaScript и HTML. Библиотека jQuery помогает легко получать доступ к любому элементу DOM, обращаться к атрибутам и содержимому элементов DOM, манипулировать ими. Также библиотека jQuery предоставляет удобный API для работы с AJAX.

Итак, поехали!

1. Плавная прокрутка к началу страницы

Без нее уже не обходится ни один сайт. Всего лишь 4 строчки кода позволят вашим посетителям в один клик плавно пркрутить всю страницу вверх.

$("a").click(function() { $("html, body").animate({ scrollTop: 0 }, "slow"); return false; });

2. Дублируем заголовки таблиц

Чтобы улучшить восприятие и читабельность ваших таблиц, можно продублировать их заголовки снизу под таблицей. Казалось бы мелочь, но это очень удобно в сложных и больших таблицах, которые не умещаются в один экран.

Var $tfoot = $(""); $($("thead").clone(true, true).children().get().reverse()).each(function(){ $tfoot.append($(this)); }); $tfoot.insertAfter("table thead");

3. Подгрузка внешних данных

С помощью jQuery очень легко подгружать на веб-страницы внешний контент. Его можно вывести прямо в блок DIV, как в примере ниже.

$("#content").load("somefile.html", function(response, status, xhr) { // error handling if(status == "error") { $("#content").html("An error occured: " + xhr.status + " " + xhr.statusText); } });

4. Одинаковая высота колонок

Известно, что выровнять блоки по высоте стандартными средствами HTML и CSS не так-то просто. Всего несколько строк кода ниже позволит вам сделать высоту всех блоков равной высоте большего блока.

var maxheight = 0; $("div.col").each(function(){ if($(this).height() > maxheight) { maxheight = $(this).height(); } }); $("div.col").height(maxheight); 5. Табличная зебра

Как известно, восприятие и читабельность таблицы будет заметно выше если сделать разноцветное чередование строк. Это очень легко реализуется на jQuery.

$(document).ready(function(){ $("table tr:even").addClass("stripe"); });

6. Частичное обновление страницы

С помощью jQuery очень просто реализовать блочное (частичное) обновление страницы. К примеру, код ниже позволит вам каждые 10 секунд автоматически обновлять блок #refresh.

SetInterval(function() { $("#refresh").load(location.href+" #refresh>*",""); }, 10000); // milliseconds to wait

7. Предзагрузка изображений

Данный код позволяет осуществлять загрузку изображений в фоновом режиме без подгрузок в процессе просмотра страницы. Просто перечислите в 7 строке необходимые вам для предзагрузки изображения.

$.preloadImages = function() { for(var i = 0; i maxWidth){ ratio = maxWidth / width; $(this).css("width", maxWidth); $(this).css("height", height * ratio); height = height * ratio; } var width = $(this).width(); var height = $(this).height(); if(height > maxHeight){ ratio = maxHeight / height; $(this).css("height", maxHeight); $(this).css("width", width * ratio); width = width * ratio; } }); //$("#contentpage img").show(); // IMAGE RESIZE });

12. Подгрузка контента при прокрутке страницу вниз

Чаще этот прием называют как бесконечный скролл. Контент подгружается по мере прокрутки пользователем страницы. Это достаточно просто реализовать с помощью кода ниже.

Var loading = false; $(window).scroll(function(){ if((($(window).scrollTop()+$(window).height())+250)>=$(document).height()){ if(loading == false){ loading = true; $("#loadingbar").css("display","block"); $.get("load.php?start="+$("#loaded_max").val(), function(loaded){ $("body").append(loaded); $("#loaded_max").val(parseInt($("#loaded_max").val())+50); $("#loadingbar").css("display","none"); loading = false; }); } } }); $(document).ready(function() { $("#loaded_max").val(50); });

13. Проверка загрузки изображения

Часто бывает нужно проверить загружено изображение в данный момент или нет. И в этом снова нам поможет jQuery.

Var imgsrc = "img/image1.png"; $("").load(function () { alert("image loaded"); }).error(function () { alert("error loading image"); }).attr("src", imgsrc);

14. Сортировка по-алфавиту

Если вам нужна динамическая сортировка списка по-алфавиту, вам обязательно поможет этот небольшой сниппет.

$(function() { $.fn.sortList = function() { var mylist = $(this); var listitems = $("li", mylist).get(); listitems.sort(function(a, b) { var compA = $(a).text().toUpperCase(); var compB = $(b).text().toUpperCase(); return (compA < compB) ? -1: 1; }); $.each(listitems, function(i, itm) { mylist.append(itm); }); } $("ul#demoOne").sortList(); });

Сохраните - пригодится.

Всё самое новое и интересное из мира Вордпресс в моём Телеграм-канале . Подписываемся!



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: