Mobile Feed Reader App – Part 2: Create RSS reader

This is the second part to the mobile application posts I had been working on.  Look for another post to come soon regarding testing and debugging as that certainly was a challenge due to the amount of javascript that was used to make this work.  You can view the previous post on this topic here.  Now back to part two…

To review, we had left off in part one where we had our IDE (Eclipse – ADT) setup and configured with a new project loaded and ready.  After about a week of playing with it on and off as time allowed in the evenings, I now have a working rss reader for Android based on PhoneGap.  As I mentioned before, this used HTML5, CSS3, and jQuery Mobile all running on top of the Cordova (PhoneGap) framework.

I will start by breaking out into the directories that house the different files that had to be modified or created for this to work from top to bottom in the project…

  • assets/www (this houses all the HTML, CSS, and JavasSript for the project).
  • res/values (strings.xml was updated with the application name to be displayed).
  • res/xml (config.xml was updated to include the domain of our RSS feed as a whitelist domain).

At this point, let’s take a second and update the two xml files listed above with the values relivent to what we are doing.

phoneGapFilesNow we need to copy the latest jQuery and jQuery Mobile frameworks so that we can use them in our project.  These will need to be placed within the assets/www directory as shown in the image on the right.

Now that we have these files in place, we can work with the main files to get the code to where it will work.

First off, we want to open the css/index.css and remove the Cordova image as our background for the .app class in this file.  Just simply replace…

/* Portrait layout (default) */
.app {
    background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */
    position:absolute; /* position in the center of the screen */
    left:50%;
top:50%;
height:50px; /* text area height */
width:225px; /* text area width */
text-align:center;
padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */
margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */
                                 /* offset horizontal: half of text area width */
}

/* Landscape layout (with min-width) */
@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
    .app {
        background-position:left center;
        padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */
        margin:-90px 0px 0px -198px; /* offset vertical: half of image height */
                                     /* offset horizontal: half of image width and text area width */
    }
}

h1 {
    font-size:24px;
    font-weight:normal;
    margin:0px;
    overflow:visible;
    padding:0px;
    text-align:center;
}

Find those sections within the index.css file and remove any of the contents within those sections to match below. Please also note there are some small changes to the h1 tag styling as well.

/* Portrait layout (default) */
.app {
}

/* Landscape layout (with min-width) */
@media screen and (min-aspect-ratio: 1/1) and (min-width:400px) {
    .app {
    }
}

h1 {
    font-size: 24px;
    font-weight: normal;
    margin: 0px;
    overflow: visible;
    padding: 0px;
    text-align: center;
    color: #39aca0;
}

Now that our styling is right, let’s move on to the js/index.js file. The contents of this file should match below…

var app = {
    // Application Constructor
    initialize: function() {
        this.bindEvents();
    },
    // Bind Event Listeners
    //
    // Bind any events that are required on startup. Common events are:
    // 'load', 'deviceready', 'offline', and 'online'.
    bindEvents: function() {
        document.addEventListener('deviceready', this.onDeviceReady, false);
        document.addEventListener('backbutton', this.onBackButton, false);
        document.addEventListener('backhistory', this.onBackButton, false); // need for ripple debugging
        document.addEventListener('menubutton', this.onMenuButton, false);
    },
    // deviceready Event Handler
    //
    // The scope of 'this' is the event. In order to call the 'receivedEvent'
    // function, we must explicity call 'app.receivedEvent(...);'
    onDeviceReady: function() {
        app.receivedEvent('deviceready');
    },
    // backButton Event Handler
    onBackButton: function() {
    	app.receivedEvent('backbutton');
    },
    // backHistory Event Handler
    onBackHistory: app.receivedEvent('backhistory'),
    // Log on a Received Event
    receivedEvent: function(id) {
        console.log('Received Event: ' + id);
    }
};

A couple things are happening within the index.js file. There will be more javascript within the index.html, but I left the handling of any cordova components within here. Mainly we will see that on initialization, we are setting up a number of event handlers. These handlers do a variety of things ranging from when the device is in a ready state, to button pushes. Since this app is simplistic in nature, all we are doing is logging the events to the console for debug purposes.

Lastly, we have the index.html file. This file should be updated with the code below…

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="format-detection" content="telephone=no" />
<meta name="viewport"
	content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
<link rel="stylesheet" type="text/css"
	href="jquery.mobile-1.3.1/jquery.mobile-1.3.1.min.css" />
<script type="text/javascript" src="cordova-2.6.0.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript"
	src="jquery.mobile-1.3.1/jquery.mobile-1.3.1.min.js"></script>
<title>The Redneck Coder - RSS Feed Reader</title>
</head>
<body>
	<div data-role="page" id="home">
		<div data-role="content">
			<h1>Redneck Coder - RSS Feed Reader</h1>
			<button onclick="loadRss();">Load Rss</button>
			<br />
			<ul data-role="listview" data-inset="true" data-filter="true"
				id="topics">
			</ul>
		</div>
	</div>
	<div data-role="page" id="blogItemView">
		<div data-role="header" data-position="fixed">
			<a href="#" data-role="button" data-icon="back" data-rel="back">Home</a>
			<h1 id="itemHeader">View Post</h1>
		</div>
		<div data-role="content">
			<h3 id="itemTitle">Title</h3>
			<div id="itemContent">Content</div>
		</div>
	</div>

	<script type="text/javascript">
		app.initialize(); // call the initialize function in the index.js file

		$.mobile.phonegapNavigationEnabled = true; // tell jQuery mobile we are using phonegap

		var blogTopics;

		function loadItem(index) {
			/* get the item from the array that was clicked
			* and display insert the contents into the appropriate
			* elements */
			var clickedItem = blogTopics[index];
			$("#itemTitle").text(clickedItem.title);
			$("#itemContent").html(clickedItem.content);
		}

		function loadRss() {
			blogTopics = new Array();
			$.mobile.loading("show", {
				text : "Loading...",
				textVisible : true
			});
			$.ajax({
				url : "https://theredneckcoder.wordpress.com/feed/",
				dataType : "xml",
				crossDomain : true
			}).done(
					function(data) {
						var $xml = $(data);
						var cnt = 0;
						$xml.find("item")
								.each(
										function(data) {
											var $xmlItem = $(this);
											var item = {
												title : $xmlItem.children(
														"title").text(),
												link : $xmlItem
														.children("link")
														.text(),
												pubDate : $xmlItem.children(
														"pubDate").text(),
												guid : $xmlItem
														.children("guid")
														.text(),
												content : $xmlItem.find(
														"encoded").text()
											};
											blogTopics.push(item);
											$("#topics").append(
													'<li><a href="#blogItemView" onclick="loadItem('
															+ cnt++ + ');">'
															+ item.title
															+ '</a></li>');
										});
						$("#topics").listview("refresh");
			}).fail(function(xhr, textStatus, errorThrown) {
				alert(textStatus.toString());
			}).always(function() {
				$.mobile.loading("hide");
			});
		}
	</script>
</body>
</html>

So in this file (the index.html) we have a number of things going on. Toward the top you will notice the typical css and javascript links to bring in those resources. Then inside the body we have our jQuery mobile pages. This is a small project so there are only two. These are div elements that have a data-role=”page” attribute to them and an identifier for the DOM. One thing that jQuery mobile uses is a hash link to switch between pages. So in this example if I wanted to simply go to the blogItemView page, I would just need to create a link using the following tag <a href=”#blogItemView” data-role=”button”>Blog Item View Page</a>. Easy!

Now a bit further down you will notice the javascript section. On line #41, you will see where we are initializing the app object as defined in the above index.js file. Then on line #43 we are telling jQuery mobile that we are using phonegap so that navigation will work correctly. After this, we are simply using javascript to source the rss feed of this blog so that we can update the DOM with the appropriate data.

It would not seem that wordpress.com allows for me to attach a zip file to this post, but as soon as I can find a good way to get it onto here, I will zip and upload the project to this post to share it.

Rss Reader Topics

Rss Reader Topic List

UPDATE!
I have just placed all the sourcecode for the RSS reader app out on github. Use this link to view the code.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s