Skip to content
opensas edited this page Nov 3, 2011 · 12 revisions

Step 4 - styling

Purpose: in this step we will give our little application a facelift. For that purpose we will use the recently released twitter bootstrap.

Note: you can get the sources of this step with the following commands

cd ~/devel/apps
git clone git://github.com/opensas/play-demo.git
cd play-demo
git checkout origin/04-styling

Get twitter's bootstrap

Download twitter's bootstrap from https://github.com/twitter/bootstrap, unzip it and copy bootstrap-1.2.0.css to /public/stylesheet folder.

Then copy play-logo.png, grid-18x.png and delete.jpg to /public/images folder.

Style list.html template

Now edit views/main.html template to include twitter's bootstrap files

views/main.html

<!DOCTYPE html>

<html>
    <head>
        <title>#{get 'title' /}</title>
        <meta charset="${_response_encoding}">
        <link href="@{'/public/stylesheets/bootstrap-1.2.0.css'}" rel="stylesheet">        
        <link rel="stylesheet" href="@{'/public/stylesheets/main.css'}" media="screen">
        #{get 'moreStyles' /}
        <link rel="shortcut icon" type="image/png" href="@{'/public/images/favicon.png'}">
        <script src="@{'/public/javascripts/jquery-1.5.2.min.js'}" type="text/javascript" charset="${_response_encoding}"></script>
        #{get 'moreScripts' /}
    </head>
    <body>
        <div class="container">    
            #{doLayout /}
        </div> <!-- /container -->
    </body>
</html>

modify list.html template to use new styles

#{extends 'main.html' /}
#{set title:'Events' /}

<section id="list">

<div class="page-header">
    <h1>Events</h1>
</div>

<div class="row">
#{if events}
    <table class="zebra-striped">
        <thead>
            <th>#</th>
            <th>Event</th>
            <th>Type</th>
            <th>Place</th>
            <th>Date</th>
            <th></th>
        </thead>
    #{list events, as:'event'}
        <tr>
            <td>${event.id}</td>
            <td>${event.name}</td>
            <td>${event.type.name}</td>
            <td>${event.place}</td>
            <td>${event.date}</td>
            <td></td>
        </tr>
    #{/list}
    </table>
#{/if}
#{else}
¡No events in sight!
#{/else}
</div> <!-- /row -->

<div class="list-actions">
    #{a @loadFromYamlFile(), class:'btn'}load from yaml#{/a}
</div>

</section>

Create topbar and footer partials

create the file app/views/partials/topbar.html

<div class="topbar">
    <div class="topbar-inner">
     <div class="container">
         <h3><a href="#">Events</a></h3>
         <ul>
             <li><a href="#masthead">about</a></li>
             <li><a href="/">homepage</a></li>
             <li><a href="http://www.linkedin.com/">follow us on LinkedIn</a></li>
         </ul>
             <ul class="nav secondary-nav">
             <li><a href="http://www.playframework.org/" id="play-logo"></a></li>
         </ul>
     </div>
    </div>
</div>

and create also a view/partials/footer.html

<div id="footer">
	<div class="inner">
		<div class="container">
			<p class="right"><a href="#">Back home</a></p>
			<p>
				Play-demo app <a href="" target="_blank">Play demo application</a>.<br />
				Fork me at <a href="https://github.com/opensas/play-demo" target="_blank">https://github.com/opensas/play-demo</a>.
			</p>
		</div>
	</div>
</div>

now include both files in main.html template

[...]
    <body>
        #{include 'partials/topbar.html' /}
        <div class="container">    
            #{doLayout /}
        </div> <!-- /container -->
        #{include 'partials/footer.html' /}
    </body>
[...]

add some cusctom css to public/stylesheets/mains.css

/* Add additional stylesheets below
-------------------------------------------------- */

/* Body and structure
-------------------------------------------------- */
body {
  background-color: #fff;
  position: relative;
}
section {
  padding-top: 20px;
}
section > .row {
  margin-bottom: 10px;
}
#masthead, #footer {
  background-color: #049cd9;
  background-repeat: no-repeat;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#004D9F), to(#049cd9));
  background-image: -webkit-linear-gradient(#004D9F, #049cd9);
  background-image: -moz-linear-gradient(#004D9F, #049cd9);
  background-image: -o-linear-gradient(top, #004D9F, #049cd9);
  background-image: -khtml-gradient(linear, left top, left bottom, from(#004D9F), to(#049cd9));
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#004D9F', endColorstr='#049cd9', GradientType=0); /* IE8 and down */
}
#masthead div.inner, #footer div.inner, #masthead div#next-event {
  background: transparent url(../images/grid-18px.png) top center;
  -webkit-box-shadow: inset 0 10px 30px rgba(0, 0, 0, 0.3);
     -moz-box-shadow: inset 0 10px 30px rgba(0, 0, 0, 0.3);
          box-shadow: inset 0 10px 30px rgba(0, 0, 0, 0.3);
}


#masthead h1,
#footer h1,
#masthead p,
#footer p {
  color: #fff;
  text-shadow: 0 1px 1px rgba(0,0,0,.3);
}
#masthead p a,
#footer p a {
  color: #fff;
  font-weight: bold;
}
#masthead {
  margin-top: 40px;
}
#masthead h1,
#masthead p {
  text-align: center;
  margin-bottom: 9px;
}
#masthead h1 {
  font-size: 54px;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,.5);
}
#masthead p {
  font-weight: 300;
}
#masthead p.lead {
  font-size: 20px;
  line-height: 27px;
}

#footer {
  margin-top: 80px;
}
#footer p {
  margin-bottom: 0;
  color: rgba(255,255,255,.8)
}
#footer p.right {
  float: right;
}
/* Topbar special styles
-------------------------------------------------- */
div.topbar-wrapper {
  position: relative;
  height: 40px;
  margin: 5px 0 15px;
}
div.topbar-wrapper div.topbar {
  position: absolute;
  margin: 0 -20px;
}
div.topbar-wrapper div.topbar .topbar-inner {
  padding-left: 20px;
  padding-right: 20px;
  -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
          border-radius: 4px;
}

#masthead p.lead .event-countdown,  #masthead p.lead .no-events {
    font-size: 16px;
    font-style: italic;
}

#masthead p.lead .next-event {
    font-size: 26px;
    font-weight: bold;
}

Make table sortable

download table sorter jquery plugin and save jquery.tablesorter.js to public/javascripts. Then add a reference to it in main.html (it's also a good opportunity to download latest jquery version)

[...]
        <link rel="shortcut icon" type="image/png" href="@{'/public/images/favicon.png'}">
        <script src="@{'/public/javascripts/jquery-1.6.3.min.js'}" type="text/javascript" charset="${_response_encoding}"></script>
        <script src="@{'/public/javascripts/jquery.tablesorter.min.js'}"></script>

and then add at the end of list.html

<script >
  $(function() {
    $("table.sorted").tablesorter({ sortList: [[1,0]] });
  });
</script>

to tell tableSorter to sort the table, you have to add a sorted class to the table, like this

[...]<div class="row">
#{if events}
    <table class="zebra-striped sorted">
        <thead>
            <th>#</th>
            <th>Event</th>
[...]

Formatting date

One final touch, format the event's date

[...]
            <td>${event.type.name}</td>
            <td>${event.place}</td>
            <td>${event?.date.format('MM-dd-yyyy HH:mm')}</td>
            <td></td>
[...]

Go to Step 5 - actions to see how to add, edit and delete events.