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の場合だけ処理など、対応を忘れずに。




