jQuery

tablesorterpagerでページ指定アクセスを可能にする

More than 1 year has passed since last update.

tablesorterpagerとは?

テーブルにソート機能を付けるjqueryライブラリtablesorterにページ指定機能を付与するアドオンです。
入手は上記リンクのDownloadの項から。

デフォルトのtablesorterpager

で、このtablesorterpagerデフォルトの導入サンプルが公式に掲載されています。
こちらがサンプルページ。

pager.png
拡大するとこんな感じ。
機能としては

  • 最初のページへ
  • 前のページへ
  • 次のページへ
  • 最後のページへ
  • 1ページあたりの表示件数変更
  • 現在のページ番号と総ページ数表示

この6つです。
そう、この中に私の求めていたページを指定してジャンプする機能が無かったのです!

ページ指定アクセス機能の実装

ソース解析

他のライブラリを探しても良かったんですがtablesorterpagerのソースを見てみるとこの足りない機能の実装ができるのでは?
と思ったので実装してみる事にしました。
以下のような最近良く見るbootstrapページャに変更します。

修正後pager.png

ソースは以下のような構造をしています。

jquery.tablesorter.pager.js

中略

  function moveToPrevPage(table) {
  var c = table.config;
  c.page--;
  if(c.page <= 0) {
    c.page = 0;
  }
  moveToPage(table);
}

中略

this.defaults = {
  size: 10,
  offset: 0,
  page: 0,
  totalRows: 0,
  totalPages: 0,
  container: null, 
  cssNext: '.next',
  cssPrev: '.prev',
  cssFirst: '.first',
  cssLast: '.last',
  cssPageDisplay: '.pagedisplay',
  cssPageSize: '.pagesize',
  seperator: "/",
  positionFixed: true,
  appender: this.appender
};
this.construct = function(settings) {
  return this.each(function() { 
    config = $.extend(this.config, $.tablesorterPager.defaults, settings);
    var table = this, pager = config.container;
    $(this).trigger("appendCache");
    config.size = parseInt($(".pagesize",pager).val());
    $(config.cssFirst,pager).click(function() {
      moveToFirstPage(table);
      return false;
    });
    $(config.cssNext,pager).click(function() {
      moveToNextPage(table);
      return false;
    });
    $(config.cssPrev,pager).click(function() {
      moveToPrevPage(table);
      return false;
    });
    $(config.cssLast,pager).click(function() {
      moveToLastPage(table);
      return false;
    });
    $(config.cssPageSize,pager).change(function() {
      setPageSize(table,parseInt($(this).val()));
      return false;
    });
  });
};
pager.html
<div id="pager" class="pager">
  <form>
    <img src="../addons/pager/icons/first.png" class="first"/>
    <img src="../addons/pager/icons/prev.png" class="prev"/>
    <input type="text" class="pagedisplay"/>
    <img src="../addons/pager/icons/next.png" class="next"/>
    <img src="../addons/pager/icons/last.png" class="last"/>
    <select class="pagesize">
      <option selected="selected"  value="10">10</option>
      <option value="20">20</option>
      <option value="30">30</option>
      <option  value="40">40</option>
    </select>
  </form>
</div>

【最初のページへ】リンクをクリックした時は【最初のページへ】関数を実行するような構造をしていたので
ここに【ページ指定】リンクをクリックした時【ページ指定】関数を実行するようにすれば良さそうです。

改修点1

関数の追加

ページ番号をクリックした時の関数を追加します。
ページ番号の指定は第2引数で持ってきています。

jquery.tablesorter.pager.js

中略

  function moveToPrevPage(table) {
  var c = table.config;
  c.page--;
  if(c.page <= 0) {
    c.page = 0;
  }
  moveToPage(table);
}
// 追加部分開始
function moveToDirectPage(table, nowpage) {
  var c = table.config;
  c.page = nowpage;
  moveToPage(table);
}
// 追加部分終了

中略

改修点2

イベントハンドラ設定

ページ番号リンクをクリックした時のクラスの設定をします。

jquery.tablesorter.pager.js

中略

this.defaults = {
  size: 10,
  offset: 0,
  page: 0,
  totalRows: 0,
  totalPages: 0,
  container: null, 
  cssNext: '.next',
  cssPrev: '.prev',
  cssFirst: '.first',
  cssLast: '.last',
// 追加部分開始
  cssDirect: '.direct',
// 追加部分終了
  cssPageDisplay: '.pagedisplay',
  cssPageSize: '.pagesize',
  seperator: "/",
  positionFixed: true,
  appender: this.appender
};

中略

改修点3

イベントハンドラの中身修正

ここが一番肝で長いです。

  • 【最初のページへ】リンクをクリックした時
    1. 【最初のページへ】リンクdisabled
    2. 【前のページへ】リンクdisabled
    3. 【次のページへ】リンクdisabled解除
    4. 【最後のページへ】リンクdisabled解除
    5. 【1ページ目】リンク選択中
  • 【前のページへ】リンクをクリックした時
    1. 1ページ目だった時【最初のページへ】リンクdisabled
    2. 1ページ目だった時【前のページへ】リンクdisabled
    3. 【次のページへ】リンクdisabled解除
    4. 【最後のページへ】リンクdisabled解除
    5. 【現在ページ】リンク選択中
  • 【次のページへ】リンクをクリックした時
    1. 最終ページだった時【最初のページへ】リンクdisabled
    2. 最終ページだった時【前のページへ】リンクdisabled
    3. 【前のページへ】リンクdisabled解除
    4. 【最初のページへ】リンクdisabled解除
    5. 【現在ページ】リンク選択中
  • 【最後のページへ】リンクをクリックした時
    1. 【最後のページへ】リンクdisabled
    2. 【次のページへ】リンクdisabled
    3. 【前のページへ】リンクdisabled解除
    4. 【最初のページへ】リンクdisabled解除
    5. 【最終ページ】リンク選択中
  • ページ指定リンクをクリックした時
    1. すべてのdisabledを解除
    2. 1ページ目だった時【最初のページへ】リンクdisabled
    3. 1ページ目だった時【前のページへ】リンクdisabled
    4. 最終ページだった時【最初のページへ】リンクdisabled
    5. 最終ページだった時【前のページへ】リンクdisabled
    6. 【現在ページ】リンク選択中
jquery.tablesorter.pager.js
$(config.cssFirst,pager).click(function() {
  moveToFirstPage(table);
// 追加部分開始
  $('.first').addClass('disabled');
  $('.prev').addClass('disabled');
  $('.next').removeClass('disabled');
  $('.last').removeClass('disabled');
  $('.pagination li').removeClass('active');
  $('.p_0').addClass('active');
// 追加部分終了
  return false;
});
$(config.cssPrev,pager).click(function() {
  moveToPrevPage(table);
// 追加部分開始
  if (config.page <= 0) {
    $('.first').addClass('disabled');
    $('.prev').addClass('disabled');
  }
  $('.next').removeClass('disabled');
  $('.last').removeClass('disabled');
  $('.pagination li').removeClass('active');
  $('.p_'+config.page).addClass('active');
// 追加部分終了
  return false;
});
$(config.cssNext,pager).click(function() {
  moveToNextPage(table);
// 追加部分開始
  if (config.page >= (config.totalPages - 1)) {
    $('.next').addClass('disabled');
    $('.last').addClass('disabled');
  }
  $('.first').removeClass('disabled');
  $('.prev').removeClass('disabled');
  $('.pagination li').removeClass('active');
  $('.p_'+config.page).addClass('active');
// 追加部分終了
  return false;
});
$(config.cssLast,pager).click(function() {
  moveToLastPage(table);
// 追加部分開始
  var nowpage = config.totalPages - 1;
  $('.first').removeClass('disabled');
  $('.prev').removeClass('disabled');
  $('.next').addClass('disabled');
  $('.last').addClass('disabled');
  $('.pagination li').removeClass('active');
  $('.p_'+nowpage).addClass('active');
// 追加部分終了
  return false;
});
// 追加部分開始
$(config.cssDirect,pager).click(function() {
  moveToDirectPage(table,   $(this).attr('page'));
  $('.pagination li').removeClass('disabled');
  $('.pagination li').removeClass('active');
  $(this).addClass('active');
  if (  $(this).attr('page') <= 0) {
    $('.first').addClass('disabled');
    $('.prev').addClass('disabled');
  }
  if (  $(this).attr('page') >= table.config.totalPages - 1) {
    $('.next').addClass('disabled');
    $('.last').addClass('disabled');
  }
  return false;
});
// 追加部分終了

改修点4

HTML

  • テキストボックス(pagedisplay)はhiddenパラメータに
  • プルダウン(pagesize)もhiddenパラメータに
  • ページ表示はDBなどから取得した件数を元にページ数を出して直接(forやforeach)記述します。
  • 内部的にはページ番号は0から始まるのでタグ内は0から記述します。
<nav>
  <form id="pager">
    <ul class="pagination">
      <li class="first disabled"><a href="#">««</a></li>
      <li class="prev disabled"><a rel="prev" href="#">«</a></li>
      <li class="direct p_0 active" page="0"><a href="#">1</a></li>
      <li class="direct p_1" page="1"><a href="#">2</a></li>
      <li class="direct p_2" page="2"><a href="#">3</a></li>
      <li class="direct p_3" page="3"><a href="#">4</a></li>
      <li class="direct p_4" page="4"><a href="#">5</a></li>
      <li class="next"><a rel="next" href="#">»</a></li>
      <li class="last"><a href="#">»»</a></li>
    </ul>
    <input type="hidden" class="pagedisplay"/>
    <input type="hidden" class="pagesize" value="10">
  </form>
</nav>

最後に

これでページ指定アクセスが可能になったはずです。
注意点として表示上は1ページからですが内部的には0から始まっています
この点にだけ気をつけていただければと思います。

1ページ内にすべてのレコードをhtmlで書いてそれをページング処理しています。
流石に10000件とかある場合重くなるので別の方法を考えたほうが良いと思います。