Buzz API

https://www.googleapis.com/buzz/v1/activities/shyam.seshadri/@self?alt=json

https://www.googleapis.com/buzz/v1/activities/shyam.seshadri/@self/B:z13dgtsrlsqvutsrb04cgtuj2se4stq4pjk/@comments?alt=json

http://code.google.com/apis/buzz/v1/getting_started.html#background-operations

<angular/> Resources Definition

angular.service('myApplication', function($resource){
 this.Activity = $resource(
     'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
     {alt:'json', callback:'JSON_CALLBACK'},
     {
       get:     {method:'JSON', params:{visibility:'@self'}},
       replies: {method:'JSON', params:{visibility:'@self', comments:'@comments'}}
     });
}, {inject:['$resource']});

<angular/> Widget

angular.widget('my:expand', function(element){
 element.css('display', 'block');
 this.descend(true);
 return function(element) {
   element.hide();
   var watch = element.attr('expand');
   this.$watch(watch, function(value){
     if (value) {
       element.delay(0).slideDown('slow');
     } else {
       element.slideUp('slow');
     }
   });
 };
});


<angular/> Controller

function BuzzController(){
 this.$watch('$location.hashPath', this.userChange);
}
BuzzController.prototype = {
 userChange: function(){
   this.userId = this.$location.hashPath;
   this.activities = this.Activity.get({userId:this.userId});
 },

 expandReplies: function(activity) {
   var self = this;
   if (activity.replies) {
     activity.replies.show = !activity.replies.show;
   } else {
     activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id}, function(){
       activity.replies.show = true;
     });
   }
 }
};


<angular/> Template

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns:ng="http://angularjs.org">
 <head>
   <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
   <script type="text/javascript" src="http://angularjs.org/ng/js/angular-debug.js#autobind"></script>
   <script type="text/javascript" src="buzz.js"></script>
   <link rel="stylesheet" type="text/css" href="http://angularjs.org/ng/css/angular.css"/>
   <link rel="stylesheet" type="text/css" href="buzz.css"/>
 </head>
 <body ng:init="$window.$root = this" ng:controller="BuzzController">
 <div>
   <span>&lt;angular/&gt; Buzz</span>
   <span>
     filter:
     <input type="text" name="filterText"/>
   </span>
   <span>
     user:
     <input type="text" name="userId" ng:required/>
     <button ng:click="$location.hashPath = userId">fetch</button>
   </span>
 </div>
 <ul>
   <li ng:repeat="item in activities.data.items.$filter(filterText)">
     <h1>
       <img src="{{item.actor.thumbnailUrl}}"/>
       <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
       <a href="#" ng:click="expandReplies(item)">Replies: {{item.links.replies[0].count}}</a>
     </h1>
     <div>
       {{item.object.content | html}}
       <div>
         <a href="{{attachment.links.enclosure[0].href}}" ng:repeat="attachment in item.object.attachments">
           <img src="{{attachment.links.preview[0].href}}"/>
         </a>
       </div>
     </div>
     <my:expand expand="item.replies.show">
       <ul>
         <li ng:repeat="reply in item.replies.data.items">
           <img src="{{reply.actor.thumbnailUrl}}"/>
           <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>:
           {{reply.content | html}}
         </li>
       </ul>
     </my:expand>
   </li>
 </ul>
 </body>
</html>

<angular/> CSS (only works in WebKit browsers)

body {

  background: -webkit-gradient(linear, left top, left 100, from(#bbb), to(#fff));

  background-repeat: no-repeat;

  margin: 0px;

  font-family: sans-serif;

  font-size: 12px;

}

body > div {

  border-top: 1px solid white;

  border-bottom: 1px solid black;

  text-align: center;

  background: -webkit-gradient(linear, left top, left bottom, from(#CCC), to(#888));

  -webkit-background-origin: padding; -webkit-background-clip: content;

}

body > div button {

  margin: 5px;

}

body > div span:FIRST-CHILD {

  float: left;

  font-family: monospace;

  font-size: 1.5em;

  color: black;

  padding: 2px 5px;

}

body > div span:last-child {

  float: right;

}

ul {

  list-style: none;

  padding: 10px;

  margin: 0;

}

body > ul > li {

  border: 1px solid black;

  margin: 15px 5px;

  padding: 0;

  -webkit-box-shadow: 5px 5px 5px #888;

}

body > ul > li > h1 {

  margin: 0;

  background: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#999));

  font-size: 13px;

  border-bottom: 1px solid black;

}

h1 > img,

li > img {

  max-height: 30px;

  max-width: 30px;

  vertical-align: middle;

  padding: 3px;

}

a > img {

  margin-right: 5px;

  margin-top: 5px;

}

body > ul > li > h1 > a:last-child {

  float: right;

  margin: 10px;

}

body > ul > li > div {

  background-color: white;

  background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ddd));

  margin: 0;

  padding: 10px;

}

body > ul > li ul {

  margin: 0;

  padding: 0;

  margin-left: 5px;

  border-left: 5px solid lightgray;

}

body > ul > li ul > li {

  margin: 0;

  padding: 10px;

  background: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#ddd));

}