- Read Tutorial
In this guide we're going to implement the design for the Post page and wire it up to the current implementation code that we already have in place. If you reference the UI guide you can see the design for the Post
page below:
There are a few components, such as the picture, the ability to preview the previous post, etc. that we haven't built the implementation code for yet, however we can mock them now and add that in later.
Let's get started by pulling out the HTML code from the design files for the post page, the designer called it article.html
(when working from templates or a designer's work you'll notice that they like using their own names for things, so you need to reconcile them like we're doing now). Integrate the design into the posts/show.html.erb
file so it looks like the below code:
<!-- app/views/topics/posts/show.html.erb --> <div class="container"> <div class="row"> <div class="col-xs-9 article-content pull-left"> <h1 class="col-xs-6 pull-left"><%= @post.title %></h1> <span>By <strong><%= @post.user.full_name %></strong> <%= @post.created_at.strftime("Published: on %m/%d/%Y at %l:%M%P") %></span> <p><strong>Topic:</strong> <%= @post.topic.title %></p> <div class="clearfix"></div> <p class="col-xs-8 first"><%= @post.content %></p> <ul class="social-box clearfix"> <li> <span class="icon facebook-icon"></span> <p>226</p> </li> <li> <span class="icon twitter-icon"></span> <p>28</p> </li> <li> <span class="icon pinterest-icon"></span> <p>4793</p> <li> <span class="icon google-icon"></span> <p>8</p> </li> </ul> <hr/> <div class="actions"> <% if current_user && @post.user_id == current_user.id %> <%= link_to "Edit Post", edit_topic_post_path(topic_id: @topic.id, id: @post.id), class: 'btn btn-default btn-green' %> <% end %> </div> </div> <div class="col-xs-3 article-sidebar pull-right"> <div class="next-article"> <div class="btn btn-left"></div> <div class="btn btn-right"></div> <h1>Scientists find closest thing yet to Earth-sun twin system</h1> <span>By <strong>Thomas Gibbons-Neff</strong> and <strong>Carol Morell</strong> June 20 at 4:05 PM</span> </div> <h1>Tags</h1> <ul class="tags clearfix"> <li class="col-xs-12 pull-left">Outer Space</li> <li class="col-xs-6 pull-right">NASA</li> <li class="col-xs-6 pull-left">Planet</li> <li class="col-xs-6 pull-right">SpaceX</li> <li class="col-xs-6 pull-right">Internet</li> <li class="col-xs-12 pull-left">Elon Musk</li> <li class="col-xs-6 pull-right">Austin</li> <li class="col-xs-6 pull-right">Marketing</li> </ul> <h1 class="separator">Social Media</h1> <div class="social clearfix"> <a href="#facebook" class="facebook"></a> <a href="#twitter" class="twitter"></a> <a href="#linkedin" class="linkedin"></a> <a href="#google" class="google"></a> <a href="#pinterest" class="pinterest"></a> </div> <ul class="video-box clearfix"> <li class="pull-left"> <a href="#video1"> <div class="play"></div> <img src="images/common/article1.png" /> </a> </li> <li class="pull-right"> <a href="#video1"> <div class="play"></div> <img src="images/common/article1.png" /> </a> </li> <li class="pull-left"> <a href="#video1"> <div class="play"></div> <img src="images/common/article1.png" /> </a> </li> </ul> <h1 class="separator">Real Time</h1> <ul class="top-articles2"> <li> <span class="pull-left">Food We Digg</span> <span class="pull-right">9:05 PM</span> <a href="#article1"><h2 class="pull-right">From Vrrrramp To Snikt: Exploring Sci-Fi's Most Iconic Movie Sound Effects</h2></a> </li> <li> <span class="pull-left">To Infinity</span> <span class="pull-right">9:05 PM</span> <a href="#article2"><h2 class="pull-right">You’ll Eat Your Vegetables, And You’ll Like It (No, Really)</h2></a> </li> <li> <span class="pull-left">A SCHOLAR OF VIROLOGY</span> <a href="#article3"><h2 class="pull-right">I Went To Tyler Oakley's Slumber Party, And Found Out Why He Went Viral</h2></a> </li> </ul> </div> </div> </div>
Let's talk about a few of the items that are added:
We're integrating the
ERB
calls for items such as the title, content, author and topic.I brought in the date for when the post was published and it will be printed out in an easy to read format by leveraging the
strftime
method:<%= @post.created_at.strftime("Published: on %m/%d/%Y at %l:%M%P") %>
As mentioned at the beginning of the post we're going to leave in some of the placeholder items that the designer has in place and in future lessons we'll integrate each of these features.
If you navigate to one of the post pages, an example one I have from the seeds
file is http://localhost:3000/topics/my-title-99/posts/48
you can see that the Post
page is working and is matching the design layout. There are a few things we need to fix, there are two items specifically that are bothering me:
The
left/right
buttons aren't showing up, and I liked that UI component.We don't have the cool sidebar slider that the designer probably spent countless nights building (or copying from a StackOverflow post...)
There's some empty room at the top of the page that are being taken up by our
alerts
partial.
Adding buttons
If you look at lines 41 and 42 you'll see the following class calls:
<div class="next-article"> <div class="btn btn-left"></div> <div class="btn btn-right"></div>
This means that in our CSS there will be some btn
selectors that are setting these images. The easiest way to find these will be to perform a universal search. Looking through the full project code base for .btn
brings up a lot of results and I don't feel like going through all of them (things to do, people to see, etc.). Looking back at the code you'll see that our buttons are nested under the next-article
class, performing a universal search for .next-article
pulls up what we're looking for. Looking at this CSS style shows that it's looking for an article_actions
image file, but much like different times in my love life, it's looking for this file in all the wrong places:
/* app/assets/stylesheets/template/main.css */ div.article-sidebar .next-article .btn { background:url(../../images/common/article_actions.png); background-repeat: no-repeat; background-position:0px 0px; width:30px; height:30px; border-radius:0px; position:absolute; }
So how can we have the CSS file know where this image is? Well I'll let you in on a little secret, HTML files aren't the only types of files that can have embedded Ruby. Run the following command (or edit the file name for our main.css
file):
mv app/assets/stylesheets/template/main.css app/assets/stylesheets/template/main.css.erb
This will make it possible to embed Ruby code into our stylesheet, including the ability to use the image_url
helper method that gives us a direct link to the Rails asset pipeline. So we can update the article-sidebar
class with the below code:
/* app/assets/stylesheets/template/main.css.erb */ div.article-sidebar .next-article .btn { background:url(<%= image_url('common/article_actions.png') %>); background-repeat: no-repeat; background-position:0px 0px; width:30px; height:30px; border-radius:0px; position:absolute; }
The image_url
helper method is a great tool when you need to be able to access the image assets. Without that you'd need to play around with traversing the file system, which isn't the way we want to live our coding lives.
If you navigate to the same page and refresh the browser you'll see that our cool buttons are there, nice work!
Implement Slider
It's not easy to see right away, however if you shrink the browser width down you can see that a Show More Details
button appears on the mock, if you click it the next post preview comes up. I think that's a great feature and will look great on tablets and phones, so it's important to ensure it's integrated. You can see it below:
If we go back to the source asset file we can see that there is a link tag for the Show More Details
button, let's paste that in under the Topic
code:
<a href="#show-sidebar" class="btn btn-default btn-green show-sidebar"><span>Show More Details</span></a>
If you refresh the page you'll see the button show up. The style is a bit off, but we can clean that up when we get to our polishing lesson. This wouldn't work yet because the button itself will only call a JavaScript function. If you look towards the bottom of the design file you'll see that there is a script tag that contains what we need to make this work. Let's start off with the naive approach and simply paste the script tag into the file itself so it matches the design file:
<!-- app/views/topics/posts/show.html.erb --> <script type="text/javascript"> $(function () { $('.filter-categories').fancySelect().on('change', function () { filter(); }); var body_height = $('body').height(); $('.article-sidebar').height(body_height); $('a.show-sidebar').click(function() { //$('.article-sidebar').css('display','block'); $('.article-sidebar').animate({ right: "+=250" }, 1000, function() { }); $('div.bg2').animate({ opacity: "show" }, "slow" ); }); $('div.bg2').click(function() { $('.article-sidebar').animate({ right: "-=250" }, 1000, function() { $(this).hide(); }); $('div.bg2').animate({ opacity: "hide" }, "slow" ); }); function filter () { $('#filter form').submit(); } }); </script>
Refreshing the page and clicking the button shows that it's not working, so what gives? Well if you look directly above the script tag in the design file you'll see that the designer brought in the jQuery library fancySelect. And if you look through the script itself you'll notice that the functions inside of it are calling the library. So we need to bring this into the application to get our cool slider working properly. Let's copy the jquery.fancySelect.min.js
and jquery-ui.theme.min.css
files from the designer's vendor
directory into the app/assets/javascript
directory. Now if you refresh the page you'll see it's all working, and we have the cool sliding sidebar action, nice work!
Now let's refactor the code since we don't want to have a big script tag on a view file. First let's convert the jQuery code to CoffeeScript syntax. We could rewrite it from scratch like barbarians, or we could simply navigate to js2coffee and have it convert it for us. Cut it from the view file and have js2coffee convert it for us. Now paste our CoffeeScript code into app/assets/javascripts/posts.coffee
:
# app/assets/javascripts/posts.coffee $ -> filter = -> $('#filter form').submit() return $('.filter-categories').fancySelect().on 'change', -> filter() return body_height = $('body').height() $('.article-sidebar').height body_height $('a.show-sidebar').click -> #$('.article-sidebar').css('display','block'); $('.article-sidebar').animate { right: '+=250' }, 1000, -> $('div.bg2').animate { opacity: 'show' }, 'slow' return $('div.bg2').click -> $('.article-sidebar').animate { right: '-=250' }, 1000, -> $(this).hide() return $('div.bg2').animate { opacity: 'hide' }, 'slow' return return
If you go back to the browser and click refresh you'll see that the feature is still working like before, so that was a successful refactor.
Fixing empty space on the header
If you noticed we have a large empty space above the title, this is because the alerts
partial that we're calling from the application template file. Let's remove that because I don't want this on every page anyways, only certain pages should have the notification bar and we're going to customize where it should be placed later on. After you pull it out of the app/views/layouts/application.html.erb
file and click refresh on the Post
page you'll see that the issues has been fixed and our Post
page is looking good!
In the next lesson we're going to start working on the Topics
pages.