Views

A view is what we refer to an HTML page as. They are called views because of the MVC design pattern. As we already discussed, a model is a data that will be displayed on a page, the view is the page itself, and the controller is the brain that communicates between the model and the view.

Our particular application is going to need two views. The first view is the home page and the second view is the image page.

The HTML in the following section relies heavily on Bootstrap, a popular HTML framework created by Twitter, which provides a standard set of user interface elements. These include buttons, fonts, layout grids, color schemes, and a whole lot more. Using Bootstrap allows us to not only present our application with a nice clean UI but also build it so that it is responsive and will look correct on any device that is viewing it. You can learn more about Bootstrap by visiting http://getbootstrap.com.

Let's start by creating the home page view. Create a new file within the views folder, name it index.Handlebars, and insert the following HTML code:

    <div class="panel panel-primary"> 
        <div class="panel-heading"> 
            <h3 class="panel-title"> 
                Upload an Image 
            </h3> 
        </div> 
The reason we named our file index.Handlebars is a purely personal choice, but it is also based on common naming conventions on the web. Typically, an HTML page that acts as the root file for any website is named index.whatever (.php, .aspx, .html, and so on). Again, this is just a common convention and not something you need to specifically adhere to.

Create a basic HTML form and set method to post and action to /images. Ensure that you set the enctype attribute of the form, since we will be uploading files as well as submitting data via form fields:

    <form method="post" action="/images" enctype="multipart/form-
data"> <div class="panel-body form-horizontal"> <div class="form-group col-md-12"> <label class="col-sm-2 control-label"
for="file">Browse:</label>

Here, we have included a standard HTML input field for the file to be uploaded:

                <div class="col-md-10"> 
                    <input class="form-control" type="file" 
name="file" id="file"> </div> </div> <div class="form-group col-md-12"> <label class="col-md-2 control-label"
for="title">Title:</label> <div class="col-md-10">

Another standard HTML input field for the title of the file can be whatever the user wants, as shown in the following code:

                    <input class="form-control" type="text" 
name="title"> </div> </div> <div class="form-group col-md-12"> <label class="col-md-2 control-label"
for="description">Description:</label> <div class="col-md-10">

A standard HTML textarea input field to allow for a description is as follows:

                    <textarea class="form-control" 
name="description" rows="2"></textarea> </div> </div> <div class="form-group col-md-12"> <div class="col-md-12 text-right">

A standard HTML button is provided that will submit the form to the server. Using Bootstrap classes, we provide btn and btn-success to make this look like a Bootstrap-style button with the default color for success (green):

                    <button type="submit" id="login-btn" 
class="btn btn-success" type="button">
<i class="fa fa-cloud-upload ">
</i> Upload Image</button> </div> </div> </div> </form> </div>

After the upload form section, we will display a list of the newest images uploaded to the website. Refer to the each block in the code snippet that follows. It is a keyword supported by Handlebars to loop over the data provided to the template in case of reusable HTML blocks. We will discuss this in detail in the following code:

<div class="panel panel-default"> 
    <div class="panel-heading"> 
        <h3 class="panel-title"> 
            Newest Images 
        </h3> 
    </div> 
    <div class="panel-body"> 
        {{#each images}} 
            <div class="col-md-4 text-center" style="padding-bottom: 
1em;"><a href="/images/{{ uniqueId }}"><img
src="/public/upload/{{filename}}" alt="{{title}}"
style="width: 175px; height: 175px;" class="img-
thumbnail"></a></div> {{/each}} </div> </div>

There are two important sections in the main home page HTML code. The first is
the form we define, which will be the main way in which users will upload images to the website. As we will be accepting image files as well as details of the image (title, description, and so on), we need to ensure that the form is set up to accept multipart data. We also set the form action to point to the /images route we defined earlier in our routes and image controller modules. When a user completes the form and clicks on the Submit button, the form will send a POST request to http://localhost:3300/images and our router will catch that and forward it to our image controller. From there, the image controller will handle the processing of the data and will save it to the database, saving the image file to the filesystem, and redirecting to the image details page. We will actually be writing this logic in the next chapter. For now, nothing will actually happen if you submit the form.

Below the main image uploading form on the home page, we also have a section that performs a Handlebars loop using each and iterates through an image collection, displaying each image as a thumbnail and the link to the image page. The images collection will be populated from our home controller. It's important to note here that when you are inside a {{#each}} loop in a Handlebars template, your context changes. That is, the path you use to access data inside each is now based on each item in the collection. Here, our object, which will be bound to the view, will have an image collection, and each item in the image collection will have a property for uniqueid, filename, and title. With the home page view out of the way, let's set up the view for the image page.

Create another file in the views folder and name it image.Handlebars. This file is going to have a bit more functionality, so I'm going to break it down into chunks so that you can review each section. First, insert the following block of code:

<div class="panel panel-primary"> 
    <div class="panel-heading"> 
        <h2 class="panel-title">{{ image.title }}</h2> 
    </div> 
    <div class="panel-body"> 
        <p>{{ image.description }}</p> 
        <div class="col-md-12 text-center"> 
            <img src="/public/upload/{{image.filename}}" 
class="img-thumbnail"> </div> </div> <div class="panel-footer"> <div class="row"> <div class="col-md-8"> <button class="btn btn-success" id="btn-like"
data-id="{{ image.uniqueId }}"><i class="fa fa-
heart"> Like</i></button> <strong class="likes-count">{{ image.likes }}
</strong> &nbsp; - &nbsp; <i class="fa fa-eye">
</i> <strong>{{ image.views }}</strong> &nbsp; - &nbsp; Posted: <em class="text-muted">{{
timeago image.timestamp }}</em> </div> </div> </div> </div>

This block of code defines the bulk of the content that will be displayed on the page for a specific image. The viewModel for this page is going to consist of an image object that has various properties defined that you see being used throughout the code; properties such as title, description, filename, likes, views, and the timestamp of when the image upload was performed.

You may have noticed a slightly different piece of syntax in the code specific to the {{ timeago image.timestamp }} timestamp. That is actually a Handlebars helper.
It is a custom function we will write shortly, which will perform some special string formatting-specifically, converting a timestamp string to how long it was some time ago (that is, 2 days ago, 12 hours ago, 15 minutes ago, and so on).

We want to allow users to post comments to images, so let's include a simple form for that:

<div class="panel panel-default"> 
    <div class="panel-heading"> 
        <div class="row"> 
            <div class="col-md-8"> 
                <strong class="panel-title">Comments</strong> 
            </div> 
            <div class="col-md-4 text-right"> 
                <button class="btn btn-default btn-sm" id="btn-
comment" data-id="{{ image.uniqueId }}">
<i class="fa fa-comments-o"> Post
Comment...</i></button> </div> </div> </div> <div class="panel-body"> <blockquote id="post-comment"> <div class="row">

The following is another standard HTML form with the method and action set. This form allows a user to enter, via standard HTML input fields, their name, email address, and comments. Another Submit button is provided to save the comment:

                <form method="post" action="/images/{{ 
image.uniqueId }}/comment"> <div class="form-group col-sm-12"> <label class="col-sm-2 control-label"
for="name">Name:</label> <div class="col-sm-10"> <input class="form-control"
type="text" name="name"> </div> </div> <div class="form-group col-sm-12"> <label class="col-sm-2 control-label"
for="email">Email:</label> <div class="col-sm-10"> <input class="form-control"
type="text" name="email"> </div> </div> <div class="form-group col-sm-12"> <label class="col-sm-2 control-label"
for="comment">Comment:</label> <div class="col-sm-10"> <textarea class="form-control"
name="comment" rows="2"></textarea> </div> </div> <div class="form-group col-sm-12"> <div class="col-sm-12 text-right"> <button type="submit" id="comment-btn"
class="btn btn-success" type="button">
<i class="fa fa-comment"></i>
Post</button> </div> </div> </form> </div> </blockquote>

The form action for comments is set to /images/{{ image.uniqueid }}/comment. Again, if you recall from the routes we set up, we specifically defined a route to handle this.

Finally, we want to display any comments that have been submitted for this image. Our viewModel includes a collection of comments in addition to the image details, so we can simply iterate over that collection using the Handlebars #each block helper:

        <ul class="media-list"> 
            {{#each comments}} 
            <li class="media"> 
                <a class="pull-left" href="#"> 
                    <img class="media-object img-circle" 
src="http://www.gravatar.com/avatar/
{{gravatar}}?d=monsterid&s=45"> </a> <div class="media-body"> {{ comment }} <br/><strong class="media-heading">{{ name
}}</strong> <small class="text-muted">{{
timeago timestamp }}</small> </div> </li> {{/each}} </ul> </div> </div>

Much like the loop, which we performed on the home page to display a collection of images, here, we simply iterate through every comment in the comments collection and display the comment and string-formatted timestamp (again using our timeago global helper). We also use Gravatar to display universal avatar images for users who have commented (assuming that they have provided their email addresses).

Gravatar is a service provided by https://wordpress.com/ that allows a user's personal profile image to be provided via his/her email address. Many popular web services rely on Gravatar as a quick and easy way to display a user's personal profile image, without requiring the additional functionality to support such a feature. You can learn more about Gravatar at http://gravatar.com.
..................Content has been hidden....................

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