Sunday, December 23, 2012

Mixing Bootstrap with JSP

A few days ago I wrote a blog post about my first contact with Twitter's Bootstrap UI framework. What I showed was how to create a simple static web site which uses java script in order to set a content area. The article can be found here: http://ecmgeek.blogspot.de/2012/12/first-contact-with-bootstrap.html

This article will show how to mix Bootstrap with JSP pages to bring a bit more dynamic into the page. Here some requirements:

  • A simple HTML template which uses Bootstrap should be used to show a web site.
  • A site should have multiple pages. The site navigation should allow to navigate to the pages.
  • It should be possible to navigate through a page by using a simple navigation menu.
  • A page should show some HTML content.
So we can derive the following Java classes :
  • Site: A site has a name and a description. One site is associated to multiple pages.
  • Page: A page has a name, an id and a target URL. It also has exactly one SubMenu and one HTMLContent item.
  • SubMenu: A sub menu has multiple menu items.
  • SubmenuItem: A sub menu item has a  name and a target URL.
  • HTMLContent: Has just a String property to store the HTML. May be used as Base class for other Content items.

 So what can now do is to create a Site instance (which is indeed kept on the server side - and so a servlet container is required to host the application) in order to provide our site template with the required content.

package de.ecmgeek.bootstrap;

public class Demo {

    private Site site;
    
    public Demo() {
       
     site = new Site("Demo", "This is a demo page");
    
     Page home = new Page("Home",new HTMLContent("<b> Home ... </b>"));
     Submenu homeSubMenu = new Submenu();
     SubmenuItem homeItem1 = new SubmenuItem("HomeSection1","#section1");
     SubmenuItem homeItem2 = new SubmenuItem("HomeSection2","#section2");
     SubmenuItem homeItem3 = new SubmenuItem("HomeSection3","#section3");
     homeSubMenu.addItem(homeItem1);
     homeSubMenu.addItem(homeItem2);
     homeSubMenu.addItem(homeItem3);
     home.setSubmenu(homeSubMenu);
    
     Page about = new Page("About",new HTMLContent("<b> About ... </b>"));
     Submenu aboutSubMenu = new Submenu();
     SubmenuItem aboutItem1 = new SubmenuItem("AboutSection1","#section1");
     SubmenuItem aboutItem2 = new SubmenuItem("AboutSection2","#section2");
     SubmenuItem aboutItem3 = new SubmenuItem("AboutSection3","#section3");
     aboutSubMenu.addItem(aboutItem1);
     aboutSubMenu.addItem(aboutItem2);
     aboutSubMenu.addItem(aboutItem3);
     about.setSubmenu(aboutSubMenu);
    
     Page contact = new Page("Contact",new HTMLContent("<b> Contact ... </b>"));
     Submenu contactSubMenu = new Submenu();
     SubmenuItem contactItem1 = new SubmenuItem("ContactSection1","#section1");
     SubmenuItem contactItem2 = new SubmenuItem("ContactSection2","#section2");
     SubmenuItem contactItem3 = new SubmenuItem("ContactSection3","#section3");
     contactSubMenu.addItem(contactItem1);
     contactSubMenu.addItem(contactItem2);
     contactSubMenu.addItem(contactItem3);
     contact.setSubmenu(contactSubMenu);
    
     site.add(home);
     site.add(about);
     site.add(contact);
    
    }
    
    public Site getSite() {
        return site;
    };
}

The class Demo is only used for demonstration purposes. Usually we would use a persistence layer like Hibernate or JPA to read the site data from a database.

The next step is to  change our more or less static web site to use a Site which is provided from the server. For this purposes we use J(ava)S(erver)P(ages). It's just easy to use and to learn and you can access your beans directly via Scriptlets and expressions. Another, the more new school way, would be to export the site data via a RESTFul Web Service which talks J(ava)S(ript)O(bject)N(otation). The advantage of the second way is that you can use the data out of the box after you got it from the server with Java Script without the need to use something like JSP scriptlets to "inject" the whole data into your HTML. However, let's go with JSP here.

So our previous HTML page becomes now a JSP page, which looks like the following one:

<!-- (0) Create an empty HTML page -->
<!DOCTYPE html>
<%@page import="de.ecmgeek.bootstrap.SubmenuItem"%>
<%@page import="de.ecmgeek.bootstrap.Page"%>
<%@page import="de.ecmgeek.bootstrap.Demo"%>
<%@page import="de.ecmgeek.bootstrap.Site"%>
<%@page import="de.ecmgeek.bootstrap.HTMLContent"%>
<html>
    <!-- (1) Some basic header info -->
    <head>
        <meta charset="utf-8">
            <title>BootstrapMeetsJSP</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="description" content="">
            <meta name="author" content="">

        <!-- (2) Import the provided CSS file -->
        <link href="css/bootstrap.min.css" rel="stylesheet" media="screen">    
    </head>
    
    <body>
        <!-- Do some JAVA initialization work -->
        <%
            //Build some demo data
            Site site = new Demo().getSite();
        %>
    
         <!-- (3) Import jQuery and Bootstrap -->
        <script src="js/jquery-latest.js"></script>
        <script src="js/bootstrap.min.js"></script>
        
        <!-- (5) At last add some JavaScript (jQuery) here to fill the page with life -->
        <script>
        
        $(document).ready(function(){
          
            
            //Inject some JAVA code into the JavaScript calls
            <%
              for (Page p : site.getPages())
              {
                      out.println("$('#"+ p.getId()  +"').click(function(){");    
                      out.println("$('div.my-content').empty();");
                      out.println("$('ul.nav-list').empty();");
                      out.println("$('div.my-content').html('"+p.getContent().getHtml()+"');");
                      
                    //Set the content and the submenu    
                    for (SubmenuItem sm : p.getSubmenu().getItems())
                    {
                        out.println("$('ul.nav-list').append('<li><a href=\"" + sm.getTarget() +"\"><i class=\"icon-chevron-right\"></i>"+ sm.getName() +"</a></li>');");
                    
                    }
                    
                    out.println("});");
              }
            %>            
               
         });      
        

        </script>

        
        <!-- (4) Bootstrap decorated HTML here -->
        <div id="container">

           <!-- A navigation header bar which is fixed to the top -->
           <div class="navbar navbar-fixed-top navbar-inverse">
                   <div class="navbar-inner">
                       <a class="brand" href="#"><%=site.getName()%></a>
                       
                       <ul id="header" class="nav">
                       
                           <%
                               for (Page p : site.getPages())
                               {
                                   out.print("<li><a href='"+p.getTarget()+"'id='"+p.getId()+"'>"+p.getName()+"</a></li>");                       
                               }
                           %>
                    
                    </ul>
                         </div>
               </div>
        
             <!-- (4.1) A simple web site header -->        
           <div class="hero-unit">
                <h1><%=site.getName()%></h1>
                <p><%=site.getDesc()%></p>
                <p>
                </p>
               </div>
          

           <!-- (4.2) A HTML grid with 12 columns, in this case we -->
             <div class="row">
            <!-- 4 columns are used for the left hand side navigation bar -->
                <div class="span4 bs-docs-sidebar">
                <ul class="nav nav-list bs-docs-sidenav">
                </ul>
            </div>
                
            <!-- (4.3) 8 columns are used for the right hand side content area -->
            <div class="span8">
                
                <!-- (4.4) The content area which can be decorated by own css -->
                <div class="my-content">
                </div>
            </div>
               </div>
            </div>    
    </body>
</html>
The result looks quite identical to the static page, but with the difference that the site data is now provided from the server to the client.



In summary the following happens:

  • Java code is used to generate the JavaScript code dependent on the site data which is provided by the server
  • The generated JavaScript code is used in order to manipulate the web site's HTML code dependent on the actions (click on the header menu item)
  • The HTML will be rendered on the client side (browser, ...)

It's easy to see that these are the basics to build a very simple W(eb)C(ontent)M(anagement) system which is based on Bootstrap. A next article will follow where I will describe how to add a database connection in order to retrieve the site data from a database. I can even imagine to create a simple Bootstrap based authoring web application which can be used to add data to this database.


2 comments:

  1. Nice article. You might be interested in a project of mine, Bootstrap.jsp, which makes it even easier to mix Bootstrap with JSP:

    https://github.com/Mrdigs/Bootstrap.jsp

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete