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

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

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

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

サンプル ダウンロード

HTMLとCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 * 表部分
 */
#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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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の場合だけ処理など、対応を忘れずに。