new pager
authorChristian Weiske <cweiske@cweiske.de>
Wed, 16 Nov 2016 10:14:23 +0000 (11:14 +0100)
committerChristian Weiske <cweiske@cweiske.de>
Wed, 16 Nov 2016 10:14:23 +0000 (11:14 +0100)
data/templates/pager.htm
src/phinde/Html/Pager.php
www/css/phinde.css

index ed86a55..d2baa8a 100644 (file)
@@ -2,48 +2,34 @@
 {% if pager.numPages > 1 %}
 <div class="pagination pagination-centered">
 <ul>
- {% if links.back %}
+ {% if links.prev.active %}
  <li>
-  {{links.back|raw}}
+  {{links.prev.html|raw}}
  </li>
  {% else %}
- <li class="disabled"><a href="#">« prev</a></li>
+ <li class="disabled"><a href="#">{{links.prev.title}}</a></li>
  {% endif %}
 
- {% if links.first %}
+ {% for link in links.pages %}
+  {% if link.active %}
  <li>
-  {{links.first|raw}}
- </li>
- {% else %}
- <li class="disabled"><a href="#">first</a></li>
- {% endif %}
-
- {% for page in links.pages %}
-  {% if page|length <= 3 %}
- <li class="active">
-  <a href="#">{{page|raw}}</a>
+  {{link.html|raw}}
  </li>
+  {% elseif link.title == "…" %}
+ <li class="disabled"><a href="#">{{link.title}}</a></li>
   {% else %}
- <li>
-  {{page|raw}}
+ <li class="active">
+  <a href="#">{{link.title}}</a>
  </li>
   {% endif %}
  {% endfor %}
 
- {% if links.last %}
- <li>
-  {{links.last|raw}}
- </li>
- {% else %}
- <li class="disabled"><a href="#">last</a></li>
- {% endif %}
-
- {% if links.next %}
+ {% if links.next.active %}
  <li>
-  {{links.next|raw}}
+  {{links.next.html|raw}}
  </li>
  {% else %}
- <li class="disabled"><a href="#">next »</a></li>
+ <li class="disabled"><a href="#">{{links.next.title}}</a></li>
  {% endif %}
 </ul>
 </div>
index 9726d95..cd944b9 100644 (file)
@@ -1,6 +1,24 @@
 <?php
 namespace phinde;
 
+/**
+ * A better result pager.
+ *
+ * Rules:
+ * - "Prev" and "next" buttons are outside
+ * - No "first" and "last", but "1" and "$totalNumOfPages"
+ * - two previous and two next pages are shown as buttons
+ * - When current page is <= 5, first 5 pages are shown
+ * - ".." is only shown for at least two skipped pages
+ *
+ * Examples:
+ * [<< prev] [1] [2] [3] [next >>]
+ * [<< prev] [1] [2] [3] [4] [5] [next >>]
+ * [<< prev] [1] [2] [3] [4] [5] ... [8] [next >>]
+ * [<< prev] [1] ... [4] [5] [6] [7] [8] ... [10] [next >>]
+ *
+ * replace ".." with actual link when between previous and next is only one
+ */
 class Html_Pager
 {
     protected $pager;
@@ -19,50 +37,108 @@ class Html_Pager
         if (strpos($filename, '%d') !== false) {
             $append = false;
         }
-        //fix non-static factory method error
-        error_reporting(error_reporting() & ~E_STRICT);
-        $this->pager = \Pager::factory(
-            array(
-                'mode'        => 'Sliding',
-                'perPage'     => $perPage,
-                'delta'       => 2,
-                'totalItems'  => $itemCount,
-                'currentPage' => $currentPage,
-                'urlVar'      => 'page',
-                'append'      => $append,
-                'path'        => '',
-                'fileName'    => $filename,
-                'separator'   => '###',
-                'spacesBeforeSeparator' => 0,
-                'spacesAfterSeparator' => 0,
-                'curPageSpanPre' => '',
-                'curPageSpanPost' => '',
-                'firstPagePre' => '',
-                'firstPageText' => 'first',
-                'firstPagePost' => '',
-                'lastPagePre' => '',
-                'lastPageText' => 'last',
-                'lastPagePost' => '',
-                'prevImg' => '« prev',
-                'nextImg' => 'next »',
-            )
-        );
+
+        $numPages = ceil($itemCount / $perPage);
+        $this->numPages = $numPages;
+
+        //1-based
+        $pages = [
+            1 => true,
+            2 => true,
+            $numPages - 1 => true,
+            $numPages     => true,
+        ];
+        if ($currentPage <= 6) {
+            $pages[3] = 3;
+            $pages[4] = 4;
+            $pages[5] = 5;
+        }
+        if ($currentPage >= $numPages - 5) {
+            $pages[$numPages - 2] = true;
+            $pages[$numPages - 3] = true;
+            $pages[$numPages - 4] = true;
+        }
+        for ($n = $currentPage - 2; $n <= $currentPage + 2; $n++) {
+            $pages[$n] = true;
+        }
+        foreach (array_keys($pages) as $key) {
+            if ($key < 1 || $key > $numPages) {
+                unset($pages[$key]);
+            }
+        }
+        if ($currentPage >= 7 && !isset($pages[4])) {
+            $pages[3] = null;
+        }
+        if ($currentPage <= $numPages - 6 && !isset($pages[$numPages - 3])) {
+            $pages[$numPages - 2] = null;
+        }
+
+        ksort($pages);
+        foreach ($pages as $pageNum => &$value) {
+            if ($pageNum == $currentPage) {
+                $value = ['active'=> false, 'title' => $pageNum];
+            } else if ($value !== null) {
+                $value = $this->makeLink($pageNum, $filename);
+            } else {
+                $value = ['active'=> false, 'title' => '…'];
+            }
+        }
+
+        $prev = ['active'=> false, 'title' => '« prev'];
+        if ($currentPage > 1) {
+            $prev = $this->makeLink($currentPage - 1, $filename, '« prev');
+        }
+        $next = ['active'=> false, 'title' => 'next »'];
+        if ($currentPage < $numPages) {
+            $next = $this->makeLink($currentPage + 1, $filename, 'next »');
+        }
+        //first and last are for opensearch
+        $first = ['active'=> false, 'title' => 'first'];
+        if ($currentPage > 1) {
+            $first = $this->makeLink(1, $filename, 'first');
+        }
+        $last = ['active'=> false, 'title' => 'last'];
+        if ($numPages > 1 && $currentPage < $numPages) {
+            $last = $this->makeLink($numPages, $filename, 'last');
+        }
+
+        $this->links = [
+            'prev'  => $prev,
+            'next'  => $next,
+            'first' => $first,
+            'last'  => $last,
+            'pages' => $pages,
+        ];
     }
 
+    protected function makeLink($pageNum, $filename, $title = null)
+    {
+        $title = $title === null ? $pageNum : $title;
+        $url   = $filename . '&page=' . $pageNum;
+        return [
+            'active' => true,
+            'url'    => $url,
+            'title'  => $title,
+            'html'   => '<a href="' . htmlspecialchars($url)
+                . '" title="Page ' . $pageNum . '">'
+                . htmlspecialchars($title)
+                . '</a>',
+        ];
+    }
 
     public function getLinks()
     {
-        $arLinks = $this->pager->getLinks();
-        $arLinks['pages'] = explode('###', $arLinks['pages']);
-        return $arLinks;
+        return $this->links;
     }
 
     public function getFullUrls()
     {
-        $arLinks = $this->pager->getLinks();
-        $arUrls = array();
-        foreach ($arLinks['linkTagsRaw'] as $key => $link) {
-            if (isset($link['url'])) {
+        $arUrls  = array();
+        foreach ($this->links as $key => $link) {
+            if ($key == 'pages') {
+                continue;
+            }
+            if ($link['active']) {
                 $arUrls[$key] = str_replace(
                     '&amp;', '&',
                     Helper::fullUrl('/'  . $link['url'])
@@ -74,6 +150,7 @@ class Html_Pager
 
     public function numPages()
     {
+        return $this->numPages;
         return $this->pager->numPages();
     }
 }
index eae8dd9..b08a03a 100644 (file)
@@ -6,6 +6,13 @@
     margin-bottom: 1ex;
 }
 
+/* bootstrap 2.1.1 does not have this style, 2.3.2 would have it */
+.pagination ul > .active > a,
+.pagination ul > .active > a:hover {
+    background-color: #0088cc;
+    color: #FFF;
+}
+
 .hits {
     list-style-type: none;
     margin-left: 0px;