<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -19,6 +19,7 @@
           &lt;span id=&quot;statusCount&quot;&gt;140&lt;/span&gt;
           &lt;label for=&quot;status&quot;&gt;Status:&lt;/label&gt;
           &lt;textarea name=&quot;status&quot; rows=&quot;3&quot; cols=&quot;52&quot;&gt;&lt;/textarea&gt;
+          &lt;input type=&quot;hidden&quot; id=&quot;in_reply_to_status_id&quot; value=&quot;&quot; /&gt;
           &lt;input type=&quot;submit&quot; value=&quot;Tweet&quot;&gt;
         &lt;/form&gt;
         &lt;p id=&quot;about&quot;&gt;&lt;a href=&quot;http://github.com/jchris/couchdb-twitter-client/tree/master&quot;&gt;CouchDB Twitter Client&lt;/a&gt;: another 24 hour hack by &lt;a href=&quot;http:/jchris.mfdz.com/&quot;&gt;J Chris Anderson&lt;/a&gt;.&lt;/p&gt;
@@ -118,8 +119,12 @@
         $('#updateStatus').submit(function(e) {
           e.preventDefault();
           var status = $('#updateStatus textarea').val();
-          tw.updateStatus(status);
+          var in_reply_to = $('#updateStatus #in_reply_to_status_id').val();
+          tw.updateStatus(status, in_reply_to);
+
+          $('#updateStatus #in_reply_to_status_id').val('');
           $('#updateStatus textarea').val('');
+
           updateCount();
           setTimeout(function() {
             tw.friendsTimeline(renderAllTweets, true);
@@ -134,4 +139,4 @@
       updateCount();
     });
   &lt;/script&gt;
-&lt;/html&gt;
\ No newline at end of file
+&lt;/html&gt;</diff>
      <filename>_attachments/index.html</filename>
    </modified>
    <modified>
      <diff>@@ -44,18 +44,18 @@ function TwitterCouch(db, design, callback) {
       }
     });
   };
-  
+
   //// WORD CLOUD
-  // words are displayed at a size that is a function of the global set of words, 
-  // compared with the user's most-used words. all this stuff with callbacks here 
-  // is to do with that. 
+  // words are displayed at a size that is a function of the global set of words,
+  // compared with the user's most-used words. all this stuff with callbacks here
+  // is to do with that.
   //
   // query plan
   // for each word, what's the chance of user using it? (times said / total words)
   // for each word, what's the chance of anyone using it?
   // (ever said / total recorded words)
   // subtract global ratio from user ratio
-  
+
   // global word count
   var gWC = null;
   function buildGWC(cb) {
@@ -78,7 +78,7 @@ function TwitterCouch(db, design, callback) {
             for (var i=0; i &lt; view.rows.length; i++) {
               var row = view.rows[i];
               if (row.value &gt; 4) {
-                gWC[row.key] = (row.value / tWords) * multpl;                  
+                gWC[row.key] = (row.value / tWords) * multpl;
               }
             };
             db.saveDoc({
@@ -91,7 +91,7 @@ function TwitterCouch(db, design, callback) {
       }
     });
   };
-  
+
   function globalWordCloud(cb) {
     if (gWC) {
       cb(gWC)
@@ -105,7 +105,7 @@ function TwitterCouch(db, design, callback) {
         }});
     }
   };
-  
+
   // user word count
   // words the user uses more than other people do, will have the highest scores.
   function calcUserWordCloud(userid, cb) {
@@ -116,19 +116,19 @@ function TwitterCouch(db, design, callback) {
       });
     });
   };
-  
+
   function userTotalWords(userid, cb) {
     design.view('userWordCloud', {
-      reduce: true, 
+      reduce: true,
       startkey : [userid],
       endkey : [userid,{}],
       group_level : 1,
       success : function(data) {
         cb(data.rows[0].value);
-      } 
+      }
     })
   };
-  
+
   function viewUserWordCloud(userid, gCloud, cb) {
     userTotalWords(userid, function(uTotal) {
       design.view('userWordCloud', {
@@ -143,7 +143,7 @@ function TwitterCouch(db, design, callback) {
           }
           var maxPerc = max / uTotal;
           var multpl = 100 / maxPerc;
-          
+
           $.each(data.rows, function(i,row) {
             var uProb = (row.value / uTotal) * multpl;
             var gProb = gCloud[row.key[1]] || 0;
@@ -157,7 +157,7 @@ function TwitterCouch(db, design, callback) {
       });
     });
   };
-  
+
   // twitter api core
   function apiCallProceed(force) {
     var previousCall = $.cookies.get('twitter-last-call');
@@ -198,10 +198,10 @@ function TwitterCouch(db, design, callback) {
         if (hasUserInfo) return;
         alert(&quot;There seems to have been a problem getting your logged in twitter info. Please log into Twitter via twitter.com, and then return to this page.&quot;)
       },2000);
-      cheapJSONP(&quot;http://&quot;+host+&quot;/statuses/user_timeline.json?limit=1&amp;callback=userInfo&quot;);      
+      cheapJSONP(&quot;http://&quot;+host+&quot;/statuses/user_timeline.json?limit=1&amp;callback=userInfo&quot;);
     }
   };
-  
+
   // a user's recent tweets
   function getUserTimeline(userid, cb) {
     getJSON(&quot;/statuses/user_timeline/&quot;+userid, {limit:200}, function(tweets) {
@@ -212,7 +212,7 @@ function TwitterCouch(db, design, callback) {
       db.saveDoc(doc, {success:cb});
     });
   };
-  
+
   // timeline for the logged in user
   function getFriendsTimeline(cb, opts) {
     getJSON(&quot;/statuses/friends_timeline&quot;, opts, function(tweets) {
@@ -226,9 +226,9 @@ function TwitterCouch(db, design, callback) {
           viewFriendsTimeline(currentTwitterID, cb);
         }});
       } // we'd need an else here if the timeline wasn't already displayed
-    });    
+    });
   };
-  
+
   //// search
   function searchToTweet(r, term) {
     return {
@@ -243,7 +243,7 @@ function TwitterCouch(db, design, callback) {
       id : r.id
     }
   };
-  
+
   function viewSearchResults(term, cb) {
     design.view('searchResults',{
       startkey : [term,{}],
@@ -256,7 +256,7 @@ function TwitterCouch(db, design, callback) {
       }
     });
   };
-  
+
   function getSearchResults(term, since_id, cb) {
     $.getJSON(&quot;http://search.twitter.com/search.json?callback=?&quot;, {q:term, since_id:since_id}, function(json) {
       var tweets = $.map(json.results,function(t) {
@@ -275,11 +275,11 @@ function TwitterCouch(db, design, callback) {
           viewSearchResults(term, cb);
         }});
       } else {
-        viewSearchResults(term, cb);        
+        viewSearchResults(term, cb);
       }
-    });    
+    });
   };
-  
+
   var publicMethods = {
     friendsTimeline : function(cb, force) {
       viewFriendsTimeline(currentTwitterID, function(storedTweets) {
@@ -311,10 +311,10 @@ function TwitterCouch(db, design, callback) {
         }
       });
     },
-    updateStatus : function(status) {
-      // todo in_reply_to_status_id
-      $.xdom.post('http://twitter.com/statuses/update.xml',{
-        status:status, source:&quot;couchdbtwitterc&quot;});
+    updateStatus : function(status, in_reply_to) {
+      var data = { status:status, source:&quot;couchdbtwitterc&quot; };
+      if (in_reply_to) data.in_reply_to_status_id = in_reply_to;
+      $.xdom.post('http://twitter.com/statuses/update.xml', data);
     },
     userInfo : function(userid, cb) {
       userid = parseInt(userid);
@@ -351,13 +351,13 @@ function TwitterCouch(db, design, callback) {
         success : function(doc) {
           cb(doc);
         },
-        error : function() {          
+        error : function() {
           cb({&quot;_id&quot; : docid, searches : []});
         }
       });
     }
   };
-  
+
   // init App, run callback
   getTwitterID(callback);
 };</diff>
      <filename>_attachments/twitter-couch.js</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@ RegExp.escape = function(text) {
     );
   }
   return text.replace(arguments.callee.sRE, '\\$1');
-}
+};
 
 function TwitterRender(tw) {
   function prettyDate(time){
@@ -31,7 +31,7 @@ function TwitterRender(tw) {
   		day_diff &lt; 730 &amp;&amp; Math.ceil( day_diff / 31 ) + &quot; months ago&quot; ||
   		Math.ceil( day_diff / 365 ) + &quot; years ago&quot;;
   };
-  
+
   function linkify(body, term) {
     // this is almost reliable...
     // if (term) {
@@ -48,16 +48,16 @@ function TwitterRender(tw) {
       return '&lt;a target=&quot;_blank&quot; href=&quot;http://search.twitter.com/search?q='+encodeURIComponent(term)+'&quot;&gt;'+word+'&lt;/a&gt;';
     });
   };
-  
+
   function a(href, text, cls, xtr) {
-    return '&lt;a target=&quot;_blank&quot; '+(cls?'class=&quot;'+cls+'&quot;':'')+' href=&quot;'+href+'&quot; '+(xtr||'')+'&gt;'+text+'&lt;/a&gt;'
+    return '&lt;a target=&quot;_blank&quot; '+(cls?'class=&quot;'+cls+'&quot;':'')+' href=&quot;'+href+'&quot; '+(xtr||'')+'&gt;'+text+'&lt;/a&gt;';
   };
-  
+
   function tweetUserDetails() {
     var li = $(this).parent('li');
     var userid = li.find('h3').attr('class');
     // todo use a local hash to get userid from screen_name if we have it
-    if (userid &amp;&amp; userid != 'undefined') { 
+    if (userid &amp;&amp; userid != 'undefined') {
       tw.userInfo(userid, function(user) {
         li.append('&lt;div class=&quot;user-details&quot;&gt;&lt;dl&gt;&lt;dt&gt;Location:&lt;/dt&gt;&lt;dd&gt;'
         + user.location
@@ -80,23 +80,23 @@ function TwitterRender(tw) {
       });
     }
   };
-  
+
   function deHex(st) {
     return parseInt(st, 16);
   };
-  
+
   function toColor(r,g,b) {
     return 'rgb('+r+', '+g+', '+b+')';
   };
-  
+
   function colorForWord(word, dim) {
     var key = word.toString() + dim.toString();
     if (colorCache[key]) {
-      return colorCache[key]
+      return colorCache[key];
     }
-    
+
     var color = hex_md4(word).substring(0,6);
-    
+
     var rgb = [(color.substring(0,2)),(color.substring(2,4)),(color.substring(4,6))];
     for (var i=0; i &lt; rgb.length; i++) {
       rgb[i] = Math.floor((deHex(rgb[i])) / dim);
@@ -104,12 +104,22 @@ function TwitterRender(tw) {
     colorCache[key] = toColor(rgb[0], rgb[1], rgb[2]);
     return colorCache[key];
   }
-  
+
+  function tweetReply(e) {
+      e.preventDefault();
+      var tweet = $(this).data('tweet');
+      var form = $('#updateStatus');
+      form.find('#in_reply_to_user_id').val(tweet.user.id);
+      form.find('#in_reply_to_screen_name').val(tweet.user.screen_name);
+      form.find('#in_reply_to_status_id').val(tweet.id);
+      form.find('textarea').val('@' + tweet.user.screen_name + ' ')[0].focus();
+  }
+
   var colorCache = {};
-  
+
   var publicMethods = {
     renderTimeline : function(tweets, userid) {
-      $(&quot;#tweets ul&quot;).html($.map(tweets, function(tweet) {
+      var timeline = $.each(tweets, function(i, tweet) {
         var cls = false, color, dim, bright;
         if (userid &amp;&amp; tweet.in_reply_to_user_id &amp;&amp; tweet.in_reply_to_user_id == userid) {
           cls = &quot;reply&quot;;
@@ -119,7 +129,7 @@ function TwitterRender(tw) {
           dim = colorForWord(tweet.search, 3.5);
           bright = colorForWord(tweet.search, 1.5);
         }
-        return '&lt;li'+(cls?' class=&quot;'+cls+'&quot;':'')
+        var item = $('&lt;li'+(cls?' class=&quot;'+cls+'&quot;':'')
           + (color ? ' style=&quot;border:4px solid '+color+'; background:'+dim+';&quot;' : '')
           + '&gt;&lt;img title=&quot;Click for details&quot; class=&quot;profile&quot; src=&quot;'
           + tweet.user.profile_image_url + '&quot; /&gt;'
@@ -130,11 +140,16 @@ function TwitterRender(tw) {
           + tweet.user.name
           +'&lt;/a&gt;&lt;/h3&gt;'
           + '&lt;p&gt;'+linkify(tweet.text) + '&lt;/p&gt;'
+          + '&lt;span class=&quot;reply_to&quot;&gt;'
+          + a('#', 'reply')
+          + '&lt;/span&gt;'
           + ' &lt;span class=&quot;created_at&quot;&gt;'
-          + a('http://twitter.com/'+tweet.user.screen_name+'/status/'+tweet.id, prettyDate(tweet.created_at))  
+          + a('http://twitter.com/'+tweet.user.screen_name+'/status/'+tweet.id, prettyDate(tweet.created_at))
           + (tweet.source?' via ' + tweet.source:'')
-          + '&lt;/span&gt;&lt;br class=&quot;clear&quot;/&gt;&lt;/li&gt;'; 
-      }).join(''));
+          + '&lt;/span&gt;&lt;br class=&quot;clear&quot;/&gt;&lt;/li&gt;');
+        item.find(&quot;.reply_to a&quot;).data('tweet', tweet).click(tweetReply);
+        $(&quot;#tweets ul&quot;).append(item);
+      });
       $(&quot;#tweets ul .created_at a&quot;).attr(&quot;target&quot;,&quot;_blank&quot;);
       $(&quot;#tweets img.profile&quot;).click(tweetUserDetails);
     }</diff>
      <filename>_attachments/twitter-render.js</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>dc898822694afe386db1adbcb1bd482151069b3f</id>
    </parent>
  </parents>
  <author>
    <name>Paul Bonser</name>
    <email>pib@paulbonser.com</email>
  </author>
  <url>http://github.com/pib/couchdb-twitter-client/commit/cdca9f3485524dd0a4b1f9f6b011212009be866a</url>
  <id>cdca9f3485524dd0a4b1f9f6b011212009be866a</id>
  <committed-date>2009-04-29T16:31:00-07:00</committed-date>
  <authored-date>2009-04-29T16:31:00-07:00</authored-date>
  <message>add reply option and in-reply-to param to twitter</message>
  <tree>b22ad1ea4e7ab87154328bbe7d6fc25e4ece1ff2</tree>
  <committer>
    <name>Paul Bonser</name>
    <email>pib@paulbonser.com</email>
  </committer>
</commit>
