Дата публикации
17 Июня 2019
Дата изменения
5 Июля 2020
Уникальных просмотров
3.679

Оглавление

pdoPage — сниппет позволяет вывести результаты работы других сниппетов с разбивкой на страницы.

Есть несколько серьезных отличий от сниппета getPage:

Параметры

Параметры сниппета pdoPage.

Параметры организации пагинации

При вызове сниппета pdoPage указываются параметры сниппета, для которого производится пагинация. Данный сниппет должен понимать параметры &page и &limit. По умолчанию pdoPage принимает все параметры pdoTools и кроме того, некоторые свои:

Название По умолчанию Описание
&plPrefix   Префикс для выставляемых плейсхолдеров.
&limit 10 Ограничение количества результатов на странице. Число должно быть больше 0, иначе вам не нужен этот сниппет.
&maxLimit 100 Максимально возможный лимит выборки. Перекрывает лимит, указанный пользователем через url.
&offset 0 Пропуск результатов от начала.
&page 1 Номер страницы для вывода. Перекрывается номером, указанным пользователем через url.
&pageVarKey page Имя переменной для поиска номера страницы в url.
&totalVar page.total Имя плейсхолдера для сохранения общего количества результатов.
&pageLimit 5 Количество ссылок на страницы. Если больше или равно 7 — включается продвинутый режим отображения.
&element pdoResources Имя сниппета для запуска.
&pageNavVar page.nav Имя плейсхолдера для вывода пагинации.
&pageCountVar pageCount Имя плейсхолдера для вывода количества страниц.
&pageLinkScheme   Шаблон генерации ссылок на страницы. Позволяет реализовать ЧПУ пагинацию. См. ниже.
&cache 0 Кэширование результатов работы сниппета.
&cacheTime 3600 Время актуальности кэша, в секундах.
&cache_user    
&toPlaceholder   Если не пусто, сниппет сохранит все данные в плейсхолдер с этим именем, вместо вывода не экран.
&ajax   Включить поддержку ajax запросов.
&ajaxMode    
&ajaxElemWrapper #pdopage jQuery селектор элемента-обёртки с результатами и пагинацией.
&ajaxElemRows #pdopage.rows jQuery селектор элемента с результатами.
&ajaxElemPagination #pdopage.pagination jQuery селектор элемента с пагинацией.
&ajaxElemLink #pdopage.pagination a jQuery селектор ссылки на страницу.
&ajaxElemMore #pdopage.btn-more jQuery селектор кнопки загрузки результатов при ajaxMode = button.
&ajaxHistory   Сохранять номер страницы в url при работе в режиме ajax.
&frontend_js [[+assetsUrl]]js/pdopage.min.js Ссылка на javascript для подключения сниппетом.
&frontend_css [[+assetsUrl]]css/pdopage.min.css Ссылка на css стили оформления для подключения сниппетом.
&setMeta 1 Регистрация мета-тегов со ссылками на предыдущую и следующую страницу.
&strictMode 1 Строгий режим работы. pdoPage делает редиректы при загрузке несуществующих страниц.

Параметры шаблонов

Название По умолчанию Описание
&tplPage @INLINE <li><a href="[[+href]]">[[+pageNo]]</a></li> Чанк оформления обычной ссылки на страницу.
&tplPageWrapper @INLINE <div class="pagination"><ul class="pagination">[[+first]][[+prev]][[+pages]][[+next]][[+last]]</ul></div> Чанк оформления всего блока пагинации, содержит плейсхолдеры страниц.
&tplPageActive @INLINE <li class="active"><a href="[[+href]]">[[+pageNo]]</a></li> Чанк оформления ссылки на текущую страницу.
&tplPageFirst @INLINE <li class="control"><a href="[[+href]]">[[%pdopage_first]]</a></li> Чанк оформления ссылки на первую страницу.
&tplPageLast @INLINE <li class="control"><a href="[[+href]]">[[%pdopage_last]]</a></li> Чанк оформления ссылки на последнюю страницу.
&tplPagePrev @INLINE <li class="control"><a href="[[+href]]">&laquo;</a></li> Чанк оформления ссылки на предыдущую страницу.
&tplPageNext @INLINE <li class="control"><a href="[[+href]]">&raquo;</a></li> Чанк оформления ссылки на следующую страницу.
&tplPageSkip @INLINE <li class="disabled"><span>...</span></li> Чанк оформления пропущенных страниц при продвинутом режиме отображения (&pageLimit >= 7).
&tplPageFirstEmpty @INLINE <li class="control"><span>[[%pdopage_first]]</span></li> Чанк, выводящийся при отсутствии ссылки на первую страницу.
&tplPageLastEmpty @INLINE <li class="control"><span>[[%pdopage_last]]</span></li> Чанк, выводящийся при отсутствии ссылки на последнюю страницу.
&tplPagePrevEmpty @INLINE <li class="disabled"><span>&laquo;</span></li> Чанк, выводящийся при отсутствии ссылки на предыдущую страницу.
&tplPageNextEmpty @INLINE <li class="disabled"><span>&raquo;</span></li> Чанк, выводящийся при отсутствии ссылки на следующую страницу.
&ajaxTplMore @INLINE <button class="btn btn-default btn-more">[[%pdopage_more]]</button> Шаблон кнопки для загрузки новых результатов при ajaxMode = button

Поддержка Ajax

pdoPage может выдавать JSON и прерывать работу движка при соответствии запроса трём характеристикам:

  1. У сниппета включен параметр &ajax.
  2. Запрос сделан при помощи XMLHttpRequest, то есть — ajax.
  3. В запросе содержится переменная, указанная у сниппета в &pageVarKey. По умолчанию, это page.

То есть, вам достаточно просто указать сниппету &ajax=`1` и отправить странице GET запрос типа:

$.get('document.html?page=5', function(response) {
    console.log(response);
}, 'json');

И в ответ вы получите JSON c результатами работы, пагинацией и служебными данными: номер страницы, сколько всего страниц и сколько всего результатов. Учитывая, что pdoPage — это сниппет-обёртка, таким образом вы можете заставить работать через ajax многие другие сниппеты.

Встроенная Ajax пагинация

Начиная с версии 1.10 pdoPage умеет загружать страницы через ajax. Вам нужно только обернуть его вызов в специальную разметку:

/* modParser */
<div id="pdopage">
    <div class="rows">
        [[!pdoPage?
            &parents=`0`
            &ajaxMode=`default`
        ]]
    </div>
    [[!+page.nav]]
</div>

/* pdoParser */
<div id="pdopage">
    <div class="rows">
        {$_modx->runSnippet('!pdoPage', [
        'parents' => 0,
        'ajaxMode' => 'default',
        ])}
    </div>
    {'page.nav' | placeholder}
</div>

Внутри [[+page.nav]] у нас div с классом pagination — так в pdoPage по умолчанию.

Вы можете менять идентификаторы этой разметки следующими параметрами:

Два последних селектора рассчитывают на то, что вы не меняли стандартное оформление блока пагинации в параметре &tplPageWrapper. Работа обеспечивается подключением javascript файла из параметра &frontent_js.

Параметр &ajax=`1` указывать необязательно. Не пустой &ajaxMode активирует его самостоятельно.

Загрузка кнопкой

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

Так что, логично его размещать вверху:

/* modParser */
<div id="pdopage">
    [[!+page.nav]]
    <div class="rows">
        [[!pdoPage?
            &parents=`0`
            &ajaxMode=`button`
            &limit=`5`
        ]]
    </div>
</div>

/* pdoParser */
<div id="pdopage">
    {'page.nav' | placeholder}
    <div class="rows">
        {$_modx->runSnippet('!pdoPage', [
        'parents' => 0,
        'ajaxMode' => 'button',
        'limit' => 5,
        ])}
    </div>
</div>

Используются всё те же селекторы, плюс:

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

Если вывод плавающего блока в пагинацией не нужен, то просто сделайте ему display: none в вашем css.

Загрузка при прокрутке

Этот способ очень похож на предыдущий, только нет кнопки и её не нужно нажимать — всё делается автоматически при прокрутке страницы.

/* modParser */
<div id="pdopage">
    [[!+page.nav]]
    <div class="rows">
        [[!pdoPage?
            &parents=`0`
            &ajaxMode=`scroll`
        ]]
    </div>
</div>

/* pdoParser */
<div id="pdopage">
    {'page.nav' | placeholder}
    <div class="rows">
        {$_modx->runSnippet('!pdoPage', [
        'parents' => 0,
        'ajaxMode' => 'scroll',
        ])}
    </div>
</div>

History API

pdoPage поддерживает работу с History API вашего браузера. Это значит, что когда &ajaxMode включен, сниппет может сохранять номер страницы в адресной строке, чтобы при перезагрузке ничего не терялось. Также правильно работает навигация кнопками «вперёд\назад» браузера.

Вы можете изменить это поведение параметром &ajaxHistory, включив или выключив его. По умолчанию он работает следующим образом:

При отключении &ajaxHistory блок в постраничной навигацией скрывается, чтобы страницы нельзя было переключать вручную.

Функции обратного вызова

Вы можете указать функции, которые будут вызываться до и после загрузки страницы через ajax вот так:

pdoPage.callbacks['before'] = function(config) {
    console.log('Конфиг перед загрузкой!', config);
};
pdoPage.callbacks['after'] = function(config, response) {
    console.log('Конфиг после загрузки!', config);
    console.log('Ответ от сервера!', response);
}

С версии 1.11.0-pl появилась возможность добавления обработчика на событие pdopage_load:

$(document).on('pdopage_load', function(e, config, response) {
    console.log(e, config, response);
});

Проверка данных в config позволит вам различить разные вызовы pdoPage на одной странице.

Человекопонятная навигация

С версии 2.2.2 можно использовать параметр &pageLinkScheme для указания схемы генерации ссылок на страницу. В параметре может быть всего 2 плейсхолдера:

Для примера укажите такой параметр:

/* modParser */
[[!pdoPage?
    &parents=`0`
    &pageLinkScheme=`/[[+pageVarKey]]-[[+page]]`
]]
[[!+page.nav]]

/* pdoParser */
{$_modx->runSnippet('!pdoPage', [
'parents' => 0,
'pageLinkScheme' => '/{$pageVarKey}-{$page}',
])}
{'page.nav' | placeholder}

Это приведёт к генерации ссылок, типа

/res/news/
/res/news/page-2
/res/news/page-3

При переходе по этим ссылкам (кроме первой) MODx будет выдавать ошибку 404, потому что страниц с этими адресами не существует. Так что, нам нужно написать плагин для их обработки:

<?php
// Реагируем только на событие OnPageNotFound
if ($modx->event->name == 'OnPageNotFound') {
    // Определяем ключ запроса из настроек
    $req = $modx->getOption('request_param_alias');
    // Ловим нужный ключ страницы
    $pageVarKey = 'page';
    // Если в запросе повторяется наш шаблон "pageVarKey-page", то работаем дальше
    if (preg_match("#.*?({$pageVarKey}-(\d+))#", $_REQUEST[$req], $matches)) {
        // Отрезаем ЧПУ строку и получаем точный адрес текущей страницы
        $uri = str_replace($matches[1], '', $matches[0]);

        // Ищем страницу по этому адресу
        $id = 0;
        // Сначала как есть, со слешем на конце
        if (!$id = $modx->findResource($uri)) {
            // Если не находим - то пробуем отрезать слэш и ищем повторно
            $id = $modx->findResource(rtrim($uri, '/'));
        }

        // Если ресурс найден
        if ($id) {
            // Добавляем номер страницы в глобальные массивы, чтобы pdoPage их там увидел
            $_GET[$pageVarKey] = $_REQUEST[$pageVarKey] = $matches[2];
            // И загружаем эту страницу
            $modx->sendForward($id);
        }
        // Если ресурс не был найден - ничего не делаем, возможно запрос поймает другой плагин
    }
}

Теперь этот плагин будет обрабатывать вашу ЧПУ навигацию.

Примеры

Так как pdoPage является частью pdoTools, в параметре &element у него сразу прописан сниппет pdoResources. Поэтому простой вызов сниппета выведет вам дочерние ресурсы:

/* modParser */
[[!pdoPage?
    &tpl=`@INLINE <p>[[+idx]] <a href="/[[+uri]]">[[+pagetitle]]</a></p>`
]]
[[!+page.nav]]

/* pdoParser */
{$_modx->runSnippet('!pdoPage', [
'tpl' => '@INLINE <p>{$idx} <a href="/{$uri}">{$pagetitle}</a></p>',
])}
{'page.nav' | placeholder}

Выводим все возможные документы сайта:

/* modParser */
[[!pdoPage?
    &tpl=`@INLINE <p>[[+idx]] <a href="/[[+uri]]">[[+pagetitle]]</a></p>`
    &parents=`0`
]]
[[!+page.nav]]

/* pdoParser */
{$_modx->runSnippet('!pdoPage', [
'tpl' => '@INLINE <p>{$idx} <a href="/{$uri}">{$pagetitle}</a></p>',
'parents' => 0,
])}
{'page.nav' | placeholder}

Включаем навигацию с пропуском страниц. Обратите внимание, что если страниц выходит меньше 7, то будет работать обычная навигация.

/* modParser */
[[!pdoPage?
    &tpl=`@INLINE <p>[[+idx]] <a href="/[[+uri]]">[[+pagetitle]]</a></p>`
    &parents=`0`
    &pageLimit=`7`
]]
[[!+page.nav]]

/* pdoParser */
{$_modx->runSnippet('!pdoPage', [
'tpl' => '@INLINE <p>{$idx} <a href="/{$uri}">{$pagetitle}</a></p>',
'parents' => 0,
'pageLimit' => 7,
])}
{'page.nav' | placeholder}

Активируем кэш на 30 минут:

/* modParser */
[[!pdoPage?
    &tpl=`@INLINE <p>[[+idx]] <a href="/[[+uri]]">[[+pagetitle]]</a></p>`
    &parents=`0`
    &pageLimit=`7`
    &cache=`1`
    &cacheTime=`1800`
]]
[[!+page.nav]]

/* pdoParser */
{$_modx->runSnippet('!pdoPage', [
'tpl' => '@INLINE <p>{$idx} <a href="/{$uri}">{$pagetitle}</a></p>',
'parents' => 0,
'pageLimit' => 7,
'cache' => 1,
'cacheTime' => 1800,
])}
{'page.nav' | placeholder}

Указываем максимальный лимит выборки. Теперь, какой бы limit не указал пользователь в url — все равно будет не больше 10 результатов на странице.

Благодарность автору

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

Один из самых популярных способов поблагодарить автора, воспользоваться сервисом Яндекс.Деньги.

Время работы: 0,1339 s
Время запросов: 0,1339 s
Количество запросов: 24
Источник: cache