A reader asked me earlier this week if I could show an example of search, with paged results, under the jQuery Mobile framework. I whipped up a simple demo in five or so minutes. This is not a testament to my coding ability, but rather to just how fracking cool jQuery Mobile is. Before I begin though so important disclaimers. This was built using jQuery Mobile Alpha 3. If you are currently wearing a jetpack then you are reading this in the future and should expect that the code I show here may not quite work the same in the final version of jQuery Mobile. Also - I’ve been using jQuery Mobile for all of one month. Take my “solution” with a huge grain of salt. Make that two grains just to be safe. Ok, enough with the disclaimers, let’s get to work.
I began by creating a simple home page for my demo. (Note - I'm not going to cover every little detail of how jQuery Mobile works here - for that, please consult the docs.)
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />
<div data-role="page" data-theme="e">
<form action="search.cfm" method="post">
<input type="search" name="search" data-inline="true"> <input type="submit" value="Search" data-inline="true">
You can see I include the relevant libraries on top and my content is really just a simple form. The search form type isn't supported by all clients, but jQuery Mobile (jqm from now on) has unicorn magic and can make it work pretty much anywhere:
So - notice the form posts to search.cfm. Let's look at that.
<cfparam name="url.search" default="">
<cfparam name="form.search" default="#url.search#">
<cfparam name="url.start" default="1">
<cfset perpage = 10>
<cfset search = "%" & trim(form.search) & "%">
select artname, price, description
where artname like <cfqueryparam cfsqltype="cf_sql_varchar" value="#search#">
or description like <cfqueryparam cfsqltype="cf_sql_varchar" value="#search#">
<cfset noSearch = true>
<cfif not isNumeric(url.start) or url.start lte 0 or round(url.start) neq url.start>
<cfset url.start = 1>
<div data-role="page" data-theme="e">
<a href="" data-rel="back">Back</a>
<a href="index.cfm" data-theme="b">Home</a>
Please <a href="index.cfm">enter a search</a> term.
<cfelseif getart.recordCount is 0>
Sorry, there were no results for #form.search#.
<cfloop query="getart" startrow="#url.start#" endrow="#url.start+perpage-1#">
<cfif url.start gt 1>
<a href="search.cfm?search=#urlEncodedFormat(form.search)#&start=#max(1,url.start-perpage)#" data-role="button" data-inline="true">Previous</a>
<!--- Didn't work... <a href="" data-role="button" disabled data-inline="true">Previous</a>--->
<cfif url.start+perpage-1 lt getart.recordCount>
<a href="search.cfm?search=#urlEncodedFormat(form.search)#&start=#url.start+perpage#" data-role="button" data-theme="b" data-inline="true">Next</a>
<!--- See above...
<a href="" data-role="button" data-theme="b" disabled data-inline="true">Next</a>
Ok, we've got a bit more going on here then before. The top portion handles my search. I'm using ColdFusion (of course), but any server side language would suffice. Scroll on down to inside the div with the data-role content. My first two IF blocks handle no search or no results. The final block handles outputting the results. For my pagination I used the same old code I've used in the past. The only difference is that I made use of JQM's ability to automatically turn links into buttons. For the most part this works really well. What did not work for me, and you can see it commented out above, was passing a "disabled" along. I probably could have simply used a 'grey' theme for my buttons. But for now I simply hid them. Here is an example:
Not bad, right? You can demo this here:
This version was done using simple UL tags. You can view source to see it yourself. It's an incredibly small modification. The detail page you see took an additional 2 minutes of work.