What I ended up doing is this. This is directly from my source code, so there is some templating logic that doesn't make sense, but anyone who might be reading this in the future should be able to adjust according to their needs.
function paginate() {
var paginator = sb.find('#' + moduleName + 'Pagination')[0];
var container = paginator.getElementsByClass('container')[0];
sb.dom.clearAll(container);
if(count && count > 0) {
sb.dom.removeClass(paginator, 'hidden');
var pages = Math.ceil(count / amount);
var maxIterations = 5;
var iterations = Math.min(pages, maxIterations);
var paginatorObjects = [];
var center = Math.round(maxIterations/2);
var offset = page-center;
if(page < center) offset = 0; //Don't go lower than first page.
if(offset + iterations > pages) offset -= (offset + iterations) - pages; //Don't go higher than total pages.
for(var i=0; i<iterations; i++) {
var label = (i+1) + offset;
paginatorObjects.push({label: label});
}
sb.template.loadFrom(templateUrl, 'paginator').toHTML(paginatorObjects).appendTo(container, function(template) {
var pageNumber = template.obj.label;
if(pageNumber != page) {
sb.addEvent(template, 'click', function() {
getAppointments(pageNumber);
});
} else {
sb.dom.addClass(template, 'highlight');
}
});
if(offset + iterations < pages) {
var dots = document.createTextNode(' ... ');
container.appendChild(dots);
sb.template.loadFrom(templateUrl, 'paginator').toHTML({label: pages}).appendTo(container, function(template) {
sb.addEvent(template, 'click', function() {
getAppointments(pages);
});
});
}
var backBtn = paginator.getElementsByClass('icon back')[0];
var forwardBtn = paginator.getElementsByClass('icon forward')[0];
sb.removeEvent(backBtn, 'click');
sb.removeEvent(forwardBtn, 'click');
if(page - 1 > 0) {
sb.dom.removeClass(backBtn, 'hidden');
sb.addEvent(backBtn, 'click', function() {
getAppointments(page-1);
});
} else {
sb.dom.addClass(backBtn, 'hidden');
}
if(page + 1 <= pages) {
sb.dom.removeClass(forwardBtn, 'hidden');
sb.addEvent(forwardBtn, 'click', function() {
getAppointments(page+1);
});
} else {
sb.dom.addClass(forwardBtn, 'hidden');
}
} else {
sb.dom.addClass(paginator, 'hidden');
}
}
When getAppointments() is called from the buttons, I use AJAX to get the next pages results, then this pagination() function is called again from that function so everything gets reset. The variables that determine the amount to show per page and the current page number are global (to the container function) and are not shown in this code sample.
The logic behind this is fairly simple. The center is determined (in my case the max it shows at once is 5, so the center is 3) and then an offset is calculated based on the page number. Clicking 4 will adjust the start number +1, and 2 would adjust it -1.