【JavaScript】Pagination.jsでページネーションをさくっと実装

人生には、JavaScriptでページネーションすることもあるでしょう。僕はありました。
というわけで[Pagination.js](https://github.com/superRaytin/paginationjs)を使った例を丁寧めに紹介します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/d082a596-9a02-f94c-8b63-4388637e26bf.png)
# HTML, JavaScript
[Pagination.js](https://pagination.js.org/)と[jQuery](https://jquery.com/)を公式から持ってきて下さい。スタイルは次の章で説明します。

```html
<head>
  <link rel="stylesheet" href="./contents.css"><!-- 後で -->
  <link rel="stylesheet" href="./pagination.css"><!-- 後で -->
</head>
<body>
  <ul>
    <div id="diary-all-contents"></div><!-- コンテンツの埋め込み先をid指定 -->
  </ul>
  <div class="pager" id="diary-all-pager"></div><!-- ページャーの埋め込み先をid指定 -->
  <script src="./jquery-3.3.1.min.js"></script>
  <script src="./pagination.min.js"></script>
  <script>
    // [1] 配列のデータを用意
    var diary = [
      {
        title: "○○を買った",
        link: "https://foobar/diary/1234",
        category: "交流",
        class: "Relationship",
        date: "2020年02月04日"
      },
      // ...以下略
    ]
    // [2] pagination.jsの設定
    $(function() {
      $('#diary-all-pager').pagination({ // diary-all-pagerにページャーを埋め込む
        dataSource: diary,
        pageSize: 5, // 1ページあたりの表示数
        prevText: '&lt; 前へ',
        nextText: '次へ &gt;',
        // ページがめくられた時に呼ばれる
        callback: function(data, pagination) {
          // dataの中に次に表示すべきデータが入っているので、html要素に変換
          $('#diary-all-contents').html(template(data)); // diary-all-contentsにコンテンツを埋め込む
        }
      });
    });
    // [3] データ1つ1つをhtml要素に変換する
    function template(dataArray) {
      return dataArray.map(function(data) {
        return '<li class="list"><a href="' + data.link + '">'
        + '<p class="category category-' + data.class + '">' + data.category + '</p>'
        + '<p class="title">' + data.title + '</p>'
        + '<p class="date">' + data.date + '</p></a></li>'
      })
    }
  </script>
</body>
```

## [1] データの用意
Pagination.jsに渡すデータは配列であればなんでもOK。
今回はこういうデータの配列があるとしましょう。

```javascript
var diary = [
  {
    title: "○○を買った",
    link: "https://foobar/diary/1234",
    category: "交流",
    class: "Relationship",
    date: "2020年02月04日"
  },
  // ...以下略
]
```

## [2] Pagination.jsの設定
要素の埋め込み先、1ページあたりの表示数、「戻る」「進む」の表記などを設定できる。

```javascript
$(function() {
  $('#diary-all-pager').pagination({ // diary-all-pagerにページャーを埋め込む
    dataSource: diary,
    pageSize: 5, // 1ページあたりの表示数
    prevText: '&lt; 前へ',
    nextText: '次へ &gt;',
    // ページがめくられた時に呼ばれる
    callback: function(data, pagination) {
      // dataの中に次に表示すべきデータが入っているので、html要素に変換
      $('#diary-all-contents').html(template(data)); // diary-all-contentsにコンテンツを埋め込む
    }
  });
});
```

以下のコールバックはページがめくられた時に呼び出され、次に表示すべきデータも渡ってくる。
このデータをhtml要素に変換することで自由な表示が可能。関数の中身は次で。

```javascript
    // ページがめくられた時に呼ばれる
    callback: function(data, pagination) {
      // dataの中に次に表示すべきデータが入っているので、html要素に変換
      $('#diary-all-contents').html(template(data)); // diary-all-contentsにコンテンツを埋め込む
    }
```

他の設定は[公式ドキュメント](https://pagination.js.org/docs/index.html)を見て下さい。

## [3] データをHTMLへ
ここでは、Pagination.jsが渡してくれた表示データをHTML要素に変換する。
今回は予め外側を`<ul>`要素で囲んでおいたので、そこに埋め込むための`<li>`のリストを作る。
ここにスタイルを当てるのは、素のJavaScriptだとちょっと辛い。

```javascript
function template(dataArray) {
  return dataArray.map(function(data) {
    return '<li class="list"><a href="' + data.link + '">'
    + '<p class="category category-' + data.class + '">' + data.category + '</p>'
    + '<p class="title">' + data.title + '</p>'
    + '<p class="date">' + data.date + '</p></a></li>'
  })
}
```

4行目ではカテゴリによってクラスが変わるようにしている。

```javascript
    + '<p class="category category-' + data.class + '">' + data.category + '</p>'
```
data.classが`Qiita`なら`category-Qiita`というクラスに。対応するCSSは後述。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/e6e8b7c8-49dc-6a45-9ad7-3a1277fa663b.png)
# スタイル
## コンテンツのスタイル
この部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/716aed2b-17a2-0bb6-5cd7-949a5c9737a1.png)
ここは表示するデータや目的に応じて好きなスタイルを付けて下さい。
あくまで一例として今回使用したスタイルを記載。

```css:contents.css
p, a, ul, li {
  margin: 0;
  padding: 0;
  border: 0;
}
ul {
  list-style: none;
}
.list {
  line-height: 1;
  border-bottom: 1px solid #d8d8d8;
  padding: 12px 0;
}
.list a {
  display: flex;
  align-items: center;
  text-decoration: none;
}
.list .date {
  color: darkblue;
  margin: 0 15px 0 auto;
}
.list .category {
  margin: 0 15px 0;
  padding: 4px;
  display: flex;
  align-items: center;
  color: white;
}
 /* カテゴリによって違う背景色に */
.list .category-Qiita {
  background-color: lightblue;
}
.list .category-Relationship {
  background-color: lightseagreen;
}
.list .category-Food {
  background-color: lightslategray;
}
.list .category-Family {
  background-color: lightcoral;
}
.pager {
  margin: 18px 0 0 0;
}
```

## ページャーのスタイル
この部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272677/48f0a41c-b468-9008-c378-4ec263dc8d8c.png)
デフォルトで`paginationjs`などのクラス名が付いたHTMLを出力されるので、それにスタイルを付けます。
もっとよい方法があるかもしれません。

```css:pagination.css
.paginationjs-pages > ul > li > a {
  padding: 6px 18px;
  color: white;
  background-color: lightgreen;
  border: 1px solid darkcyan;
}
.paginationjs-pages > ul > li > a:hover {
  color: black;
  background-color: white;
}
.paginationjs-pages > ul > li.active > a {
  color: black;
  background-color: white;
}
.paginationjs-pages > ul > li.disabled > a {
  color: black;
  background-color: white;
}
.paginationjs-prev {
  margin: 0 16px 0 0;
}
.paginationjs-next {
  margin: 0 0 0 16px;
}
.paginationjs-page {
  margin: 0 4px;
}
.paginationjs-pages > ul {
  display: flex;
  align-items: baseline;
}
.paginationjs-pages > ul > li.paginationjs-ellipsis.disabled > a {
  border: none;
  color: black;
  margin: 0 4px;
  padding: 0;
}
```


# 感想
さくっと実装できました。遷移もスムーズでよかったです。
Pagination.jsはけっこう奥が深そうなので、次の機会があればもう少し掘り下げようと思います。