YUI Library Home

YUI Library Examples: Paginator: Manually rendering Paginator UI Components

Paginator: Manually rendering Paginator UI Components

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).

For this example, we'll create a table from a data array and render a few controls into the generated <tfoot> using the Paginator's template. We'll also subscribe to the Paginator's render event with a callback that renders a CurrentPageReport UI Component into a <div> above the table.

Page 1 of 3
ItemQuantityDescription
previousnext
Helmet43Red baseball helmet. Size: Large.
Football84Leather football.
Goggles31Light blue swim goggles
Badminton Set56Set of 2 badminton rackets, net, and 3 birdies.
Tennis Balls128Canister of 3 tennis balls.

Example Data

In this example, we'll be working with a data array stored in YAHOO.example.data.inventory.

1YAHOO.namespace('example.data').inventory = [ 
2    {SKU:"23-23874", Quantity:43, Item:"Helmet", Description:"Red baseball helmet. Size: Large."}, 
3    {SKU:"48-38835", Quantity:84, Item:"Football", Description:"Leather football."}, 
4    ... 
5]; 
view plain | print | ?

Start with the content

We'll start with two empty divs:

1<div id="demo"
2    <div id="report"></div> 
3    <div id="tbl"></div> 
4</div> 
view plain | print | ?

To populate div#tbl we write some application code to generate a table with a tfoot. The table will be wrapped in an object with an API including a showPage(pageNumber) method.

1YAHOO.util.Event.onDOMReady(function () { 
2 
3var Ex = YAHOO.namespace('example'), 
4    d  = document; 
5 
6// API for generating the table 
7Ex.table = { 
8    table   : null
9    columns : ['Item','Quantity','Description'], 
10    pageSize: 5, 
11    data    : null
12    tbody   : null
13    tfoot   : null
14 
15    load : function (data) { ... }, 
16    render : function (container) { ... }, 
17    showPage : function (page) { ... } 
18}; 
19 
20... 
view plain | print | ?

Add Pagination

Create a Paginator and a method to subscribe to its changeRequest event. Note the configured container is a generated <div> and is not yet on the page. We'll append this to the <tfoot> when it is available.

1Ex.handlePagination = function (state) { 
2    // Update the content via API call 
3    Ex.table.showPage(state.page); 
4 
5    // Confirm page change with Paginator 
6    Ex.paginator.setState(state); 
7}; 
8 
9// Create a Paginator and configure the UI Components included 
10// in the template and the CurrentPageReport we'll render manually 
11Ex.paginator = new YAHOO.widget.Paginator({ 
12    rowsPerPage  : Ex.table.pageSize, 
13    totalRecords : Ex.data.inventory.length, 
14    containers   : d.createElement('div'), 
15 
16    template              : "{PreviousPageLink}{NextPageLink}"
17    pageReportTemplate    : "Page {currentPage} of {totalPages}"
18    previousPageLinkLabel : "previous"
19    nextPageLinkLabel     : "next" 
20}); 
21 
22Ex.paginator.subscribe('changeRequest', Ex.handlePagination); 
view plain | print | ?

Subscribe to create the CurrentPageReport

To synchronize the rendering of all UI Components, we subscribe to the Paginator's render event with a callback to add a CurrentPageReport into div#report.

UI Components' render methods take a string seed usually used by Paginator to guarantee uniqueness of generated IDs when rendering into multiple containers. When rendering them manually, you'll need to provide your own seed. If you render more than one of the same type of UI Component, respective render calls must be passed different seeds.

1Ex.paginator.subscribe('render'function () { 
2    var pageReport, pageReportNode, report; 
3 
4    report = YAHOO.util.Dom.get('report'); 
5 
6    // Instantiate the UI Component 
7    pageReport = new YAHOO.widget.Paginator.ui.CurrentPageReport(Ex.paginator); 
8 
9    // render the UI Component, passing an arbitrary ID seed (the ID of the 
10    // destination container by convention) 
11    pageReportNode = pageReport.render('report'); 
12 
13    // Append the generated node into the container 
14    report.appendChild(pageReportNode); 
15}); 
view plain | print | ?

Render everything

Render the table and the Paginator. The CurrentPageReport will be rendered in response to the Paginator's emitted render event.

The Paginator was configured to use a <div> created off the page DOM, so the template controls are not visible until the <div> is then added to the table's <tfoot>.

1// Render the UI 
2Ex.table.load(Ex.data.inventory).render('tbl'); 
3 
4// Render the Paginator controls into the off DOM div passed as a container 
5// just to illustrate that it is possible to do so. 
6Ex.paginator.render(); 
7 
8// Add the Paginator's configured container to the table's tfoot. 
9Ex.DOM.add(Ex.table.tfoot.rows[0].cells[0],Ex.paginator.getContainerNodes()[0]); 
view plain | print | ?

Full Code Listing

JavaScript

Some convenience methods were created to aid in the DOM structure assembly.

1YAHOO.util.Event.onDOMReady(function () { 
2 
3var Ex = YAHOO.namespace('example'), 
4    d  = document; 
5 
6/* Convenience functions for building the DOM structure */ 
7Ex.DOM = { 
8    create : function (el,innerHTML) { 
9        el = el && el.nodeName ? el : d.createElement(el); 
10 
11        if (el && innerHTML !== undefined) { 
12            el.innerHTML = innerHTML; 
13        } 
14 
15        return el; 
16    }, 
17    add : function (par, child, innerHTML) { 
18        par = par && YAHOO.util.Dom.get(par); 
19        if (par && par.appendChild) { 
20            child = Ex.DOM.create(child,innerHTML); 
21            if (child) { 
22                par.appendChild(child); 
23            } 
24        } 
25 
26        return child; 
27    } 
28}; 
29 
30/* Table generation/maintenance API */ 
31Ex.table = { 
32    table   : null
33    columns : ['Item','Quantity','Description'], 
34    pageSize: 5, 
35    data    : null
36    tbody   : [], 
37    tfoot   : null
38 
39    load : function (data) { 
40        if (YAHOO.lang.isArray(data)) { 
41            this.data = data; 
42            this.tbody = []; 
43        } 
44        return this
45    }, 
46    render : function (container) { 
47        if (!this.table) { 
48            container = (container && YAHOO.util.Dom.get(container)) || d.body; 
49 
50            var thead, tbody, row, cell, i, len; 
51 
52            this.table = Ex.DOM.create('table'); 
53            thead = Ex.DOM.add(this.table,'thead'); 
54            row   = Ex.DOM.add(thead,'tr'); 
55 
56            for (i=0,len=this.columns.length; i<len; ++i) { 
57                Ex.DOM.add(row,'th',this.columns[i]); 
58            } 
59 
60            this.tfoot = Ex.DOM.add(this.table,'tfoot'); 
61            cell = Ex.DOM.add(Ex.DOM.add(this.tfoot,'tr'),'td'); 
62            cell.colSpan = this.columns.length; 
63 
64            if (this.data) { 
65                this.showPage(1); 
66            } else { 
67                row  = Ex.DOM.create('tr'); 
68                cell = Ex.DOM.add(row,'td','No Data'); 
69                cell.colSpan = this.columns.length; 
70 
71                Ex.DOM.add(Ex.DOM.add(this.table,'tbody'),row); 
72            } 
73 
74            container.innerHTML = ''
75            Ex.DOM.add(container,this.table); 
76        } 
77        return this
78    }, 
79    showPage : function (page) { 
80        var cur, tbody, row, i, j, len, limit; 
81 
82        if (this.table) { 
83            cur = this.table.getElementsByTagName('tbody')[0]; 
84 
85            if (YAHOO.lang.isNumber(page)) { 
86                tbody = this.tbody[page]; 
87                if (!cur || cur !== tbody) { 
88                    if (!tbody) { 
89                        tbody = this.tbody[page] = Ex.DOM.create('tbody'); 
90 
91                        i = (page - 1) * this.pageSize; 
92                        limit  = Math.min(Ex.data.inventory.length, 
93                                          i + this.pageSize); 
94                        for (; i < limit; ++i) { 
95                            row = Ex.DOM.add(tbody,'tr'); 
96                            for (j=0,len=this.columns.length; j<len; ++j) { 
97                                Ex.DOM.add(row,'td'
98                                    this.data[i][this.columns[j]]); 
99                            } 
100                        } 
101                    } 
102 
103                    if (cur) { 
104                        this.table.replaceChild(tbody,cur); 
105                    } else { 
106                        Ex.DOM.add(this.table,tbody); 
107                    } 
108                } 
109            } 
110        } 
111        return this
112    } 
113}; 
114     
115Ex.handlePagination = function (state) { 
116    Ex.table.showPage(state.page); 
117 
118    Ex.paginator.setState(state); 
119}; 
120 
121Ex.paginator = new YAHOO.widget.Paginator({ 
122    rowsPerPage  : Ex.table.pageSize, 
123    totalRecords : Ex.data.inventory.length, 
124    containers   : d.createElement('div'), 
125 
126    template              : "{PreviousPageLink}{NextPageLink}"
127    pageReportTemplate    : "Page {currentPage} of {totalPages}"
128    previousPageLinkLabel : "previous"
129    nextPageLinkLabel     : "next" 
130}); 
131 
132Ex.paginator.subscribe('changeRequest', Ex.handlePagination); 
133Ex.paginator.subscribe('render'function () { 
134    var pageReport, pageReportNode, report; 
135 
136    report = YAHOO.util.Dom.get('report'); 
137 
138    // Instantiate the UI Component 
139    pageReport = new YAHOO.widget.Paginator.ui.CurrentPageReport(Ex.paginator); 
140 
141    // render the UI Component, passing an arbitrary string (the ID of the 
142    // destination container by convention) 
143    pageReportNode = pageReport.render('report'); 
144 
145    // Append the generated node into the container 
146    report.appendChild(pageReportNode); 
147}); 
148 
149 
150// Render the UI 
151Ex.table.load(Ex.data.inventory).render('tbl'); 
152 
153// Render the Paginator controls into the off DOM div passed as a container 
154// just to illustrate that it is possible to do so. 
155Ex.paginator.render(); 
156 
157// Add the Paginator's configured container to the table's tfoot. 
158Ex.DOM.add(Ex.table.tfoot.rows[0].cells[0],Ex.paginator.getContainerNodes()[0]); 
159 
160}); 
view plain | print | ?

CSS

Custom positioning and style were added to the UI Components used. You'll see the Sam skin overrides as the rules with selectors beginning with .yui-skin-sam.

1/* Sam skin rule overrides */ 
2.yui-skin-sam .yui-pg-container { margin0} 
3.yui-skin-sam .yui-pg-current   { margin-right15px} 
4
5.yui-skin-sam .yui-pg-previous { 
6    floatleft
7    padding3px 5px
8} 
9.yui-skin-sam .yui-pg-next { 
10    floatright
11    padding3px 5px
12} 
13.yui-skin-sam span.yui-pg-next, 
14.yui-skin-sam span.yui-pg-previous { 
15    displaynone
16} 
17 
18/* content specific styles */ 
19#tbl, 
20#report, 
21#paging { 
22    width400px
23    margin0 auto
24} 
25#report { 
26    color: #fff; 
27    background: #ccc; 
28    font-size200%
29    margin-bottom1em
30    text-alignright
31} 
32#demo table { 
33    border-collapsecollapse
34    color: #333
35    width100%
36} 
37#demo th { 
38    border-bottom4px solid #999
39    color: #444
40    fontnormal 125%/100% Trebuchet MS, Arial, sans-serif; 
41    padding0 6px
42} 
43#demo tbody { 
44    background: #fff; 
45    border-left1px solid #ccc; 
46    border-right1px solid #ccc; 
47} 
48#demo tbody td { 
49    border-bottom1px solid #eee; 
50    padding5px
51} 
52#demo tfoot td { 
53    overflowhidden
54} 
view plain | print | ?

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Copyright © 2009 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings