This undocumented plugin is really worth adding to the repository I think. It needs a little fleshing out, which I've tried to do, but all in all is a super fast, super easy to implement pager.
I've modified it with spread (how many pages to either side of your current page will show in the navigation) and nonNumerical arguments (whether to show page numbers or not) to make it a bit more versatile. I've come across one problem though, which I hope someone can figure out. If the number if line items per page (step) is divisible equally into the total number of line items, I end up with a 'phantom' empty page at the end. For example, if my line item limit is set to 10 ( ul.pager(10) ), and I have 30 line items in total, the pager will produce 4 pages instead of 3 with the 4th page being empty (nonNumerical setting makes no difference). I could hack it away of course, but I 'd really like to know why this happens. The bug is present in the original too, http://jquery.com/api/js/pager.js. As far as I can see there's no way to upload files in Ggroups, so it's all below. Adam // John Resig's Pager - http://jquery.com/api/js/pager.js // // modified July 2007 - Adam Davis (agent2026) // $.fn.pager = function(step,spread,nonNumerical) { var types = { UL: "li", OL: "li", DL: "dt", TABLE: "tr" }; return this.each(function(){ var type = types[this.nodeName]; var pagedUI = type == "tr" ? $("tbody",this) : $(this); var rows = $(type, pagedUI); var curPage = 0; var names = [], num = []; if ( !step || step.constructor != Function ) { step = step || 10; if (rows.length > step) for ( var i = 0; i <= rows.length; i += step ) { names.push( names.length + 1 ); num.push( [ i, step ] ); } } else { var last; rows.each(function(){ var l = step( this ); if ( l != last ) { names.push( l ); var pre = num.length ? num[ num.length - 1 ][0] + num[ num.length - 1 ][1] : 0; num.push( [ pre, 0 ] ); last = l; } num[ num.length - 1 ][1]++; }); } if ( names.length > 1 ) { var pager = $(this).prev("ul.nav-page").empty(); if ( !pager.length ) pager = $("<ul class='nav-page'></ul>"); // agent2026 - nonNumerical argument (optional) // if ( !nonNumerical ) { for ( var i = 0; i < names.length; i++ ) $("<a href=''></a>").attr({ rel: i, innerHTML: names[i] }).click(function() { return handleCrop( this.rel ); }).wrap("<li></li>").parent().appendTo(pager); } pager.insertBefore( this ); var prev = $("<a href=''>« Prev</a>").click(function(){ return handleCrop( --curPage ); }).wrap("<li class='prev, noTrim'></ li>").parent().prependTo(pager); var next = $("<a href=''>Next »</a>").click(function(){ return handleCrop( ++curPage ); }).wrap("<li class='next, noTrim'></ li>").parent().appendTo(pager); // add first/last jumps - agent2026 // var fJump = $("<a href=''>‹ First</a>").click(function(){ return handleCrop( 0 ); }).wrap("<li class='first, noTrim'></ li>").parent().prependTo(pager); var lJump = $("<a href=''>Last ›</a>").click(function(){ return handleCrop( names.length-1 ); }).wrap("<li class='last, noTrim'></ li>").parent().appendTo(pager); // end first/last // handleCrop( 0 ); } function handleCrop( page ) { curPage = page - 0; var s = num[ curPage ][0]; var e = num[ curPage ][1]; if ( !curPage ) prev.hide(); else prev.show(); if ( curPage == names.length - 1 ) next.hide(); else next.show(); // show first/last only when needed - agent2026 // if ( curPage < 5 ) fJump.hide(); else fJump.show(); if ( curPage > names.length - 6 ) lJump.hide(); else lJump.show(); // end show // $("li:not(.noTrim)",pager) .removeClass("cur") .eq( curPage ) .addClass("cur"); pagedUI.empty().append( jQuery.makeArray( rows ).slice( s, s + e ) ); pageTrim(); return false; } // trim pages when page count is high using spread - agent2026 // function pageTrim(){ $("li:not(.noTrim)",pager).show(); $("li:not(.noTrim)",pager).lt(curPage-spread-1).hide(); $("li:not(.noTrim)",pager).gt(curPage+spread+1).hide(); } }); };