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. Clignement d'œil 

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:

image image

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:

image

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:

image image

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:

image image

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 :

image

And here is the result with my own blog’s feed:

image image

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>! Sourire 

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