skull

Robert Tamayo

R
B
blog
skull

Adding Comments to a Blog Part 2: The Frontend

In part one of this series, I covered how to prepare the backend API and database for blog comments. This time, I'm going to cover the frontend, which is what the user actually sees and interacts with to write and post a comment. When I first design something, I think in terms of how it will behave.

1. The User Experience Phase


This is where I start building a frontend project. The user experience is what I consider to be what actually happens; it means laying out what the user is able to do on the page, and making sure they know how to figure out what they're expected to do. I started by looking for inspiration for how to build a comment system on popular blogs and YouTube. I ended up going for the YouTube experience. Here is how it is laid out:


Just by looking at the design, a user should be able to figure out what to do. At the end of the post, a comment count tells the user how many comments have already been made. Immediately after that, the user able to comment on the post using a simple form, clearly labeled by the title "Leave a Comment". In this case, the user needs to write down their name and email because they haven't commented on the site before. Below the comment form, the user can see comments by others, and can see clearly that they are able to reply to other users' comments.

2. The Guest Module


My blogging platform, Bob Blog 2, uses an API to fetch and submit comments. I went over creating the backend of the API in the previous part of this series, so all we need to do now is create the logic that will submit the comment on the frontend. This will involve simple HTML forms and JavaScript. As part of the comment system, it's important to know some basic user information. We'll create a user and check if the user is already "logged in" in this next section using a JavaScript Guest module.

The file Guest.js is located here. Inside of the module, I'm using a jQuery document-ready to run through the core logic to check if a user is already logged in.

$(document).ready(function(){
        var cookie = getCookie(userCookieName);
        console.log("we are a here");
        if (cookie == '') {
            
        } else {
            $('body').addClass(loggedInClassName);
            var user = JSON.parse(cookie);
            UserInfo.guestemail = user.guestemail;
            UserInfo.guestname = user.guestname;
            UserInfo.guestid = user.guestid;
        }
});
The module is only exposing the following 4 variables: 

return {
    signedIn: false,
    logIn: logInAction,
    logOut: logOutAction,
    userInfo: showUserInfo
}
The most important function of those 4 is logInAction, which we call when a user submits a comment for the first time without being logged in already. Take a look at the source code to see how logInAction works in detail. 

3. The Comments Module


The Comments.js file is too large to go into much detail here, but take a look at the source code on github. One of the things to note is that the Comments.js file sets the event listeners and handlers for all of the user interactions, such as submitting a comment or starting a reply. One trend I use is to set classes on the <body> tag to control display logic, instead of using jQuery hide() and show() functions on every individual element. 

The Comments.js _init() function starts the process of getting a default number of replies from the API for the specific post. I had to decide when I created the backend to not include replies in this type of request. Instead, replies are handled in the comments module by making a separate request for replies whenever the "View Replies" buttons are clicked.

Although I could technically use the API in PHP through a curl call to load the comments as part of the HTML directly (as in page source), I chose not to because I want the page load to be speedier.

4. The Comments HTML


This is the html block I added to the file blogPage.php:

<div class="blog-comment-section">
        <div class="blog-comment-section-top">
            
            <div class="blog-comment-title">Comments: <?= $blog['hascomments'] ?></div>
            <div class="blog-comment-likes"><i class="far fa-heart"></i> <?= $blog['likecount'] ?></div>
        </div>
        <div class="leave-a-comment-section comment-form">
            <div class="leave-a-comment-title">Leave a Comment</div>
            <div class="enter-comment">
                <textarea name="comment" class="leave-a-comment" id="leave-a-comment" placeholder="Leave a comment..."></textarea>
            </div>
            <div class="sign-in-form">
                <div>
                    <input name="guestname" type="email" id="leave-a-comment-name" placeholder="Your Name">
                </div>
                <div>
                    <input name="guestemail" type="text" id="leave-a-comment-email" placeholder="Email Address">
                </div>
            </div>
            <div class="submit-comment" id="submit-comment">Submit</div>
        </div>
            
        <div class="blog-comment-section-comments"></div>
    </div>
    <script>
        var postid = <?= $blog['id']; ?>;
    </script>

The only things that are important to note here are that I'm using the HTML5 input type "email" to handle email validation and that I'm setting a limit on the character count in the comment to 280 using the html. It's important to validate on the backend that these values are not changed by the user editing the page through a code inspector.

The comments themselves are a perfect use case for the JavaScript HTML templates module I wrote about previously. Once the comment data is returned, it's only necessary to run the data through the HTML template processor and everything is done for you.

<script type="blog/template" id="comment-template">
            <div class="blog-comment" data-replies-visible="false" data-comment-id="{{commentid}}">
                <div class="commentor-name">{{guestname}}</div>
                <div class="comment-content">
                    {{comment}}
                </div>
                <div class="comment-replies comment-reply-count-{{hasreplies}}">
                    <div class="comment-replies-title view-replies" data-replies-loaded="false">Show {{hasreplies}} Replies <i class="fas fa-angle-down"></i></div>
                    <div class="hide-replies">Hide Replies <i class="fas fa-angle-up"></i></div>
                    <div class="comment-replies-content" data-commentid="{{commentid}}"></div>
                </div>
                <div class="comment-reply"><i class="fas fa-reply"></i> Reply</div>
                
                <div class="comment-leave-a-reply comment-form" data-replyto="{{commentid}}">
                    <div class="enter-comment">
                        <textarea class="leave-a-comment" name="comment" placeholder="Leave a reply..."></textarea>
                    </div>
                    <div class="sign-in-form">
                        <div>
                            <input name="guestname" type="email" placeholder="Your Name">
                        </div>
                        <div>
                            <input type="text" name="guestemail" placeholder="Email Address">
                        </div>
                    </div>
                    <input style="display: none;" type="hidden" name="replyto" value="{{commentid}}"> 
                    <div class="submit-reply submit-comment" >Reply</div>
                </div>
                
            </div>
        </script>

5. Final Words and Next Steps


That's all for this part. Feel free to test it out by submitting a comment below. The Comments System for Bob Blog 2 is not complete yet, though. For one, there are probably bugs. Second, I still have a couple features I would like to implement for it, such as content filtering and notifications. But the way I like to do things is the most basic elements first, so those things will have to wait.

I'm also planning a restructuring of the Bob Blog platform to be hosted on a single domain and use user accounts and the API to manage the writing and displaying of blog posts. That will make it much easier for me to control the development of Bob Blog, and it also makes it an interesting take on the blogging platform itself; instead of installing the platform on your server, you would create an account on bobblog2.com (for example) and write your posts there. Bobblog2.com would host the blog posts and media, and then all you would have to do is use the API to pull the posts onto your account. But more on that later.
Comments:
Leave a Comment
Submit