XPages – Create a responsive layout with Twitter Bootstrap – #2

Two days ago I wrote about Twitter Bootstrap (TB) and how to integrate it into an XPages application. I got a few responses and by what people are saying I reckon responsive design is an issue in the community. So here is part 2 of my series. Today I want to show you how to integrate Twitter Bootstrap into your database and how to create a first responsive layout.

Let’s go then. In my first post I had a link to the current TB sources. Download a copy if you have not done it yet and unpack the zip. We create a new database and open it in DDE. If you have not already added the Package Explorer to your XPages perspective do it now.

Open the database in the Package Explorer view and navigate to “WebContent”. Create 3 folders named “js”, “css” and “img”. Now take your System Explorer and copy the files to the directories as shown in the screenshot.

Move back to the database view and open the application properties. Click the XPages tab and set the values as shown in the next screenshot.

Twitter Bootstrap requires the HTML 5 doctype as you can see in the documentation. We disable the CSS and JS minimize settings so that we are able to use Firebug & Co. properly later on. In a production environment you may tick the box to minimize source code. You might as well use the already minimized sources from TB.

Save the application properties and create a new XPage. Name it as you like. We do not need a datasource yet so leave this option blank. Once opened move to the Source Tab of your page. Here’s my source:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
 <xp:this.resources>
 <xp:styleSheet href="css/bootstrap.css"></xp:styleSheet>
 <xp:styleSheet href="css/bootstrap-responsive.css"></xp:styleSheet>
 <xp:styleSheet href="css/hedersoft.css"></xp:styleSheet>
 <xp:metaData name="viewport" content="width=device-width, initial-scale=1.0">
 </xp:metaData>
 </xp:this.resources>

<!-- NAVIGATION BAR -->

<xp:panel styleClass="navbar navbar-inverse navbar-fixed-top">
 <xp:panel styleClass="navbar-inner">
 <xp:panel styleClass="container">
 <xp:panel styleClass="row">
 <xp:panel styleClass="span4">
 <xp:label id="label1">
 <xp:this.value><![CDATA[#{javascript:"Welcome " + @Name("[CN]",@UserName())}]]></xp:this.value>
 </xp:label>
 </xp:panel>
 <xp:panel styleClass="span6">
 <ul class="nav nav-pills">
 <li class="dropdown">

 <a class="dropdown-toggle" data-toggle="dropdown" href="#">
 <i class="icon-white icon-file"></i>
 Dropdown
 <b class="caret"></b>
 </a>
 <ul class="dropdown-menu">
 <li>
 <a tabindex="-1" href="#">Action</a>
 </li>
 <li>
 <a tabindex="-1" href="#">Another action</a>
 </li>
 <li>
 <a tabindex="-1" href="#">Something else here</a>
 </li>
 <li class="divider"></li>
 <li>
 <a tabindex="-1" href="#">Separated link</a>
 </li>
 </ul>
 </li>
 </ul>
 </xp:panel>
 <xp:panel styleClass="span2">
 <xp:label value="Logout" id="label3"></xp:label>
 </xp:panel>
 </xp:panel>
 </xp:panel>
 </xp:panel>
 </xp:panel>

<!-- APPLICATION LAYOUT -->

<xp:panel styleClass="subhead">
 <xp:panel styleClass="container">
 <xp:panel styleClass="row">
 <xp:panel styleClass="span4">
 <ul class="nav nav-list sidebar-nav-fixed">
 <li class="nav-header">List header</li>
 <li class="active">
 <a href="#">
 <i class="icon-white icon-home"></i>
 Home
 </a>
 </li>
 <li>
 <a href="#">
 <i class="icon-book"></i>
 Library
 </a>
 </li>
 <li>
 <a href="#">
 <i class="icon-pencil"></i>
 Applications
 </a>
 </li>
 <li class="nav-header">Another list header</li>
 <li>
 <a href="#">
 <i class="icon-user"></i>
 Profile
 </a>
 </li>
 <li>
 <a href="#">
 <i class="icon-cog"></i>
 Settings
 </a>
 </li>
 <li class="divider"></li>
 <li>
 <a href="#">
 <i class="icon-flag"></i>
 Help
 </a>
 </li>
 </ul>
 </xp:panel>
 <xp:panel styleClass="span8">
 <xp:table>
 <xp:tr>
 <xp:td>
 <xp:label value="First Name" id="label2"></xp:label>
 </xp:td>
 <xp:td>
 <xp:inputText id="inputText1"></xp:inputText>
 </xp:td>
 </xp:tr>
 <xp:tr>
 <xp:td>
 <xp:label value="Last Name" id="label4"></xp:label>
 </xp:td>
 <xp:td>
 <xp:inputText id="inputText2"></xp:inputText>
 </xp:td>
 </xp:tr>
 <xp:tr>
 <xp:td>
 <xp:label value="Address" id="label5"></xp:label>
 </xp:td>
 <xp:td>
 <xp:inputTextarea id="inputTextarea1"></xp:inputTextarea>
 </xp:td>
 </xp:tr>
 <xp:tr>
 <xp:td>
 <xp:label value="Phone" id="label6"></xp:label>
 </xp:td>
 <xp:td>
 <xp:inputText id="inputText3"></xp:inputText>
 </xp:td>
 </xp:tr>
 </xp:table>
 </xp:panel>
 </xp:panel>
 </xp:panel>
 </xp:panel>

<script type="text/javascript" src="js/jQuery-1.8.0.min.js"
 clientSide="true"></script>
 <script type="text/javascript" src="js/bootstrap.js" clientSide="true"></script>

</xp:view>

Feel free to copy the code and use it for whatever purpose you want. I just want to point out some crucial elements. First of all we need the stylesheets on our page which we include as resources.


<xp:this.resources>
 <xp:styleSheet href="css/bootstrap.css"></xp:styleSheet>
 <xp:styleSheet href="css/bootstrap-responsive.css"></xp:styleSheet>
 <xp:styleSheet href="css/hedersoft.css"></xp:styleSheet>
 <xp:metaData name="viewport" content="width=device-width, initial-scale=1.0">
 </xp:metaData>
</xp:this.resources>

I used the responsive css to make my site responsive. I added the viewport meta tag as demanded by Bootstrap. I added my own stylesheet “hedersoft.css” to do some adjustments. It currently only holds one element.

@CHARSET "ISO-8859-1";

@media (min-width: 980px) {
.subhead{
 padding-top:50px;
}
}

As you can see I used the @media tag to tell the .subhead class that it only applies if the width of the page is at least 980px.

At the end of the page I load the JavaScript Files jQuery and Bootstrap to speed page loading up a bit.

<script type="text/javascript" src="js/jQuery-1.8.0.min.js"
 clientSide="true"></script>
<script type="text/javascript" src="js/bootstrap.js" clientSide="true"></script>

I used a fixed layout for this page. To do this you need a div tag and a the class “container” to it. Within the div tag you create another div tag for the first row in your container. Add the class “row” to it. Then you can add 1-12 divs according to the grid system and add “span*” classes to the divs. All “*” must sum up to 12, no more and no less. Check the TB documentation for further details. Here is an example using the xp:panel:

<xp:panel styleClass="container">
<xp:panel styleClass="row">
 <xp:panel styleClass="span4"></xp:panel>
 <xp:panel styleClass="span8"></xp:panel>
 </xp:panel>
 </xp:panel>

You can use divs or xp:divs as well since they all get rendered to divs in the end. When I now open this page in my webbrowser it looks like this:

When I resize my page the content will get resized as well to fit the different formats from small smartphones to big screens. Here is another screenshot of the same page resized to smartphone size:

It’s not a beauty yet but it shows what Twitter Bootstrap can do for you without having to code all the css yourself. This being said I close the 2nd part of my series and hope it may be of any help to start your project. In the next part I dig a little deeper into the Bootstrap soil to make the page look a little better and to show you some elements you might want to use in your application.