diff --git a/reviewboard/htdocs/media/rb/css/reviews.css b/reviewboard/htdocs/media/rb/css/reviews.css
--- a/reviewboard/htdocs/media/rb/css/reviews.css
+++ b/reviewboard/htdocs/media/rb/css/reviews.css
@@ -858,6 +858,32 @@
   z-index: 1000;
 }
 
+#reply-comments-banner{
+  padding-bottom: 4.5em;
+}
+
+#reply-comments-banner .banner-comments {
+  left: 0;
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: 1000;
+  background: #cdff9c;
+  border: 1px #4e9a06 solid;
+  margin-bottom: 10px;
+  padding: 8px 10px;
+}
+
+#reply-comments-banner .banner-comments h1 {
+  display: inline;
+  margin-right: 0.7em;
+  margin-left: 0.7em;
+  padding: 0;
+}
+
+#reply-comments-banner .banner-comments input {
+  margin-left: 10px;
+}
 
 /****************************************************************************
  * Tooltips
diff --git a/reviewboard/htdocs/media/rb/js/datastore.js b/reviewboard/htdocs/media/rb/js/datastore.js
--- a/reviewboard/htdocs/media/rb/js/datastore.js
+++ b/reviewboard/htdocs/media/rb/js/datastore.js
@@ -8,7 +8,9 @@ RB.DiffComment = function(filediff, interfilediff, beginLineNum, endLineNum,
     this.endLineNum = endLineNum;
     this.text = textOnServer || "";
     this.saved = (textOnServer != undefined);
-
+    this.isReplyComment = false;
+    this.replyToCommentId = -1;
+    this.reviewId = -1;
     return this;
 }
 
@@ -32,6 +34,24 @@ $.extend(RB.DiffComment.prototype, {
         return this.endLineNum - this.beginLineNum + 1;
     },
 
+    _getData: function() {
+
+        if(this.isReplyComment){
+            return {
+                    value:      this.text,
+                    id:         this.replyToCommentId,
+                    type:       "comment",
+                    review_id:  this.reviewId
+                    }
+        }else{
+            return {
+                    action:     "set",
+                    num_lines:  this.getNumLines(),
+                    text:       this.text
+                   }
+        }
+    },
+
     /*
      * Saves the comment on the server.
      */
@@ -40,22 +60,41 @@ $.extend(RB.DiffComment.prototype, {
         options = options || {};
 
         rbApiCall({
-            path: this._getURL(),
-            data: {
-                action: "set",
-                num_lines: this.getNumLines(),
-                text: this.text
-            },
-            success: function() {
-                self.saved = true;
-                $.event.trigger("saved", null, self);
+                path: this._getURL(),
+                data: this._getData(),
+                success: function() {
+                    self.saved = true;
+                    $.event.trigger("saved", null, self);
 
-                if ($.isFunction(options.success)) {
-                    options.success();
+                    if ($.isFunction(options.success)) {
+                        options.success();
+                    }
                 }
-            }
-        });
+            });
+
+    },
+    publishReply: function() {
+        var self = this;
+        var path = "/reviewrequests/" + gReviewRequestId + "/reviews/" +
+                     this.reviewId + "/replies/draft/save/";
+        rbApiCall({
+                path: path,
+                success: function() {
+                    $.event.trigger("publishedreply", null, self);
+                }
+            });
     },
+    discardReply: function() {
+        var self = this;
+        var path = "/reviewrequests/" + gReviewRequestId + "/reviews/" +
+                     this.reviewId + "/replies/draft/discard/";
+        rbApiCall({
+                path: path,
+                success: function() {
+                    $.event.trigger("discardedreply", null, self);
+                }
+            });
+     },
 
     /*
      * Deletes the comment from the server.
@@ -101,6 +140,10 @@ $.extend(RB.DiffComment.prototype, {
     _getURL: function() {
         var interfilediff_revision = null;
         var interfilediff_id = null;
+        if(this.isReplyComment){
+            return "/reviewrequests/" + gReviewRequestId + "/reviews/" +
+                     this.reviewId + "/replies/draft/";
+        }
 
         if (this.interfilediff != null) {
             interfilediff_revision = this.interfilediff['revision'];
diff --git a/reviewboard/htdocs/media/rb/js/diffviewer.js b/reviewboard/htdocs/media/rb/js/diffviewer.js
--- a/reviewboard/htdocs/media/rb/js/diffviewer.js
+++ b/reviewboard/htdocs/media/rb/js/diffviewer.js
@@ -86,7 +86,7 @@ var gCommentDlg = null;
 var gHiddenComments = {};
 var gDiffHighlightBorder = null;
 var gStartAtAnchor = null;
-
+var gReplyCommentsBanner = $("#reply-comments-banner");
 
 /*
  * Creates a comment block in the diff viewer.
@@ -114,6 +114,7 @@ function DiffCommentBlock(beginRow, endRow, beginLineNum, endLineNum,
     this.endRow = endRow;
     this.comments = [];
     this.draftComment = null;
+    this.isOtherRevision = false;
 
     this.el = $("<span/>")
         .addClass("commentflag")
@@ -153,6 +154,13 @@ function DiffCommentBlock(beginRow, endRow, beginLineNum, endLineNum,
 
             if (comment.localdraft) {
                 this._createDraftComment(comment.text);
+                if(comment.reply_to_id > 0){
+                    this.draftComment.isReplyComment = true;
+                    this.draftComment.reviewId = comment.review_id;
+                    this.draftComment.replyToCommentId = comment.context_id;
+                }
+                this.addReplyCommentBanner(this.draftComment)
+
             } else {
                 this.comments.push(comment);
             }
@@ -273,6 +281,55 @@ $.extend(DiffCommentBlock.prototype, {
             .close();
     },
 
+    /*
+     * This anonymous fucntion creates a publish, discard banner for each reply
+     * comment
+     */
+    addReplyCommentBanner: function(comment) {
+        var self = this;
+        var thisBannerId = "yourcomment_" + comment.reviewId +
+                           "_" + comment.replyToCommentId;
+        elBannerComments = $(".banner-comments", gReplyCommentsBanner);
+        elBannerComments.append($("<div id='" + thisBannerId + "' />")
+            .append($('<input type="button"/>')
+                .val("Publish")
+                .click(function() {
+                    comment.publishReply();
+                 })
+             )
+             .append($('<input type="button"/>')
+                .val("Discard")
+                .click(function() {
+                    comment.discardReply();
+                })
+            )
+            .append("<h1>This reply comment is a draft</h1>")
+            .append(comment.text)
+        );
+
+        if (gReplyCommentsBanner.is(":hidden")) {
+            gReplyCommentsBanner
+                .slideDown()
+                .find(".banner-comments")
+                    .hide()
+                    .slideDown();
+        }
+    },
+
+    resetComment: function() {
+        $("#your_comment_title").html("Your comment");
+        this.draftComment = null;
+        this.updateTooltip();
+        this.updateCount();
+        var elBannerComments = $(".banner-comments", gReplyCommentsBanner);
+        if(elBannerComments.children().size() == 0)
+        {
+           gReplyCommentsBanner.slideUp()
+           .find(".banner-comments")
+           .slideUp();
+        }
+    },
+
     _createDraftComment: function(textOnServer) {
         if (this.draftComment != null) {
             return;
@@ -290,12 +347,14 @@ $.extend(DiffCommentBlock.prototype, {
 
         $.event.add(comment, "deleted", function() {
             self.notify("Comment Deleted");
+            self.resetComment();
         });
 
         $.event.add(comment, "destroyed", function() {
             self.draftComment = null;
 
             /* Discard the comment block if empty. */
+            self.resetComment();
             if (self.comments.length == 0) {
                 el.fadeOut(350, function() { el.remove(); })
                 self.anchor.remove();
@@ -310,7 +369,41 @@ $.extend(DiffCommentBlock.prototype, {
             self.updateCount();
             self.updateTooltip();
             self.notify("Comment Saved");
-            showReviewBanner();
+            if(comment.isReplyComment) {
+                self.addReplyCommentBanner(comment);
+            }else{
+                showReviewBanner();
+            }
+        });
+
+        $.event.add(comment, "publishedreply", function() {
+
+            var thisBannerId = "yourcomment_" + comment.reviewId +
+                           "_" + comment.replyToCommentId;
+            // We can copy most values from the previous comment
+            // in this comment block.
+            var prevCommentCopy = self.comments[self.comments.length-1];
+            var jsonComment = {
+                "num_lines": prevCommentCopy.num_lines,
+                "url": prevCommentCopy.url,
+                "text": comment.text,
+                "comment_id": -1,
+                "localdraft": false,
+                "user": {"username": "", "name": gUserFullName},
+                "context_id": prevCommentCopy.context_id,
+                "line": prevCommentCopy.line,
+                "review_id": prevCommentCopy.review_id
+            }
+            self.comments.push(jsonComment);
+            $("#"+thisBannerId).remove();
+            self.resetComment();
+        });
+
+        $.event.add(comment, "discardedreply", function() {
+            var thisBannerId = "yourcomment_" + comment.reviewId +
+                           "_" + comment.replyToCommentId;
+            $("#"+thisBannerId).remove();
+            self.resetComment();
         });
 
         this.draftComment = comment;
@@ -1086,6 +1179,12 @@ function loadFileDiff(filediff_id, filediff_revision,
         /* We must rebuild this every time. */
         updateAnchors(diffTable);
 
+        /* gStartAtAnchor is null on page load, so do a check here */
+        var url = document.location.toString();
+        if (url.match("#")) {
+            gStartAtAnchor = url.split("#")[1];
+        }
+
         if (gStartAtAnchor != null) {
             /* See if we've loaded the anchor the user wants to start at. */
             var anchor = $("a[name='" + gStartAtAnchor + "']");
diff --git a/reviewboard/htdocs/media/rb/js/reviews.js b/reviewboard/htdocs/media/rb/js/reviews.js
--- a/reviewboard/htdocs/media/rb/js/reviews.js
+++ b/reviewboard/htdocs/media/rb/js/reviews.js
@@ -653,10 +653,17 @@ $.fn.commentDlg = function() {
                 var actions = $('<span class="actions"/>')
                     .appendTo(header);
                 $('<a href="' + this.url + '">View</a>').appendTo(actions);
-                $('<a href="' + gReviewRequestPath +
-                  '?reply_id=' + this.comment_id +
-                  '&reply_type=' + replyType + '">Reply</a>')
-                    .appendTo(actions);
+                var user = this.user;
+                var commentId = this.context_id;
+                var reviewId = this.review_id;
+                $('<a href="javascript:void(0);">Reply</a>')
+                .appendTo(actions).click(function() {
+                    $("#your_comment_title").html("Your reply to " + user.name);
+                    $("#comment_text").focus();
+                    comment.isReplyComment = true;
+                    comment.replyToCommentId = commentId;
+                    comment.reviewId = reviewId;
+                });
                 $("<pre/>").appendTo(item).text(this.text);
 
                 item.appendTo(commentsList);
diff --git a/reviewboard/reviews/templatetags/reviewtags.py b/reviewboard/reviews/templatetags/reviewtags.py
--- a/reviewboard/reviews/templatetags/reviewtags.py
+++ b/reviewboard/reviews/templatetags/reviewtags.py
@@ -118,27 +118,68 @@ def commentcounts(context, filediff, interfilediff=None):
     else:
         query = Comment.objects.filter(filediff=filediff,
                                        interfilediff__isnull=True)
-
+	comment_id_list = []
     for comment in query:
         review = get_object_or_none(comment.review)
 
         if review and (review.public or review.user == user):
             key = (comment.first_line, comment.num_lines)
 
-            comment_dict.setdefault(key, []).append({
-                'comment_id': comment.id,
-                'text': comment.text,
-                'line': comment.first_line,
-                'num_lines': comment.num_lines,
-                'user': {
-                    'username': review.user.username,
-                    'name': review.user.get_full_name() or review.user.username,
-                },
-                #'timestamp': comment.timestamp,
-                'url': comment.get_review_url(),
-                'localdraft': review.user == user and \
-                              not review.public,
-            })
+            if comment.id not in comment_id_list:
+                """ Add this comment, then add its replies """
+
+                comment_dict.setdefault(key, []).append({
+                    'comment_id': comment.id,
+                    'text': comment.text,
+                    'line': comment.first_line,
+                    'num_lines': comment.num_lines,
+                    'user': {
+                        'username': review.user.username,
+                        'name': (review.user.get_full_name() or
+                                review.user.username),
+                    },
+                    #'timestamp': comment.timestamp,
+                    'url': comment.get_review_url(),
+                    'localdraft': review.user == user and \
+                                  not review.public,
+                    'review_id': review.id,
+                    'context_id': comment.id,
+                    'reply_to_id': comment.reply_to_id,
+                })
+                comment_id_list.append(comment.id)
+                comment_replies = comment.public_replies(user)
+                
+                """ If a comment has replies, then we want to get the
+                    correct attrubutes for it. The values returned in
+                    query for reply comments contain corrupt attributes.
+                """
+                for comment_reply in comment_replies:
+                    if comment_reply.id not in comment_id_list:
+                        comment_reply_review = \
+                                        get_object_or_none(comment_reply.review)
+                        if comment_reply_review:
+                            comment_dict.setdefault(key, []).append({
+                                'comment_id': comment_reply.id,
+                                'text': comment_reply.text,
+                                'line': comment_reply.first_line,
+                                'num_lines': comment_reply.num_lines,
+                                'user': {
+                                    'username': \
+                                    comment_reply_review.user.username,
+                                    'name': \
+                                    (comment_reply_review.user.get_full_name()
+                                    or comment_reply_review.user.username),
+                                },
+                                #'timestamp': comment.timestamp,
+                                'url': comment.get_review_url(),
+                                'localdraft': (comment_reply_review.user == user
+                                            and not comment_reply_review.public),
+                                'review_id': review.id,
+                                'context_id': comment.id,
+                                'reply_to_id': comment_reply.reply_to_id,
+                            })
+                            comment_id_list.append(comment_reply.id)
+
 
     comments_array = []
 
diff --git a/reviewboard/templates/reviews/comments_dlg.html b/reviewboard/templates/reviews/comments_dlg.html
--- a/reviewboard/templates/reviews/comments_dlg.html
+++ b/reviewboard/templates/reviews/comments_dlg.html
@@ -5,7 +5,7 @@
   <ul id="review_comment_list"></ul>
  </div>
  <form id="draft-form" method="post">
-  <h1 class="title">{% trans "Your comment" %}</h1>
+  <h1 class="title" id="your_comment_title">{% trans "Your comment" %}</h1>
   <input type="hidden" name="action" id="comment_action" value="" />
 {% if not request.user.is_authenticated %}
 {%  url login as login_url %}
diff --git a/reviewboard/templates/reviews/reviewable_base.html b/reviewboard/templates/reviews/reviewable_base.html
--- a/reviewboard/templates/reviews/reviewable_base.html
+++ b/reviewboard/templates/reviews/reviewable_base.html
@@ -16,4 +16,10 @@
   <input id="review-banner-discard" type="button" value="{% trans "Discard" %}" />
  </div>
 </div>
+<div id="reply-comments-banner" style="display:none;">
+    <div class="banner-comments">
+        
+    </div>
+</div>
+
 {% endblock %}
