+1

Code Snippet: Rolling Paged Navigation Control

Coldfusion, UI

An approach to rolling links to "pages" in a result set when you want to constrain the amount of space used for navigation. The basic idea is having a leading and trailing offset relative to the page of results you're on to produce something that looks like this:

Page 1: Previous 1 2 3 4 5 Next
Page 2: Previous 1 2 3 4 5 Next
Page 3: Previous 1 2 3 4 5 Next
Page 4: Previous 2 3 4 5 6 Next
Page 5: Previous 3 4 5 6 7 Next
Page 6: Previous 4 5 6 7 8 Next
Page 7: Previous 5 6 7 8 9 Next
Page 8: Previous 6 7 8 9 10 Next
Page 9: Previous 6 7 8 9 10 Next
Page 10: Previous 6 7 8 9 10 Next

Where the underlined values would hyperlinks in practice. Presumably you would pass the value for what page is being viewed along the URL or via a form POST.

Code:

<cffunction name="pagination" output="false" returntype="struct" hint="
	Keys:
		start	int
		end		int
		hasPrev	bool
		hasNext	bool
">
	<cfargument name="cPage" type="numeric" required="true"/>
	<cfargument name="pages" type="numeric" required="true"/>
	<cfargument name="startOffset" type="numeric" required="true"/>
	<cfargument name="endOffset" type="numeric" required="true"/>
	<cfset var local = structNew()/>
	<cfset var p = structNew()>
	<cfset var window = min(pages, startOffset + endOffset + 1)>

	<cfif cPage LT 1 OR cPage GT pages>
		<cfthrow message="cPage (#cPage#) must be a value between 1 and #pages#.">
	</cfif>

	<cfset p.end = min(pages, max(cPage + endOffset, window))>
	<cfset p.start = max(0,  min(cPage - startOffset, p.end - window )) + 1>

	<cfset p.hasPrev = p.start GT 1>
	<cfset p.hasNext = p.end LT pages>
	<cfreturn p>
</cffunction>

<cffunction name="showNav" output="false" access="public" returntype="string" hint="">
	<cfargument name="p" type="struct" required="true"/>
	<cfargument name="cPage" type="numeric" required="true"/>
	<cfset var local = structNew()/>
	<cfset local.output = arrayNew(1)>

	<cfif p.hasPrev>
		<cfset arrayAppend(local.output, "<u>Previous</u>")>
	<cfelse>
		<cfset arrayAppend(local.output, "Previous")>
	</cfif>

	<cfloop from="#p.start#" to="#p.end#" index="local.idx">
		<cfif local.idx EQ cPage>
			<cfset arrayAppend(local.output, local.idx)>
		<cfelse>
			<cfset arrayAppend(local.output, "<u>#local.idx#</u>")>
		</cfif>
	</cfloop>

	<cfif p.hasNext>
		<cfset arrayAppend(local.output, "<u>Next</u>")>
	<cfelse>
		<cfset arrayAppend(local.output, "Next")>
	</cfif>

	<cfreturn arrayToList(local.output, "&nbsp;")>
</cffunction>

<cfset pages = 10>
<cfset startOffset = 2>
<cfset endOffset = 2>

<cfoutput>
<pre>
<cfloop from="1" to="#pages#" index="page">Page #page#: #showNav(pagination(cPage=page,pages=pages,startOffset=startOffset,endOffset=endOffset), page)#
</cfloop>
</pre>
</cfoutput>

Search