Iterating on the UI

Now that we have our application working fairly well and can actually interact with it, it's time to step back and take a look at some areas we may be able to improve.

One area is the Post Comment form on the image page. I don't think it's necessary that this form is always visible, but instead it should be made available only when someone actually wants to post a comment.

Additionally, I'd love the Like button to not have to post a full form submission to the server and cause the entire page to reload (like the form on the homepage does when it uploads an image). We will use jQuery to submit an AJAX call to the server to handle the likes, and send and retrieve data in real time without ever reloading the page!

To make these tweaks, we're going to need to introduce a small amount of JavaScript on the page to add a little interactivity. To make things even easier, we'll use the popular jQuery JavaScript library to make creating interactive features like these a breeze.

Tip

jQuery has been around for a number of years and has been explosively popular in frontend development. Simply put, jQuery is JavaScript with training wheels. It allows you to manipulate the Document Object Model (DOM—the HTML structure of any page) extremely easily as you will see in the next section. You can learn more about jQuery at http://jquery.com.

You may not have noticed, but in the HTML code that was provided for the main.handlebars layout file, jQuery has already been included as an external script tag (referencing jQuery hosted on a CDN). Additionally, a local scripts.js tag is also included, where we will put our custom jQuery JavaScript code for the changes we're going to make to the UI. When you look at the very bottom of main.handlebars, you can see the following code:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="/public/js/scripts.js"></script>

The first script tag points to Google's Code Content Delivery Network (CDN), which means we don't have to worry about hosting that file with our code. The second file, however, is our own file, so we are going to need to make sure that exists.

Tip

CDN is a means of delivering a file from a globally distributed network of caching servers. What this means, generally speaking, is that files that are very commonly downloaded by web visitors (such as jQuery for example) can be loaded much quicker via a regionally closer download source as well as improved caching. If multiple websites use the same CDN URL to host jQuery, for example, it stands to reason that a visitor to your website may have already downloaded jQuery from visiting a previous unrelated website. Therefore, your website will load that much quicker!

Create the public/js/scripts.js file and insert the following code:

$(function(){
    // to do...
});

This is a standard code block that you'll see almost every time anyone uses jQuery. What this code does is execute an anonymous function within the $() jQuery wrapper, which is shorthand for writing the following code:

$(document).ready(function(){
  // to do...
});

This code basically just means that the callback function will wait until the page is fully loaded and ready before executing. This is important because we don't want to apply UI event handlers and/or effects to DOM elements that don't actually exist yet because the page is still loading. This is also another reason why the script tags in the main.handlebars layout file are the last lines of the page; so, they are the last to load ensuring that the document has already been fully downloaded and is ready to be manipulated.

First, let's address the Post Comment functionality. We want to hide the comment form by default, and then display it only when a user clicks on the Post Comment button below an image (to the right of the Like button). Insert the following code inside the callback function where the // to do... comment exists:

    $('#post-comment').hide();
    $('#btn-comment').on('click', function(event) {
        event.preventDefault();

        $('#post-comment').show();
    });

The first line of code executes the hide function on the HTML div that has a 'post-comment' ID. We then immediately apply an event handler to the HTML button with a 'btn-comment' ID. The event handler we apply is for onClick because we want it to execute the anonymous function we provided whenever a user clicks on that button. That function simply prevents the default behavior (the default behavior for that particular element; in this case, a button) and then calls the show jQuery function, which reveals the 'post-comment' div that was previously hidden. The event.preventDefault() part is important because if we didn't include that, the action of clicking on the button would do what a browser expects it to do and try to execute our custom JavaScript function at the same time. If we didn't include this, it's likely that our UI will behave in ways that are less than ideal. A good example is if you want to override the default behavior of a standard HTML link, you can assign an onClick event handler and do whatever you want. However, if you don't perform event.preventDefault(), the browser is going to send the user to the HREF for that link, regardless of what your code is trying to do.

Now let's add some code to handle the Like button functionality. We are going to want to add an event handler for the button, the same way we did for the Post Comment button, using jQuery's .on function. After the code that you added previously, insert this additional block of code:

$('#btn-like').on('click', function(event) {
    event.preventDefault();

    var imgId = $(this).data('id'),

    $.post('/images/' + imgId + '/like').done(function(data) {
        $('.likes-count').text(data.likes);
    });
});

The preceding code attaches an onClick event handler to the 'btn-like' button. The event handler first retrieves the data-id attribute from the Like button itself (assigned via the image.handlebars HTML template code and the viewModel) and then performs a jQuery AJAX POST to the /images/:image_id/like route. Recall the following line from our Node server/routes.js file:

app.post('/images/:image_id/like', image.like);

Once that AJAX call is done, another anonymous callback function will be executed that will change the text of the HTML element with a likes-count class and replace it with the data that was returned from the AJAX call—in this case, the updated total count of likes (typically, it would be whatever it was previously plus one).

In order to test this functionality, we are going to need to implement some fixture data in our like function inside the image controller. Edit controllers/image.js and within the like function, replace the existing res.send function call with the following code:

like: function(req, res) {
    res.json({likes: 1});
},

All this code does is return JSON to the client with a simple object that contains a single likes property with a value of 1. In the next chapter, when we introduce MongoDB to the app, we'll update this code to actually increment the count of likes and return the true value for the liked image.

With all of those changes in place, you should be able to re-launch the node server and open the website in your browser. Click on any image on the homepage to view the image page and then click on the Like button to see it change from 0 to 1. Don't forget to check out the fancy new Post Comment button too—clicking on this should reveal the comment form!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.194.44