Небольшой апгрейд постраничной навигации Drupal-a

Прислано: Stutzer

чт, 29/10/2009 - 19:57

Другие статьи по теме:

На мой взгляд, у стандартной постраничной навигации Друпала есть несколько недостатков.

Во-первых, ссылка на последнюю страницу стала бы более информативна и занимала бы меньше места, если её заменить на номер последней страницы [28].

Во-вторых, стоит нам перейти на вторую страницу и мы тут же видим две ссылки на первую страницу: [1] и [Первая]

Аналогичную картину мы видим с противоположной стороны навигационной линейки

Итак, привожу наглядный вариант своего решения этих недочетов:

Как вы можете видеть, ссылки на крайние страницы диапазона представлены в виде номеров, а также интегрированы в саму линейку.
Ссылки «Назад» и «Вперед» вынесены наружу и представлены в виде стрелок (но это уже мелочь, сделанная просто путем перевода интерфейса)

Кроме того, я добавил возможность пролистывать страницы с помощью клавиш Ctrl + ← и Ctrl + →
Протестировано в IE6+ FF3.5 Chrome 3.

Все, что нужно — это дописать несколько строк в файл template.php вашей темы оформления (а точнее переопределить функцию  theme_pager()), создать в директории темы папку js, а в ней файл jquery.paginatior.js, после чего обновить реестр тем.

UPD: Кстати, может ли быть на странице более одного пэйджера? Если да, то js-код надо бы немного переделать.

Переопределнный код функции theme_pager()

function YOURTHEMENAME_pager($tags = array(), $limit = 10, $element = 0, $parameters = array(), $quantity = 9) {
 
  global $pager_page_array, $pager_total, $theme;
 
  // Add js code for Ctrl+arrows navigation
  drupal_add_js( drupal_get_path('theme', $theme) .'/js/jquery.paginator.js' );
 
  // Calculate various markers within this pager piece:
  // Middle is used to "center" pages around the current page.
  $pager_middle = ceil($quantity / 2);
  // current is the page we are currently paged to
  $pager_current = $pager_page_array[$element] + 1;
  // first is the first page listed by this pager piece (re quantity)
  $pager_first = $pager_current - $pager_middle + 1;
  // last is the last page listed by this pager piece (re quantity)
  $pager_last = $pager_current + $quantity - $pager_middle;
  // max is the maximum page number
  $pager_max = $pager_total[$element];
  // End of marker calculations.
 
  // Prepare for generation loop.
  $i = $pager_first;
  if ($pager_last > $pager_max) {
    // Adjust "center" if at end of query.
    $i = $i + ($pager_max - $pager_last);
    $pager_last = $pager_max;
  }
  if ($i <= 0) {
    // Adjust "center" if at start of query.
    $pager_last = $pager_last + (1 - $i);
    $i = 1;
  }
  // End of generation loop preparation.
  $li_previous = theme('pager_previous', (isset($tags[1]) ? $tags[1] : t('previous page')), $limit, $element, 1, $parameters);
  $li_next = theme('pager_next', (isset($tags[3]) ? $tags[3] : t('next page')), $limit, $element, 1, $parameters);
 
  $li_first = theme('pager_first', 1, $limit, $element, $parameters);
  $li_last = theme('pager_last', $pager_max, $limit, $element, $parameters);
 
  // First-page link display condition
  $show_first = ( $i > 1 ) ? true : false ;
 
  if ($pager_total[$element] > 1) {
 
    if ( $li_previous ) $items[] = array( 'class' => 'pager-previous', 'data' => $li_previous );
    if ( $show_first && $li_first ) $items[] = array( 'class' => 'pager-first', 'data' => $li_first );
 
    // When there is more than one page, create the pager list.
    if ($i != $pager_max) {
 
      if ($i > 2) $items[] = array( 'class' => 'pager-ellipsis', 'data' => '<span>...</span>' );
 
      // Now generate the actual pager piece.
      for (; $i <= $pager_last && $i <= $pager_max; $i++) {
        if ($i < $pager_current ) $items[] = array( 'class' => 'pager-item', 'data' => theme('pager_previous', $i, $limit, $element, ($pager_current - $i), $parameters) );
        if ($i == $pager_current) $items[] = array( 'class' => 'pager-current', 'data' => '<span>' . $i . '</span>' );
        if ($i > $pager_current) $items[] = array( 'class' => 'pager-item', 'data' => theme('pager_next', $i, $limit, $element, ($i - $pager_current), $parameters) );
      }
 
      if ($i < $pager_max) $items[] = array( 'class' => 'pager-ellipsis', 'data' => '<span>...</span>' );
 
    }
 
    // Last-page link display condition
    $show_last = ( $pager_max  > ($i-1) ) ? true : false ;  
 
    // End generation.
    if ( $show_last && $li_last) $items[] = array( 'class' => 'pager-last', 'data' => $li_last );
    if ( $li_next) $items[] = array( 'class' => 'pager-next', 'data' => $li_next );
 
    return theme('item_list', $items, NULL, 'ul', array('class' => 'pager'));
  }
}

Код файла jquery.paginatior.js

if (Drupal.jsEnabled) {
 
  paginator = function () {
 
    /**
     *  Private properties
     */
    var linkNext = null;
    var linkPrev = null;
 
    /**
     *  Private methods
     */
    var setLinks = function () {
 
      linkPrev = $("ul.pager li.pager-previous a").attr("href");
      linkNext = $("ul.pager li.pager-next a").attr("href");
 
    }
 
    var navigate = function (event) {
 
      var href = null;     
      if ( event.ctrlKey && event.keyCode == 37 ) href = linkPrev;
      if ( event.ctrlKey && event.keyCode == 39 ) href = linkNext;
      if ( href ) document.location = href;
 
    }
 
 
     /**
       *  Public methods
       */
    this.__init = function () {
 
      // Get next/prev hrefs
      setLinks();
 
      // Ctrl + arrow event handle
      $(document).keydown( function(event) {
        navigate(event);
      });
 
    }
 
  }
 
 
 
  $(document).ready(function(){
 
    var pageNavigation = new paginator();
    pageNavigation.__init();
 
  });
}

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано Stan.Ezersky в чт, 29/10/2009 - 20:47.

Отлично! Но заработало только с function phptemplate_theme_pager(.......


Опубликовано Stutzer в чт, 29/10/2009 - 20:52.

Stan.Ezersky написал(а):

Отлично! Но заработало только с function phptemplate_theme_pager(.......

Спасибо, исправил. Хотя у меня и так работает.


Опубликовано Stan.Ezersky в чт, 29/10/2009 - 20:56.

"Stutzer" написал(а):

Хотя у меня и так работает.

У меня не работает, странно. Спасибо, отличная работа!-)


Опубликовано topy в чт, 29/10/2009 - 21:15.

а для 5 есть какие-нибудь варианты?


Опубликовано PVasili в чт, 29/10/2009 - 21:23.

Можно попробовать предложить и в ядре обновить дефаултного монстра?
Мы пофлешмобим ;) В 7 - думаю можно попытаться красоты добавить...


Опубликовано Stutzer в чт, 29/10/2009 - 21:28.

PVasili написал(а):

Можно попробовать предложить и в ядре обновить дефаултного монстра?
Мы пофлешмобим ;) В 7 - думаю можно попытаться красоты добавить...

Да, я думал насчет этого. Завтра переведу на английский и запощу. Кстати, куда постить то? ))


Опубликовано Stutzer в чт, 29/10/2009 - 21:38.

topy написал(а):

а для 5 есть какие-нибудь варианты?

Для пятерки нужно переопределть две функции:  theme_pager() и  theme_pager_list().


Опубликовано PVasili в чт, 29/10/2009 - 21:37.

Х.м. не завелось :(


Опубликовано Stutzer в чт, 29/10/2009 - 22:48.

PVasili написал(а):

Х.м. не завелось :(

У меня в данный момент функция определена как themename_pager(), а не phptemplate_theme_pager().
Попробуйте и так и так. У Stan.Ezersky не заработало с themename_pager(), а с phptemplate_theme_pager() заработало.

Ну и реестр тем обновить не забудьте.


Опубликовано lopata24 в чт, 29/10/2009 - 21:50.

не заработало на 6ке =\


Опубликовано Stan.Ezersky в чт, 29/10/2009 - 21:59.

lopata24, всё прекрасно работает


Опубликовано lopata24 в чт, 29/10/2009 - 22:06.

заработало, только с theme_pager
Посмотрел, как у меня определено в самом pager`e

Спасибочки ;-)

p.s. в вдогонку вопрос по стилям. Как сделать также, как в Вашем примере? =Р


Опубликовано Stutzer в чт, 29/10/2009 - 22:09.

lopata24 написал(а):

в вдогонку вопрос по стилям. Как сделать также, как в Вашем примере? =Р

Я думаю, вы получите больше удовольствия и пользы, если сами попытаетесь ;)


Опубликовано PVasili в чт, 29/10/2009 - 22:10.

С темой в имени завелось :) Классное(а главное удобное) решение.
Ещё бы строки в t() оставить как в оригинале...


Опубликовано lopata24 в чт, 29/10/2009 - 22:15.

не поверите, сам сегодня потратил не один час на это (новичек =) ).
Выжал максимум вот так

к сожалению так и не смог и не понял как сделать
1) стрелки, как у Вас
2) активную страницу в рамке, в отличии от остальных


Опубликовано Stutzer в чт, 29/10/2009 - 22:19.

lopata24 написал(а):

к сожалению так и не смог и не понял как сделать
1) стрелки, как у Вас
2) активную страницу в рамке, в отличии от остальных

Стрелки, как у нас, сделаны элементарно переводом интерфейса.
А рамки — это CSS чистой воды.


Опубликовано Stan.Ezersky в чт, 29/10/2009 - 22:33.

"lopata24" написал(а):

p.s. в вдогонку вопрос по стилям. Как сделать также, как в Вашем примере? =Р

Текущая страница: .pager-current span {background: #cecece; padding: 5px 10px; }. Дальше включайте фантазию.
Вот вам пару стрелок: ← (&larr;) и → (&rarr;)


Опубликовано Stan.Ezersky в чт, 29/10/2009 - 22:57.

"Stutzer" написал(а):

функция определена как themename_pager()

тоже заработало и перестало работать с phptemplate_theme_pager(). Загадочно...


Опубликовано sadmin в пт, 30/10/2009 - 04:55.

bellisimo


Опубликовано Dark_kz в пт, 30/10/2009 - 05:23.

волшебно! побежал пробовать)


Опубликовано xxandeadxx в пт, 30/10/2009 - 05:25.

по ссылкам "первая" и "последняя" гораздо удобнее попадать чем по номерам, и глядя на номера ещё нужно сообразить что это за числа. есть хорошая статья эту на тему http://www.birzool.com/page-navigation/


Опубликовано vgoodvin в пт, 30/10/2009 - 05:35.

Спасибо. phptemplate_pager - работает. Остальные варианты не пробовал.


Опубликовано andypost@drupal.org в пт, 30/10/2009 - 05:40.

Неплохо, для начала стоит предложить сие в  Custom pagers

А почему бы проосто не переопределить темизацию  theme_pager_first() и соседей?

PS: ссылки у автора ведут не на API, а на страницы модулей - просьба поправить...


Опубликовано PVasili в пт, 30/10/2009 - 06:37.

"andypost@drupal.org" написал(а):

для начала стоит предложить сие в Custom pagers

а почему не замахнутся на Шекспира ядро? Вроде родное ососбо ни на что не влияет, и красивости будет больше в 7...


Опубликовано apaden в пт, 30/10/2009 - 07:25.

А у меня не получилось. В каталоге с темой нет файла template.php, но есть node.tpl.php и page.tpl.php. Попробовал добавлять в оба файла код - изменений не обнаружил. И кстати что значит "обновить реестр тем"? Точнее где и как? =\ Спасибо.


Опубликовано Stutzer в пт, 30/10/2009 - 07:51.

apaden написал(а):

А у меня не получилось. В каталоге с темой нет файла template.php ... И кстати что значит "обновить реестр тем"? Точнее где и как? =\ Спасибо.

Так создайте его!
Чтобы обновить реестр, надо переустановить тему в соответствующем разделе админки.


Опубликовано lopata24 в пт, 30/10/2009 - 07:57.

"Stan.Ezersky" написал(а):

Вот вам пару стрелок: ← (&larr;) и → (&rarr;)

коды стрелок, то я знаю, только вот как их вставить?
если так t('&larr;')), то и отображает &larr;, вместо стрелки (


Опубликовано PVasili в пт, 30/10/2009 - 07:58.

"lopata24" написал(а):

к: ← (←) и →

вставьте их в перевод.
Хотя я бы оставил эти строки как в оригинале.


Опубликовано PVasili в пт, 30/10/2009 - 08:59.

Где-то с округлением вылезло :(


Опубликовано lopata24 в пт, 30/10/2009 - 09:16.

спасибо, все ок ;-)


Опубликовано Mr.Alinaki@drup... в пт, 30/10/2009 - 09:48.

Неплохо!

Но я просто поставил Paginator 3000 и все мои проблемы остались в прошлом.

Впрочем, осталось понять, как вернуть на место AJAX-возможности страничного контроля.


Опубликовано Химический Али в пт, 30/10/2009 - 09:49.

Мне больше нравится пейджер яндекса (там ссылки вперед и назад рядом), но ваш тоже оптически привлекателен.

Иссу по юзабилити для 7-рки постят где-то тут: http://drupal.org/project/issues/search/drupal?version[0]=7.x&issue_tags=Usability%2C%20d7ux

Но я думаю, его пока отклонят, предоставив возможность темизаторам самостоятельно определять внешний вид пейджера.


Опубликовано PVasili в пт, 30/10/2009 - 13:37.

Красивые текстовые стрелочки: ◄ ► видны всеми ослами ;)


Опубликовано Master of Tragedy в пт, 30/10/2009 - 13:55.

"PVasili" написал(а):

Красивые текстовые стрелочки: ◄ ► видны всеми ослами ;)

Василий как бэ намекает, что все ослы :)))))


Опубликовано p-code в пт, 30/10/2009 - 14:04.

Мой 6-ой осел пустые квадратики показывает.

//об этих символах: я для своих сайтов специально пытался избавиться от этого бага, указывал конкретно шрифт Courier New, но гад иногда все равно что-то свое выведет. Поэтому в конечном итоге решил в графику перегнать.


Опубликовано Stutzer в пт, 30/10/2009 - 20:29.

PVasili написал(а):

Где-то с округлением вылезло :(

Спасибо за найденный баг — пофиксим )


Опубликовано andypost@drupal.org в пт, 30/10/2009 - 21:02.

Насчет 7ки - еще весной была поднята тема http://www.angrydonuts.com/modernizing-the-drupal-pager-system

Нашел только http://drupal.org/node/33809 и http://drupal.org/node/173037

Походу так ни у кого и не дошли руки... а вот на www.d7ux.org вообще как-то не обсуждалось


Опубликовано PVasili в пт, 30/10/2009 - 21:08.

Может пофлешмобим активно>


Опубликовано andypost@drupal.org в пт, 30/10/2009 - 21:36.

Было бы чем :) я как-то пропустил, что там с pager - знаю только, что теперь это дело сделали в слое базы данных экстендером, а вот на уровне рендера...


Опубликовано Stutzer в сб, 31/10/2009 - 01:47.

Немного обновлений:

  • Пофиксил баг, обнаруженный пользователем  PVasili
  • Вынес JS-код в отдельный файл и переписал его в виде объекта, поскольку эстеты с Хабра загнобили )


Опубликовано Dan в сб, 31/10/2009 - 09:25.

"Stutzer" написал(а):

UPD: Кстати, может ли быть на странице более одного пэйджера? Если да, то js-код надо бы немного переделать.

Да, может - у каждого свой номер, начиная с нуля.


Опубликовано CASHMAR в сб, 31/10/2009 - 10:09.

Очень полезная и нужная вещь. Спасибо.

А как можно уменьшить число возможных страниц для перехода?
То есть, сейчас друпал показывает сразу 9 возможных страниц, а нужно всего три.


Опубликовано Stutzer в сб, 31/10/2009 - 10:21.

CASHMAR написал(а):

А как можно уменьшить число возможных страниц для перехода?

За это отвечает параметр $quantity. Можете его явно задать непосредственно в функции, в самом начале.


Опубликовано CASHMAR в сб, 31/10/2009 - 10:29.

Благодарю.
Всё работает как часы.


Опубликовано andypost@drupal.org в пн, 02/11/2009 - 00:51.

В D7 произошли изменения с выводом постраничности - теперь перед списком выводится заголовком второго уровня h2 - Pages


Опубликовано PVasili в пн, 02/11/2009 - 07:35.

Может модернизировать под обратный пейджинг? добавить константу: направление отсчёта.


Опубликовано AkeLLbl4 в пн, 02/11/2009 - 10:12.

Спасибо за решение работает замечательно!


Опубликовано aliaric в вт, 03/11/2009 - 19:58.

спасибо, заработало.


Опубликовано PVasili в чт, 05/11/2009 - 16:50.

В новой версии периодически вылезает:
warning: file_get_contents(sites/all/themes/.../js/jquery.paginator.js) [function.file-get-contents]: failed to open stream: No such file or directory in /.../includes/common.inc on line 2403.


Опубликовано Stutzer в пт, 06/11/2009 - 18:25.

PVasili написал(а):

В новой версии периодически вылезает:
warning: file_get_contents(sites/all/themes/.../js/jquery.paginator.js) [function.file-get-contents]: failed to open stream: No such file or directory in /.../includes/common.inc on line 2403.

Эм... Честно говоря идей нет.
А при каких именно действиях вылетает?
JS подгружается здесь:

// Add js code for Ctrl+arrows navigation
drupal_add_js( drupal_get_path('theme', 'YOURTHEMENAME') .'/js/jquery.paginator.js' );

Соответственно, это может произойти при смене темы, например.

UPD: Заменил
drupal_add_js( drupal_get_path('theme', 'YOURTHEMENAME') .'/js/jquery.paginator.js' );
на
drupal_add_js( drupal_get_path('theme', $theme) .'/js/jquery.paginator.js' );