The Paginator class
Ojay.Paginator is a class designed to handle splitting content up into several pages
and allowing the user to scroll between them. It allows you to break large galleries
up into scrollable areas, and it allows you to lazy-load pages of content into the
current page using Ajax.
Required files
http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.jshttp://yui.yahooapis.com/2.6.0/build/selector/selector-beta.jshttp://yui.yahooapis.com/2.6.0/build/animation/animation.jshttp://yoursite.com/ojay/js-class.jshttp://yoursite.com/ojay/core.jshttp://yoursite.com/ojay/pkg/paginator.js
To use Ojay.AjaxPaginator:
http://yui.yahooapis.com/2.6.0/build/connection/connection.jshttp://yoursite.com/ojay/pkg/http.js
To manage history and allow pages to be bookmarked:
http://yui.yahooapis.com/2.6.0/build/history/history.jshttp://yoursite.com/ojay/pkg/history.js
To use the YUI Slider control:
http://yui.yahooapis.com/2.6.0/build/dragdrop/dragdrop.jshttp://yui.yahooapis.com/2.6.0/build/slider/slider.js
Examples
- A paginated photo gallery with bookmarkable pages
- Vertically scrolling gallery with a slider control
- Lazy-loading pages of content with Ajax
Setting up your document
As with all other Ojay components, Paginator is designed to work unobtrusively. The starting
point for your paginator should be a set of content accessible without the need for JavaScript.
Paginator assumes you have several items of content, each of which has the same dimensions.
For example:
<div id="the-content">
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
<!-- more items ... -->
</div>
The class item used here is not required – Paginator will just look for the child elements
of the-content when we set it up. You can style your content using CSS, but keep the following
in mind:
- Do not apply margins, borders or padding to
the-contentas they will be removed. If you need to use these, wrapthe-contentin a containerdivand use that for CSS instead. - Do not apply margins to the child elements, they too will be removed. You should use borders
and padding to arrange the presentation of the
itemelements internally.
Paginator also assumes your item elements will be floated to form a grid of items. You
should apply such floating rules yourself. See the example for
some suggested CSS rules.
Adding a Paginator
With your content in place, you can enhance the UI for JavaScript-enabled browsers. To set up
a Paginator, you must specify the width and height of the visible area (in whatever units
you like) and the scrolling direction (horizontal or vertical). You may also specify the
scrollTime in seconds and the name of an easing function – see the examples.
var pager = new Ojay.Paginator('#the-content', {
width: '680px',
height: '120px',
direction: 'horizontal'
});
pager.setup();
The reason for the extra setup() call will be explained when we get to history management.
This script will wrap your #the-content element in a div with a class of paginator,
and #the-content will be setup up to scroll within its new wrapper. The paginator
element will have the width and height that you specify when setting up the new
Ojay.Paginator. Also, all the child elements will be grouped by page into containers
so that the final state of the markup will be as follows:
<div class="paginator">
<div id="the-content">
<div class="page">
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
</div>
<div class="page">
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
<div class="item"><!-- content here --></div>
</div>
<!-- more pages ... -->
</div>
</div>
Each <div class="page"> element is set up to completely fill the paginator’s visible space
to ensure items don’t break across neighbouring pages. They also allow for horizontally
scrolling paginators to have more than one row of items rather than floating all the items
out in one long line.
In some situations – for example if you want to offer continuous scrolling rather than paging,
or if you find you run into performance issues – you can skip the process of creating the
wrapper <div class="page"> tags by passing grouping: false as an option when creating
the paginator.
You’ll probably want an interface for the user to navigate from page to page. You can set up your own using the API as described below, but Ojay provides a default UI for you, with ‘previous’ and ‘next’ buttons and numbered links to all the pages. To use one of these, just call:
// You can specify 'before' or 'after'
pager.addControls('after');
This will insert the HTML for the UI after the HTML for the paginated content. The links
are setup to monitor the pager object for page changes so you can use class names to
style them. See the example for some ideas – notice how
dragging the slider automatically changes the highlighted page number so your code does
not need to handle this event. If you want to roll your own UI, read on for the API details
and check out the source code
for the Paginator.Controls class.
Looping options
As of version 0.3, Paginator supports two options that allow the ‘previous’ and ‘next’
controls (which map to the decrementPage() and incrementPage() methods) to cause the
paginator to wrap back to the start rather than stopping at the end of the list. You
may use one of the options when setting up a Paginator instance:
looped: this causes the paginator to scroll back to the beginning when you try toincrementPage()from the last page in the list, and similarly fordecrementPage()at the beginning of the list.infinite: this is similar toloopedmode, but the paginator will scroll in the same direction forever, i.e. it will pan right a single frame from the last page in the list, rather than scrolling back left through all the frames. This does not mean you get an infinite number of pages, it just means they appear to form an infinite loop.
These options must be specified as part of the constructor, for example:
var pager = new Ojay.Paginator('#the-content', {
width: '680px',
height: '120px',
direction: 'horizontal',
looped: true
});
pager.setup();
API methods
The pager object we created above has an API that allows you to script its behaviour
and respond to events it generates. The following methods are available for getting bits
of information out of the paginator:
pager.getContainer()– returns an Ojay collection wrapping thepaginatorelement used to wrap#the-content.pager.getSubject()– returns an Ojay collection wrapping#the-contentitself.pager.getRegion()– returns aRegioninstance representing the area occupied by the paginator.pager.getItems()– returns an Ojay collection wrapping all theitemelements. Remember, theitemclass is not required –Paginatorsimply searches for child elements.pager.getPages()– returns the number of pages the paginator has.pager.getCurrentPage()– returns the number of the current page. Pages are numbered from 1.pager.pageForItem(n)– returns the page number containing the nth item. Pages and items are numbered from 1, not from 0.
The following methods can be used to control the paginator:
pager.setPage(n)– scrolls thepagerto pagen(numbered from 1), firing apagechangeevent if the page changes (see the Events section below).pager.incrementPage()– scrolls to the next page, firing apagechangeevent.pager.decrementPage()– scrolls to the previous page, firing apagechangeevent.pager.snapToPage()– ifpager.setScrollis used to position the scroll part-way between pages, this method snaps the scroll amount to the closest page.pager.focusItem(n)– scrolls thepagerto the page containing the nth item and adds afocusedclass name to the focused item’s containing element.pager.setScroll(amount, options)– sets the scroll amount. Ifamountis between 0 and 1 inclusive, it is treated as a fraction of the total scroll distance. If it is greater than 1, it is treated as an absolute offset in pixels.optionsshould be an object with two optional properties:animatesays whether the scroll should be animated or not, andsilenttells it whether to fire ascrollevent.
// Scrolls halfway along
pager.setScroll(0.5);
// Scrolls all the way along
pager.setScroll(1);
// Scrolls to 2px without animation
pager.setScroll(2, {animate: false});
// Scrolls to 50px with no 'scroll' event
pager.setScroll(50, {silent: true});
Events
Paginator instances publish a number of events that you can listen to in order to
respond to their actions. To listen to an event, use a similar syntax to that for DOM
events:
pager.on(eventName, callback, scope);
eventName is the name of the event, callback is a function, and scope is an optional
argument that specifies callback’s execution context. All event callbacks receive the
Paginator instance that fired the event as their first argument, and some events pass
additional arguments as detailed below. Here’s an example of handling a pagechange:
pager.on('pagechange', function(paginator, page) {
console.log(page);
});
pagechange– fires whenever the paginator’s current page changes. This even fires if you set the scroll offset manually usingsetScroll(). Passes the new current page as the second argument to your callback.firstpage– fires when the first pages becomes focused.lastpage– fires when the list page receives focus.scroll– fires whenever any scrolling takes place. Passes the scroll offset (between 0 and 1) as the second callback argument, and the total scroll range in pixels as the third.focusitem– fires whenfocusItem()is used. Passes the item’s id (numbered from 1) as the second argument, and a reference to the item’s DOM element as the third.
Browser history management
Ojay.Paginator is designed so that it can be used with Ojay.History to keep track of
the current page. This means that people can use the browser back/forward buttons to
navigate the gallery, and can bookmark individual pages. To add history management
to a paginator, you need to tell Ojay.History to manage it before calling its
setup() method:
var pager = new Ojay.Paginator('#my-id', options);
Ojay.History.manage(pager, 'gallery');
pager.setup();
Remember to call Ojay.History.initialize() once all your objects are registered.
See the history documentation for more info.
Ajax pagination
Ojay allows you to lazy-load pages of scrollable content using the Ojay.AjaxPaginator
class. This is useful for improving page load times as the only content that gets
loaded from the server is content that the user has specifically asked for (by clicking
a link that scrolls to that page, say). AjaxPaginator is a subclass of Paginator
and thus has all its features plus a few more. See the example
for some implementation ideas.
When an Ajax paginator calls its setPage() method, it first checks to see if the
content for the given page is loaded. If not, it fetches it from the server using Ajax
and inserts it into the document.
First, creating an AjaxPaginator is just like creating a Paginator, except you
need to pass in a list of URLs from which content should be requested. For example:
var pager = new Ojay.AjaxPaginator('#container', {
width: '680px',
height: '360px',
urls: ['/info.html', '/features.html', ...]
});
pager.setup();
Ajax paginators have the following API methods in addition to all the Paginator ones
listed above:
pager.pageLoaded(n)– returnstrueiff the content from page numbernhas been loaded from the server.pager.loadPage(n)– causes the content for pagento be loaded from the server, if it has not already been loaded.
In addition to all the events listed above, Ajax paginators publish the following events:
pagerequest– fired when a request for content is made to the server. Passes the requested URL as the second callback argument.pageload– fires when an Ajax request completes successfully. Passes the requested URL and theHTTP.Responseobject in case, say, you have script in the response that you want to execute:
pager.on('pageload', function(paginator, url, response) {
response.evalScripts();
});
