Sunburned and brain fried

I wrote a javascript pager tonight. It'll be in use on my new Javascript front end, hopefully coming here soon. It's all AJAX-y. I like it. Here's the code:

function Pager(){
this.init = function(divid){
this.div = document.getElementById(divid);
this.divToPage = document.getElementById(this.div.getAttribute("divtopage"));
this.pageSize = parseInt(this.div.getAttribute("pageSize"));
this.elementCount = this.divToPage.childNodes.length;
this.currentPage = (params(divid+"_page") != null ? parseInt(params(divid+"_page")) : 0);
this.pageCount = this.elementCount == 0 ? 0 : Math.ceil(this.pageSize / this.elementCount);
this.initialized = true;
}

this.refresh = function(){
if (this.initialized){
this.elementCount = this.divToPage.childNodes.length;
this.pageCount = this.pageSize == 0 ? 20 : Math.ceil(this.elementCount/this.pageSize);
if (this.elementCount < this.pageSize){
this.div.style.display = "none";
}
else {
this.div.style.display = "block";
clearChildren(this.div);
this.showPager();
}
}
}

this.showPager = function(){
var firstlink = new PagerLink("<<< first", this, function() { this.pageChanged(0); });
var nextlink = new PagerLink("next >>", this, function() { this.pageChanged(this.pager.currentPage+1); }) ;
var prevlink = new PagerLink("<< prev", this, function() { this.pageChanged(this.pager.currentPage-1); }) ;
var lastlink = new PagerLink("last >>>", this, function() { this.pageChanged(this.pager.pageCount); });

var pagelinks = Array();
for (var i = 0; i < this.pageCount; i++){
var pl = new PagerLink("" + (i+1), this, function(){ this.pageChanged(this.pageIndex); });
pl.setPageIndex(i);
pagelinks.push(pl);
}

if (this.pageCount > 10) this.div.appendChild(firstlink.link);

this.div.appendChild(prevlink.link);
for (var i = 0; i < pagelinks.length; i++){
this.div.appendChild(pagelinks[i].link);
}
this.div.appendChild(nextlink.link);

if (this.pageCount > 10) this.div.appendChild(lastlink.link);

this.pageChanged(this.currentPage);
}

this.pageChanged = function(pageNumber){
if (pageNumber >= this.pageCount) pageNumber = this.pageCount-1;
if (pageNumber < 0) pageNumber = 0;

var pageRange = [pageNumber*this.pageSize, (pageNumber+1)*this.pageSize];
for (var i = 0; i < this.elementCount; i++){
if (i >= pageRange[0] && i < pageRange[1]){
this.divToPage.childNodes[i].style.display = "block";
}
else this.divToPage.childNodes[i].style.display = "none";
}
this.currentPage = pageNumber;
}
}

function PagerLink(text, pager, clickEvent){
this.link = getLink(text, clickEvent);
this.pager = pager;
this.text = text;
this.link.pager = pager;
this.link.pageIndex = -1; // for page number links

this.link.pageChanged = function(pageNumber){
this.pager.pageChanged(pageNumber);
}

this.setPageIndex = function(i){
this.link.pageIndex = i;
}


}


It's used like this:

addEvent(window, "load", loaded);
var pager = new Pager();

function loaded(){
pager.init("pager");
}


You initialize the pager with the id of the element you want to hold the pager links.

<div id="pager" divtopage="existingNotes" pageSize="2">

</div>



Then when you add or remove elements from the element you are paging (I hard-coded a div), you refresh the pager, in case the number of pages has changed:

function saveNote(){
var note = getNote();
saveObject(note, noteSaved);
}

function noteSaved(note){
appendNote(note);
clearForm();

pager.refresh();
}
function deleteNote(note){
if (confirm("Are you sure you want to delete the note '" + note.Title + "'?")){
deleteObject(note, noteDeleted);
clearForm();
}
}
function noteDeleted(note){
removeNote(note.NoteId);

pager.refresh();
}


The code I'm writing uses AJAX, JSON and regular old javascript to talk to my ORM. So I can call stuff like "deleteObject" and it'll create the XML (parsing XML on the server is easier than parsing JSON) to make the call, call it, and get back a response. It's super simplistic right now, there's nothing returned except for some easy things.

The pager uses some common functions that have to be linked somewhere (which were either shamelessly stolen from quirksmode.org or I wrote them myself)

Array.prototype.clear = function(){
while (this.length >= 1){
this.shift();
}
}

function addEvent(obj, evType, fn, useCapture){
if (obj.addEventListener){
obj.addEventListener(evType, fn, useCapture);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be attached");
}
}

function clearChildren(node){
while ( node.childNodes.length >= 1 )
{
node.removeChild( node.firstChild );
}
}

function params(name){
var qs = document.location.search;
if (qs && qs.length > 1){
var start = qs.indexOf(name);
var end = start != -1 ? (qs.indexOf("&", start) != -1 ? qs.indexOf("&", start) : qs.length) : -1;
if (start != -1 && end != -1){
var value = unescape(qs.substring(start+1+name.length, end));
return value;
}
else return null;
}
else return null;

}

function getLink(text, clickEvent){
var jsl = document.createElement("a");
jsl.setAttribute("href", "javascript:void(0)");
if (text) jsl.appendChild(document.createTextNode(text));
if (clickEvent) addEvent(jsl, "click", clickEvent);
return jsl;
}

blog comments powered by Disqus