Two months ago I wrote a blog entry on how to build a simple PhoneGapp application. This application just read in an RSS feed and used jQuery Mobile to display the results. I think this was helpful, but a few readers pointed out some issues with the code that caused me to come back to it this weekend and work on some updates. The issues were...
Error Handling
I admit it. I do not do a good job of error handling in most of my AJAX based applications. While this may be acceptable in some applications, in a mobile application where the entire functionality depends on things working right, there is no excuse for lacking proper error handling. My application really just did one main thing - fetch an RSS feed. Everything after that was display. But as with server side apps, any network call is a point of failure. My first change was to add in a simple error handler. In jQuery, this is rather simple. Since the application can't do much of anything without an RSS feed (or can it - see my PS below), for now we just display a simple error message.
$.ajaxSetup({
error:function(x,e,errorThrown) {
console.log(x.getStatusCode());
$("#status").prepend("Error!");
}
});
That's it. jQuery makes it simple to add global handlers and since we only have one network operation anyway, I can use this just fine. As I said, we don't really need to provide a lot of detail in this case, but we can at least let the user know something went wrong. To be fair, in a real application I'd probably add a bit more text. I'd let the user know the data couldn't be loaded and to please try again.
Page load issues
This one was a bonehead mistake. If you look at the code in the original blog entry, I do my network call and render results using the pageshow event. This means that every time the page is shown, it will fire, including times when the user hits back from an entry view. As I said - bonehead. Luckily it's simple enough to change to pageinit. Another change I made was to not make use of jQuery's document.ready logic. Instead, I simply load everything up at once. Here is my updated JavaScript file in it's entirety.
$.ajaxSetup({
error:function(x,e,errorThrown) {
console.log(x.getStatusCode());
$("#status").prepend("Error!");
}
}); //EDIT THESE LINES
//Title of the blog
var TITLE = "ColdFusion Jedi";
//RSS url
var RSS = "http://feedproxy.google.com/RaymondCamdensColdfusionBlog";
//Stores entries
var entries = [];
var selectedEntry = ""; //listen for detail links
$(".contentLink").live("click", function() {
selectedEntry = $(this).data("entryid");
}); //Listen for main page
$("#mainPage").live("pageinit", function() {
//Set the title
$("h1", this).text(TITLE); $.get(RSS, {}, function(res, code) {
entries = [];
var xml = $(res);
var items = xml.find("item");
$.each(items, function(i, v) {
entry = {
title:$(v).find("title").text(),
link:$(v).find("link").text(),
description:$.trim($(v).find("description").text())
};
entries.push(entry);
}); //now draw the list
var s = '';
$.each(entries, function(i, v) {
s += '<li><a href="#contentPage" class="contentLink" data-entryid="'+i+'">' + v.title + '</a></li>';
});
$("#linksList").html(s);
$("#linksList").listview("refresh");
}); }); //Listen for the content page to load
$("#contentPage").live("pageshow", function(prepage) {
//Set the title
$("h1", this).text(entries[selectedEntry].title);
var contentHTML = "";
contentHTML += entries[selectedEntry].description;
contentHTML += '<p/><a href="'+entries[selectedEntry].link + '">Read Entry on Site</a>';
$("#entryText",this).html(contentHTML);
});
And here is the front end HTML. The only change here was the addition of the status div used by error handling.
<div data-role="page" id="mainPage"> <div data-role="header">
<h1></h1>
</div> <div data-role="content"> <div data-role="footer">
<h4>SimpleBlog by Raymond Camden</h4>
</div> </div> <div data-role="page" id="contentPage"> <div data-role="header">
<a href="#mainPage" data-rel="back">Home</a>
<h1></h1>
</div> <div data-role="content" id="entryText">
</div> </div> </body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" href="js/jquery.mobile-1.0.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="js/jquery.mobile-1.0.min.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div id="status"></div>
<ul id="linksList" data-role="listview" data-inset="true"></ul>
</div>
There you go! I've wrapped up the entire Eclipse project into a zip. It also includes a debug APK you can install to your device if you want to try it out.
p.s. Technically, we could try to handle network issues better. I'm not just talking about the RSS feed being down, but what if the user is offline? I've decided to follow this up with a third version that will try storing the RSS feed in local storage. If the user is offline, we can at least resort to the older data.