PhoneGap RSS Reader - Part 2

This post is more than 2 years old.

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.

<!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 data-role="page" id="mainPage">

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

&lt;div data-role="content"&gt;  
	&lt;div id="status"&gt;&lt;/div&gt;  
    &lt;ul id="linksList" data-role="listview" data-inset="true"&gt;&lt;/ul&gt;
&lt;/div&gt;

&lt;div data-role="footer"&gt;
    &lt;h4&gt;SimpleBlog by Raymond Camden&lt;/h4&gt;
&lt;/div&gt;

</div>

<div data-role="page" id="contentPage">

&lt;div data-role="header"&gt;
    &lt;a href="#mainPage" data-rel="back"&gt;Home&lt;/a&gt;
    &lt;h1&gt;&lt;/h1&gt;
&lt;/div&gt;

&lt;div data-role="content" id="entryText"&gt;
&lt;/div&gt;

</div>

</body> </html>

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.

Download attached file.

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 https://www.raymondcamden.com

Archived Comments

Comment 1 by Mike posted on 12/26/2011 at 11:09 AM

Hey Raymond,

You may remember me, you helped me out when trying to change the main.js file to link directly to the article instead of going to the #contentpage and clicking a link... It worked great on my browser, so I just decided to put it into xcode, but I ran into a problem; there was no content on the page :(

This is what the simulator looked like:

http://bit.ly/rMkwxL

So I thought it was a problem w/ linking to the main.js file, so i just included the javascript in the header, but still nothing. This is what the Xcode console looks like as of right now:

http://bit.ly/uY0Xmb

Do you know what I can do to make this work on Xcode?

<iframe src="http://pastebin.com/embed_i..." style="border:none;width:100%"></iframe>

Comment 2 by Mike posted on 12/26/2011 at 11:10 AM

here is the correct link to the raw HTML

http://pastebin.com/raw.php...

Comment 3 by Raymond Camden posted on 12/26/2011 at 10:30 PM

Change that console.log to an alert and tell me what you see.

Comment 4 by Mike posted on 12/27/2011 at 2:01 AM

http://pastebin.com/raw.php...

changed the console.log to alert, but still no luck... do I have to add anything to the external host p.list? I already have *pipes.yahoo.com on there

Comment 5 by Raymond Camden posted on 12/27/2011 at 2:04 AM

Looks right to me. Unfortunately, I don't have OSX to test on to see if it is an issue with the remote host. It shouldn't be. For the heck of it, after this:

$("#mainPage").live("pageinit", function() {

add alert('Ray');

and see if that shows up. Want to ensure the pageinit handler is running.

Comment 6 by Mike posted on 12/27/2011 at 2:37 AM

http://pastebin.com/raw.php...

No alert.... did I put it in the right place?

Comment 7 by Raymond Camden posted on 12/27/2011 at 2:42 AM

You did. So this implies your code isn't setting up the event handler right. Notice how I put mine in a JS file loaded via script. Change it to that please.

Comment 8 by Mike posted on 12/27/2011 at 4:22 AM

Ok i linked to the main.js file in the header... but it didn't work... I made a 2 minute video on what I am doing in Xcode... I think it could be that since I modified the javascript it may have too many bugs in it.. but if it works in the browser and not in Xcode, it must not be anything too major... thanks for any suggestions

http://youtu.be/z9QBUea_T2E

Comment 9 by Raymond Camden posted on 12/27/2011 at 8:07 PM

Woah - wait - did I see right? The first page loaded, right? I mean the content. I thought it _wasn't_ working there? It looks like the mod to make it NOT go to page2 isn't working.

Right?

Comment 10 by Chad posted on 12/29/2011 at 12:15 AM

Ray,

Thanks for this awesome tutorial. I mean, I could have easily ripped the code but the step by step really helped me grasp the concept. I've since added a few things but this was exactly what I was looking for.

Thanks again!

Comment 11 by Chad posted on 12/29/2011 at 8:48 PM

Ray,

I did run into a small snag trying to get this to run properly with phonegap after a minor modification.

I added an entry to the main.js right below the others:
content:$.trim($(v).find('content\\:encoded').text())

I did this simply because my rss feed doesn't spit out much in the description.

I also changed this:
contentHTML += entries[selectedEntry].description;
to
contentHTML += entries[selectedEntry].content;

Everything works great in the browser (http://parkrumors.com/mobile)

The only thing different between the browser and apk is the inclusion of phonegap js and the addition of some other pages. When I revert the contentHTML back to description, it works fine in the emulator.

I think I made the issue clear? Your thoughts?

Comment 12 by Raymond Camden posted on 12/30/2011 at 12:47 AM

Can you confirm content is right? Right after the line where you get the value, do an alert on it (or console.log).

Comment 13 by Chad posted on 12/30/2011 at 1:08 AM

On PC browser, alert shows the content, on emulator its empty.

Comment 14 by Raymond Camden posted on 12/30/2011 at 9:48 PM

Interesting. It could imply that XML parsing is acting differently. Not sure what to say. What I'd do though is create a new PhoneGap project. Have your code get the XML and ONLY get the content from one item. Confirm it isn't working in the emulator and then send me a copy of the code. (If that doesn't make sense, I'm basically asking you to build an app that does JUST this so we can narrow down on the issue.)

Comment 15 by Chad posted on 12/30/2011 at 10:29 PM

http://parkrumors.com/mobil...

Thanks for your help!

Comment 16 by Raymond Camden posted on 12/31/2011 at 9:50 PM

I have a solution, but I don't yet know _why_ it works, but switch

content:$.trim($(v).find('content\\:encoded').text())

to

content:$.trim($(v).find('encoded').text())

I'm researching now as to _why_ this match works.

Comment 17 by Raymond Camden posted on 12/31/2011 at 9:57 PM

Ok, it was the namespace, duh. And now I know why \\ didn't work. I talked about it on G+, so instead of repeating myself, I'll just link to the discussion.

https://plus.google.com/115...

Comment 18 by Raymond Camden posted on 12/31/2011 at 10:00 PM

UGH. Be warned, it works in jQuery 1.6.x, not 1.7.x.

Comment 19 by Raymond Camden posted on 12/31/2011 at 10:07 PM

Ok, after research, it turns out that it is indeed a bug in jQuery, but has been marked 'wontfix'. My understanding is that it's not something that can be fixed in a stable cross platform manner. However, this solution was proposed:

$(v).find("content:encoded, encoded").text();

In the bug and it works well. Here is more details on the bug: http://bugs.jquery.com/tick...

Comment 20 by Raymond Camden posted on 12/31/2011 at 10:10 PM

More info on the workaround: http://www.steveworkman.com...

Comment 21 by Chad posted on 1/3/2012 at 6:07 PM

Oh wow!

You've gone above and beyond! You sir have made my day! (Side note, today is also my Birthday!) lol

Thanks so much!

Comment 22 by Raymond Camden posted on 1/3/2012 at 7:01 PM

I did it just for your birthday. Honest. (Ahem.)

Comment 23 by Johannes Wilm posted on 1/9/2012 at 4:44 AM

Hey,
I'm rather new to Phonegap development. But looking at your example I hacked together something that stores the contents in an sql database and then retrieves it from there if the user isn't online (which is which I think you described you would do in installment 3). It uses the title of the post as a unique identifier -- that will likely work 95% of the time. It will theoretically also store old entries that have disappeared from the stream.

I wonder though what you think baout the following:

1. The fact that I escape the entire text string before putting it in the DB.

2. The fact that it seems impossible to use a db that is not called 'test' (without getting an error).

3. The combination of phonegap and jquery listeners (looks dirty).

4. If you have any opinions about how to organize image caching (currently not working).

Code: http://pastebin.com/9gXXmDV6

Comment 24 by Johannes Wilm posted on 1/9/2012 at 6:52 AM

If I'm not mistaken, the way to do image caching would be to:

1. Take the description text of each entry and replace each instance of <img src="..."> with <canvas id="..."> before saving it in the database

2. Create a new table in the DB called fx IMAGES. For each of the above <img>s, download the image file and save them in the IMAGES table using base64 encoding. A second column in that table should specify the id that was used in the canvas-element that we inserted under 1. A third column in the table should specify which RSS-entry the image was on.

---

3. When retrieving an RSS entry, also download all the entries in the IMAGES table that are related to it.

4. After inserting the RSS-entries into the HTML, for each of the entries from the IMAGES table we retrieved in 3, use drawImageOnCanvas to draw the base64-encoded image data on the corresponding canvas element.

This is basically what I would go for. The reason I'm hesitating is that it seems a fairly simple operation, and I haven't found any references to doing it like this anywhere on the web. Does it seem right to you though?

Comment 25 by Raymond Camden posted on 1/10/2012 at 1:56 AM

@JW: Wow, very cool to see you run with this. Some thoughts...

1) Primary key: You can probably find a decent JS library to simulate UUIDs. You can also use autonumbering in SQLite. Since this is a single user db, you could single thread the insert, get max(id), and have your new id. I'd probably do that myself.

2) Escaping text... don't do that. For your insert, use a bound parameter. (If that doesn't make sense, just ask.)

3) Sorry - what? :) (In terms of phonegap/jquery event listeners)

4) Image caching: Your solution is interesting, but don't forget you can use data urls too. That may be easier than a canvas implementation.

Comment 26 by Neil Thoms posted on 1/13/2012 at 8:43 PM

Great update!

I still can't get images to show on mine. Using FeedBurner I can't figure out what tag[s] are being used to show images.

Have you implemented images before?

Thanks,

Comment 27 by Raymond Camden posted on 1/13/2012 at 8:45 PM

No, but it should be simple enough. Can you share your feed url?

Comment 28 by Neil Thomas posted on 1/13/2012 at 8:59 PM

Hi Raymond,

The feed URL is: http://feeds.feedburner.com...

I've also tried using 'content' rather than 'desrciption' by including...

content$(v).find("content:encoded, encoded").text(),

...then for displayinh on contentPage:

contentHTML += '<p> '+entries[selectedEntry].content +'</p>';

I thought by showing content it would show images.

Thanks,

Comment 29 by Raymond Camden posted on 1/13/2012 at 9:02 PM

That should definitely work. If you console.log the value of contentHTML, do you still see the image tags present in the RSS?

Comment 30 by Neil Thomas posted on 1/13/2012 at 9:14 PM

How do I console.log? Sorry I'm new to this.

If its any use...I'm implementing it on Xcode.

Comment 31 by Raymond Camden posted on 1/13/2012 at 9:16 PM

console is an object in most modern web browsers. It's used for debugging messages. It can be a bit tricky via PhoneGap. For now, just use an alert(), although it may be hard to read ona mobile device.

Comment 32 by Neil Thomas posted on 1/13/2012 at 9:32 PM

I'm not sure where to put the alert(), though I know what it would do (flag when it is run?)

Comment 33 by Raymond Camden posted on 1/13/2012 at 9:35 PM

Well, we want to ensure the value is right. You would put it right after the line you share above.

contentHTML += '<p> '+entries[selectedEntry].content +'</p>';
alert(contentHTML);

Comment 34 by Neil Thomas posted on 1/13/2012 at 9:40 PM

I've inserted 'alert(contentHTML);'.

Unfortunately, nothing is responding in the app. It stopped working since I changed from using 'description' to using 'content'.

I get the header and footer but nothing in between, therefore can't see the contentPage for the alert to work.

Comment 35 by Neil Thomas posted on 1/13/2012 at 10:01 PM

I've almost sorted the problem.

Replaced:

content$(v).find("content:encoded, encoded").text()

With:

content:$.trim($(v).find("content:encoded, encoded").text()

It now displays the articles with proper paragraphs etc. Image placeholders/boxes are shown but the actual images are not showing. I have ensured that I have declared the allowed ExternalHosts in Xcode (i.e. the website/image sites reference. But they will not display.

Comment 36 by Raymond Camden posted on 1/13/2012 at 11:05 PM

Odd - it's just an image, so it should work.

So what I'd do now is simplify. Start a NEW project, virgin code. Use JavaScript to set a div to HTML like so:

$("#somediv").html("<h1>Hello</h1><img src='....'>");

In other words, use a very simple test best that uses HTML with an external image URL and see if that works out alright.

Comment 37 by Developer posted on 1/17/2012 at 1:15 PM

Hi Raymon, can you help me?
I have been build an app to read differents XML (in different div pages in the same HTML file), with a fixed navbar when I'm viewing the first XML list and I would like to go to the other list clicking in a link of the navbar, have this effect:

- Show the new page
- Show the old page
- Show and stay in the new page.

This effect shows in 1 second...
why it's show this?

I would like to go to the new page without this effect. I have tried with all options of data-transition but nothing...

Maybe the problem is on $("#list").listview("refresh"); ???

Sorry for my bad english.

Gracias (Thanks) :)

Comment 38 by Raymond Camden posted on 1/17/2012 at 7:01 PM

Having a hard time understanding you. If you are talking about page transitions, and if you are using jQuery Mobile, you can disable the transition.

Comment 39 by Arihant posted on 1/21/2012 at 1:52 PM

I am eagerly waiting for the third version with which we can cache 7 display old information if the user is offline. Please do this as soon as possible.....Awesome....The whole article saved my life

Comment 40 by Kevin Thomas posted on 1/24/2012 at 1:12 PM

All code works beautifully! I am working on a few requests to tweak the UX (user experience) due to some feedback I received. The most common comment is that when going back and forth between the RSS Title list and the content page is that the previous content shows for just a split second when view subsequent entries. I suppose the best way to tackle this would be to set the #linksList html to "" when clicking the back button so we can clear the previous content stuff out. Question is, is the back button click event the best place to add the code to blank out the #linksList div?

Comment 41 by Raymond Camden posted on 1/24/2012 at 7:37 PM

Um... you could. There is also a page event system in jQM you can use as well. How about I tackle your request as well as the offline request in p3?

Comment 42 by Raymond Camden posted on 1/25/2012 at 4:09 AM

Holy crap. This turned out to be a bit more difficult then I expected. I'm done though and about to post part 3.

Comment 43 by Raymond Camden posted on 1/25/2012 at 4:25 AM

Hey @Kevin/@Arihant: Please see: http://www.raymondcamden.co...

Comment 44 by Arihant posted on 1/25/2012 at 10:11 AM

Thanks...Checking the 3 article...GOD BLESS YOU! :)

Comment 45 by Neil Thomas posted on 2/12/2012 at 7:09 AM

Hi Raymond,

I fixed my previous problem with displaying images. It was in fact a whitelisting URL (external hosts) issue. All fixed now and looking great.

I've also modified the code with Part 3 caching etc, works great.

I was wondering, is it possible to render thumbnails in my list? Either as media:thumbnail or by somehow extracting the first image from each post?

Thanks,

Comment 46 by Raymond Camden posted on 2/12/2012 at 9:37 PM

Yes. First, I'd point you to the jQuery Mobile support for thumbnails in lists:

http://jquerymobile.com/dem...

But as to the URL, you would have a few options. First off, I do not quite remember if the RSS spec supports a icon per item. If you check the content of the RSS item, you can use a regular expression to find an image, and if so, include it.

Comment 47 by Neil Thomas posted on 2/12/2012 at 9:58 PM

Thanks for this. There doesn't seem to be icon or thumbnail item in my feed (http://feeds.feedburner.com....

I've uploaded my XML feed source to pastebin: http://codeupload.com/5147 .

How do you recommend implementing a regular epression?

Comment 48 by Raymond Camden posted on 2/12/2012 at 10:04 PM

You would get the content and then use a regex for the img tag to find the first one. If it exists. :)

Comment 49 by Neil Thomas posted on 2/12/2012 at 10:38 PM

Just had a look at examples of image tag/url/src reg expressions and its way over my head. A bunch of cryptic symbols :P.

Where would I put the expression in the main.js? I found a good example that picks up the first image of a html source... http://zytzagoo.net/blog/20... ... but its in PHP.

Comment 50 by Raymond Camden posted on 2/13/2012 at 7:50 AM

This regular expression will search a string and return all the images tags in an array.

var imgpat = /<img.*?>/g;
var matches = str.match(imgpat);
console.dir(matches);

Comment 51 by Neil Thomas posted on 2/13/2012 at 4:54 PM

Thanks for this Raymond,

I inserted this into the main.js just before '$.each(entries, function(i, v) {' . But the app is not showing any content now. Can you tell me where I need to insert it and how to call in the thumnail list item?

Thanks,

Comment 52 by Raymond Camden posted on 2/14/2012 at 3:30 AM

Um, well, you can't just insert it willy nilly. The sample I gave you was just that - a sample. You would want to run it _inside_ of the loop to perform the regex against each item matched.

Comment 53 by Neil Thomas posted on 2/16/2012 at 5:52 PM

Hi Raymond,

Thanks. Been trying everything for 3 days now but all examples are in PHP, which Phonegap/Xcode won't allow. Not giving up though :).

Comment 54 by Raymond Camden posted on 2/16/2012 at 7:25 PM

Care to share what you have so far via Pastebin?

Comment 55 by Neil Thomas posted on 2/16/2012 at 7:42 PM

Apologies for the stupidness that is about to be posted here...

The JS I inserted into my HTML <body>:

http://codeupload.com/5160

What I've done in your my main.js:

http://codeupload.com/5161

What the app currently looks like...

List: http://d.pr/U2tn
Entry: http://d.pr/KK9a

Thanks :)

Comment 56 by Raymond Camden posted on 2/16/2012 at 7:55 PM

Ok, so to be clear, the code you want to modify is here:

entry = {
link:$(v).find("link").text(),
pubDate:$(v).find("pubDate").text(),
creator:$(v).find("creator").text(),
title:$(v).find("title").text(),
link:$(v).find("link").text(),
llun:$.trim($(v).find("media:content").text()),
commentRss:$.trim($(v).find("wfw:commentRss").text()),
content:$.trim($(v).find("content:encoded, encoded").text())
};

This is the object we add to the array, and it contains all the info we care about for the entry. Since our regex logic is a bit complex, I'd do my mod AFTER the above.

I'd add the code to perform the regex, as I demonstrated. If there are matches, you take that first one and add it to the entry object, so imagine I've done that:

if(matches.length) {
entry.image = matches[0];
}

You may want to supply a blank value too:

} else {
entry.image = "";
}

or use some default image like you've done in your screen shot.

Comment 57 by Neil Thomas posted on 2/16/2012 at 8:39 PM

I have inserted the code after entry: http://codeupload.com/5162

Not bringing anything up in the content area now.

Off topic..but do you have a PayPal donate button on this blog? Or a PayPal email address?

Thanks,

Comment 58 by Raymond Camden posted on 2/16/2012 at 8:58 PM

On line 51, you are looking against the variable, str, which came form my example, but isn't valid here. You want to look against the content. Change str to content (I mean entry.content)

As for donations, I've got an Amazon Wish List link on the right. If you visit it, be sure to let me know as Amazon does a bad job of telling me who got me stuff. Even more, if you give me a UPS tracking #, you can watch my productivity dive in real time as I obsessively reload every 5 minutes.

Comment 59 by Neil Thomas posted on 2/16/2012 at 9:46 PM

There's a copy of Designing with Web Standards (3rd Edition) by the good old Zeldman on its way to you (by 18th Feb). Will email tracking details once available :).

I've now changed line 51 and its still not bringing back any content at all. :(

Comment 60 by Raymond Camden posted on 2/16/2012 at 9:47 PM

To be clear, is nothing working, or just this new image thing?

Comment 61 by Neil Thomas posted on 2/16/2012 at 9:50 PM

This is what is displayed:

http://d.pr/z9mC

Comment 62 by Raymond Camden posted on 2/16/2012 at 9:54 PM

At this point, it makes sense for you to maybe send me your code. What I'm going to do is take your XML, save it locally, take your HTML and run JUST it (no phone involved), and see if I can diagnose the issue.

Comment 63 by Neil Thomas posted on 2/16/2012 at 10:03 PM

Thanks Raymond.

I've zipped the HTML, CSS, JS and images here: http://d.pr/R9r4

Raw XML feed is at: http://codeupload.com/5165
Or here: feed://feeds.feedburner.com...

Really appreciate you doing this.

Comment 64 by J posted on 2/17/2012 at 12:15 AM

title:$(v).find("title").text()

this codes returns not only title, but also <media:title>

<title>My Title</title>
<media:title type="html">spoon-01</media:title>

So the title in the main page shows "My Titlespoon-01"

Comment 65 by Raymond Camden posted on 2/17/2012 at 12:40 AM

@J: In the find result, try adding a check for attr("type"), if it isn't there, you can assume it is your media tag. That's not 100% safe, but, it's something.

Comment 66 by Raymond Camden posted on 2/17/2012 at 7:50 PM

Neil, found the error right away:

var imgpat = /<img.*?>/g;
var matches = entry.content.match(imgpat);
console.dir(matches);

if(matches.length) {
entry.image = matches[0];
}

} else {
entry.image ="";
}

See the else block? You have 2 } before it.

Comment 67 by Raymond Camden posted on 2/17/2012 at 7:51 PM

By the way, I saw this right away by simply opening it up in Chrome, and in the Dev Tools, it clearly showed the syntax error. Just an FYI - I like to help people learn to solve problems instead of just solving the problems. ;)

Comment 68 by Neil Thomas posted on 2/17/2012 at 8:32 PM

Thanks Raymond,

I've changed it now and am calling '+ entry.image +' in my list.

Its bringing back an image, but the same one (from my last article entry. Screenshot here: http://d.pr/Ov4r .

Is it something to do with looping to the last entry and only bringing back that image?

Thanks,

Comment 69 by Raymond Camden posted on 2/17/2012 at 8:45 PM

Post the latest JS file to pastebin.

Comment 70 by Neil Thomas posted on 2/17/2012 at 8:49 PM

http://codeupload.com/5169

Image is called at line 20.

Thanks,

Comment 71 by Raymond Camden posted on 2/17/2012 at 8:51 PM

To be clear, that is NOT the thumb picture, but just the image from the last entry, right?

Comment 72 by Raymond Camden posted on 2/17/2012 at 8:53 PM

Oh dude, dumb error (err, not calling you dumb, just saying you will think so ;)

$.each(entries, function(i, v) {
s += '<li style="-webkit-border-radius:0px;"><a href="#contentPage" class="contentLink" data-entryid="'+i+'" style="-webkit-border-radius:0px;">' + entry.image + ' ' + v.title + '<br><span class="published-date-list">' + v.pubDate + '</span><br><span class="creator-list">by ' + v.creator+ '</span></a></li>';
});

Inside the loop, v represents the current entry you are going over. Change entry.image to v.image.

Comment 73 by Neil Thomas posted on 2/17/2012 at 8:53 PM

Its not the thumb picture.

thumb.jpg is a blue image.

Comment 74 by Neil Thomas posted on 2/17/2012 at 8:57 PM

You Sir are a genius. That was it! its working perfect now.

Thanks for all your help, I will stop pestering you now :)

Comment 75 by Raymond Camden posted on 2/17/2012 at 8:59 PM

Glad to help!

Comment 76 by Lincoln posted on 2/20/2012 at 1:39 PM

Thanks a lot, I've been looking for this.
Quick question, do this code show RSS images too?

Comment 77 by Lincoln posted on 2/20/2012 at 1:42 PM

Ok just saw the comments. Forget my prev question.
Thanks for your work Ray.

Comment 78 by maddom73 posted on 3/10/2012 at 1:16 AM

Hi ray,
your work is very good, so thanks a lot. However I have a little problem: the code in the brackets (entry.image = "/images/thumb.jpg";) displays the advertising of my rss feed and not a local thumb.
Thanks for your help!

Comment 79 by Raymond Camden posted on 3/10/2012 at 2:23 AM

No idea what you mean. If you can share a screen shot it may make more sense.

Comment 80 by maddom73 posted on 3/10/2012 at 2:22 PM

Ok! As you can see in the <a href="https://www.evernote.com/sh...">screenshot</a>some thumbs in the listview, instead of a local image shows the advertising pictures of my rss feed.
Thanks

Comment 81 by maddom73 posted on 3/10/2012 at 2:32 PM

Sorry for my previous comment. The right link is https://bitly.com/wTiWel.
Thank you!

Comment 82 by Raymond Camden posted on 3/12/2012 at 2:57 PM

Oh... well, the code I had demonstrated used a regex to find the first image. If your RSS has ads added to it (mine does that too), then that's why the ad shows up.

A way around this would be to modify the regex to look for images that include a src pointing to your main site. Of course, if you ever put an image in your blog that is from another server, then it wouldn't work.

Comment 83 by maddom73 posted on 3/12/2012 at 5:33 PM

Thank you very much! May be it's better to keep this regex and always put the images into the posts. If I can: Do you know How to change the options of a android native menuinflater in the transition from listview to appView?

Comment 84 by Raymond Camden posted on 3/12/2012 at 5:35 PM

I have no idea what this means: " If I can: Do you know How to change the options of a android native menuinflater in the transition from listview to appView?" Can you rephrase?

Comment 85 by maddom73 posted on 3/12/2012 at 5:55 PM

Ok! I made a mistake because I tried to translate an idiom of my language. I would like to implement an android native menu options (about, search, refresh, exit) in the first page (the listview of the rss feed) and another menu (back, share) in the page with the content of the post (appview). In java it's easy but I don't know using phonegap!

Comment 86 by Raymond Camden posted on 3/12/2012 at 5:57 PM

If I'm reading you right, you can use the PhoneGap Event API for the Android menu event. This allows you to do "stuff" on that button click. You would need to design some menu div in HTML that shows up when the user clicks there.

Comment 87 by maddom73 posted on 3/12/2012 at 6:34 PM

Yes, but I want to change the menu when I click on the item listview not just on the button

Comment 88 by Raymond Camden posted on 3/12/2012 at 6:41 PM

Unless I'm misunderstanding you, you need to add a click handler for the LI then. This is not a 'mobile' or PhoneGap question, but more just a general JavaScript question.

Comment 89 by luke321 posted on 3/18/2012 at 2:28 AM

hey there,
i got a strange problem with your code...
it shows the rss feed in safari and dreamweaver just fine.
but when i try it on my iphone or in firefox no items are loaded.
do you have any idea what the problem could be?

Comment 90 by Raymond Camden posted on 3/18/2012 at 2:35 AM

Are you on a Mac? If so - you have to add the RSS url in the whitelist in xcode.

Comment 91 by Luke321 posted on 3/18/2012 at 4:10 AM

yeah that fixed it.. (I should go to bed -.-)
thx a lot!!!!

Comment 92 by maddom73 posted on 3/18/2012 at 1:07 PM

Hi Raymond,
I just solved some problems but I don't know how to autoresize my thumb in the listview!

Comment 93 by Raymond Camden posted on 3/19/2012 at 12:09 AM

Use a set width and height. Your image may distort, but it will fit. You can either add it to the <img> tag or use CSS.

In other words, this is an HTML issue, not a PhoneGap issue.

Comment 94 by maddom73 posted on 3/22/2012 at 7:30 PM

Ok, solved!
Last question: How can I implement a context menu in "contentPage" to share my post? Best regards!

Comment 95 by Raymond Camden posted on 3/22/2012 at 7:34 PM

A context menu? Well Android supports a Menu click event that you can listed to with PhoneGap. If you wanted iOS too you would need an alternative, like perhaps a 'taphold' even.t

Comment 96 by maddom73 posted on 3/30/2012 at 11:06 PM

Thanks for your answers.
How do I format the pubDate? I would like to delete +0000 and set up the timezone.

Comment 97 by Raymond Camden posted on 3/31/2012 at 1:32 AM

You would need to use regex (or string functions) in JavaScript to do that. Definitely possible.

Comment 98 by maddom73 posted on 4/7/2012 at 12:35 PM

Hi, I took your advice and solved the problem! Now I would like to parse the youtube videos embedded in the CDATA tag. Can you help me?
Thank you!

Comment 99 by Raymond Camden posted on 4/10/2012 at 7:29 PM

I'd look at JavaScript's string parsing routines. If you have an example of the content (use pastebin!) I'd possibly be able to give you a hand.

Comment 100 by maddom73 posted on 4/10/2012 at 8:31 PM

I used your way to parse content encoded and I can see the youtube video in the iframe but as you know android has a little bad way to manage html5 video. I'm trying to implement Video player phonegap plugin but I can't handle onclick event on the video iframe. I think it's possibile to use the youtube api to handle and a string url to execute window.plugins.videoPlayer....(url).
Any suggestions?

Comment 101 by Raymond Camden posted on 4/11/2012 at 6:02 PM

No idea - haven't done Youtube in a PG app yet - sorry.

Comment 102 by Kieran posted on 7/20/2012 at 8:34 PM

Hi

I have a problem.

I have uploaded the index.html and the js folder as is to my web server but nothing is displaying. All I get is the header and the footer but no content inside.

This is strange because when i view it locally it works fine, no problems at all. I've tried it in lots of different browsers with no luck.

Any Idea's??

Comment 103 by Raymond Camden posted on 7/20/2012 at 8:39 PM

You uploaded it to your web server? This code is for a PhoneGap app. It makes a XHR request to a remote server which is blocked in "normal" browsers. You can't do it that way.

If you want to use a RSS feed in a desktop site, consider Google's Feed API. See my 4th entry in this series.

Comment 104 by Kieran posted on 7/20/2012 at 8:44 PM

Oh I see.

Thanks for your quick response, I will check that out.

Comment 105 by Maximilian Grimm posted on 9/18/2012 at 4:51 PM

Hello Raymond,

do you have any Idea how i can format the Date from the XML FEED "pubDate" into a german format via your Script and jQuery.

Thank a lot.

Comment 106 by Raymond Camden posted on 9/18/2012 at 5:45 PM

I'd consider trying this library: http://momentjs.com/

Comment 107 by Maximilian Grimm posted on 9/19/2012 at 1:45 PM

Hello Raymond,

thanks for the Tip. But as i see - i dont understand it :(
I get this Date Format: Wed, 29 Aug 2012 10:19:00 +0200
Because as i know thats the standard for rss.

And now i want to have this Format like 29.08.2012

Will try it a lot...

Comment 108 by Raymond Camden posted on 9/19/2012 at 3:15 PM

You don't understand what - the library I pointed to - or something else?

Comment 109 by Pascal Kuilboer posted on 2/16/2013 at 6:54 AM

I've tried to add an atribute to the code to load the image from an (owm) xml file... but no luck. Could you please assist?
xml line is:

<item>
<title>This is the tile</title>
<link>content.html</link>
<description>Brett S., een van de hoofdverdachten van de geruchtmakende mishandeling in Eindhoven, is vanavond in tranen te zien in Pownews. Hij betuigt spijt van zijn actie. "Ik slaap er zelfs niet goed door."</description>
<author>Pascal Kuilboer</author>
<category>nieuws</category>
<pubDate>Fri, 15 Feb 2013 13:30:00 +0100</pubDate>
<guid>content.html</guid>
<enclosure type="image/jpeg" url="images/foto1.jpg" />
</item>

title:$(v).find("title").text(),
link:$(v).find("link").text(),
img:$(v).find("enclosure.url").text(),
description:$.trim($(v).find("description").text())

Comment 110 by Raymond Camden posted on 2/16/2013 at 6:58 AM

I think you would want something like this:

img = $(v).find("enclosure").attr("url").

Comment 111 by Pascal Kuilboer posted on 2/16/2013 at 7:03 AM

Tried that with a minor adjustment.
Changed the = for : and it works

img:$(v).find("enclosure").attr("url")

So many thanks and also for your amazing quick reply.

Comment 112 by Pascal Kuilboer posted on 2/16/2013 at 8:43 AM

Could you tell me why the script is working wonderful in Dreamweaver Phonegap, but not in my app, Safari, Chrome of Firefox... locally or on server I'm lost!
Would really like your help in this. Thanks

Comment 113 by Pascal Kuilboer posted on 2/16/2013 at 12:00 PM

Also one more thing. how could i limit the list to lets say 10 items?
Thanks in advance...

Comment 114 by Raymond Camden posted on 2/16/2013 at 6:47 PM

Because Ajax requests to other servers are blocked by the browser for security reasons. You can bypass that in Chrome w/ a command line argument for testing.

To limit, you would just add a check in the loop. Once you hit your max you can stop looping.

Comment 115 by Pascal Kuilboer posted on 2/17/2013 at 6:58 PM

Can't get the dateformat to work (day - month year) with your tip to moment.js. It's driving me nuts (fairly common for programmers haha)

Also the limit loop you suggested still give all the entries in the xml

Any tips and help? Please...

Comment 116 by Raymond Camden posted on 2/17/2013 at 10:51 PM

Can you share the code you are trying? Please use pastebin or Gists.

Comment 117 by Pascal Kuilboer posted on 2/18/2013 at 1:49 AM
Comment 118 by Raymond Camden posted on 2/18/2013 at 6:31 PM

Um, you didn't put in any code to actually limit the entries. Look in the $.get block. Change that $.each to a for loop that goes up to, at most, your desired max.

I'm also not seeing where you tried to use moment.

Comment 119 by Pascal Kuilboer posted on 2/19/2013 at 3:31 AM

That's true... i deleted the code before i uploaded it and made it as clean as possible. Also the images if there is not an atrribute was showing undefined and got some code to eliminate that, but doesn't work anymore in after click in de detailspage.

Love your script but it's giving me some problems as you know... Hope you can help me with your expertise.

Comment 120 by Raymond Camden posted on 2/19/2013 at 5:25 AM

I'm afraid I don't understand though. I'm not going to write this code for you. You really need to show me what you tried first. Let's focus on limiting the data. I'd try what I suggested above - changing the $.each for a for loop.

Comment 121 by Pascal Kuilboer posted on 2/19/2013 at 9:57 PM

This is what i tried to limit the items to display..

------
$.get(RSS, {}, function(res, code) {
entries = [];
var xml = $(res);
var items = xml.find("item");
for(var i = 0; i < $items.length && i < 10; i++);
$.each(items, function(i, v) {
entry = {
title:$(v).find("title").text(),
link:$(v).find("link").text(),
img:$.trim($(v).find("enclosure").attr("url")),
description:$.trim($(v).find("description").text())
};
entries.push(entry);
});
----

Comment 122 by Raymond Camden posted on 2/20/2013 at 2:52 AM

Woah, this is not valid at all:

for(var i = 0; i < $items.length && i < 10; i++);

You have an empty for loop there. Please see the Mozilla Developer Network docs on basic JavaScript syntax if you don't understand how for loops work:

https://developer.mozilla.o...

You need to get rid of the existing $.each as I said. THe for loop is a replacement.

Comment 123 by Jake posted on 3/19/2014 at 5:42 PM

Great tuts Raymond,

is there a way to make the Feed Reader work when I come back to the app after visiting an external link?

When I click on external link and then come back the article text and title go lost.
How to retrieve the content when I come back?

The same happen using chrome or other browsers and not only the emulator or the compiled app.

Comment 124 by Raymond Camden posted on 3/24/2014 at 4:04 PM

Try the most recent version: http://www.raymondcamden.co...

But be sure to NOT use the plugin - use the InAppBrowser feature instead. (Basically ChildBrowser was rolled into cored PG after the article was written.)

Comment 125 by Jake posted on 3/24/2014 at 5:03 PM

Thanks for your reply.

I'm using the latest versione but the content get lost when coming back.

I'm also trying to use the InAppBrowser but something strange happens. If I put allow origin * the InAppBrowser doesn't work and the feed reader work.

If I whitelist single URL the InAppBrowser works but the feed no. I'm using phonegap 3.4.

I think it's a bug of phonegap or of InAppBrowser.

When I use the access origin configuration that make the InAppBrowser works it doesn't show the navigation bar and the done button.

Have you been able to make it works?

Comment 126 by Raymond Camden posted on 3/24/2014 at 6:08 PM

"I'm using the latest versione but the content get lost when coming back."
So to be clear, you see the new window open up, you can view the content, and then when you close the window, stuff is messed up?

"I'm also trying to use the InAppBrowser but something strange happens. If I put allow origin * the InAppBrowser doesn't work and the feed reader work."
What do you mean? You mean in the access block in config?

Comment 127 by Jake posted on 3/24/2014 at 7:10 PM

Exactly. Stuff is messed up cause probably the inappbrowser is not working.

If I put in the config.xml

<access origin="http://*.mydomain.it" subdomains="true" />
<access origin="http://*.google.com" subdomains="true" />
<access origin="http://*.googleapis.com" subdomains="true" />
<access origin="http://127.0.0.1" subdomains="true" />

or whatever you want the inappbrowser works and show the URL bar with the option to close it, but the Feed parsing is not working and I can't see the Articles.

If I put in the www/config.xml

<access origin="*" />

The feed reader works, but the inappbrowser not.

Comment 128 by Raymond Camden posted on 3/24/2014 at 8:32 PM

Testing on iOS:
First, I added the InAppBrowser plugin.
Then I changed

window.plugins.childBrowser.showWebPage($(this).attr("href"));

to

window.open($(this).attr("href"), "_blank");

And it worked for me. Did you make that last change?

Comment 129 by Jake posted on 3/24/2014 at 9:22 PM

I found the issue!!

In the access I need to specify both http and https for Google and Googleapis.

Comment 130 by Jake posted on 3/25/2014 at 1:11 AM

But what do you have in your access origin?

I've already addedd the window.open($(this).attr("href"), "_blank");

Comment 131 by Raymond Camden posted on 3/25/2014 at 1:24 AM

I left it at default - *.