Paginator: Configuring the Paginator

YUI.widget.Paginatorについては、親切というかなんというか、「バラバラに解体しちゃう」ようなExampleがあってありがたい。

このExampleの画面は下。

このExampleの説明にはこう書いてある。

In this example we'll demonstrate the use of all of Paginator's configuration options, including the options added by the bundled UI Components. Most notably, we'll use the template and pageLabelBuilder options to render the pagination controls in a custom layout with more descriptive page links. All content in the left column is generated by the Paginator.(YUIのExampleのページから引用)

この例は、Paginatorの全てのコンフィギュレーション・オプションを使ったデモとなっている(これには、UIコンポーネントで負荷されるオプションも含まれている)。一番注目なのは、templateと、pageLabelBuilderオプションで、ページを生成する上でのカスタムレイアウトと、記述的なページリンクを使っていることだ。左側の列の全てはPaginatorによって生成されている。

この通りに、Defaultも含めて、Paginatorの全てのコンフィグ属性がソース中に示されている。
これを見れば、「Paginatorのみで実現できること」が分かってしまうのだからありがたい。
ページリンク(を生成する関数)は凝った作りになっているので、多少煩雑ではあるが、(長いわりには)スッキリしたコードとなっている。

以下にHTMLの全文を示す。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
    <meta http-equiv="content-type" content="text/html; charset=utf-8"> 
<title>Ajax Sample</title> 
 
<style type="text/css"> 
body {
	margin:0;
	padding:0;
}
</style> 

<link rel="stylesheet" type="text/css" href="scripts/yui/fonts/fonts-min.css" /> 
<link rel="stylesheet" type="text/css" href="scripts/yui/paginator/assets/skins/sam/paginator.css" /> 
<link rel="stylesheet" type="text/css" href="scripts/yui/datatable/assets/skins/sam/datatable.css" /> 
<script type="text/javascript" src="scripts/yui/yahoo-dom-event/yahoo-dom-event.js"></script> 
<script type="text/javascript" src="scripts/yui/element/element-beta-min.js"></script> 
<script type="text/javascript" src="scripts/yui/paginator/paginator-min.js"></script> 
<script type="text/javascript" src="scripts/yui/datasource/datasource-min.js"></script> 
<script type="text/javascript" src="scripts/yui/datatable/datatable-min.js"></script> 

<style type="text/css" id="defaultstyle">
#main {
	margin: 2px;
	padding: 3px;
	width: 450px;
	height: auto;
}

#demo {
    width: 525px;
}
#pag {
    display: inline;
    float: left;
    width: 250px;
    margin-top: 0;
}
#pag a {
    color: #0000de;
}
#pag label {
    display: block;
    margin: 1ex 0;
}
#pag p {
    margin: .25ex 0;
}
.yui-skin-sam #pag .yui-pg-pages {
    display: block;
}
.yui-skin-sam #pag .yui-pg-page {
    display: block;
    background: transparent;
    border: none;
    padding: .5ex 0;
    white-space: normal;
}
.yui-skin-sam #pag .yui-pg-current-page {
    padding: .5ex 0;
    background-color: #ffe;
    font-style: italic;
}
.yui-skin-sam #pag .yui-pg-current {
    margin: 0;
    white-space: normal;
    font-weight: bold;
    font-size: 113%;
}
.yui-skin-sam #demo .yui-dt caption {
    margin: 0.2em 0 0;
    color: #e76300;
    font-weight: bold;
}

</style>

<script type="text/javascript" src="scripts/yui/paginator/assets/areacodes.js"></script>
<script type="text/javascript"> 
YAHOO.util.Event.onDOMReady(function () {
	 
	// YAHOO.exampleというNameSpaceを定義
	var Ex = YAHOO.namespace('example');

	// カスタム・ソーター
	// state > area codeでソート
	Ex.data.areacodes.sort(function (a,b) {
	    return YAHOO.util.Sort.compare(a.state,b.state) ||
	           YAHOO.util.Sort.compare(a.areacode,b.areacode);
	});
	 
	// ページラベル;state(area code) - state(area code)の作成する関数
	// state(area code) - state(area code)と表示するのが普通だが、
	// 頭文字(A,B,C...)の切れ目に当たったら、頭文字を表示する。
	Ex.buildPageLabel = function (recs) {
	    var data  = Ex.data.areacodes,
	        start = recs[0],
	        end   = recs[1];
	 
	    // Nested function to find the smallest substring
	    // to indicate how two strings differ
	    var diffNames = function (a,b) {
	        var aa = a.state.toLowerCase(),
	            bb = b.state.toLowerCase();
	 
	        for (var i = 0, len = aa.length; i < len; ++i) {
	            if (aa.charAt(i) !== bb.charAt(i)) {
	                return a.state.substr(0,i+1);
	            }
	        }
	 
	        return a.state + ' ('+a.areacode+')';
	    };
	 
	    // Build label as "A - C" or "Abc - Def"
	    var label = '';
	    if (!start) {
	        label = data[0].state.substr(0,2) + ' - ';
	    } else {
	        label = diffNames(data[start], data[start-1]) + ' - ';
	    }
	 
	    if (data[end+1]) {
	        label += diffNames(data[end], data[end+1]);
	    } else {
	        label += diffNames(data[end], data[start]);
	    }
	 
	    return label;
	};
	 
	 
	// PaginatorのConfiguration Attributes
	// Defaultについても、全て書いてあるので、辞書的に使える。
	Ex.config = {
	    // REQUIRED
	    rowsPerPage : 20,
	 
	    // REQUIRED, but DataTable will default if not provided
	    containers  : 'pag',
	 
	    // If not provided, there is no last page or total pages.
	    // DataTable will set this in the DataSource callback, so this is
	    // redundant.
	    totalRecords : Ex.data.areacodes.length,
	 
	    // page to activate at load
	    initialPage : 3,
	 
	    // Class the element(s) that will contain the controls
	    containerClass : 'yui-pg-container', // default
	 
		// Templateの指定(コンテナのinnerHTML)
		// Palaceホルダーに、Paginatorからのコントロールが入る。
	    template :
	        '<h3>Now showing:</h3>' +
	        '<p>{CurrentPageReport}</p>' +
	        '<p class="pg-nav">' +
	            '{FirstPageLink} {PreviousPageLink} ' +
	            '{NextPageLink} {LastPageLink}' +
	        '</p>' +
	        '<label>Page size: {RowsPerPageDropdown}</label>' +
	        '<h3>Directory</h3>' +
	        '{PageLinks}',
	 
	    // If there is less data than would display on one page, pagination
	    // controls can be omitted by setting this to false.
	    alwaysVisible : true, // default
	 
	    // Override setPage (et al) to immediately update internal values
	    // and update the pagination controls in response to user actions.
	    // Default is false; requests are delegated through the changeRequest
	    // event subscriber.
	    updateOnChange : false, // default
	 
	    // Options for FirstPageLink component
	    firstPageLinkLabel : "&lt;&lt;",
	    firstPageLinkClass : "yui-pg-first", // default
	 
	    // Options for LastPageLink component
	    lastPageLinkLabel : "&gt;&gt;",
	    lastPageLinkClass : "yui-pg-last", // default
	 
	    // Options for PreviousPageLink component
	    previousPageLinkLabel : "&lt; previous",
	    previousPageLinkClass : "yui-pg-previous", // default
	 
	    // Options for NextPageLink component
	    nextPageLinkLabel : "next &gt;", // default
	    nextPageLinkClass : "yui-pg-next", // default
	 
	    // Options for PageLinks component
	    pageLinksContainerClass : 'yui-pg-pages',        // default
	    pageLinkClass           : 'yui-pg-page',         // default
	    currentPageClass        : 'yui-pg-current-page', // default
	 
	    // Display a maximum of X page links.  Use
	    // YAHOO.widget.Paginator.VALUE_UNLIMITED to show all page links
	    pageLinks               : YAHOO.widget.Paginator.VALUE_UNLIMITED,
	 
	    // ページラベルの作成にはカスタムの関数を使う。
	    pageLabelBuilder        : function (page,paginator) {
	        return Ex.buildPageLabel(paginator.getPageRecords(page));
	    },
	 
	    // 一ページに表示する行数
	    rowsPerPageDropdownClass : "yui-pg-rpp-options", // default
	    rowsPerPageOptions       : [
	        { value : 20, text : "small" },
	        { value : 40, text : "medium" },
	        { value : 100, text : "large" }
	    ],
	 
	    // Options for CurrentPageReport component
	    pageReportClass : 'yui-pg-current', // default
	 
	    // Provide a key:value map for use by the pageReportTemplate.
	    // Unlikely this will need to be customized; see API docs for the
	    // template keys made available by the default value generator
	    pageReportValueGenerator : function (paginator) {
	        var recs  = paginator.getPageRecords();
	 
	        return {
	            start     : Ex.data.areacodes[recs[0]].state,
	            end       : Ex.data.areacodes[recs[1]].state
	        };
	    },
	 
	    // How to render the notification of the Paginator's current state
	    pageReportTemplate : '{start} - {end}'
	};
	 
	// Paginatorのインスタンス化
	Ex.paginator = new YAHOO.widget.Paginator(Ex.config);
	 
	// 列の定義
	Ex.tableCols = [ {key:"state",    label:"State", minWidth: 150},
	                 {key:"areacode", label:"Code",  width: 30}];
	 
	// DataSourceのインスタンス化
	Ex.dataSource = new YAHOO.util.DataSource(Ex.data.areacodes, {
	    responseType   : YAHOO.util.DataSource.TYPE_JSARRAY,
	    responseSchema : {
	        fields : ["state","areacode"]
	    }
	});
	 
	// DataTableのConfiguration Attributes
	// paginator属性を指定
	Ex.tableConfig = {
	    paginator : Ex.paginator,
	    caption   : 'Area Codes by State'
	};
	 
	// DataTableのインスタンス化
	Ex.dataTable = new YAHOO.widget.DataTable('tbl',
	    Ex.tableCols, Ex.dataSource, Ex.tableConfig);
	
});
</script>
</head> 
 
<body class=" yui-skin-sam">
<div id="main">
<p>PaginatorのConfigを全て指定したサンプルです。
</p>
<div id="demo"> 
    <div id="pag"></div> 
    <div id="tbl"></div> 
</div> 
</div>
</body> 
</html>