Как вывести постраничную навигацию в MODX Revolution с помощью GetPage?

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

Что такое getPage?

getPage  - это сниппет MODx Revolution, который позволяет вам добавлять пагинацию к элементам сайта, которые могут быть разбиты постранично. Согласно документации getPage - это…  общий сниппет для представления, навигации и возможного кеширования, многостраничных просмотров любых Елементов, которые принимают ограничительные и офсетные параметры для ограничения набора данных и устанавливает плейсхолдер, который getPage может использовать для получения общего количества элементов  выводимых на странице.

Особенности getPage

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

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

Предположим, что вы еще не запутались, и продолжим далее.

  • Следуя вышеизложеному, обратите внимание, что ваш сниппет должен включать параметры вашего обёрнутого сниппета (getResources в нашем случае) и параметры  самого getPage.
  • Не делайте вызов getPage кешируемым. Он должен быть некешируемым, даже если вы кешируете все остальные ресурсы.

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

Код
[[!getResources? &showHidden=`1` &tpl=`articleTpl` &limit=`10` &includeContent=`1` &includeTVs=`1` &processTVs=`1` &parents=`[[*id]]` &hideContainers=`1`]]

Сайт в данный момент имеет только 9, поэтому они все видны и образуют очень длинную страницу. Давайте изменим наш вызов, чтобы он показывал только 3 элемента:

Код
[[!getResources? &showHidden=`1` &tpl=`articleTpl` &limit=`3` &includeContent=`1` &includeTVs=`1` &processTVs=`1` &parents=`[[*id]]` &hideContainers=`1`]]

Теперь ваша страница отобразит только три последние статьи без навигации к остальным. Вот и настал момент для сниппета getPage.

Как использовать getPage?

Как я уже сказал ранее, getPage просто обёртывает вызов, который выводит некоторое содержимое, поэтому мы вызываем getPage и определяем обёртываемый элемент. В основном,  нам нужно заменить наш вызов getResources приведенный выше вызовом, обёрнутым всередине вызовом getPage.

Наш вызов getPage теперь будет выглядеть так:

Код
[[!getPage? &elementClass=`modSnippet` &element=`getResources` &showHidden=`1` &tpl=`articleTpl` &limit=`3` &includeContent=`1` &includeTVs=`1` &processTVs=`1` &parents=`[[*id]]` &hideContainers=`1`]]

Если вы взглянете на него внимательно, то обратите внимание, что начиная с 4 строчки, у нас всё идёт точно так же, как и в вызове getResources.  То есть мы используем те же параметры, что и в обычном вызове getResources, и всё, что мы сделали, это обернули эти параметры в вызов getPage и далее сказали getPage, что мы обёртываем сниппет (elementClass=`modSnippet`) и что этот сниппет – это getResources (element=`getResources`). Теперь понятно?

Обратите внимание:Чтобы быть совсем точным, то нам на самом деле не нужно определять здесь elementClass, так как он имеет по умолчанию значение modSnippet, поэтому вы не всегда это увидите в других примерах. Но я добавил это для завершенности и в целях обучения.

Если мы взлянем на страницу, то не увидим пока что никаких управляющих элементов для навигации по страницам. Для этого нам нужно установить два параметра в нашем вызове getPage. Это:

  • pageLimit – устанавливает максимум ссылок страниц для вывода в элементах управления перед добавлением кнопки следующая. По умолчанию, данное значение равно 5.
  • pageNavVar  - устанавливает заполнитель (плейсхолдер) для элементов управления пагинацией. По умолчанию: page.nav.

getPage имеет другие параметры, которые вы можете найти в официальной документации и использовать в зависимости от ваших нужд, в конце урока вы найдёте ссылки на официальную документацию.

Итак для завершения, мы добавим еще два параметра к нашему вызову вышу и вызовем плейсхолдер для вывода элементов управления.

Код
[[!getPage? &elementClass=`modSnippet` &element=`getResources` &showHidden=`1` &tpl=`articleTpl` &limit=`3` &includeContent=`1` &includeTVs=`1` &processTVs=`1` &parents=`[[*id]]` &hideContainers=`1` &pageLimit=`5` &pageNavVar=`page.nav` ]] [[!+page.nav]]

Обратите внимание, что вызов плейсхолдера ([[+page.nav]]) некешируемый. Вот почему я рекомендую обращатся к официальной документации.

Сохраните изменения и просмотрите страницу и внизу под тремя статьями вы должны увидеть элементы управления, которые в моём случае выглядят так:

Начальная навигация

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

 Элементы управления страницами

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

Шаблон для вывода getPage

Если мы взлянем на шаблон, который используем, то увидим, что наше управление навигацией выглядит так:

 Нормальные элементы навигации

Отлично, как же нам сделать, чтобы наша навигация выглядела так же как и в этом шаблоне?

Сниппет getPage имеет несколько параметров для шаблонизации вывода, описание которых можно найти в официальной документации (см. конец поста). Вы могли бы подумать, что вы можете установить их прямо в вызове вашего сниппета, так же как и другие параметры. Однако, согласно официальной документации вам НЕ СЛЕДУЕТ это делать. Вместо этого, вы должны использовать наборы свойств (property sets) для шаблонизации.

Что за наборы свойств?

Если вы ленитесь заглядывать в официальную документацию или не знаете английского, то специально для вас:

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

[[ElementName@PropertySetName]]

Вот и всё, лучший способ понять это – установить одно свойство и использовать его, поэтому давайте попробуем это сделать.

Если мы просмотрим исходный код для нашей страницы, то вот, что выводит вызов getPage (в версиях до 1.2.3):

Код
<p><li><a class="active" href="index.php?id=12&page=1">1</a></li> <li><a href="index.php?id=12&page=2">2</a></li> <li><a href="index.php?id=12&page=3">3</a></li> <li class="control"><a href="index.php?id=12&page=2">&gt;&gt;</a></li> <li class="control"><a href="index.php?id=12&page=3">Last</a></li></p>

Если вы посмотрите внимательно на этот код и сравните его с выводом по умолчанию в официальной документации, то увидите, что нет никакой разницы.  А нам нужно сделать, чтобы этот код выглядел как в нашем HTML шаблоне:

Код
<div class="wp-pagenavi"> <span class="pages">Page 1 of 3</span> <span class="current">1</span> <a href="#" class="page" title="2">2</a> <a href="#" class="page" title="3">3</a> <a href="#">&raquo;</a> </div>

Перед созданием набора свойств, вам нужно обратить внимание, что мы можем сделать еще пару вещей, чтобы приблизиться к нашей цели без особых сложностей. Мы можем установить теги div, а также span элементы, которые сообщают Page 1 of x.

Давайте поменяем наш заполнитель, чтобы он соответствовал нужному выводу:

Код
<div class="wp-pagenavi"> [[!+page.nav]] </div> 

Достаточно просто. Далее для span класса, мы используем два свойства: page, которое возвращает значение текущей страницы и pageCount, которое возвращает общее количество страниц. Мы будем использовать заполнители, связанные с этими свойствами используя обычный синтаксис для заполнителей показанный ниже, снова чтобы он соответствовал коду нашего шаблона:

Код
<div class="wp-pagenavi"> <span class="pages">Page [[+page]] of [[+pageCount]]</span> [[!+page.nav]] </div>

Сделав только эти изменения, мы видим, что наш вывод начинает выглядеть схоже с нашим шаблоном:

 Навигация становится похожей на навигацию в шаблоне

Поэтому давайте создадим набор свойств и вставим правильный HTML код для изменения значений по умолчанию.

Создание Набора свойств

Зайдите в дерево сайта, откройте вкладку Elements, и под Snippets, нажмите на сниппет getPage для его открытия. Далее нажмите на вкладку Properties , чтобы открыть страницу свойств.

 Набор свойств сниппета getPage

Здесь вы увидите, что у вас есть список всех свойств, которые мы видели на странице документации getPage.  Однако, они неактивны и мы не можем их редактировать и показывается сообщение "Default Properties Locked”.  Всё в порядке, это потому что мы НЕ ХОТИМ редактировать значения по-умолчанию. Если бы хотели это сдедать, тогда наши изменения перезаписались при очередном обновлении сниппета getPage, и вся работа по шаблонированию была бы утрачена. Вместо этого мы хотим создать наш собственный набор свойств и любые значения, которые мы установим в нашем пользовательском наборе будут перезаписывать значения по умолчанию в случае если мы их прикрепим к вызову. И преимуществом будет то, что часть нашего пользовательского набора свойств будет неизменной при обновлении getPage.

Давайте рассмотрим это в действии. Нажмите "add property set":

 Добавление набора свойств в getPage

У вас появится диалог, в котором вы начнёте вводить детали для вашего нового набора. Нажмите на чекбокс  "Create New Property Set" для получения полей для имени и описания, которые вы потом заполните так же, как и я:

Добавление набора свойств для getPage

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

Пользовательский набор свойств getPage

Теперь мы можем начать редактирование свойств шаблонизации для соответствия нашему HTML коду из шаблона. Помните, что если вы не уверены какие свойства указывать, то можете нажать на маленький знак «+», чтобы расскрылось описание.

Текстовое поле для отдельного свойства

Для смены значения свойства нажмите двойным кликом в поле значения и оно станет редактируемым.

Для моего набора свойств я сделаю следующие изменения:

pageNavTpl:

Код
<a href="[[+href]]" class="page" title="[[+pageNo]]">[[+pageNo]]</a>

pageActiveTpl:

Код
<span class="current">[[+pageNo]]</span>

pageFirstTpl и pageLastTpl:
Наш шаблон не содержит специальных кнопок для первой и последней страниц, поэтому оставим их пустыми. Если вы, просто оставите их пустыми, то будут использованы значения по-умолчанию, поэтому что я сделал – это вставил по пробелу в каждое поле.

pagePrevTpl:

Код
<a href="[[+href]]">&lt;&lt;</a>

pageNextTpl:

Код
<a href="[[+href]]">&gt;&gt;</a>

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

Нажмите клавишу «Сохранить» для внесения изменений в ваш набор свойств.  Теперь мой набор выглядит так:

 Пользовательский набор свойств getPage

Зелёный цвет показывает, что эти свойства взяты по-умолчанию и если вы внесёте изменения или добавите своё свойство, то цвет сменится на красный.

Отлично, теперь мы создадим наш новый набор свойств, но как наш вызов сниппета getPage будет знать, чтобы использовать их?

Прикрепление набора свойств к getPage

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

[[ElementName@PropertySetName]]

Теперь мой вызов getPage будет выглядеть вот так:

Код
[[!getPage@articlePaging? &elementClass=`modSnippet` &element=`getResources` &showHidden=`1` &tpl=`articleTpl` &limit=`3` &includeContent=`1` &includeTVs=`1` &processTVs=`1` &parents=`[[*id]]` &hideContainers=`1` &pageLimit=`5` &pageNavVar=`page.nav` ]] <div class="wp-pagenavi"> <span class="pages">Page [[+page]] of [[+pageCount]]</span> [[!+page.nav]] </div>

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

 Навигация getPage почти готова

И её функции в точности как мы ожидали при навигации на разных страницах:

 Навигация getPage по разным страницам

Неплохо, неправда ли? 

Пару дней назад Джейсон Ковард (Jason Coward) aka Opengeek обновил getPage до версии 1.2.3 желающие обновится должны будут сделать это локально, так как в Управлении дополнениями не показывает новую версию... Исходя из изменений можно улучшить отображение вывода страниц через задание параметра pageNavScheme следующим образом (см. таблицу):

ЗначениеОписание
-1(значение по-умолчанию) URL относителен к site_url
0см. http
1см. https
fullURL абсолютный, добавляется site_url из конфигурации
absURL абсолютный, добавляется base_url из конфигурации
httpURL абсолютный, принудительное приведение к http схеме
httpsURL абсолютный, принудительное приведение к https схеме

Заключение

Ну вот мы и подошли к концу этого урока основ использования getPage для создания системы пагинации для агрегированной страницы, которая использует getResources для извлечения контента, как обычно бывает в блоге. Мы рассмотрели как формировать вызов getPage и использовать его для обёртки нашего элемента getResources. Мы также немного узнали про набор свойств и как создавать и вызывать наш сниппет getPage с шаблонизацией его вывода.

14726