Skip to content

Instantly share code, notes, and snippets.

@tanakahisateru
Last active October 7, 2017 08:29
Show Gist options
  • Save tanakahisateru/d198092ff42e53100d1e to your computer and use it in GitHub Desktop.
Save tanakahisateru/d198092ff42e53100d1e to your computer and use it in GitHub Desktop.
Bootstrap responsive pagination widget for Yii
<?php
namespace app\utils\widgets;
use yii\helpers\Html;
use yii\widgets\LinkPager;
/**
* ResponsiveLinkPager can reduce or style each buttons for responsive design.
*
* Define CSS classes as if maxButtonCount would be so. For example below applies hidden-xs class
* to page buttons to show only 5 buttons for narrow device.
*
* ~~~
* <?= ResponsiveLinkPager::widget([
* 'pagination' => $dataProvider->pagination,
* 'maxButtonCount' => 10,
* 'pageCssClassButtonCountMap' => [
* 'hidden-xs' => 5,
* ],
* ]) ?>
* ~~~
*
* ~~~
* <?= ListView::widget([
* 'dataProvider' => $dataProvider,
* // ...
* 'pager' => [
* 'class' => ResponsiveLinkPager::className(),
* 'maxButtonCount' => 10,
* 'pageCssClassButtonCountMap' => [
* 'hidden-xs' => 5,
* ]
* ]
* ]) ?>
* ~~~
*/
class ResponsiveLinkPager extends LinkPager
{
/**
* @var array
*/
public $pageCssClassButtonCountMap = [];
/**
* @inheritdoc
*/
protected function renderPageButtons()
{
$pageCount = $this->pagination->getPageCount();
if ($pageCount < 2 && $this->hideOnSinglePage) {
return '';
}
$buttons = [];
$currentPage = $this->pagination->getPage();
// first page
$firstPageLabel = $this->firstPageLabel === true ? '1' : $this->firstPageLabel;
if ($firstPageLabel !== false) {
$buttons[] = $this->renderPageButton($firstPageLabel, 0, $this->firstPageCssClass, $currentPage <= 0, false);
}
// prev page
if ($this->prevPageLabel !== false) {
if (($page = $currentPage - 1) < 0) {
$page = 0;
}
$buttons[] = $this->renderPageButton($this->prevPageLabel, $page, $this->prevPageCssClass, $currentPage <= 0, false);
}
// internal pages
list($beginPage, $endPage) = $this->getPageRange();
//////////////////////////////// modification begin
$class2ranges = [];
foreach ($this->pageCssClassButtonCountMap as $class => $buttonCount) {
$class2ranges[$class] = $this->buttonsVisibilityRange($currentPage, $beginPage, $endPage, $buttonCount);
}
for ($i = $beginPage; $i <= $endPage; ++$i) {
$classes = [];
foreach ($class2ranges as $class => $range) {
list($leftLimit, $rightLimit) = $range;
if (!($i >= $leftLimit && $i <= $rightLimit)) {
$classes[] = $class;
}
}
$buttons[] = $this->renderPageButton($i + 1, $i, implode(' ', $classes), false, $i == $currentPage);
}
//////////////////////////////// end
// next page
if ($this->nextPageLabel !== false) {
if (($page = $currentPage + 1) >= $pageCount - 1) {
$page = $pageCount - 1;
}
$buttons[] = $this->renderPageButton($this->nextPageLabel, $page, $this->nextPageCssClass, $currentPage >= $pageCount - 1, false);
}
// last page
$lastPageLabel = $this->lastPageLabel === true ? $pageCount : $this->lastPageLabel;
if ($lastPageLabel !== false) {
$buttons[] = $this->renderPageButton($lastPageLabel, $pageCount - 1, $this->lastPageCssClass, $currentPage >= $pageCount - 1, false);
}
return Html::tag('ul', implode("\n", $buttons), $this->options);
}
/**
* @param integer $active
* @param integer $begin
* @param integer $end
* @param integer $buttonCount
* @return array
*/
protected function buttonsVisibilityRange($active, $begin, $end, $buttonCount)
{
$leftLimit = $active - floor($buttonCount / 2);
if ($leftLimit < $begin) {
$leftLimit = $begin;
}
$rightLimit = $leftLimit + $buttonCount - 1;
if ($rightLimit > $end) {
$leftLimit -= $rightLimit - $end;
if ($leftLimit < $begin) {
$leftLimit = $begin;
}
$rightLimit = $end;
}
return [$leftLimit, $rightLimit];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment