My first jQuery Mobile experiment

This post is more than 2 years old.

I've been following the progress on jQuery Mobile since it was first announced. While I've taken a look at the demos, I had not yet gotten a chance to actually look at the code. This weekend I read Pete Freitag's excellent introductory blog post (Getting Starting with jQuery Mobile) where I discovered just hard darn easy it is. jQuery Mobile does almost all of it's working using simple HTML attributes. That means you can build a simple mobile ready web site without one darn lick of JavaScript - and that's incredible. I took a look at the docs, and basically, if you can write HTML, you can use the framework. As an example, here is what one basic page looks like.

<!DOCTYPE html> <html> <head> <title>Page Title</title> <link rel="stylesheet" href="" /> <script src=""></script> <script src=""></script> </head> <body>

<div data-role="page">

&lt;div data-role="header"&gt;
	&lt;h1&gt;Page Title&lt;/h1&gt;
&lt;/div&gt;&lt;!-- /header --&gt;

&lt;div data-role="content"&gt;	
	&lt;p&gt;Page content goes here.&lt;/p&gt;		
&lt;/div&gt;&lt;!-- /content --&gt;

&lt;div data-role="footer"&gt;
	&lt;h4&gt;Page Footer&lt;/h4&gt;
&lt;/div&gt;&lt;!-- /header --&gt;

</div><!-- /page -->

</body> </html>

Each page consists of one div with an optional header, content, and footer. This by itself will render as:

To add another page, you can just link to it. By default, AJAX is used to load the page and a default transition effect is used. And dude (and dude-ettes) - that's it! Obviously more complex sites will need some JavaScript, but if you are looking at just getting some basic content up you can be done in minutes.

With that in mind I decided to build a simple ColdFusion site that provides a view of the art gallery sample database. I began by abstracting out the jQuery Mobile page into a custom tag.

<cfparam name="attributes.header" default=""> <cfparam name="attributes.footer" default="">

<cfif thisTag.executionMode is "start">

<!DOCTYPE html> <html> <head> <title>Art Browser</title> <link rel="stylesheet" href="" /> <script src=""></script> <script src=""></script> </head> <body>

<div data-role="page">

&lt;cfif len(attributes.header)&gt;
	&lt;div data-role="header"&gt;


&lt;cfif len(attributes.footer)&gt;
	&lt;div data-role="footer"&gt;


</body> </html>


All I've done above is simple break the page "in half" so I can use it as a wrapper. I then built this as a home page.

<cfquery name="getArtists" datasource="cfartgallery"> select artistid, firstname, lastname from artists order by lastname asc </cfquery>

<cf_layout header="Artists" footer="jQuery Mobile Demo by Raymond Camden">

&lt;div data-role="content"&gt;	

	&lt;ul data-role="listview" data-inset="true"&gt;
		&lt;cfoutput query="getArtists"&gt;
		&lt;li&gt;&lt;a href="artist.cfm?id=#artistid#"&gt;#lastname#, #firstname#&lt;/a&gt;&lt;/li&gt;


I felt a bit dirty putting my query in the view, but I got over it. Notice the use of data-role and data-insert. All your jQuery Mobile attributes will look like this. My next page displays the artist and his or her artwork.

<cfparam name="" default="">

<cfquery name="getArtist" datasource="cfartgallery"> select artistid, firstname, lastname, address, city, state, postalcode from artists where artistid = <cfqueryparam cfsqltype="cf_sql_integer" value=""> </cfquery>

<cfquery name="getArt" datasource="cfartgallery"> select artid, artname from art where artistid = <cfqueryparam cfsqltype="cf_sql_integer" value=""> and mediaid is not null </cfquery>

<cf_layout header="#getArtist.firstname# #getArtist.lastname#" footer="jQuery Mobile Demo by Raymond Camden">

&lt;div data-role="content"&gt;

	&lt;h2&gt;#getArtist.firstname# #getArtist.lastName#&lt;/h2&gt;
	#getArtist.address#&lt;br/&gt;, #getArtist.state# #getArtist.postalcode#

	&lt;ul data-role="listview" data-inset="true"&gt;
		&lt;cfoutput query="getArt"&gt;
		&lt;li&gt;&lt;a href="art.cfm?id=#artid#"&gt;#artname#&lt;/a&gt;&lt;/li&gt;



Again - no JavaScript, just HTML. Finally, here is the art page:

<cfparam name="" default="">

<cfquery name="getArt" datasource="cfartgallery"> select a.artid, a.artname, a.description, a.price, a.largeimage, a.issold, m.mediatype from art a, media m where a.artid = <cfqueryparam cfsqltype="cf_sql_integer" value=""> and a.mediaid = m.mediaid </cfquery>

<cf_layout header="#getArt.artname#" footer="jQuery Mobile Demo by Raymond Camden">

&lt;div data-role="content"&gt;

	Price: #dollarFormat(getArt.price)# &lt;cfif isBoolean(getArt.issold) and getArt.issold&gt;&lt;b&gt;Sold!&lt;/b&gt;&lt;/cfif&gt;&lt;br/&gt;
	Type: #getArt.mediatype#&lt;br/&gt;
	Description: #getArt.description#

	&lt;img src="images/#getArt.largeImage#"&gt;



You can see this in action by clicking the big ole demo button below. I tested it in my Android phone and it worked great. I'd love to hear from people using the Fruit Company phone too. I've only scratched the surface here and the framework itself is still in Alpha, but I'm very impressed by the direction of the framework so far.

Thanks to reader Bill King you can use the following QR code to quickly view the demo:

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Kris Korsmo posted on 10/31/2010 at 12:21 AM

Sid Maestre did an excellent presentation at MAX on mobile page creation with jQTouch, which it seems was the predecessor of jQuery mobile. What a great way to build a mobile app without having to go through any kind of app store! BTW - you can even create an icon that will display on the iPhone in place of the screenshot it uses by default. the result is very much like a native app. I'll see if I can find a link to Sid's code and post it here.

Comment 2 by Raymond Camden posted on 10/31/2010 at 12:23 AM

re:icon - Yep, I believe Apple pretty much set the standard on those meta tags. You could add that quickly enough.

Comment 3 by SuperAlly posted on 10/31/2010 at 12:41 AM

That is really neat Ray, thanks again.
I'll have to take a closer look when the boss jumps on to his next mobile push!!

Comment 4 by OlPeculier posted on 10/31/2010 at 1:08 AM

Works fine on my iTouch - transitions going forwards have a delay, going back is fine except it flashes up the content from the page you'd just come from before sorting itself out.

It's given me the inspiration to try something which isn't a good idea at 10pm :-)

Comment 5 by Dave Ferguson posted on 10/31/2010 at 8:20 AM

Great example Ray. I have a fruit phone and it looks good. The footer does get cut off due to text length. Just like jQTouch, jQuery mobile has a fix amount of space for header/footer bar text.

Comment 6 by Christian Gurney posted on 10/31/2010 at 7:57 PM

We took one of our JQTouch prototypes (basically a webApp for a legal organization with 2 dozen "panels" or "pages" and re-implemented it with JQMobile 1.0a. The finished results were similar.

We did see differences across iOS 4 and Android 2.2 that rendered some elements unusable. There is also a range of performance issues that can result in the base HTML being displayed in an un-styled mode before the JS rendering takes hold. Posts to the JQM forum indicate that performance on earlier iPhones is unusable and the JQM authors acknowledge this. We would not consider releasing anything (like something a client paid us for) at this point. Duh, it's ALPHA.

That said, for an Alpha based roughly 60 days of work, JQMobile shows a tremendous amount of promise.

Comment 7 by Matthew posted on 11/4/2010 at 1:43 AM

Hi Ray. Thanks for the intro. Just tried it on my Nokia N=n73 and it was fine but no nice styling or transitions, a very raw HTML look.

Comment 8 by Raymond Camden posted on 11/4/2010 at 1:46 AM

Looks like Nokia isn't listed here:

So that may be why.

Comment 9 by Glyn Jackson posted on 12/20/2010 at 5:09 PM

Thanks for this Ray. When searching on Google I came accross this post. Forgot you had done this, really helped me today :)

Comment 10 by Raymond Camden posted on 12/20/2010 at 5:38 PM

Not a problem. Glad it was helpful.

Comment 11 by Paul Stewart posted on 1/20/2011 at 1:51 PM

I take it ajax magic is not happening here? - or don't you need remote attribute set, JSON returned from queries for Jquery mobile?

Comment 12 by Raymond Camden posted on 1/20/2011 at 6:59 PM

No - it's just being loaded normally for the most part -if I remember my own code right. ;)

Comment 13 by Bill King posted on 2/2/2011 at 10:35 PM

Ray. I made a quick QR code for this if you would like to add it to the bottom of this post:|0

Comment 14 by Raymond Camden posted on 2/2/2011 at 10:37 PM

@Bill: Sorry - what is the QR Code for?

Comment 15 by Bill King posted on 2/2/2011 at 10:43 PM

I created the QR code so that I could see your demo on my phone. If you put it right next to the Big'ol button up above your readers can use their phone, point it at your blog and go right to the demo, without having to type in a URL with their phone. Follow the link and give it a try.

Comment 16 by Raymond Camden posted on 2/2/2011 at 10:46 PM

Wow, I thought QR codes were just for app installs. Unfortunately I think my blogware may have munged your URL. Perhaps post a short url version?

Comment 17 by Bill King posted on 2/2/2011 at 10:49 PM

@Ray - Sorry about that. Here is a shortened URL for the QR code.

I would suggest putting a smaller version of this graphic up with your entry so that folks can preview the demo.

Comment 18 by Raymond Camden posted on 2/2/2011 at 10:52 PM

I'll edit the blog entry now (give me 5). What QR app do you recommend for Android phones?

Comment 19 by Bill King posted on 2/2/2011 at 10:57 PM

@Ray, Most users should have a built in bar-code reader. On my myTouch the barcode scanner app picks up the code and takes me right to the browser. I believe the OS handles it. It determines whether to take the user to a browser or to the App store. Anybody know for sure? Give it a try when the QR code appears on the screen just hold up your phone as you would an app.

Comment 20 by Raymond Camden posted on 2/2/2011 at 11:00 PM

Dude - I had no idea I had one installed. ;) It worked perfectly. Thank you.

Comment 21 by bobbytuck posted on 2/10/2011 at 7:56 AM

Can this be dropped into main web folder in phonegap to give it the iOS wrapper for app deployment?

BTW -- Would you ever consider offering up a zipfile alongside the demo of the actual pages you use to create your apps on here? I love this blog, but sometimes it's a bit hard to figure out what's what in terms of what is actually on the page. Here, I'm confused about your custom tag and what you're naming the file(s).

Comment 22 by Raymond Camden posted on 2/10/2011 at 8:01 AM

1) I'd guess maybe. Unfortunately I can't play with Phonegap anymore as it is Mac only.

2) I use zips from time to time. It depends. For stuff like this (jQuery based stuff) I don't normally do a zip since you can just view source. For ColdFusion demos you can't so I try to attach a zip there when the demo is more than one file.

Comment 23 by jlig posted on 8/4/2011 at 1:34 AM

Ray, really enjoying all of your JQM posts & Connect Prez..

I'm hung up on Tags.. and not sure what to try next? (for now I'm "bypassing" your "abstraction" to get it to work)
When I try to use your Custom Tag, I get error: "element executionmode is undefined in thistag"
- Where do I save the tag? (tried multiple places.. root, tag folder, etc)
- What do I call the Tag when I save it? (currently using mobtag.cfm)
- I'm using CF9 Std, Developer Ed..

One other question on cfquery:
- I have this query on my JQM page 2..

<cfparam name="" default="">
<cfquery name="rsTicketDetail" datasource="ctickets">
SELECT ticketNum, acctNum, businessName, city
FROM tickets
WHERE status <> 'Closed' AND ticketNum = <cfqueryparam cfsqltype="cf_sql_numeric" value="">

- Cannot get DW to accept my dynamic ticketNum from page 1, but when I add in the default value, page 2 displays fine..
- Any ideas on this..

Thanks again

Comment 24 by Raymond Camden posted on 8/4/2011 at 4:42 AM

1) It sounds like you are trying to run the custom tag itself via the browser. That's now how custom tags are used. They are used with other CFMs.

2) Not sure what you mean by DW.

Comment 25 by jlig posted on 8/4/2011 at 8:02 AM

Sorry, wrong error posted..
- I have the Tag file saved in the same place as the index file..
- I'm getting "Cannot find CFML template for custom tag layout."
ps: DW is for Dreamweaver (CS5.5).. you knew that Ray, I'm sure..!

Comment 26 by Raymond Camden posted on 8/4/2011 at 8:19 PM

So you have the tag saved as layout.cfm right?

As to your Dreamweaver q - I don't know what you mean. DW isn't a server side program, so why would it need to "accept" anything? Unless you are trying live preview or something.

Comment 27 by jlig posted on 8/5/2011 at 1:16 AM

Thats It! sorry, I did not have the Tag named properly..
I also figured out my issue with the id field in Dreamweaver..
- On one of my JQM pages I had overlooked the little, itty-bitty "id" part of the string.. and had replaced "id" with "ticketNum". (see below)
<cfoutput query="rsTickets">
<h3 ><a href="p2.cfm?id=#rsTickets.ticketNum#">#rsTickets.Customer#</a></h3>
Thanks again for the "very practical" approach to CF. Congrats on the Adobe promo..