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.
<div data-role="page"> <div data-role="header">
<h1>Page Title</h1>
</div><!-- /header --> <div data-role="content">
<p>Page content goes here.</p>
</div><!-- /content --> <div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /header -->
</div><!-- /page --> </body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.css" />
<script src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.js"></script>
</head>
<body>
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="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.css" />
<script src="http://code.jquery.com/jquery-1.4.3.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.js"></script>
</head>
<body> <div data-role="page"> <cfif len(attributes.header)>
<cfoutput>
<div data-role="header">
<h1>#attributes.header#</h1>
</div>
</cfoutput>
</cfif> <cfelse> <cfif len(attributes.footer)>
<cfoutput>
<div data-role="footer">
<h4>#attributes.footer#</h4>
</div>
</cfoutput>
</cfif> </div> </body>
</html> </cfif>
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.
<cf_layout header="Artists" footer="jQuery Mobile Demo by Raymond Camden"> <div data-role="content"> <ul data-role="listview" data-inset="true">
<cfoutput query="getArtists">
<li><a href="artist.cfm?id=#artistid#">#lastname#, #firstname#</a></li>
</cfoutput>
</ul> </div> </cf_layout>
<cfquery name="getArtists" datasource="cfartgallery">
select artistid, firstname, lastname
from artists
order by lastname asc
</cfquery>
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.
<cfquery name="getArtist" datasource="cfartgallery">
select artistid, firstname, lastname, address, city, state, postalcode
from artists
where artistid = <cfqueryparam cfsqltype="cf_sql_integer" value="#url.id#">
</cfquery> <cfquery name="getArt" datasource="cfartgallery">
select artid, artname
from art
where artistid = <cfqueryparam cfsqltype="cf_sql_integer" value="#url.id#">
and mediaid is not null
</cfquery> <cf_layout header="#getArtist.firstname# #getArtist.lastname#" footer="jQuery Mobile Demo by Raymond Camden"> <div data-role="content"> <cfoutput>
<h2>#getArtist.firstname# #getArtist.lastName#</h2>
<p>
#getArtist.address#<br/>
#getArtist.city#, #getArtist.state# #getArtist.postalcode#
</p>
</cfoutput> <ul data-role="listview" data-inset="true">
<cfoutput query="getArt">
<li><a href="art.cfm?id=#artid#">#artname#</a></li>
</cfoutput>
</ul> </div> </cf_layout>
<cfparam name="url.id" default="">
Again - no JavaScript, just HTML. Finally, here is the art page:
<cfparam name="url.id" 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="#url.id#">
and a.mediaid = m.mediaid
</cfquery> <cf_layout header="#getArt.artname#" footer="jQuery Mobile Demo by Raymond Camden"> <div data-role="content"> <cfoutput>
<h2>#getArt.artname#</h2>
<p>
Price: #dollarFormat(getArt.price)# <cfif isBoolean(getArt.issold) and getArt.issold><b>Sold!</b></cfif><br/>
Type: #getArt.mediatype#<br/>
Description: #getArt.description#
</p> <p>
<img src="images/#getArt.largeImage#">
</p>
</cfoutput> </div> </cf_layout>
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:
Archived Comments
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.
re:icon - Yep, I believe Apple pretty much set the standard on those meta tags. You could add that quickly enough.
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!!
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 :-)
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.
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.
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.
Looks like Nokia isn't listed here: http://jquerymobile.com/gbs/
So that may be why.
Thanks for this Ray. When searching on Google I came accross this post. Forgot you had done this, really helped me today :)
Not a problem. Glad it was helpful.
I take it ajax magic is not happening here? - or don't you need remote attribute set, JSON returned from queries for Jquery mobile?
No - it's just being loaded normally for the most part -if I remember my own code right. ;)
Ray. I made a quick QR code for this if you would like to add it to the bottom of this post:
http://chart.apis.google.co...|0
@Bill: Sorry - what is the QR Code for?
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.
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?
@Ray - Sorry about that. Here is a shortened URL for the QR code.
http://bit.ly/dEAjIS
I would suggest putting a smaller version of this graphic up with your entry so that folks can preview the demo.
I'll edit the blog entry now (give me 5). What QR app do you recommend for Android phones?
@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.
Dude - I had no idea I had one installed. ;) It worked perfectly. Thank you.
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).
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.
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="url.id" default="">
<cfquery name="rsTicketDetail" datasource="ctickets">
SELECT ticketNum, acctNum, businessName, city
FROM tickets
WHERE status <> 'Closed' AND ticketNum = <cfqueryparam cfsqltype="cf_sql_numeric" value="#url.id#">
</cfquery>
- 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
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.
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..!
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.
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 url.id string.. and had replaced "id" with "ticketNum". (see below)
-----------------------------
<cfoutput query="rsTickets">
<li>
<h3 ><a href="p2.cfm?id=#rsTickets.ticketNum#">#rsTickets.Customer#</a></h3>
</li>
</cfoutput>
----------------------------
Thanks again for the "very practical" approach to CF. Congrats on the Adobe promo..