Ajax非同期通信を使ったページャー表現
表示する件数が多い場合に、ページ選択アイコンが並びぶページャーを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"><<</a>'; html += '<a href="#" id="page'+backpage+'"><</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+'">></a>'; if(page >10) html += '<a href="#" id="page'+endpage+'">>></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の場合だけ処理など、対応を忘れずに。