[pdoTools] 1.9.6-rc Ajax пагинация в pdoPage
Предлагаю вам обновление pdoTools с одной очень интересной функцией — возможностью работы pdoPage через ajax.
С этого момент pdoPage может выдавать JSON и прерывать работу движка при соответствии запроса трём характеристикам:
На этом сайте и на bezumkin.ru все страницы с пагинацией уже переведены на работу через ajax — можно тестировать, а под катом вас ждёт готовый код для внедрения у себя.
Написать универсальный javascript для всех сайтов с пагинацией не представляется возможным, хотя бы потому, что я не знаю, какие у вас там используются идентификаторы на странице. Так что показываю готовый код с комментариями, который вы легко сможете адаптировать для себя.
Первым делом оборачиваем вызов pdoPage в блоки с идентификаторами:
Теперь вешаем javascript на эту разметку:
В итоге, вы получаете нормальную ajax навигацию в современных браузерах, с сохранением параметров в url, и обычную загрузку страниц поисковиками и древним IE6.
Вот еще пара наворотов, которые можно добавить после
1. Прокрутка контента страницы вверх:
2. Если вы используете мой сниппет Title, то неплохо бы эмулировать его работу и при ajax навигации.
Всем успешных ajax навигаций!
С этого момент pdoPage может выдавать JSON и прерывать работу движка при соответствии запроса трём характеристикам:
- Запрос сделан при помощи XMLHttpRequest, то есть — ajax.
- В запросе содержится переменная, указанная у сниппета в &pageVarKey. По умолчанию, это page.
- У сниппета включен параметр &ajax=`1`.
$.get('document.html?page=5', function(response) {
console.log(response);
}, 'json');
И в ответ вы получите JSON c результатами работы, пагинацией и служебными данными: номер страницы, сколько всего страниц и сколько всего результатов.На этом сайте и на bezumkin.ru все страницы с пагинацией уже переведены на работу через ajax — можно тестировать, а под катом вас ждёт готовый код для внедрения у себя.
Написать универсальный javascript для всех сайтов с пагинацией не представляется возможным, хотя бы потому, что я не знаю, какие у вас там используются идентификаторы на странице. Так что показываю готовый код с комментариями, который вы легко сможете адаптировать для себя.
Первым делом оборачиваем вызов pdoPage в блоки с идентификаторами:
<div id="tickets-wrapper">
<div id="tickets-rows">
[[!pdoPage?
&element=`getTickets`
&parents=`0`
&ajax=`1`
]]
</div>
[[!+page.nav]]
</div>
Внутри [[+page.nav]] у нас div с классом pagination — так в pdoPage по умолчанию.Теперь вешаем javascript на эту разметку:
// Работаем только при поддержке браузером History Api
if (window.history && history.pushState) {
var JustLoaded = true;
// Задаём функцию загрузки страницы
function loadPage(href) {
// Обёртка всего блока
var parent = $('#tickets-wrapper');
// Индикация загрузки контента
parent.css({opacity: .3});
// Если загружается первая страница, то у неё нет параметра ?page=1 -
// нужно добавить самостоятельно, иначе pdoPage не отзовётся
if (!href.match(/page=\d+/)) {
href += href.match(/\?/)
? '&page=1'
: '?page=1';
}
// Запрос на сервер по указанной ссылке
$.get(href, function(response) {
// Дальше работаем только если пришел нормальный ответ
if (response && response['total']) {
// Вставляем контент и пагинацию в заранее подготовленные элементы
parent.find('#tickets-rows').html(response['output']);
parent.find('.pagination').html(response['pagination']);
// Убираем индикацию загрузки
parent.css({opacity: 1});
}
}, 'json');
}
// Вешаем обработчик ссылок в нашей разметке на кнопки пагинации
$(document).on('click', '#tickets-wrapper .pagination a', function(e) {
e.preventDefault();
var href = $(this).prop('href');
history.pushState({href: href}, '', href);
loadPage(href);
JustLoaded = false;
});
// Вешаем обработчик на переключение кнопок браузера взад-вперёд
$(window).on('popstate', function(e) {
if (!JustLoaded && e.originalEvent.state && e.originalEvent.state['href']) {
loadPage(e.originalEvent.state['href']);
}
JustLoaded = false;
});
// При первой загрузке страницы помещаем в историю текущий адрес
history.replaceState({href: window.location.href}, '');
}
Выглядит страшно, но если убрать все комментарии, то останется одна небольшая функция и 2 обработчика событий.В итоге, вы получаете нормальную ajax навигацию в современных браузерах, с сохранением параметров в url, и обычную загрузку страниц поисковиками и древним IE6.
Вот еще пара наворотов, которые можно добавить после
parent.css({opacity: 1});
1. Прокрутка контента страницы вверх:
$('html, body').animate({
scrollTop: parent.position().top + 50 || 0
}, 0);
К parent.position().top можно прибавить несколько пикселей для более точного позиционирования. На стандартной верстке Bootstrap3 нужно плюсовать высоту навигационной панели — 50px.2. Если вы используете мой сниппет Title, то неплохо бы эмулировать его работу и при ajax навигации.
var delimeter = ' / ';
var title = [];
var tmp = $('title').text().split(delimeter);
for (var i = 0; i < tmp.length; i++) {
if (i === tmp.length - 1 && response.page && response.page > 1) {
title.push('стр. ' + response.page + ' из ' + response.pages);
}
if (!tmp[i].match(/^стр\./)) {
title.push(tmp[i]);
}
}
$('title').text(title.join(delimeter));
Всем успешных ajax навигаций!
Комментарии: 45
И это теперь из коробки?! Ну спасибо! Больше не нужно костыли собственного изготовления!
Вот это новость!
Работает все великолепно. Спасибо за ajax.
На здоровье!
Классно! Компоненты постепенно переходят на ajax из коробки — становится всё приятнее с ними работать. Спасибо!
Нашел небольшой баг с js-скриптом — если с обычной страницы перейти на страницу с пагинацией (или наоборот) и после воспользоваться кнопками браузера следующая/предыдущая страница — поле контента (даже если возвращаешься на страницу без пагинации) применяет свойство opacity: .3 и останавливается на этом.
Это из-за
Как сделать лучше — не придумал.
// При первой загрузке страницы помещаем в историю текущий адрес
history.replaceState({href: window.location.href}, '');
Как сделать лучше — не придумал.
Добавил индикацию первой загрузки через переменную JustLoaded — проблема решена.
БлагоДарю, Василий! Порадовал!
Приветствую. Есть вопрос по поводу запроса $.get(href, function(response){… — он возвращает объект, в котором responseText = содержимое страницы, откуда берутся response['output'] и response['pagination'] что-то не совсем пойму.
Пишу, так как в виде из коробки не работает. Стопориться как раз на запросе.
Пишу, так как в виде из коробки не работает. Стопориться как раз на запросе.
- Запрос сделан при помощи XMLHttpRequest, то есть — ajax.
- В запросе содержится переменная, указанная у сниппета в &pageVarKey. По умолчанию, это page.
- У сниппета включен параметр &ajax=`1`.
С этого момент pdoPage может выдавать JSON и прерывать работу движка при соответствии запроса трём характеристикам:
Что-то из этого ты упустил.
[[!pdoPage?
&element=`msProducts`
&tpl=`catalogListitem`
&includeThumbs=`270х320`
&limit=`12`
&totalVar=`total_products`
&tplPageWrapper=`
@INLINE
<div class="beta-pagination text-center"><div class="pagination">[[+prev]][[+pages]][[+next]]</div></div>
`
&tplPageActive=` @INLINE <a class="is-active">[[+pageNo]]</a>`
&tplPagePrev=`@INLINE <a href="[[+href]]"><i class="fa fa-chevron-left"></i></a>`
&tplPageNext=`@INLINE <a href="[[+href]]"><i class="fa fa-chevron-right"></i></a>`
&tplPage=`@INLINE <a href="[[+href]]">[[+pageNo]]</a>`
&tplPagePrevEmpty=``
&tplPageNextEmpty=``
]]
[[!+page.nav]]
Не могу понять, что не так, js такой же, как в примере.prntscr.com/5j94e2
prntscr.com/5j94il
Ты действительно не понимаешь, что сниппету нужно указать &ajax=`1`?
Извиняюсь, параметр был включен, я скопировал уже после того, как убрал его. Так что не в этом дело.
Версия pdoTools 1.9.6 или выше?
Блин, 1.9.3. В этом проблема. Еще раз извиняюсь, был уверен что последняя версия стоит, так как не горела кнопка «обновить»
Нет слов.
Замечен небольшой косяк. Например, видно на главной странице этого замечательного сайта. После перехода на вторую страницу через пагинатор, нажатие на кнопку «назад» в браузере ни к чему не приводит. Потом, после следующих кликов по пагинатору все ок. Проблема в переменной JustLoaded, решение: JustLoaded = false в обработчике кликов для пагинатора.
- The “footer” of the page will be typically impossible to reach.
- Currently there is no way to cancel or opt-out of the behavior.
- There is no permalink to a given state of the page.
- Dynamically adding more content to the page increases the memory footprint of the browser. Depending on the browser, this could account for around 50megs of RAM.
- Analytics will not immediately capture the event, so custom configuration is required.
Поправил, спасибо!
Василий, если есть возможность, подскажи, как сделать кнопку «Показать еще 50 (зависит от лимита на странице) товаров» на аяксе вместо обычной пагинации? Очень востребованная штуковина. Пример можно посмотреть на юлмарте.
Если штука сложная, готов проспонсировать доработку в стандартный pdoPage.
Заранее благодарен.
Если штука сложная, готов проспонсировать доработку в стандартный pdoPage.
Заранее благодарен.
Я такие штуки не люблю, потому что нельзя дать ссылку на конкретную страницу.
А некий якорь вставлять в выдачу каждых N товаров?
А потом что? При открытии страницы сразу делать 5 ajax запросов, чтобы загрузить 5 страниц и дойти до 6й?
Или грузить сразу 6ю и 2 ссылки «загрузить до» и «загрузить после»?
И какой профит, по сравнению с нормальными страницами? Я его не вижу. Разве что радоваться, что «каквконтактике».
Или грузить сразу 6ю и 2 ссылки «загрузить до» и «загрузить после»?
И какой профит, по сравнению с нормальными страницами? Я его не вижу. Разве что радоваться, что «каквконтактике».
Мне до вконтактиков дела нет, хотя и у них есть чему поучиться. Пользователям удобно. Им важно не ссылки давать, а товар искать. Кнопку Ткнул и тебе подгрузились еще тридцать товаров. Заскроллил вперед и вернулся к предыдущему экрану без всяких «назад-вперед » и переключения пагинации. Тем более, что доля мобильных посещений выросла с 7% до внушительных 32%. На мобильном проскроллить страницу вниз и вверх в разы удобнее. А в пагинацию попасть пальцем — это отдельная история.
Сайт опрашивали анонимно. От 10к посещений в сутки. Сайт-каталог. 71,4% выбрали подгрузку товаров по кнопке, как наиболее удобную.
Это я не к тому, что я весь из себя прав. В блого-социальной нише пагинация функциональнее. Когда же речь идет о каталоге с фильтрами — клиентам незачем ссылаться на пагинацию, они скидывают ссылки на товар или лайкают во вконтактике или лицокниге.
Спасибо, что ответил.
Сайт опрашивали анонимно. От 10к посещений в сутки. Сайт-каталог. 71,4% выбрали подгрузку товаров по кнопке, как наиболее удобную.
Это я не к тому, что я весь из себя прав. В блого-социальной нише пагинация функциональнее. Когда же речь идет о каталоге с фильтрами — клиентам незачем ссылаться на пагинацию, они скидывают ссылки на товар или лайкают во вконтактике или лицокниге.
Спасибо, что ответил.
Аргументы хорошие и логичные. Есть, правда, и контраргументы:
Для добавления «в коробку» нужно решить хотя бы основную проблему — прямую ссылку на страницу. Вконтакте есть хороший пример такой работы.
Если ты готов оплатить 3500 рублей, то я добавлю в pdoPage ajax навигацию двумя способами: по страницам и прокруткой.
Для добавления «в коробку» нужно решить хотя бы основную проблему — прямую ссылку на страницу. Вконтакте есть хороший пример такой работы.
Если ты готов оплатить 3500 рублей, то я добавлю в pdoPage ajax навигацию двумя способами: по страницам и прокруткой.
Деньги переведу в понедельник. Рад, что ты прислушался. Спасибо!
Вконтакте схема немного другая. Там контент подгружается динамически при прокрутке по вертикали. Это действительно нагружает систему. Поэтому в каталогах используют кнопку «Показать еще 30 товаров». Они подгружаются на ту же страницу. Это ничем по ресурсоемкости не отличается от пагинации и в то же время очень удобно. Именно о таком решении я рассказывал.
Вконтакте схема немного другая. Там контент подгружается динамически при прокрутке по вертикали. Это действительно нагружает систему. Поэтому в каталогах используют кнопку «Показать еще 30 товаров». Они подгружаются на ту же страницу. Это ничем по ресурсоемкости не отличается от пагинации и в то же время очень удобно. Именно о таком решении я рассказывал.
Т.е., в контексте коммерции (магазина) интересен именно такой вариант — подгрузка по кнопке.
Отправил через спасибо 3500Р.
Пришло!
Всё уже в работе, завтра постараюсь выложить новую версию.
Всё уже в работе, завтра постараюсь выложить новую версию.
Отлично! Спасибо за оперативность!
Готово, можно тестировать.
Василий, добрый день. Заметил такую особенность. Если вызывать pdoPage кэшированным и на странице уже есть вывод, например крошек, то в крошки выводится контент из pdoPage. С чем это может быть связано? Также при кэшируемом вызове, первый раз пагинация отображается, после пропадает.
Сниппет для пагинации нельзя вызывать кэшированным.
Очень надеюсь, что не придётся объяснять — почему.
Очень надеюсь, что не придётся объяснять — почему.
Окей, возможно что-то не дочитал в документации. Исправлюсь.
Видимо, объяснить всё же нужно.
Сниппет пагинации должен принимать параметр с номером страницы, чтобы выводить те или иные ресурсы, в зависимости от него. Соотвественно, он должен вызываться всегда, при каждой загрузке страницы. А кэшированные сниппеты вызываются только один раз — в этом сам смысл кэширования.
Отсюда следует простейший вывод, что такие сниппеты, как pdoPage и getPage нельзя кэшировать в принципе, иначе они не будут работать.
Сниппет пагинации должен принимать параметр с номером страницы, чтобы выводить те или иные ресурсы, в зависимости от него. Соотвественно, он должен вызываться всегда, при каждой загрузке страницы. А кэшированные сниппеты вызываются только один раз — в этом сам смысл кэширования.
Отсюда следует простейший вывод, что такие сниппеты, как pdoPage и getPage нельзя кэшировать в принципе, иначе они не будут работать.
Спасибо за доходчивое объяснение. Вопрос снят.
Василий, немного не в теме пишу, но к сожалению ответа не получил ни от кого вот по какому вопросу.
modx.pro/help/5339/. Если не сложно, не могли бы вы подсказать, как правильно делать. А то приходится для фильтров использовать getProducts, а у него есть свои недостатки.
modx.pro/help/5339/. Если не сложно, не могли бы вы подсказать, как правильно делать. А то приходится для фильтров использовать getProducts, а у него есть свои недостатки.
Василий приветствую! Сколько ты возьмешь денег что бы записать подробный видео урок о том как выводить настроить pdoPage что бы он выводил ресурсы, и можно было переключатся по ресурсам, без перезагрузки общей страницы. Простите что пишу своими словами, только что начинаю изучать не знаю терминологию.
Вот мой чанк ни чего не работает
[[!pdoPage?
&element=`pdoResources`
&showHidden=`1`
&limit=`6`
&pageLimit=`5`
&parents=`3`
&cache=`1`
&cacheTime=`2600000`
&cache_user=`1`
&pageNavVar=`nav-page`
&ajax=`1`
&tpl=`ListPortTpl`
&includeTVs=`port-teg, image-small, image-big`
]]
точнее все работает, в url ( /portfolio/?page=2), но идет перезагрузка общей страницы. А нужно что бы только перезагружалась область вывода ресурсов в определенном блоке на сайте.
Если оборачивать в
<div id="pdopage">
<div class="rows">
</div>
[[!+page.nav]]
</div>
то почему то 1 страница работает, на 2 переключает, но ресурсы не активные....((( как это сделать не понятно
Возникла проблема при использовании ajax пагинации с помощью кнопки «Загрузить еще» и мультиязычности. В шаблоне &tpl используется перевод фразы [[%babel.download? &topic=`translate` &namespace=`babel`]]. При загрузке страницы перевод выводится в том правильном контексте. Но после попытки подгрузить следующие страницы аяксом перевод срабатывает в контексте, который настроен по умолчанию. На сайте два языка: русский и английски. По умолчанию используется русский. Однако когда в английском варианте сайта начинаешь подгружать другие страницы, то перевод выводит русский. Если в шаблон вставить [[++cultureKey]] то выводит после подгрузки «ru», а должно «en». Как поправить?
Нашел для себя пока решение вот таким способом: [[*context_key:is=`web`:then=`Скачать`:else=`Download`]]
Приветствую! Мучаюсь с проблемой… надеюсь на помощь
При ajax-загрузке контента с помощью pdopage перестают работать скрипты слайдеров и галерей, потому что они работают только с контентом, который был загружен во время загрузки страницы. Перепробовал уже
$('body').on( 'click', '.btn-more', function() { });
и
pdoPage.callbacks['after'] = function(config, response) { };
и
$(document).ajaxSuccess(function() { };
ничто не отрабатывает правильно. При вызове обычного alert, изначально появляется модальное окно, а уже потом подгружается контент, из чего делаю вывод, что при клике по кнопке с классом .btn-more изначально загружаются скрипты, а уже потом подгружается контент с помощью ajax, с которым подгруженные скрипты уже не работают. Помогите понять как решить проблему
При ajax-загрузке контента с помощью pdopage перестают работать скрипты слайдеров и галерей, потому что они работают только с контентом, который был загружен во время загрузки страницы. Перепробовал уже
$('body').on( 'click', '.btn-more', function() { });
и
pdoPage.callbacks['after'] = function(config, response) { };
и
$(document).ajaxSuccess(function() { };
ничто не отрабатывает правильно. При вызове обычного alert, изначально появляется модальное окно, а уже потом подгружается контент, из чего делаю вывод, что при клике по кнопке с классом .btn-more изначально загружаются скрипты, а уже потом подгружается контент с помощью ajax, с которым подгруженные скрипты уже не работают. Помогите понять как решить проблему
Всем привет еще раз!
Получилось заставить работать галерею с помощью ajaxStop. Правда тут возникла другая сложность — после подгрузки контента ajax'ом функция, которая была отработана во время изначальной загрузки страницы продолжает работать и после загрузки контента ajax'ом, при этом дублируя результаты отработки после каждого нажатия на кнопку btn-more. Пока не могу понять как обнулить результаты отработки функции и одновременно снова загрузить скрипт.
Получилось заставить работать галерею с помощью ajaxStop. Правда тут возникла другая сложность — после подгрузки контента ajax'ом функция, которая была отработана во время изначальной загрузки страницы продолжает работать и после загрузки контента ajax'ом, при этом дублируя результаты отработки после каждого нажатия на кнопку btn-more. Пока не могу понять как обнулить результаты отработки функции и одновременно снова загрузить скрипт.
$(function(){
var $gallery = $('.rows a').simpleLightbox();
$gallery.on('show.simplelightbox', function(){
console.log('Requested for showing');
})
.on('shown.simplelightbox', function(){
console.log('Shown');
})
.on('close.simplelightbox', function(){
console.log('Requested for closing');
})
.on('closed.simplelightbox', function(){
console.log('Closed');
})
.on('change.simplelightbox', function(){
console.log('Requested for change');
})
.on('next.simplelightbox', function(){
console.log('Requested for next');
})
.on('prev.simplelightbox', function(){
console.log('Requested for prev');
})
.on('nextImageLoaded.simplelightbox', function(){
console.log('Next image loaded');
})
.on('prevImageLoaded.simplelightbox', function(){
console.log('Prev image loaded');
})
.on('changed.simplelightbox', function(){
console.log('Image changed');
})
.on('nextDone.simplelightbox', function(){
console.log('Image changed to next');
})
.on('prevDone.simplelightbox', function(){
console.log('Image changed to prev');
})
.on('error.simplelightbox', function(e){
console.log('No image found, go to the next/prev');
console.log(e);
});
});
$(document).ajaxStop(function() {
var $gallery = $('.rows a').simpleLightbox();
});
it-stroyka.ru/
код PDO page выдает ошибку после пагинации Array что не так
[[!pdoPage?
&element=`getTickets`
&tpl=`tpl.tickets.post`
&includeTVs=`tel,gorod,cena,vadelit,map,phototik,photo1`
&limit=`10`
&ajaxMode=`scroll`
&includeContent=`1`
]] [[!+page.nav]]
код PDO page выдает ошибку после пагинации Array что не так
[[!pdoPage?
&element=`getTickets`
&tpl=`tpl.tickets.post`
&includeTVs=`tel,gorod,cena,vadelit,map,phototik,photo1`
&limit=`10`
&ajaxMode=`scroll`
&includeContent=`1`
]] [[!+page.nav]]
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.