Implementing Styles for the Post Page
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.
Guide Tasks
  • 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:

large

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:

  1. The left/right buttons aren't showing up, and I liked that UI component.

  2. We don't have the cool sidebar slider that the designer probably spent countless nights building (or copying from a StackOverflow post...)

  3. 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:

medium

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!

large

In the next lesson we're going to start working on the Topics pages.

Resources