Paginator: Manually rendering Paginator UI Components
タイトルのManually Renderingとは何を指すのか、と思ってしまうが、このExampleの説明は以下のように書かれている。
If you have a UI where it doesn't make sense to place all controls in a single container (or set of containers), you can place individual UI Components manually outside Paginator's configured container(s).(YUIのExampleページから引用)
もし、コンテナに(Paginatorの)全てのコントロールを置く場所がないなら、Paginatorの個々のコンポーネントをコンテナの外で利用することができる。
つまり、Paginatorの「部品取り」をしようというサンプルである。画面は下。
この表では、「ページの遷移状況の監督」にはPaginatorが使われているが、表そのものは、完全に手作りとなっている。
この表を管理する(手作りの)関数系と、Paginatorを、イベントハンドラ内で同期して利用することで、カスタマイズされた表ができあがっている。
上の説明にもあるように、ヘッダー部はPaginatorのuiコンポーネントが用いられているが、フッターは、手作りの表の中に、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" /> <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> <style type="text/css" id="defaultstyle"> #main { margin: 2px; padding: 3px; width: 450px; height: auto; } /* デフォルトスキン(Sam)のカスタマイズ */ .yui-skin-sam .yui-pg-container { /* margin: 0; */ } .yui-skin-sam .yui-pg-current { margin-right: 15px; } .yui-skin-sam .yui-pg-previous { float: left; padding: 3px 5px; } .yui-skin-sam .yui-pg-next { float: right; padding: 3px 5px; } .yui-skin-sam span.yui-pg-next, .yui-skin-sam span.yui-pg-previous { display: none; } #tbl, #report, #paging { width: 400px; /* margin: 0 auto;*/ } #report { color: #fff; background: #ccc; font-size: 200%; margin-bottom: 1em; text-align: right; } #demo table { border-collapse: collapse; color: #333; width: 100%; } #demo th { border-bottom: 4px solid #999; color: #444; font: normal 125%/100% Trebuchet MS, Arial, sans-serif; padding: 0 6px; } #demo tbody { background: #fff; border-left: 1px solid #ccc; border-right: 1px solid #ccc; } #demo tbody td { border-bottom: 1px solid #eee; padding: 5px; } #demo tfoot td { overflow: hidden; } </style> <script type="text/javascript" src="scripts/yui/paginator/assets/inventory.js"></script> <script type="text/javascript"> YAHOO.util.Event.onDOMReady(function () { // YAHOO.exampleというNameSpaceを定義 var Ex = YAHOO.namespace('example'); var d = document; // DOMをハンドルするためのオブジェクト・リテラルの定義 Ex.DOM = { // HTMLElementをもらって、そのinnerHTMLに文言を仕込む create : function (el,innerHTML) { el = el && el.nodeName ? el : d.createElement(el); if (el && innerHTML !== undefined) { el.innerHTML = innerHTML; } return el; }, // HTMLElementをもらって、子要素を作成し、そのinnerHTMLに文言を仕込む add : function (par, child, innerHTML) { par = par && YAHOO.util.Dom.get(par); if (par && par.appendChild) { child = Ex.DOM.create(child,innerHTML); if (child) { par.appendChild(child); } } return child; } }; // Table作成するために主要な役割を担う関数群(オブジェクト・リテラル) Ex.table = { table : null, columns : ['Item','Quantity','Description'], pageSize: 5, data : null, // 表示する1ページ全体を配列にもつ。(ページ数分だけの要素がある) tbody : [], tfoot : null, // コンストラクタ的な役割をもつ load : function (data) { if (YAHOO.lang.isArray(data)) { this.data = data; this.tbody = []; } return this; }, // テーブルを作成する render : function (container) { // Tableが空なら作成・表示する。 if (!this.table) { container = (container && YAHOO.util.Dom.get(container)) || d.body; var thead, tbody, row, cell, i, len; this.table = Ex.DOM.create('table'); thead = Ex.DOM.add(this.table,'thead'); row = Ex.DOM.add(thead,'tr'); for (i=0,len=this.columns.length; i<len; ++i) { Ex.DOM.add(row,'th',this.columns[i]); } this.tfoot = Ex.DOM.add(this.table,'tfoot'); cell = Ex.DOM.add(Ex.DOM.add(this.tfoot,'tr'),'td'); cell.colSpan = this.columns.length; // Dataがあれば1ページ目を表示し、なければ、'データがありません'と表示する。 if (this.data) { this.showPage(1); } else { row = Ex.DOM.create('tr'); cell = Ex.DOM.add(row,'td','データがありません'); cell.colSpan = this.columns.length; Ex.DOM.add(Ex.DOM.add(this.table,'tbody'),row); } container.innerHTML = ''; Ex.DOM.add(container,this.table); } return this; }, // 指定されたページを表示する showPage : function (page) { var cur, tbody, row, i, j, len, limit; if (this.table) { // 現在のページを取得。 cur = this.table.getElementsByTagName('tbody')[0]; if (YAHOO.lang.isNumber(page)) { tbody = this.tbody[page]; // TBody(テーブルの表示部)が空か、指定されたページ(this.tbody[page])と違うなら、 // テーブルを作成する。 if (!cur || cur !== tbody) { if (!tbody) { tbody = this.tbody[page] = Ex.DOM.create('tbody'); // 指定されたページ番号を元に地道にテーブルを作成 i = (page - 1) * this.pageSize; limit = Math.min(Ex.data.inventory.length, i + this.pageSize); for (; i < limit; ++i) { row = Ex.DOM.add(tbody,'tr'); for (j=0,len=this.columns.length; j<len; ++j) { Ex.DOM.add(row,'td', this.data[i][this.columns[j]]); } } } // 現在の表示ページがnullでないなら、算出したテーブルでreplace、nullなら // tableにbody要素を加える。 if (cur) { this.table.replaceChild(tbody,cur); } else { Ex.DOM.add(this.table,tbody); } } } } return this; } }; // Paginatorで「ページを表示せよ」というイベントが発火したときのハンドラ Ex.handlePagination = function (state) { // 上で定義した、tableオブジェクトでページを表示 Ex.table.showPage(state.page); // Paginatorのステートを(指定されたページに)かえる。 Ex.paginator.setState(state); }; // Paginatorのインスタンス化 Ex.paginator = new YAHOO.widget.Paginator({ rowsPerPage : Ex.table.pageSize, totalRecords : Ex.data.inventory.length, // コンテナは適当に作る(これでもいいことを例示しているだけ) containers : d.createElement('div'), // paginatorでテンプレートを利用(UIコンポーネント)。 template : "{PreviousPageLink}{NextPageLink}", pageReportTemplate : "Page {currentPage} of {totalPages}", previousPageLinkLabel : "previous", nextPageLinkLabel : "next" }); Ex.paginator.subscribe('changeRequest', Ex.handlePagination); Ex.paginator.subscribe('render', function () { var pageReport, pageReportNode, report; report = YAHOO.util.Dom.get('report'); // Paginator.ui.CurrentPageReportのインスタンス化(ページ;n/n形式) // http://developer.yahoo.com/yui/docs/YAHOO.widget.Paginator.ui.CurrentPageReport.html pageReport = new YAHOO.widget.Paginator.ui.CurrentPageReport(Ex.paginator); // Paginator.ui.CurrentPageReportのレンダリング。 // 引数は任意でいいが、普通は、ターゲットとなるコンテナのIDを指定。 pageReportNode = pageReport.render('report'); // ターゲット(report)の子要素として、レンダリングしたCurrentPageReportのインスタンスを入れる。 report.appendChild(pageReportNode); }); // Tableオブジェクトのload Ex.table.load(Ex.data.inventory).render('tbl'); // Paginatorのレンダリング Ex.paginator.render(); // TableのFooterにPaginaterのコンポーネントを使う。 Ex.DOM.add(Ex.table.tfoot.rows[0].cells[0], Ex.paginator.getContainerNodes()[0]); }); </script> </head> <body class=" yui-skin-sam"> <div id="main"> <p>表部分と表現形式(の殆ど)はJasvscript、遷移にYUI.widget.Paginatorを利用したサンプルです。 </p> <div id="demo"> <div id="report"></div> <div id="tbl"></div> </div> </div> </body> </html>