Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

A Little HTML5: Using JSON and File API to View Starred Google Reader Posts

5.00/5 (1 vote)
28 May 2013CPOL3 min read 9.6K  
Using JSON and File API to view starred Google Reader posts.

A couple of months ago, Google announced that it was retiring its web feed reader Google Reader. As a long-time user of the service, I was disappointed. But there are a couple of substitutes out there like FeedlyThe Old ReaderNetVibes, etc. Google gives you the option of exporting your data from Reader through Google Takeout. This is where my inspiration for a little project started.

When you go through the process to export your data through Takeout, you receive a zip file. It contains an XML file with all of your subscriptions in OPML format, as well as seven JSON files containing information like your social connections, stories you “liked,” stories you shared with others, notes you took about stories, stories that you put in your favorites list, etc. The problem I found is that none of the above mentioned substitutes know what to do with any of these JSON files.

I typically used my favorites list (the “starred” items) as an “I’ll read this later” group. But now, I have a 1.5 MB file of saved items and no way to read them.

So, let’s create a way to read them using JSON and the File API!

The Solution

google-reader-import.html

XML
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="robots" content="noindex">
        <title>Google Reader Import</title>
        <link type="text/css" 
          rel="stylesheet" href="google-reader-import.css">
    </head>
    <body>
<h1>Google Reader Import</h1>
        <input type="file" id="fileInput" />
        <div id="stories" class="stories"></div>
        <script src="google-reader-import.js">

        </script>
    </body>
</html>

I also created a CSS file to style the posts similarly to how they are presented in the original Google Reader application:

google-reader-import.css

CSS
.stories {
    margin: 10px 0px 0px;
    max - width: 650px;
}
    .entry - main {
    padding: 5px 10px 0px 13px;
    margin - bottom: 20px;
    border - top: 0px none;
    border - bottom: 0px none;
    background: none repeat scroll 0 % 0 % rgb(247, 247, 247);
    border: 1px solid rgb(233, 233, 233);
    min - height: 20px;
    padding: 19px;
    margin - bottom: 20px;
    background - color: rgb(245, 245, 245);
    border: 1px solid rgb(227, 227, 227);
    border - radius: 4px 4px 4px 4px;
    box - shadow: 0px 1px 1px rgba(0, 0, 0, 0.05) inset;
}
    .entry - date {
    float: right;
    color: rgb(102, 102, 102);
    text - decoration: none;
    margin: 0px;
}
    .entry - title {
    color: rgb(17, 85, 204);
    font - size: 140 % ;
    margin: 0px;
    max - width: 650px;
}
    .entry - title - link {
    color: rgb(17, 85, 204);
    text - decoration: none;
}
    .entry - author {
    color: rgb(102, 102, 102);
    text - decoration: none;
    margin: 0px;
}
    .entry - source - title - parent {
    color: rgb(102, 102, 102);
}
    .entry - source - title {
    color: rgb(17, 85, 204);
    display: inline - block;
    text - decoration: none;
}
    .entry - body {
    color: rgb(0, 0, 0);
    padding - top: 0.5em;
    max - width: 650px;
    margin: 0px;
}
    .item - body {
    margin: 0px;
}

However, the real work is done in the JavaScript.

The first function I’ve named handleFileSelect. When the user selects a file, the handleFileSelect() function gets called. We use the JavaScript File API to read in the file, using the FileReader to handle actually asynchronously loading the JSON file. After creating the new FileReader object, we set up its onload function, then call readAsText() to start the read operation in the background. When the entire contents of the JSON file are loaded, we pass it to the JSON.parse() function in our onload callback. Our implementation of this routine takes the JSON objects and iterates through its item list, where each item represents a single post from our starred list.

The second function, createStoryEntry, creates the HTML for each post using a format similar to the original application. The date in the JSON is along in seconds, so we take it and multiply by 1000 to convert it to milliseconds and create a JavaScript Date object so we can create a user-friendly date representation.

Another thing to consider is that some posts have full content, while others just contain a summary of the full content. We do a quick check to determine if the post has full or partial content and then set our content to the correct value. Each post is then appended as a child to our “stories” div:

google-reader-import.js

JavaScript
function createStfunction createStoryEntry(jsonItem) {
    var publishedDate = new Date(jsonItem.published * 1000);
    var content = (typeof jsonItem.content === 'undefined') ? 
                     jsonItem.summary.content : jsonItem.content.content;
    var entryMain = document.createElement("div");
    entryMain.className = "entry-main";
    entryMain.innerHTML = '</pre>
<div class="entry-date">' + publishedDate.toDateString() + ' ' +
 publishedDate.toTimeString() + '</div>
<h2 class="entry-title">' +
 '<a class="entry-title-link" href="' + 
   jsonItem.alternate.href + '" target="_blank">' +
 jsonItem.title + '</a></h2>
<div class="entry-author">' +
 '<span class="entry-source-title-parent">from <a class="entry-source-title" href="' + 
    jsonItem.origin.htmlUrl + '" target="_blank">' + jsonItem.origin.title +
 '</a></span></div>
<div class="entry-body">
<div>' +
 '
<div class="item-body">
<div>' + content + '</div>
</div>
' +
 '</div>
</div>
<pre>
';
    return entryMain;
}

function handleFileSelect() {
    var storiesContainer = document.getElementById('stories');

    var reader = new FileReader();
    reader.onload = function (evt) {
        var parsedStories = JSON.parse(evt.target.result);
        for (var i = 0; i < parsedStories.items.length; i++) {
            storiesContainer.appendChild(createStoryEntry(parsedStories.items[i]));
        }
    };
    reader.readAsText(this.files[0]);
}
document.getElementById('fileInput').addEventListener(
              'change', handleFileSelect, false);

If you want to see more of what you can do with the File API, Mozilla has a great resource on adding additional features like drag-and-drop.

This particular program will only work with a modern browser, but you could also use a JavaScript library like Modernizr to determine if the browser has the capability to use the File API and JSON. Good luck!

– Brice McIver, asktheteam@keyholesoftware.com

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)