ロゴ
HOME > jQuery・Javascript > Ajax非同期通信を使ったページャー表現

Ajax非同期通信を使ったページャー表現

2014年07月27日

表示する件数が多い場合に、ページ選択アイコンが並びぶページャーをjQuery+非同期通信で実現する方法です。調べるとおそらくはプラグイン等がたくさんあると思うのですが、そこは先ず自分で作ってみてからって事で。

サンプルは郵便局ホームページからダウンロード出来るCSVを利用させて頂きました。

サンプル ダウンロード

HTMLとCSS

/*
 * 表部分
 */
#pager table{
	border: 1px solid #DDDDDD;
	border-collapse: collapse;
  font-size:85%
}
#pager table tr th{
	border: 1px solid #DDDDDD;
	padding:3px;
  background: #828282;
  color:#FFF;
}
#pager table tr td{
	border: 1px solid #DDDDDD;
	padding:5px;
}

/*
 * ページャーアイコン
 */
#ajax_pager{
	height: 30px;
	margin-bottom: 10px;
	line-height: 30px;
	overflow: hidden;
	padding:2px;
}
#ajax_pager a{
	display: block;
	border: 1px solid #DDDDDD;
	float: left;
  padding-left:5px;
  padding-right:5px;
	text-align:center;
	text-decoration:none;
	margin-right:2px;
}
#ajax_pager a:hover{
	background-color: #828282;
	color: #FFFFFF;
}
#ajax_pager .nowpage{
	border: 1px solid #DDDDDD;
	float: left;
  padding-left:5px;
  padding-right:5px;
	height:30px;
	background-color: #828282;
	color: #FFFFFF;
	text-align:center;
	line-height: 30px;
	margin-right:2px;
}
#ajax_pager .page_message{
	float: left;
	height:30px;
  line-height: 30px;
  padding-left: 30px;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="pager.js"></script>

    <div id="pager"><!-- 表を表示する部分 --></div>
    <script type="text/javascript">
       $(function(){
          $('#pager').pager({
              'page_max': '30' //1ページの表示件数
             ,'row'     : ['zip','area','add1','add2'] //tableに表示する項目
             ,'th'      : ['郵便番号','都道府県','住所1','住所2'] //表題
          });
       });
    </script>

オプションで1ページあたりの表示件数と、表示したい項目や表題などが設定出来ます。

pager.js


(function($){
  $.fn.pager = function(options){
    
    var settings = $.extend( {
      'page_max' : 100
      ,'row' : ['']
      ,'th'  : ['']
    }, options); 
 
/*
 * データの読み込み
 */
    var reading = function(div,nowpage){ 
      
      $("#list_div").html('<img src="loader2.gif" />'); 
      
      var page_max = settings.page_max;
      
      var start = 0;
      if( nowpage > 1 ){
        start = (page_max*nowpage) - page_max+1; //2ページ目以降は次の開始位置を計算
      }

      $.ajax({
          type: "POST",
          url: "pager.php",
          data: "page_max="+page_max+"&start="+start,
          async:false,
          success: function(xml){
            var len = $(xml).find("len").text();
            
            page_icon (nowpage,len);
            var len = len.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , '$1,' ); //3桁ごとにカンマ
            $("#ajax_pager").append('<p class="page_message">データ件数は <strong>'+len+'</strong>件です</p>');
            
            var html = '<table>';
            
            html += '<tr>';
              for(var i=0; i<settings.th.length; i++){
                html += '<th>'+settings.th[i]+'</th>';
              }
            html += '</tr>';
            
            
              $(xml).find("item").each(function(){
                html += '<tr>';
                    for(var i=0; i<settings.row.length; i++){
                      html += '<td>'+$(this).find(settings.row[i]).text()+'</td>';
                    }
                html += '</tr>';
              });
              html += '</table>';
              
              $("#list_div").html(html);
          }
      });

    };
    
/*
 * ページアイコンの作成
 */
    var page_icon = function(nowpage,len){ 

      var p = 1; //ページ開始位置

    //7ページ以上ならば、開始ページを1加算
      if(nowpage > 6){
        p = nowpage-5;
      }

      $("#ajax_pager").html('<img src="loader2.gif" />'); 
      
      var page = len/settings.page_max; //全件数をページ表示件数で割る
          page = Math.ceil(page); //小数点切り上げ
      var html = '';
      
        if( nowpage > 1){
          var backpage = nowpage-1; //前のページに戻る数
          html += '<a href="#"  id="page1">&lt;&lt;</a>';
          html += '<a href="#"  id="page'+backpage+'">&lt;</a>';
        }
          
          for(var i=0; i<10; i++){ //最大10ページ分のアイコン
            if(nowpage == p){
              html += '<p class="nowpage">'+p+'</p>'; //現在のページならば
            }else{
              html += '<a href="#" id="page'+p+'">'+p+'</a>';
            }
            p++;
            if(p >= page) break; //ページ数より大きくなったら停止
          }
          
          var nextpage = nowpage+1;
          var endpage  = page-1;
          
          if( endpage != nowpage){
            html += '<a href="#"  id="page'+nextpage+'">&gt;</a>';
            if(page >10) html += '<a href="#" id="page'+endpage+'">&gt;&gt;</a>'; //10ページ以上あるならば
          }
          
        $("#ajax_pager").html(html); //ページアイコンの表示
    };
    
    
/*
 * ページをクリックしたら
 */
    $(document).on('click','#ajax_pager a',function(e){
      var page= $(this).attr("id");
          page = page.match(/page(\d+)/)[1]|0; //page123 からpageを除去*数値にする
          reading(this,page);
      e.preventDefault();
    });
    
/*
 * <div id="pager"> 以下に要素の追加
 */
    $(this).prepend('<div id="ajax_pager"></div>');
    $(this).append('<div id="list_div"></div>');

    reading(this,1);
  };
  
})(jQuery)

現在の表示ページや表示件数等をpager.phpに非同期通信で渡す処理や、[1][2][3]といったアイコン表示を行っています。

pager.php

<?php
/*
 * サニタイズなどは事前に処理
 * ここではとりあえず$_POSTに対して仮の処理
 */
if( is_array($_POST) ){
  $data = array();
  foreach($_POST AS $key=>$str){
    $str = htmlspecialchars($str , ENT_QUOTES , "UTF-8");
    $data[$key] = $str;
  }
}

/*
 * pager.phpに直でアクセスされた場合など、停止させる
 * 特にここでデータベースからデータを取り出す場合は注意を!
 */
if(!$data['page_max']) exit; 


$row_all = file('zip.csv'); //ファイルを配列へ
$output = array_slice($row_all, $data['start'], $data['page_max']); // 配列を指定行数から指定分だけ取り出す

 header("Content-type: application/xml");
 echo '<?xml version="1.0" encoding="UTF-8" ?> ' . "\n";
 echo '<rss>'."\n"; 
 echo '      <len>'.count($row_all).'</len>'."\n"; //全件数
 
 foreach($output AS $row){
   $row = str_ireplace('"',"",$row); //""で括られているので除去
   $row = explode(",",$row); //カンマ区切りで配列に
   echo '  <item>'."\n"; 
// オプションで指定した 'row' : ['zip','area','add1','add2'] に合わせて名前を付ける
   echo '      <zip>'.$row['2'].'</zip>'."\n"; 
   echo '      <area>'.$row['6'].'</area>'."\n"; 
   echo '      <add1>'.$row['7'].'</add1>'."\n"; 
   echo '      <add2>'.$row['8'].'</add2>'."\n"; 
   echo '  </item>'."\n"; 
 }
 
 echo '</rss>'."\n"; 

非同期通信で送信された$_POSTのサニタイズはご自由に。サンプルは$_POSTをループし、htmlspecialcharsでHTMLエンコードだけの、仮のものを書いています。

ページ数に応じて配列をarray_sliceで指定分だけ取り出し、XML形式で書き出します。ここでデータベースからデータを取り出すのであれば、LIMITで処理しても良いと思います。

注意

pager.phpに直でアクセスされると色々と問題があるので、正しい経路からの処理で有ることを確認する事が大切です。特にデータベースからデータを取り出す場合はより注意が必要だと思います。HTML側をphpにし、Sessionにランダムなワンタイムキーを記録、pager.php側でそれと照合し、OKの場合だけ処理など、対応を忘れずに。