Before getting into this entry, let me share two quick notes about the last entry. First off, if you are a subscriber and only read the emails, I had made a small mistake in my logic. It was corrected on the entry. Thanks to my reader Fernando for pointing it out. Secondly, Rob Gonda made the point that you probably don't want to do pagination in ColdFusion if you are returning a hundred thousand or so results. He is absolutely correct and shows a better alternative here.
In the first entry, I demonstrated how you can use ColdFusion to do simple pagination. I had a query and a variable determining how many records to show per page. I showed how you could make links to let the user go back and forward one page a time. This works fine for a small set of results, but if you have more results, a user will have to hit "Next Page" a few too many times. What if you could simply provide a list of pages so a user could immediately jump to the page? It is really rather simple and I will show you how. Before going on though, be sure you read the last entry. (Boy, I sure wish BlogCFC support related entries. Oh wait, it does!.)
Let me start by showing the code, and then explaining what I did. At the end of the entry I'll post the complete code.
<cfset page = 0>
<cfloop index="x" from="1" to="#data.recordCount#" step="#perpage#">
<cfset page = page + 1>
<cfif url.start is not x>
<cfset link = cgi.script_name & "?start=" & x>
<cfoutput><a href="#link#">#page#</a></cfoutput>
<cfelse>
<cfoutput>#page#</cfoutput>
</cfif>
</cfloop>
The first thing I do is create a variable that will store the page number. This isn't actually needed as I could use math, but I've learned not to use math before I've had enough coffee.
Next I do a loop from one to the record count of the query. However, I use a step value of perpage. This makes it easy for me to split up my data into the right segments.
Inside the loop I increment page by one. Then I check to see if our current starting position is equal to X. If it isn't, it means I'm not on that page. I make a link (just like I did for the previous and next links) and just use X for my starting position. If not, I simply output X.
That's it. Now I have both a previous and next link, and between them, a list of pages for direct access to a particular page. Here is the complete code.
<cfset data = queryNew("id,name,age,active","integer,varchar,integer,bit")>
<cfloop index="x" from="1" to="31">
<cfset queryAddRow(data)>
<cfset querySetCell(data,"id",x)>
<cfset querySetCell(data,"name","User #x#")>
<cfset querySetCell(data,"age",randRange(20,90))>
<cfset querySetCell(data,"active",false)>
</cfloop>
<cfset perpage = 10>
<cfparam name="url.start" default="1">
<cfif not isNumeric(url.start) or url.start lt 1 or url.start gt data.recordCount or round(url.start) neq url.start>
<cfset url.start = 1>
</cfif>
<h2>Random People</h2>
<cfoutput query="data" startrow="#url.start#" maxrows="#perpage#">
#currentrow#) #name#<br />
</cfoutput>
<p align="right">
[
<cfif url.start gt 1>
<cfset link = cgi.script_name & "?start=" & (url.start - perpage)>
<cfoutput><a href="#link#">Previous Page</a></cfoutput>
<cfelse>
Previous Page
</cfif>
<cfset page = 0>
<cfloop index="x" from="1" to="#data.recordCount#" step="#perpage#">
<cfset page = page + 1>
<cfif url.start is not x>
<cfset link = cgi.script_name & "?start=" & x>
<cfoutput><a href="#link#">#page#</a></cfoutput>
<cfelse>
<cfoutput>#page#</cfoutput>
</cfif>
</cfloop>
<cfif (url.start + perpage - 1) lt data.recordCount>
<cfset link = cgi.script_name & "?start=" & (url.start + perpage)>
<cfoutput><a href="#link#">Next Page</a></cfoutput>
<cfelse>
Next Page
</cfif>
]
</p>