I’ve been spending a lot of time recently getting my JavaScript and HTML chops up because I think that Adobe is going to have a lot of impact in the HTML5/JS/CSS3 world next year and as a web developer, HTML and JavaScript have become incredibly interesting (and fun) with the rise of frameworks and the mobile landscape. As part of that experiment I’ve been digging into jQuery mobile. I’m obviously not a jQuery pro but after playing with both Flex “Hero” for mobile applications and now jQuery mobile, I thought it would be helpful to do a quick getting started post on jQuery mobile and talk about some of the UI paradigms it uses while walking through a basic application. jQuery mobile is in alpha2 right now, so it’s a little rough around the edges, but still very capable of providing a basis to create mobile applications.
jQuery Mobile divides the world up into pages, which are essentially just screens. Each page has three areas for content; the header, the main content, and the footer. Those are each defined by setting the data-role attribute within the div tag to specify “header”, “content”, or “footer”. The data-role attribute is also used to set up pages by setting it to the “page” value. With jQuery mobile the pages can be set up in different HTML files or all in one file. For this example I’m going to build a two-screen application. The first screen has a button that the user clicks to enable the use of the Geolocation APIs and the second screen is going to be a list of Wikipedia entries that are close to the coordinates. So I have two pages each with the three content types set using data-role.
<div>
<div>
<h1>Find Location</h1>
</div>
<div>
This application will use the <a href="http://geonames.org">Geonames</a> API and your location to bring back a list of Wikipedia articles about features that are near you. To get started, click the button below and allow the application to read your geolocation information.
<input id="getLocation" type="button" value="Get My Location" /></div>
<div>
<h4>By <a href="http://blog.digitalbackcountry.com">Ryan Stewart</a></h4>
</div>
</div>
<div id="dashboard">
<div>
<h1>Data List</h1>
</div>
<div>
<ul id="wikiList">
</ul>
</div>
<div>
<h4>By <a href="http://blog.digitalbackcountry.com">Ryan Stewart</a></h4>
</div>
</div>
With my structure set up I can now start adding jQuery-mobile specific interactions. As soon as I add the jQuery mobile libraries to my application it knows how to parse the data-role attributes and themes the application accordingly. What you get is something like on the right. Notice how it automatically styles the header and footer sections as well as providing a nice, big, touchable button and some styling on the footer link to indicate that it can be tapped.
With the external jQuery and jQuery mobile files included I can move on to adding interactivity. I start by adding a click handler to my button, which will go out and grab the geolocation information if it’s available. It’s just using the HTML5 geolocation API, which is supported by most modern browsers. When the user clicks the button, it will get the current position and then call onSuccess or onError depending on whether or not the API call worked.
$(document).ready(function(){
// Add a click listener on the button to get the location data
$('#getLocation').click(function(){
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(onSuccess, onError);
} else {
// If location is not supported on this platform, disable it
$('#getLocation').value = "Geolocation not supported";
$('#getLocation').unbind('click');
}
});
});
Next I set up a namespace for the geonames information. It has variables for the baseURL and then a search function with the getJSON function that goes out and calls the Geonames API. The function loops through each one of the results and then creates an <li> tag and appends the data we want to show to it, including the title of the Wikipedia article, the distance, and a summary. This is all straight jQuery. But after that we get into a couple of jQuery mobile-specific parts.
// create the geonames namespace for calling the API
var geonames = {};
geonames.baseURL = "http://ws.geonames.org/";
geonames.method = "findNearbyWikipediaJSON";
geonames.search = function(lat,lng){
// get the data in JSON format from Geonames
$.getJSON(geonames.baseURL + geonames.method + '?formatted=true&lat=' + lat + '&lng=' + lng + '&style=full&radius=10&maxRows=25',function(data){
// Loop through each item in the result and add it to the DOM
$.each(data.geonames, function() {
$('
')
.hide()
.append('<a href="http://'+this.wikipediaUrl+'">
<h2>'+this.title+'</h2>
</a>
'+ this.summary + '
<span class="ui-li-aside">
<h5>'+this.distance+' (km)</h5>
</span>')
.appendTo('#wikiList')
.show();
});
// Once the data is added to the DOM, make the transition
$.mobile.changePage('#dashboard',"slide",false,true);
// refresh the list to make sure the theme applies properly
$('#wikiList').listview('refresh');
});
};
The page model in jQuery mobile gives you a lot of control over how those pages are displayed. By default, when you set up an anchor tag it will play a default transition and go to the page you want. If that page is an external page it will load that external page in the browser. If it’s an internal, local link (with a hash), then jQuery will perform a slide transition and then swap out the old page content with the new one. It also updates the URL by default so you can use the back button that’s included in the header or the back button on your device/browser and go back to the original page. Pretty slick that this all happens by default. However, if you want more control you can use the $.mobile.changePage method, which is what I’m using because I wanted to only change the page after I had parsed the data from Geonames. With mobile.changePage I specify the URL, which in this case is just the id of the new div tag, the transition I want, whether I want the animation to be reversed, and finally whether I want to change the URL so the user can go back to the first screen. By default when you use mobile.changePage the last attribute is set to false so it won’t update the URL in the navbar. In this case I want them to be able to update their location when they move so I set the property to true.
The last thing I have to do is refresh the list to make sure the styles are applied to the new data. Lists are incredibly sick in jQuery an jQuery mobile. By using the data-role attribute and the data-theme attribute you can create some very powerful lists. In this case, I’m just using the default list so my <ul> tag has an id of wikiList, and a data-role of “listview”. That means any <li> tags I add to it will become jQuery mobile list items. And that’s exactly what happens in my Geonames callback function when I iterate through each item. It’s creating <li> elements with my data and appending them to my wikiList <ul> tag. Then when I call .listview('refresh') on my wikiList, it styles them appropriately. One cool feature of jQuery mobile lists is that there are a few different properties I can set to add some stylistic touch. For example, to show distance I’m using a span tag with the class set to ui-li-aside. That class will right-justify the content so my distance shows up on the right side.
And that’s pretty much all there is to it. The last bit of code I have is just the onSuccess and onError functions that handle the geolocation API.
// Success function for Geolocation call
function onSuccess(position)
{
geonames.search(position.coords.latitude,position.coords.longitude);
}
// Error function for Geolocation call
function onError(msg)
{
alert(msg);
}
You can check out the full application here and see it in action. This is just scratching the surface of what you can do with jQuery mobile but hopefully you got a sense of the page model and how to move back and forth between screens. In some later posts I’ll hopefully cover the new gestures, the new components, and some of the ways to lay out content.