Google reader is the most popular web-based feed-reader. A lot of ajax techniques and well-defined layout — that's all Google Reader offers. This tutorial is aimed at creating a Google reader mock-up with some of its awesome features.


Download Source Try Demo

Building The Layout

Google Reader has a fluid table based layout having header, a left pane containing the feeds and a right view-area. Our simple-reader would have a header area, a left pane and a view-area.

We create the index.php file and add the following code:

<html>
<head>
<title>Simple Reader</title>
<style type='text/css'>
body {
 margin:0px;
 padding:0px;
 font-family:Arial, serif;
 font-size:14px;
}
a {outline:none;}
#header {
 background:url("images/logo.png") no-repeat center left;
 height:10%;
 overflow:hidden;
}

#loader {
 background:#f9dd7d;
 width:75px;
 margin:auto;
 display:block;
 padding:6px;
 font-weight:bold;
 display:none;
}

#wrapper {
 height:90%;
 margin:0px;
 padding:0px;
}
</style>
<script type='text/javascript' src='jquery.pack.js'></script>
<script type='text/javascript' src='jquery.layout.js'></script>
</head>
<body>
 <div id='header'>
  <div id='loader'>Loading...</div>
 </div>
 <div id='wrapper'> </div>
</body>
</html>
Notice that we have added a div with id 'loader'. We have hidden it by setting display:none but we would show it while making ajax calls.

Within #wrapper we'd have two sections: #sidebar and #view-area. For the purpose of building this, we are going to use jQuery layout plugin which makes things easier by adding panes and resizers that come handy in creating rich ajax based web-application interface.

jQuery Layout has a very simple structure. If we just add five divs with class names ui-layout-north, ui-layout-west, ui-layout-center, ui-layout-east and ui-layout-south, it automatically aligns the divs the following way and also adds resizers to collapse the panes.
But for the purpose of our layout we just need the west and the center sections. So within the #wrapper div we add:
<div class='ui-layout-west' id='sidebar'></div>

<div class='ui-layout-center' id='view-area'></div>
We also include the javascript files within the head tag.
<script type='text/javascript' src='jquery.pack.js'></script>
<script type='text/javascript' src='jquery.layout.js'></script>
But nothing happens to our layout. That's because we have not initiated the layout with jquery. To do so we add the following code in the head tag.
<script type='text/javascript'>
$(document).ready(function () {
 var my_layout = $('#wrapper').layout({applyDefaultStyles:true});
 });
</script>
Now we have something like this:
Notice that the layout plugin has added a resizer to our sidebar section. If you inspect this element in Firebug, you'd find that the resizer is a span section with class name ui-layout-resizer-west-open and within the span, there's a div section having a class name ui-layout-toggler-west-open. If you close the panel clicking the grey area, the class name of the span turns to ui-layout-resizer-west-closed and that of the div turns to ui-layout-toggler-west-closed.
So now we add some css to make it look better.
.ui-layout-resizer-west {
 background:#ebeff9;
}

.ui-layout-toggler-west-open {
 background:url("images/toggle-lt.gif") no-repeat center;
}
.ui-layout-toggler-west-closed {
 background:url("images/toggle-rt.gif") no-repeat center;
}
.ui-layout-center {
 border-top:2px solid #ebeff9;
}

.ui-layout-west {
 background:#ffffff;
 border-top:2px solid #ebeff9;
}
We also remove the default styling of the layout by removing {applyDefaultStyles:true} So now, our javascript looks like:
var my_layout = $('#wrapper').layout();
Our layout now looks much nicer with the toggler images.


Creating And Connecting To The Database

Now that we have the layout prepared, we create a database that would contain URL and feed names.
Here we have table called feeds with four fields.

Next, we create file called config.php.
<?php
$hostname = "YOUR_HOSTNAME";
$username = "YOUR_USERNAME";
$password = "YOUR_PASSWORD";
$database = "YOUR_DATABASE_NAME";

$link = mysql_connect($hostname, $username, $password) or die("Cannot connect to the database!");
mysql_select_db($database) or die("Cannot select database!");
?>
We also include the config.php file at the top of index.php to gain access to database credentials.
<?php
include("config.php");
?>

Adding Feeds To The Reader

So we have the table and we have connected to the database. We now add feeds — that too with Ajax!

Within the sidebar section we create a link to add feeds.

<a class='add-feed' href='javascript:;'>Add Feed</a>
And some css to make it look good.
a.add-feed {
 background:url("images/add_feed.gif") no-repeat center left;
 padding:6px 6px 6px 35px;
 font-size:1.5em;
 display:block;
 color:#000000;
 text-decoration:none;
}

a.add-feed:hover {
 text-decoration:underline;
}
What we want is when the add-feed link is clicked an ajax call would be made to the server and a form would be sent. We do this with jquery.
$("a.add-feed").click(function(){
  $("#loader").fadeIn();
  $.ajax({
   type: "POST",
   data: "action=show_form",
   url: "add.php",
   success: function(msg)
    {
     $("#view-area").html(msg);
     $("#loader").fadeOut();
    }
  });
 });
In the above code, we show the loader when the ajax call is in process and when response has reached the browser, we hide the loader and show the reponse in view-area. Remember the above javascript will go inside the curly braces of $(function(){ }); because the javascript will be available for execution after the page is loaded.

But we don't have the add.php page. Let's create it.
<?php
include("config.php");
if(!$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')
 {
 die("No direct access to files is allowed");
 }
$action = trim($_POST["action"]);

if($action == "show_form")
 {
?>
<form action='' id='add_form'>
<label for='feed_name'>Name:</label>
<input type='text' id='feed_name' name='feed_name'/>
<label for='feed_url'>Feed URL:</label>
<input type='text' id='feed_url' name='feed_url'/>
<input type='submit' value='add' class='submit-button'/>
</form>
<?php
 }
?>
First, we stop access to the page except through ajax call. Then, we show the form.

Now if you click the Add Feed link, the form will be displayed. But it looks horrible without css. Let's give it some style.
form#add_form {
 width:300px;
 margin:auto;
}

form#add_form {
 width:300px;
 margin:25px auto;
}

#add_form label {
 float:left;
 text-align:right;
 margin-right:15px;
 width:75px;
 padding-top:5px;
 cursor:pointer;
}

#add_form input {
 margin:0px 0px 10px;
 padding:3px;
 font-size:1.2em;
}

#add_form .submit-button {
 border:1px solid #e8e8ff;
 float:right;
}
Remember that since we are showing everything on the index.php page, all css definitions will go within the <style> tag of index.php

Now, we want to add feed — with Ajax. For that purpose we use the following javascript code.
$("form#add_form").live("submit", function()
  {
  $("#loader").fadeIn();
  $.ajax({
   type: "POST",
   data: "action=submit&"+$(this).serialize(),
   url: "add.php",
   success: function(msg)
    {
    alert(msg);
    $("#loader").fadeOut();
    }
  });
  
  return false;
  });
First we show the loader and then make ajax call. We then show the response as an alert. We added return false because we don't want the page to be reloaded when the form is submitted. Also notice that instead of using the usual click() method we have made use of the new live() method (available in jQuery 1.3). That's because the view-area is dynamically loaded and we have to rebind all the events after every ajax call. That would be complex. The new live() method does the job with ease.

Notice that when the form is submitted, we send action=submit through ajax. But we have not defined any action for the same in add.php. Let's do that.

We append the following code to add.php
<?php
elseif($action == "submit")
 {
 $feed_name = filter_var($_POST["feed_name"], FILTER_SANITIZE_STRING);
 $feed_url = filter_var($_POST["feed_url"], FILTER_SANITIZE_STRING);
 if(empty($feed_name) || empty($feed_url))
  {
  echo "You have not filled up all the fields!";
  }
 else
  {
  $q = "INSERT INTO feeds (name, url) VALUES ('$feed_name', '$feed_url')";
  $r = mysql_query($q);
  if(mysql_affected_rows($link)==1)
   {
   echo "Feed is added. Please reload the page.";
   }
  else
   {
   echo mysql_error();
   }
  }
 }
?>
First we sanitize the data. Then check whether they are non-empty. If not, we add the data to the table. Pretty simple.

Now that you have created the add functionality, add a few feeds. Don't you forget to add AbhiTech feed!

Show The Data

Now, we list all the feeds in the sidebar and when we click on a link, the view-area will show the latest updates. To list the feeds in the sidebar we add the following code within the #sidebar in index.php

<ul id="feed-list">
<?php
$q = "SELECT * FROM feeds ORDER BY name";
$r = mysql_query($q);

if(mysql_num_rows($r)>0)
 {
 while($row = mysql_fetch_assoc($r))
  {
  echo "<li><a href=".$row["url"]." class='item_link'>".$row["name"]."</a></li>";
  }
 
 }

?>
</ul>
Here we just select all the added feeds in the table and then loop through the rows to show them as list elements. But without css, it's looking ugly.
ul#feed-list {
 margin:0px;
 padding:0px;
 overflow:auto;
 height:85%;
}

ul#feed-list li {
 list-style:none;
 margin-top:6px;
 padding:4px;
}

ul#feed-list li:hover  {
 background-color: #fdf9e8;
}

ul#feed-list li a {
 background: url("images/rss.png") no-repeat center left;
 display:block;
 padding:3px 3px 3px 18px;
 color:#000000;
 font-size:100%;
 text-decoration:none;
 font-weight:bold;
}
Now, we want to make ajax calls to display the feed. Notice that each link of the feeds has a class name item_link. Thus our javascript will deal with clicking on item_link class. We add the following javascript code.
$("a.item_link").click(function()
  {
   $("#loader").fadeIn();
   
   feed_url = $(this).attr("href");
   $.ajax({
    type: "POST",
    data: "url="+feed_url,
    url: "view.php",
    success: function(msg)
     {
     $("#view-area").html(msg);
     
     $("#loader").fadeOut();
     
     }
   });
   return false;
  });
First, we show the loader. Then, we get the feed url and with that, make ajax call to view.php (which we have not created yet). When the response has reached, we show it in the view-area. Finally, we hide the loader. Notice that we have added return false because we want to stop the browser to go to the feed URL when clicked. Instead, we want to execute the javascript.

We now create view.php. To parse feeds with PHP, we are going to use SimplePie. Download SimplePie and put simplepie.inc in the same directory. We create a file view.php and put the following code in it.
<?php
if(!$_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')
 {
 die("No direct access to files is allowed");
 }
include("simplepie.inc");
include("config.php");

$url = filter_var($_POST["url"], FILTER_SANITIZE_STRING);
$q = "SELECT * FROM feeds WHERE url = '$url'";
$r = mysql_query($q);

if(mysql_num_rows($r)==1)
 {
 $row = mysql_fetch_assoc($r);
 $feed = new SimplePie($url);
 $feed->handle_content_type();
echo "<a href='".$row['url']."' class='feed-title' target='_blank'>".$row['name']." &raquo;</a>
  <ul class='entries'>";
 foreach ($feed->get_items() as $item)
  {
  echo "<li>
   <a href='javascript:;' class='title'>".$item->get_title()."</a>  
   <div class='content'>
    <a class='entry-title' href='".$item->get_link()."' target='_blank'>".$item->get_title()." &raquo;</a>"
    .$item->get_content()."
   </div>
   </li>";
  }
 echo "</ul>";
 }
else
 {
 echo "Feed not found!";
 }

?>
A lot of code! Let me explain.

First we stop access to the script except through ajax call. We then add simplepie.inc and config.php. We filter the requested url and then select the row in the table where the url matches. If url is found in the table, we get the row with mysql_fetch_assoc and then create a simplepie object. Then for each item, we create a list element and put the title of the feed and the content inside it.

We also add css to make it look better.
ul.entries {
 list-style:none;
 margin:0px;
 padding:0px;
}

.entries li {
 border-bottom:1px solid #e8e8ff;
}

.entries .title {
 background:url("images/item-icon.png") no-repeat center left;
 font-size:100%;
 font-weight:bold;
 color:#000000;
 text-decoration:none;
 display:block;
 padding:2px 2px 2px 18px;
}

.entries .content {
 text-align:justify;
 padding:18px;
 display:none;
 border-bottom: 1px solid #e8e8ff;
}

.content a.entry-title {
 font-size:150%;
 text-decoration:none;
 display:block;
}

.content a img {
 border:none;
}
Notice that we have set display:none; to the main content of the feed. That is because we are going to give it some nice jQuery effect. We add the following javascript code.
$("a.title").live("click", function(){
 $(this).next("div.content").slideToggle();

});
When we click on the title of an item, this simple snippet will slide down the hidden content next to the link.

You should have something like this.


Speed it up

Notice that after you click on a feed link, it takes a long time before you get the content. That's because we have not create a 'cache' directory in the same directory. Do that and see the difference for yourself!


Conclusion

This is a very simple example of how to create a simple RSS reader. It leaves out a lot of space to improve. Play with it and try to extend its features with your own. Your comments and thoughts are always welcome! :)

Icons courtesy Dryicons.com. The logo belongs to SimplePie Community.

Labels: , ,

blog comments powered by Disqus
Blogger Frequent Reader said...
This comment has been removed by a blog administrator.
OpenID Montana Flynn said...
Greeeeeaaat! I love this example, the tutorial is kind of hard to follow but if you know what your doing it is the perfect tutorial! Thanks again.