🦾

paginathing.jsで切り替えたページにブラウザバックして戻れるようにする

2021/12/28に公開

これは何?

paginathing.js は自動的にページネーションを作成してるとても助かるjQueryプラグインですが、ブラウザで「戻る」と1ページ目が表示されてしまったり、任意のページに直接リンクすることができません。
コードを修正し、ブラウザバックしても見ていたページが表示されるようにします。

実装

テストページの作成

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>paginathing.js</title>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  </style>
</head>
<body>
  <div class="container">
    <div class="row">
      <div class="col-sm-12 text-center">
        <h1 class="h1"><a href="https://github.com/alfrcr/paginathing">paginathing.js</a></h1>
        <ul class="list-group list-unstyled">
          <li><a class="list-group-item" href="http://www.pref.hokkaido.jp/">北海道</a></li>
          <li><a class="list-group-item" href="http://www.pref.aomori.lg.jp/">青森県</a></li>
          <li><a class="list-group-item" href="http://www.pref.akita.lg.jp/">岩手県</a></li>
          <li><a class="list-group-item" href="http://www.pref.miyagi.jp/">宮城県</a></li>
          <li><a class="list-group-item" href="http://www.pref.akita.lg.jp/">秋田県</a></li>
          <li><a class="list-group-item" href="http://www.pref.yamagata.jp/">山形県</a></li>
          <li><a class="list-group-item" href="http://www.pref.fukushima.jp/">福島県</a></li>
          <li><a class="list-group-item" href="http://www.pref.ibaraki.jp/">茨城県</a></li>
          <li><a class="list-group-item" href="http://www.pref.tochigi.jp/">栃木県</a></li>
          <li><a class="list-group-item" href="http://www.pref.gunma.jp/">群馬県</a></li>
          <li><a class="list-group-item" href="http://www.pref.saitama.lg.jp/">埼玉県</a></li>
          <li><a class="list-group-item" href="http://www.pref.chiba.jp/">千葉県</a></li>
          <li><a class="list-group-item" href="http://www.metro.tokyo.jp/">東京都</a></li>
          <li><a class="list-group-item" href="http://www.pref.kanagawa.jp/">神奈川県</a></li>
          <li><a class="list-group-item" href="http://www.pref.niigata.jp/">新潟県</a></li>
          <li><a class="list-group-item" href="http://www.pref.toyama.jp/">富山県</a></li>
          <li><a class="list-group-item" href="http://www.pref.ishikawa.jp/">石川県</a></li>
          <li><a class="list-group-item" href="http://www.pref.fukui.jp/">福井県</a></li>
          <li><a class="list-group-item" href="http://www.pref.yamanashi.jp/">山梨県</a></li>
          <li><a class="list-group-item" href="http://www.pref.nagano.jp/">長野県</a></li>
          <li><a class="list-group-item" href="http://www.pref.gifu.lg.jp/">岐阜県</a></li>
          <li><a class="list-group-item" href="http://www.pref.shizuoka.jp/">静岡県</a></li>
          <li><a class="list-group-item" href="http://www.pref.aichi.jp/">愛知県</a></li>
          <li><a class="list-group-item" href="http://www.pref.mie.jp/">三重県</a></li>
          <li><a class="list-group-item" href="http://www.pref.shiga.jp/">滋賀県</a></li>
          <li><a class="list-group-item" href="http://www.pref.kyoto.jp/">京都府</a></li>
          <li><a class="list-group-item" href="http://www.pref.osaka.jp/">大阪府</a></li>
          <li><a class="list-group-item" href="http://web.pref.hyogo.jp/">兵庫県</a></li>
          <li><a class="list-group-item" href="http://www.pref.nara.jp/">奈良県</a></li>
          <li><a class="list-group-item" href="http://www.pref.wakayama.lg.jp/">和歌山県</a></li>
          <li><a class="list-group-item" href="http://www.pref.tottori.jp/">鳥取県</a></li>
          <li><a class="list-group-item" href="http://www.pref.shimane.jp/">島根県</a></li>
          <li><a class="list-group-item" href="http://www.pref.okayama.jp/">岡山県</a></li>
          <li><a class="list-group-item" href="http://www.pref.hiroshima.jp/">広島県</a></li>
          <li><a class="list-group-item" href="http://www.pref.yamaguchi.jp/">山口県</a></li>
          <li><a class="list-group-item" href="http://www.pref.tokushima.jp/">徳島県</a></li>
          <li><a class="list-group-item" href="http://www.pref.kagawa.jp/">香川県</a></li>
          <li><a class="list-group-item" href="http://www.pref.ehime.jp/">愛媛県</a></li>
          <li><a class="list-group-item" href="http://www.pref.kochi.jp/">高知県</a></li>
          <li><a class="list-group-item" href="http://www.pref.fukuoka.lg.jp/">福岡県</a></li>
          <li><a class="list-group-item" href="http://www.pref.saga.lg.jp/">佐賀県</a></li>
          <li><a class="list-group-item" href="http://www.pref.nagasaki.jp/">長崎県</a></li>
          <li><a class="list-group-item" href="http://www.pref.kumamoto.jp/">熊本県</a></li>
          <li><a class="list-group-item" href="http://www.pref.oita.jp/">大分県</a></li>
          <li><a class="list-group-item" href="http://www.pref.miyazaki.lg.jp/">宮崎県</a></li>
          <li><a class="list-group-item" href="http://www.pref.kagoshima.jp/">鹿児島県</a></li>
          <li><a class="list-group-item" href="http://www.pref.okinawa.jp/">沖縄県</a></li>
      </ul>
    </div>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript" src="paginathing.js"></script>
<script type="text/javascript">
  jQuery(document).ready(function($){
    $('.list-group').paginathing({
      perPage: 5,
      pageNumbers: true
    })
  });
</script>
</body>
</html>

このままだとページ推移してからリンクをクリックし、ブラウザバックすると1ページ目が表示されてしまいます。
そこで、(1)推移したページをハッシュでURLに表示 させ、ブラウザバックした際に何ページ目が表示されていたのかがわかるようにし、(2)ハッシュ値を取得して該当のページを表示させる ようにします。

推移したページをハッシュでURLに表示

paginathing.js はそのままだとページ番号をクリックしてもURLはなんの変化もないため、リンク先としてハッシュでページ番号を指定するように変更します。
また、クリックした際にURLを変更するために、history.pushState()を使います。

paginathing.js
#52行目あたり
-      li.append(a.html(text));
+      li.append(a.html(text).attr('href', '#'+page));


#200行目あたり
        _li.click(function(e) {
          e.preventDefault();
          var page = _li.data('page');

          _self.currentPage = page;
          _self.show(page);
+         history.pushState('','','#'+page);
        });

これでリンクにハッシュが設定されました。
ページ番号をクリックしてみると、index.html#3といったようにページ数がURLに追加されているのが確認できると思います。

ハッシュ値を取得して該当のページを表示させる

ページをロードする際、ハッシュ値がページ番号として正しければそのページを表示させるようにします。

paginathing.js
#27行目あたり
    this.container = $('<nav></nav>').addClass(this.options.containerClass);
    this.ul = $('<ul></ul>').addClass(this.options.ulClass);

+   var hash = Number(location.hash.substr(1));
+   if (Number.isInteger(hash) && hash>0 && hash<=this.totalPages){
+     this.currentPage = hash;
+   }
+ 
-   this.show(this.startPage);
+   this.show(this.currentPage);

    return this;

ここまでの変更で、外部リンクからのブラウザバックや、ページを指定して表示するのは完了です。ただ、このままだとページ番号を何度かクリックした後に「戻る」をしても戻りません。現状は「ページを読み込んだとき」のみハッシュからページを割り出すようになっているため、JavaScriptでの推移は動作外になっています。
ブラウザの戻るはJavaScriptでは検知できないようなので、history.replaceStateが実行されて履歴が書き換わった際にリロードするような仕組みにします。

index.html
#68行目あたり
 <script type="text/javascript">
+  history.replaceState(null, document.getElementsByTagName('title')[0].innerHTML, null);
+  window.addEventListener('popstate', function(e) {
+    window.location.reload();
+  });
 
   jQuery(document).ready(function($){
     $('.list-group').paginathing({
       perPage: 5,
       pageNumbers: true
     })
   });
 </script>

参考

Discussion