jQuery Pagination with ColdFusion Pt. 2 building the Form
For this part of the tutorial we will create a form and use jQuery AJAX to call a CFC, when we get back our JSON we will populate our pagination code.
In part one we set up the database and listed the jquery plugins you will need to get the pagination working. Now on to the code.
We wil start out with a basic web page with a plain old search form. We use cfloop to generate some select box values.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>ColdFusion 8 jQuery Pagination Demo</title> <script src="js/jquery.js" type="text/javascript"></script> <script src="js/jquery.pagination.js" type="text/javascript"></script> <link rel="stylesheet" href="js/pagination.css" /> <link rel="stylesheet" href="style.css" /> <script type="text/javascript"> // inline jquery goes here </script> </head> <body> <cfoutput> <div id="search"> Min Price: <select id="minPrice"> <cfloop from="50000" to="900000" step="50000" index="i"> <option value="#i#">#dollarFormat(i)#</option> </cfloop> </select> Max Price: <select id="maxPrice"> <cfloop from="100000" to="950000" step="50000" index="i"> <option value="#i#">#dollarFormat(i)#</option> </cfloop> </select> Min Beds: <select id="minBeds"> <cfloop from="1" to="6" index="i"> <option value="#i#">#i#+</option> </cfloop> </select> Min Baths: <select id="minBaths"> <cfloop from="1" to="4" index="i"> <option value="#i#">#i#+</option> </cfloop> </select> Sort Order: <select id="sortOrder"> <option value="desc">Price High to Low</option> <option value="asc">Price Low to High</option> </select> <input type="button" id="btnSubmit" value="Search"> </div> </cfoutput> </body> </html>
At this point you should have a plain old form that looks like this:

Let's add in some divs after the for the result count ("total"), the pagination ("Pagination") and the actual results ("Searchresult") we will get back from our CFC.
<h1 id="tots">Total: <span id="total"></span></h1> <div id="Pagination" class="pagination"></div> <br style="clear: both;"> <div id="Searchresult"></div>
The next step is to add some paginatin code. Up in the javascript section add this. It's a jQuery "doc ready" function and a call to the pagination plugin to just build a pagination bar with 300 listings. that will be 30 pages with ten each.
<script type="text/javascript"> $(document).ready(function(){ $("#Pagination").pagination(300); }); </script>
Run the page now and you should have an idea of where we are headed.
Now we need to cover the CFC we will use to hit the db and get back a json object for our pagination. I am using the CFC as a webservice called from jQuery AJAX, it is a technique I picked up from a Ben Nadel post on CFCs and AJAX.
Below is a cold fusion component files called "Listings.cfc"
<cfcomponent output="false"> <cffunction name="CountListings" access="remote" returntype="struct" returnformat="json" output="false" hint="Returns the number of listings that match the search criteria."> <cfargument name="minPrice" type="Numeric" required="true" /> <cfargument name="maxPrice" type="Numeric" required="true" /> <cfargument name="minBeds" type="Numeric" required="true" /> <cfargument name="minBaths" type="Numeric" required="true" /> <cfset var LOCAL = {} /> <cfquery name="listingCount" datasource="jq_test" cachedwithin="#CreateTimeSpan(0,0,10,0)#"> SELECT Count(listings.listingID) AS totalListings FROM listings WHERE listings.listingPrice BETWEEN '#arguments.minPrice#' AND '#arguments.maxPrice#' AND listings.bedrooms >= '#arguments.minBeds#' AND listings.bathrooms >= '#arguments.minBaths#' </cfquery> <cfset LOCAL.totalListings = listingCount.totalListings> <cfreturn LOCAL /> </cffunction> <cffunction name="GetListings" access="remote" returntype="struct" returnformat="json" output="false" hint="Returns the number of listings that match the search criteria."> <cfargument name="minPrice" type="Numeric" required="true" /> <cfargument name="maxPrice" type="Numeric" required="true" /> <cfargument name="minBeds" type="Numeric" required="true" /> <cfargument name="minBaths" type="Numeric" required="true" /> <cfargument name="sortOrder" type="String" default="desc" /> <cfargument name="pageID" type="Numeric" required="true" /> <cfset var LOCAL = {} /> <cfquery maxrows="300" name="listingCount" datasource="jq_test" cachedwithin="#CreateTimeSpan(0,0,10,0)#"> SELECT listings.listingID, listings.listingPrice, listings.bedrooms, listings.bathrooms FROM listings WHERE listings.listingPrice BETWEEN '#arguments.minPrice#' AND '#arguments.maxPrice#' AND listings.bedrooms >= '#arguments.minBeds#' AND listings.bathrooms >= '#arguments.minBaths#' ORDER BY listings.listingPrice #arguments.sortOrder# </cfquery> <cfset LOCAL.listings = []> <cfoutput query="listingCount" startrow="#((pageID*10)+1)#" maxrows="10"> <cfset sTemp = structNew()> <cfset sTemp.ROWID = listingCount.currentRow> <cfset sTemp.PROPID = listingCount.listingID> <cfset sTemp.LISTPRICE = listingCount.listingPrice> <cfset sTemp.BATHS = listingCount.bathrooms> <cfset sTemp.BEDS = listingCount.bedrooms> <cfset arrayAppend(LOCAL.listings,sTemp)> </cfoutput> <cfreturn LOCAL /> </cffunction> </cfcomponent>
What we have is two functions, one to count the listings, and one for retrieving the listings. Both of these used cached queries, and both of them include the four search form items, Min/Max Price and Min Beds and Min Baths. The "GetListings" function has two additional arguments, one for the page_id and the other is for sort order. The Page ID will come in handy when we are returning only a portion of the query for the pagination.
Now that we have a form, a div for holding the pagination and search results, and a cfc web service, all that is left is the javascript for our ajax. This is the complete Javascript head section. So remove the pagination example I showed you earlier.
<script type="text/javascript"> var maxProps = 300; $(document).ready(function(){ $('#btnSubmit').click(callSearch); }); function callSearch(){ $.getJSON("Listings.cfc?wsdl", { method : "CountListings", minPrice: $("#minPrice").val(), maxPrice: $("#maxPrice").val(), minBeds: $("#minBeds").val(), minBaths: $("#minBaths").val() } , function(data){ $('#total').text(data.TOTALLISTINGS); $("#Pagination").pagination(Math.min(maxProps,data.TOTALLISTINGS), { num_edge_entries: 2, num_display_entries: 8, callback: listingCallback }); }); } function listingCallback(page_id, jq){ $.getJSON("Listings.cfc?wsdl", { method : "GetListings", minPrice: $("#minPrice").val(), maxPrice: $("#maxPrice").val(), minBeds: $("#minBeds").val(), minBaths: $("#minBaths").val(), sortOrder: $("#sortOrder").val(), pageID: page_id } , function(data){ $("#Searchresult").empty(); $.each(data.LISTINGS,function(i,d){ resultDiv = " <div class='result'>"; resultDiv += " <div class='listingHeader'>"; resultDiv += d.ROWID; resultDiv += ". Listing#: "; resultDiv += d.PROPID; resultDiv += "</div> "; resultDiv += " <div class='listingBody'>"; resultDiv += " <div class='listingImage'>"; resultDiv += '<img width="70" height="50" src="img/'+ (Math.round(Math.random() * 10)+1) +'.jpg"/>'; resultDiv += "</div> "; resultDiv += " <div class='listingInfo'>"; resultDiv += "Price: <strong>$" + d.LISTPRICE + "</strong>"; resultDiv += "Beds: " + d.BEDS + ""; resultDiv += "Baths: " + d.BATHS; resultDiv += "</div> "; resultDiv += " <div class='clearBoth'></div> "; resultDiv += "</div> "; resultDiv += "</div> "; $('#Searchresult').append(resultDiv); }); }); } // inline jquery goes here </script>
At the top of the Javascript we set a maxProps variable. Next is the jquery on ready command and we use that to assign a listener to the search Button, when it is clicked fire the "callSearch" function.
The Call searchFunction uses a getJSON() to send our form elements to the CFC. Notice how we are passing the method: CountListings through to the cfc, that is becuase we only want to get the total number of listings that match our search. When the "data" is returned we pass it into the getJSON callback, in this case it is an ad-hoc function, We pull the totalListings value from the JSON DATA and plug it into the text portion of the "total" span. Then we Build a pagination object and we use the Number of results or the maxProps (in this case 300) whichever is lesser. We set a few of the pagination parameters including the callback, this is the function that will run when a page number is clicked.
Our callback is a function called "listingCallback". Note that by default, when you build a "pagination" object, it will fire off the callback for page one automatically.
So, the last piece of the puzzle, the function listingCallback(). Pretty much the same as the callSearch function except this time we pass in a page_id and we use the method of GetListings. When our web service returns the JSON data we clear the Searchresults DIV and we loop over the returned listings with an EACH statement. We build a string called "resultDiv", I am sure there is a better way to build a display div, but this is how I am doing it for this example.
Once we have a Div object full of our listing data, we append it to the "Searchresult" container.
And That is it.
Please feel free to comment on this, I know that I glossed over the CFC itself and I did not go into details for the jQuery stuff. I will attach my source code. And I hope the comments work now, I have had terrible luck with Wordpress lately.
Source Code Here





