Windows 8 HTML5 Metro Style App: RSS reader in 30min - building your WordPress or Community Server version
I got nice feedbacks on my 2 previous small tutorials:
- Windows 8 HTML5 Metro Style App: How to create a small RSS reader in 30min (part 1/2)
- Windows 8 HTML5 Metro Style App: How to create a small RSS reader in 30min (part 2/2)
But many of you sent me emails or messages on Twitter to know how to plug the tutorials on a WordPress blog. So let me show you how to do that in 5 minutes rather than giving you directly the code.
You’ll need of course to read the 2 previous tutorials before going through this one. What’s more, please note again that the below details won’t be enough to make a great Windows 8 App ready for the store. That’s why also, I will continue this series in the next weeks to show you how to add the navigation framework, a splash screen, the snap view, etc.
Update on 09/07/2012: I’ve added also an example using a Community Server RSS feed (on my blog) as I had requests about that also. If you’ve got another type of blogs platform, just follow the principles described below to find the matches between your XML structure and the JS code.
Ok, let’s start by reviewing what you need to change in the part 1 of the tutorials to match the RSS feed sent back by a WordPress blog or Community Server.
For WordPress, let’s go on the official WordPress site: https://wordpress.com/ and try some of the suggested blogs. I’ve randomly chosen this one: Wax Wane and its RSS feed: Wax Wane RSS Feed.
For Community Server, let’s use my own blog RSS feed: https://blogs.msdn.com/b/davrous/rss.aspx
What we need to do is analyzing the XML content sent back by the RSS feed and find the nodes we’re interesting in to change this previous download function:
function downloadC9BlogFeed() {
WinJS.xhr({ url: "https://channel9.msdn.com/coding4fun/articles/RSS" }).then(function (rss) {
var items = rss.responseXML.querySelectorAll("item");
for (var n = 0; n < items.length; n++) {
var article = {};
article.title = items[n].querySelector("title").textContent;
var thumbs = items[n].querySelectorAll("thumbnail");
if (thumbs.length > 1) {
article.thumbnail = thumbs[1].attributes.getNamedItem("url").textContent;
article.content = items[n].textContent;
articlesList.push(article);
}
}
});
}
that was made to work fine with the XML tree of the RSS feed of the Channel9 blog.
View the WordPress RSS Feed and/or the Community Server version in your browser:
And right-click to view the source. It will probably open it in Notepad which is not the best tool to review some XML. Copy/paste the whole XML feed into a new XML file in Visual Studio 2012:
After reviewing the WordPress or the Community Server feed, you’ll notice that there is no “thumbnail” attribute like we have in the Channel9 feed.
Note: the first simple solution would then be to have the same XML structure as the Channel9 one by using the MediaRSS plugin for WordPress. But let’s see a more generic approach.
Let’s start by the WordPress version. The interesting XML parts are stored in:
- “ <content:encoded> ” for the article itself
- “ <media:content> ” for the possible images to use as thumbnails for the main page
It turns out that taking the last <media:content> node of the list seems to works fine. To reflect that, here is the download function I’m suggesting you:
function downloadThisWordPressBlogFeed(WPFeedUrl) {
WinJS.xhr({ url: WPFeedUrl }).then(function (rss) {
var items = rss.responseXML.querySelectorAll("item");
for (var n = 0; n < items.length; n++) {
var article = {};
article.title = items[n].querySelector("title").textContent;
var thumbs = items[n].querySelectorAll("content");
if (thumbs.length > 1) {
article.thumbnail = thumbs[thumbs.length - 1].attributes.getNamedItem("url").textContent;
article.content = items[n].querySelector("encoded").textContent;
articlesList.push(article);
}
}
});
}
You then need to call this function instead of the previous one and pass the URL of your blog’s feed as parameter. For instance:
args.setPromise(WinJS.UI.processAll().then(downloadThisWordPressBlogFeed("https://wax-wane.com/feed/")));
If you’re running with those modifications, it will start to work:
To enhance a little bit the experience, let’s add the title of the current blog being read in the title of the home page and let’s display the title of the article at the top when navigating to it. For that, declare these variables at the top of “default.js”:
var wordPressBlogTitle;
var mainTitle;
In the onactivated function, retrieve the div associated to the main title:
mainTitle = document.getElementById("maintitle");
Then modify the download function to add these 2 additional lines:
function downloadThisWordPressBlogFeed(WPFeedUrl) {
WinJS.xhr({ url: WPFeedUrl }).then(function (rss) {
wordPressBlogTitle = rss.responseXML.querySelector("title").textContent;
mainTitle.innerHTML = "Welcome to " + wordPressBlogTitle + " blog!";
var items = rss.responseXML.querySelectorAll("item");
for (var n = 0; n < items.length; n++) {
var article = {};
article.title = items[n].querySelector("title").textContent;
var thumbs = items[n].querySelectorAll("content");
if (thumbs.length > 1) {
article.thumbnail = thumbs[thumbs.length - 1].attributes.getNamedItem("url").textContent;
article.content = items[n].querySelector("encoded").textContent;
articlesList.push(article);
}
}
});
}
Finally, modify the navigation logic to add those lines in the appropriate functions:
function backButtonClick(e) {
articlecontent.style.display = "none";
articlelist.style.display = "";
mainTitle.innerHTML = "Welcome to " + wordPressBlogTitle + " blog!";
WinJS.UI.Animation.enterPage(articlelist);
}
function itemInvoked(e) {
var currentArticle = articlesList.getAt(e.detail.itemIndex);
WinJS.Utilities.setInnerHTMLUnsafe(articlecontent, currentArticle.content);
articlelist.style.display = "none";
articlecontent.style.display = "";
mainTitle.innerHTML = currentArticle.title;
WinJS.UI.Animation.enterPage(articlecontent);
}
And that’s it. Running the application on the Wax Wane RSS Feed will give you these results:
You will probably have to use Blend to work on the design of your blog to have better results.
At last, while testing this solution, I’ve discovered that some blogs’ urls some of you sent me doesn’t work with the above code. This is because no <media:content> nodes are available in their feeds. Same problem for the Community Server feed. The content itself is store inside the <description> node and, at least for the Technet & MSDN versions we’ve got, there is no <media:content> nodes we could use as a base for our thumbnails.
A possible fallback solution would be to search for the first available image URL in the blog post itself and use it as a thumbnail.
Here is a suggested possible solution for WordPress:
function downloadThisWordPressBlogFeed(WPFeedUrl) {
WinJS.xhr({ url: WPFeedUrl }).then(function (rss) {
wordPressBlogTitle = rss.responseXML.querySelector("title").textContent;
mainTitle.innerHTML = "Welcome to " + wordPressBlogTitle + " blog!";
var items = rss.responseXML.querySelectorAll("item");
for (var n = 0; n < items.length; n++) {
var article = {};
article.title = items[n].querySelector("title").textContent;
var thumbs = items[n].querySelectorAll("content");
article.content = items[n].querySelector("encoded").textContent;
if (thumbs.length > 1) {
article.thumbnail = thumbs[thumbs.length - 1].attributes.getNamedItem("url").textContent;
}
else {
var firstindex = article.content.indexOf("<img");
if (firstindex !== -1) {
var secondindex = article.content.indexOf("src=", firstindex) + 5;
var thirdindex = article.content.indexOf("\"", secondindex);
article.thumbnail = article.content.slice(secondindex, thirdindex);
}
}
if (article.thumbnail) {
articlesList.push(article);
}
}
});
}
And here is a suggested possible solution for Community Server:
function downloadThisCommunityServerBlogFeed(WPFeedUrl) {
WinJS.xhr({ url: WPFeedUrl }).then(function (rss) {
wordPressBlogTitle = rss.responseXML.querySelector("title").textContent;
mainTitle.innerHTML = "Welcome to " + wordPressBlogTitle + " blog!";
var items = rss.responseXML.querySelectorAll("item");
for (var n = 0; n < items.length; n++) {
var article = {};
article.title = items[n].querySelector("title").textContent;
var thumbs = items[n].querySelectorAll("content");
article.content = items[n].querySelector("description").textContent;
if (thumbs.length > 1) {
article.thumbnail = thumbs[thumbs.length - 1].attributes.getNamedItem("url").textContent;
}
else {
var firstindex = article.content.indexOf("<img");
if (firstindex !== -1) {
var secondindex = article.content.indexOf("src=", firstindex) + 5;
var thirdindex = article.content.indexOf("\"", secondindex);
article.thumbnail = article.content.slice(secondindex, thirdindex);
}
}
if (article.thumbnail) {
articlesList.push(article);
}
}
});
}
You’ll notice the only difference is that the name of the XML node containing the content of the article on Community Server is “<description>” whereas it’s “<content:encoded>” for WordPress.
This code is not robust enough to address all possible cases, so you will have probably to work on that part for your own blog. Still, this solution works fine in various cases like with this blog dedicated to Super Heros: https://comicsgen.fr/feed :
And here is the result with my own blog’s feed:
Again, the design is far from being optimal. As I’m choosing the first image as the thumbnail, it’s not always appropriate or quality enough. You could think about enhancing that part by choosing the best quality image in the feed or tagging one of the images with a specific class to automatically extract it in your JS code as a thumbnail. Still, you’ll notice that the videos in my blogs posts work fine as they’re are using… HTML5 <video>!
So, we’re already have a nice working application in a very few lines of HTML5/CSS3/JS code. You should then now all the basics pieces to build your own Windows 8 app connected to your WordPress or Community Server RSS feed.
You can download the Visual Studio 2012 solution here: Basic Generic WordPress Metro Reader
Enjoy!
David
Comments
Anonymous
July 11, 2012
Hi How to make it work with feeds from feedburner, because when I going to load feeds I get this error: APPHOST9601: Can’t load <feeds.feedburner.com/.../itemcontent.css>. An app can’t load remote web content in the local context. File: default.htmlAnonymous
July 12, 2012
How to resize images in pages?Anonymous
September 03, 2012
Nice blog .I will surely used in this rss reader in my next blog
Kedar <a href="http://www.tuljabhavani.in>my current blog</a>
Anonymous
September 27, 2012
Hi, When I try the code on my machine I get the following error: Error 1 Could not find SDK "Microsoft.WinJS.1.0.RC, Version=1.0". C:WindowsMicrosoft.NETFrameworkv4.0.30319Microsoft.Common.targets 1701 5 BasicGenericWordPressMetroReader I'm running VS2012 What can be the problem? Thanks, MikeAnonymous
September 27, 2012
Hi Mike, This is because it was the RC version coming with Win8 RP. You've got to unreferenced WinJS.1.0.RC and reference WinJS.1.0 the RTM version. I've done it and re-uploaded the solution. If you download it again, it should now works. DavidAnonymous
October 06, 2012
The comment has been removedAnonymous
October 06, 2012
Scratch the previous question, i found the solution, some code mixing between wordpress sample and channel 9 did the trick.Anonymous
October 07, 2012
Hi again, I order the code to work i have changed this: var thumbs = items[n].querySelectorAll("content"); article.content = items[n].querySelector("description").textContent; into this: var thumbs = items[n].querySelectorAll("thumbnail"); article.content = items[n].querySelector("content").textContent; but now, when a new article is added, the application is not updated. Any thoughts?Anonymous
October 07, 2012
Hi Nikos, This is why I've added in the article this sentence: "If you’ve got another type of blogs platform, just follow the principles described below to find the matches between your XML structure and the JS code.". My code can't support any type of XML format sent back by the various blog engines available on the market. If the application is not updated after an article is being added, it's probably because it's not sent back into the RSS feed yet. Have you checked if the newest article is there in the XML feed? Bye, DavidAnonymous
October 07, 2012
Sorry for the above, the current code is: var thumbs = items[n].querySelectorAll("desciption"); article.content = items[n].querySelector("encoded").textContent; Yes the article is sent back to feed 15 minutes now. I used the above code , because it's the only that show correctly the thumbs of the posts and the full post content when i click on a post.Anonymous
October 08, 2012
Maybe a refresh button would do the trick, or auto refresh when the app is loaded. Any thoughts?Anonymous
October 10, 2012
Thanks a lot, David. It works OK also on Blogger platform (hopefully, it won't break with win8 final release). Any chance we can have these last pieces sometime in the near future: ''I will continue this series in the next weeks to show you how to add the navigation framework, a splash screen, the snap view, etc.''Anonymous
October 26, 2012
Is there anyway you can release the code? I have been playing around with it for days and still can't get it to work!Anonymous
October 26, 2012
Hi Lee. I don't get it. The code is available for download at the end of the article. Are you talking about something else? DavidAnonymous
October 29, 2012
Is there a roadmap about the tutorials regarding snapped view etc..?Anonymous
November 12, 2012
Please help. I have been creating a news application, but I can not get the images from the site. I need to get the Image form the "enclosure" elemant. The feed looks like this: <item> <guid>rt.com/.../guid> <link>rt.com/.../link> <dc:creator>RT</dc:creator> <enclosure url="rt.com/.../peter-thomas-reuters.jpg" type="image/jpeg"/> <pubDate>Tue, 13 Nov 2012 01:43:48 +0400</pubDate> I removed the description form the feed because of the space it would take up </item> Here is my code: WinJS.xhr({ url: "rt.com/.../" }).then(function (rss) { var items = rss.responseXML.querySelectorAll("item"); for (var n = 0; n < items.length; n++) { var article = {}; article.title = items[n].querySelector("title").textContent; article.pubDate = items[n].querySelector("pubDate").textContent; article.link = items[n].querySelector("link").textContent; article.story = items[n].querySelector("description").textContent; var thumbs = items[n].querySelectorAll("enclosure"); if (thumbs.length > 1) { article.thumbnail = thumbs[1].attributes.getNamedItem("url").textContent; article.content = items[n].textContent; articlesList.push(article); } else { article.thumbnail = "/images/logo.png"; article.content = items[n].textContent; articlesList.push(article); } } }); It always just goes to the else statement.Anonymous
November 14, 2012
hello David Rousset, will it work for feedburner (feeds.feedburner.com/techzost) my site http://www.techzost.com -thanks, waiting for your response.Anonymous
November 17, 2012
Hi David, I can't make like this using blogger rss feed but when i use the wax wan rss feed as shown above the project has succeed but when i use mine blogger rss feed ,the project can open/feed unavaible/error.Anonymous
November 28, 2012
when a new article is added, the application is not updated.. i have checked my RSS XML and article is there but the application does not check for updates. It just downloads once in the start and after that it keeps a cache of articles I think. When I restart my PC it checks again. It should check every time the app is run. Also I was checking WordPress Store Application today and I notices that it is also a RSS reader but it checks for new articles everytime you click on the tile and run the app.Anonymous
December 10, 2012
The comment has been removedAnonymous
December 10, 2012
just tried store.steampowered.com/.../newreleases.xml and this version isn't the rdf version. i also get same error. weirdAnonymous
December 12, 2012
Hi David, This tutorial is great. I just wanted to ask that :- Is there any way to get notifications of new posts on the wordpress blog? Thanks.Anonymous
January 25, 2013
The comment has been removedAnonymous
February 26, 2013
The comment has been removedAnonymous
March 23, 2013
Hi, The error related to "article.content = items[n].querySelector("encoded").textContent;" is certainly due to the settings of your blog in WordPress. If the RSS feed does not include the full article (i.e. only the desciption), you'll not get the XML tag for content (<content:encoded">). As a result Visual Studio breaks. Check your RSS link (myblog.wordpress.com/feed) and if you see only the description, change your WordPress reading settings. The try again (clear your cache to be sure that when testing again, you get the new RSS feed including full articles).