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 of the areas we might 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 (just as the form on the home page 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 will 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 a breeze.

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

You might not have noticed, but in the HTML code that was provided for the main.Handlebars layout file, jQuery was already 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 will 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 that we don't have to worry about hosting that file with our code. The second file, however, is our own file, so we will need to make sure that exists.

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) 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 might have already downloaded jQuery when 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...
});

The preceding code basically 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; it is so that 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 under 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 it, 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 would behave in ways that are less than ideal. A good example of this is that 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 will 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 will 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 inside the ready statement:

$('#btn-like').on('click', function(event) {
event.preventDefault();
let 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 (assigned via the image.Handlebars HTML template code and 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 will 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(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 increase 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 relaunch the node server and open the website in your browser. Click on any image on the home page 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
3.142.135.249