css and javascript optimization using granule library

We got “B” rating in YSlow (before it was “D”) after using granule library (no spritification, no gzip compression and no CDN). It is very popular JS and CSS optimization tool and can be used with any Java based web application. The library simply minifies and combines the CSS and Javascript files of your web page. It comes with Apache License 2.0. Follow the below steps to get started!

1. Download the granule1.0.9.jar from here and put it in your lib folder
2. Open up the web.xml (for grails applications, use the ‘grails install-templates’ command to generate the web.xml) and include the servlet mapping for CompressServlet

<servlet>
    <servlet-name>CompressServlet</servlet-name>
    <servlet-class>com.granule.CompressServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>CompressServlet</servlet-name>
    <url-pattern>/combined.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>CompressServlet</servlet-name>
    <url-pattern>/combined.css</url-pattern>
</servlet-mapping>

3. Now you are ready to use the granule library. Just include the taglib directive and use the tags in your JSPs/GSPs like following:

<%@ taglib uri="http://granule.com/tags" prefix="granule" %>

<granule:compress>
    <link rel="stylesheet" type="text/css" href="/testapp/css/main.css" />
    <link rel="stylesheet" type="text/css" href="/testapp/css/jquery-ui.css"/>
    <link rel="stylesheet" type="text/css" href="/testapp/css/accordion.css" />
    <link rel="stylesheet" type="text/css" href="/testapp/css/tooltip.css" />
    <link rel="stylesheet" type="text/css" href="/testapp/css/datepicker/jdpicker.css"  />
</granule:compress>

<granule:compress>
    <script type="text/javascript" src="/testapp/js/jquery-1.8.1.min.js" ></script>
    <script type="text/javascript" src="/testapp/js/jquery-ui.js" ></script>
    <script type="text/javascript" src="/testapp/js/test.js" ></script>
    <script type="text/javascript" src="/testapp/js/jQuery.equalHeights.js"></script>
    <script type="text/javascript" src="/testapp/js/jquery.collapse.js"></script>
</granule:compress>

4. And it will produce output like this when you do view-source of your web page:

<link rel="stylesheet" type="text/css" href="/testapp/combined.css?id=cad58bbf13d4b0d"   />
<script src="/testapp/combined.js?id=288c577b13d4b0d"></script>

If you do view-source of combined.js and combined.css you will see the minified content.

report generation using Jasper plugin in Grails application

I could not able to find an example for this over the internet. Even the documentation page clearly says this tutorial is not about going into details of how to create the jrxml/jasper file as it is not the author’s ‘strong side’, thus making it incomplete. So this time I’m writing one example to save time for future googlers.

When your requirement is a report generation, Jasper is the first choice of Java community. To generate a report, you need just only a ‘Collection’ of records, and put down the same on ‘XLS’, ‘PDF’ various formats. I am sticking to use the ‘Collection’ of records to PDF/XLS scenario because of simplicity. This plugin has the capability of fetching the records directly from database though.

So, preciously the input of this example is – a List of records and choice of format and file-name and output – a ‘PDF’ or ‘XLS’ document. Following is the step by step guide. People in hurry may download the full sourcecode (I have used Grails 2.2.0) right here.

1. Create a Grails project with name – ‘testapp’
2. Open up the ‘BuildConfig.groovy’ file in your project and add two lines inside the ‘plugins’ closure:

    plugins {
        ....
        ....
        compile ":jasper:1.6.1"
        runtime ':jasper:1.6.1'
    }

3. Now run ‘refresh-dependencies’ on ‘testapp’ project, this will download and install the plugin. If you face any issues (yes, I faced it too) downlading the plugin by ‘refresh-dependencies’, feel free to run ‘grails install-plugin jasper’ command.
4. Run the ‘run-app’ command on ‘testapp’. The plugin consists of one important controller named ‘org.codehaus.groovy.grails.plugins.jasper.JasperController’, which will be shown on the welcome page of the ‘testapp’ project when viewed in browser.
5. Now create a package ‘com.testapp.controller’ in your src/Groovy directory
6. Create a class ‘JasperDTO.groovy’ in that package (src/Groovy directory):

    package com.testapp.controller
    class JasperDTO {
        String name
        String age
        String gender
        String address
    }

7. Now create a Controller, JasperReportController which deals with a service JasperDTOService like the followings:
JasperReportController.groovy

package com.testapp.controller
import com.testapp.controller.JasperDTO
class JasperReportController {
    def jasperDTOService
    /*this method shows the records listing page*/
    def index() {
        def jasperDTOList = jasperDTOService.loadAllJasperDTO(20)
        render(view:"index", model:[jasperDTOList:jasperDTOList])
        return false
    }
    /*this method serves the report document for download*/
    def generateReport() {
        def jasperDTOList = jasperDTOService.loadAllJasperDTO(120)
        params.title = "Hello World !"
        params.reportId = "220/B, Baker Street, London"
        params.operationTime = new Date()
        chain(controller:'jasper', action:'index',
                                  model:[data:jasperDTOList],
                                  params:params)
        return false
    }
}

JasperDTOService.groovy

package com.testapp.service
import com.testapp.controller.JasperDTO
class JasperDTOService {
    def loadAllJasperDTO(int counts) {
        def jasperDTOList = []
        def jasperDTO
        for(int i = 1; i <= counts; i++) {
            jasperDTO = new JasperDTO(name: "name" + i,
                                        age: i,
                                        gender:"male",
                                        address:"address" + i)
            jasperDTOList.add(jasperDTO)
        }
        return jasperDTOList
    }
}

8. Now create the view /jsperReport/index.gsp for displaying records and the Download links for the report.

<!Doctype HTML>
<html>
    <head>
        <title>testapp : jasper report</title>
    </head>
    <body>
        Total record found : ${jasperDTOList.size()}
        <g:if test="${jasperDTOList.size() > 0}">
        <table border="1">
        <tr>
            <td>Name</td>
            <td>Age</td>
            <td>Gender</td>
            <td>Address</td>
        </tr>
        <g:each var="jasperDTO" in="${jasperDTOList}">
        <tr>
            <td>${jasperDTO.name}</td>
            <td>${jasperDTO.age}</td>
            <td>${jasperDTO.gender}</td>
            <td>${jasperDTO.address}</td>
        </tr>
        </g:each>
        </table>
        <a href="/testapp/jasperReport/generateReport?_format=XLS&_name=all_dto
&_file=all_dto">
            XLS
        </a>
        |
        <a href="/testapp/jasperReport/generateReport?_format=PDF&_name=all_dto
&_file=all_dto">
            PDF
        </a>
        </g:if>
    </body>
</html>

9. To explain about the codes in /jsperReport/index.gsp, we are just iterating the ‘jasperDTOList’ in tabular format. But the key things are last two href links for downloading the report. As you can see, the links are pointing to our ‘JasperReportController’ and ‘generateReport’ action. With parameters: _format, _name, _file. Here are the meaning of these parameters:

_format —> specifies file-format you want to generate
_name —> specifies the file-name should appear while downloading the report
_file —> specifies the ‘jrxml’ file it should use to generate our report

as you can see, I use these parameters in chain to call the auto-generated ‘jasper’ controller in chain at this line of our JasperReportController.generateReport() action, along with the ‘jasperDTOList’ as a model named ‘data’:

chain(controller:’jasper’, action:’index’, model:[data:jasperDTOList], params:params)

10. Now is time to create the jrxml file with iReports tool for our ‘testapp’ application.

a) Download and install iReport-5.0.0
The download is a bit large in size (95 MB), so I suggest using a download manager.
b) Follow the video below to create your ‘all_dto.jrxml’ file.

In case you are facing issues view this on flicker.
c) Place your ‘all_dto.jrxml’ file into ‘/web-app/reports’ directory

11. Now you are ready to download the reports. just refresh the listing page and click on the ‘XML’, ‘PDF’ links.

In case you are facing issues at any stage, please post a comment/mail/skype me. Thank you so much !

error block in jQuery Ajax

The ‘error’ block in a jQuery AJAX handler is optional. In most of the cases we just ignore writing it. Here is an example how ‘error’ block in jQuery AJAX comes to use and why we should consider writing it. Consider a controller which calculates the division of two numbers received from user input.

Front end code:

JAVASCRIPT:
$("#trigger").click(function() {
    $.ajax({
        url : "/testapp/test/divideTwoNums",
        type : 'POST',
        dataType : 'html',
        data : { num1 : $("#num1").val(), num2 : $("#num2").val() },
        success : function(data) {
            alert(data);    
        }
    });
});

HTML:
<div>Num 1 : <input type="text" name="num1" id="num1" /></div>
<div>Num 2 : <input type="text" name="num2" id="num2" /></div>
<div><input type="button" id="trigger" value="Divide"/></div>

In controller what you would do :

void doPost(HttpServletRequest request, HttpServletResponse response) {
    PrintWriter out = response.getWriter();
    int num1 = Integer.parseInt(request.getParameter("num1"));
    int num2 = Integer.parseInt(request.getParameter("num2"));
    out.println(num1/num2);
}

This works fine, as long as user delivers proper integer data for num1 and num2 field and does not input a 0(zero) in num2. So wise people will try to re-program the controller like this now:

void doPost(HttpServletRequest request, HttpServletResponse response) {
    PrintWriter out = response.getWriter();
    try {
        int num1 = Integer.parseInt(request.getParameter("num1"));
        int num2 = Integer.parseInt(request.getParameter("num2"));
        out.println(num1/num2);
    }
    catch(Exception e) {
        out.println("Invalid inputs!");
    }
}

But the same effect can be achieved by using an ‘error’ block in jQuery-ajax.

$("#trigger").click(function() {
    $.ajax({
        url : "/testapp/test/divideTwoNums",
        type : 'POST',
        dataType : 'html',
        data : { num1 : $("#num1").val(), num2 : $("#num2").val() },
        success : function(data) {
            alert(data);    
        },
        error: function(jqXHR, textStatus, errorThrown) {
            alert("Invalid inputs!");
        }
    });
});

You don’t need to explicitly catch exceptions in controller, just let it flow over the response, jqXHR will get to know if a 500 error was occurred, and eventually call the ‘error’ block defined in your ajax-handler.

‘return’ statement in grails controller

Consider a controller :

class TestController {
    def index() {
 	log.info("I am here ---> ")
	render(view:"/test/index")
	log.info("I am here too ---> ")
    }
}

This is the output it will produce when called:

INFO  controller.TestController  - I am here ---> 
INFO  controller.TestController  - I am here too ---> 

But if we had used this:

	def index() {
	    log.info("I am here ---> ")
	    render(view:"/test/index")
	    return
	    log.info("I am here too ---> ")
	}

The output would be :

INFO  controller.TestController  - I am here --->

Conclusion:
Whenever you have written a ‘render’ (or ‘redirect’) statement, use a ‘return’ to explicitly exit from controller. Or else the program-control will tend to flow until the end of action closure.

Crossdomain data transfer with AJAX and JSON-P

Nowadays programmers find JSON as a simple and fast standard for transferring data on the web. JSON is used with AJAX call, jQuery libraries, autocomplete everywhere. But when the case is loading JSON from another server with XMLHTTPRequest (i.e. AJAX), then there is a bar called Same Origin Policy.

What Same Origin Policy is: It is a general rule for almost all browsers. Any XHR (AJAX request ) towards another
server, will be rejected. So, if your source-data (whether it is JSON or not) is coming of another server, there is no way to use
the classical AJAX (or, jQuery) to pull it.

Some details about JSON: As I said, JSON is just a format for representing information. e.g. I want to pass an entity with properties “name” as “tusar” and “age” as “23″. The JSON representation of the entity is:

{
    "name": "tusar",
    "age": "23"
}

What is JSON-P: JSONP is JSON with padding. i.e, you put a string at the beginning and a pair of parenthesis around it, followed by a semicolon(;). e.g. the above JSON data will be called JSONP if I write it like:

func(
    {
        "name": "tusar",
        "age": "23"
    }
);

And the best feature of JSON-P is, it can be loaded from another domain via XHR.

Here is an example of how to load JSON-P from cross domain.
My source url is (it loads tweets of twitter account):

https://api.twitter.com/1/statuses/user_timeline/tusar_busybird.json

The code used for loading data is (FOR LIVE EXAMPLE SEE HERE):

    
HTML:
    <div id='tweet-list'></div>
	
JAVASCRIPT:
    window.myCallback = function(tweets) {
        for(i in tweets) {
            tweet = tweets[i];
            $("#tweet-list").append(tweet.text + "<hr />");
        }
    };
    $.ajax({
        url: "https://api.twitter.com/1/statuses/user_timeline/tusar_busybird.json",
        type: 'GET',
        data: {
            'foo': 'bar' //discard it if you dont need to pass any parameter
        },
        dataType: 'jsonp',
        jsonp: 'callback',
        jsonpCallback: 'myCallback'
    });

What this `myCallback` code does is, it writes down the tweets one by one inside the `tweet-list` div element. As you know, JSON-P is nothing but an extension of JSON format, we could use the $getJSON shorthand function also for loading the JSON-P objects. See the code below (LIVE EXAMPLE IS HERE):

var url =  "https://api.twitter.com/1/statuses/user_timeline/tusar_busybird.json";
$.getJSON(url + "?callback=?", null, function(tweets) {
    for(i in tweets) {
        tweet = tweets[i];
        $("#tweet-list").append(tweet.text + "<hr />");
    }
});

Notice the `?callback=?` at the end of the requested URL. That indicates to the $getJSON function that we want to use JSONP. Remove it, and it will be treated as a plain JSON request. Which will fail due to the Same Origin Policy.

jQuery Autocomplete and Address lookup with Google Map v3

If you are in a rush to get the code right now, visit here.

Here is the explanation of the code. First add the js and one css library files :

<script type="text/javascript" src="jquery-1.8.3.min.js"></script>        
<script src="http://maps.googleapis.com/maps/api/js?sensor=false" type="text/javascript"></script>
<script type="text/javascript" src="gmap3.js"></script> 
<script type="text/javascript" src="jquery-autocomplete.js"></script>
<link rel="stylesheet" type="text/css" href="jquery-autocomplete.css"/>

Here goes the initialize function code for Google map :

<script type="text/javascript">
    $(function(){ // or $(document).ready(function(){
        $("#test").gmap3();
    });
</script>

And the html :

<input id="address" type="text" size="60" />
<div id="test" class="gmap3"></div>

Now setup autocomplete plugin like this :

$('#address').autocomplete({
    source: function() {
        $("#test").gmap3({
            action:'getAddress',
            address: $(this).val(),
            callback:function(results){
                if (!results) return;
                $('#address').autocomplete(
                    'display',
                    results,
                    false);
            }
        });
    },
    cb:{
        cast: function(item){
                  return item.formatted_address;
              },
        select: function(item) {
            $("#test").gmap3( 
                {action:'clear', name:'marker'},
                {
                    action:'addMarker',
                    latLng:item.geometry.location,
                    map:{center:true}
                }
            );
        }
    }
});

VISIT HERE FOR LIVE EXAMPLE

Sticky Header/Footer Like Facebook

So, you need a sticky header like facebook website ? Or both header and footer, like this below one ? Here is the jsfiddle version of the example. It is based on plain CSS and no javascript is used.

Sticky header/footer

Sticky header/footer

The header and footer are fixed, but the middle content is scroll-able. When your content is incredibly large, this makes the top and bottom navigation links always available to the user thus giveing fairly better user experience, than an ordinary html page.

There are 3 parts in this layout (including header, content, footer). And the HTML structure look like this :

<!Doctype html>
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="style.css"/>
    </head>
    <body>
        <div class="container">
            <div class="header">
                This is header
            </div>
            <div class="content">
                <div class="gap"></div>
                <p>First line...............</p>
                <p>Long content goes here...</p>
                <p>Long content goes here...</p>
                <p>Long content goes here...</p>
                ................................
                ................................
                ................................
                <p>Last line................</p>
                <div class="gap"></div>
            </div>
            <div class="footer">
                This is footer
            </div>
        </div>
    </body>
</html>

And the CSS style definitions of style.css file goes here :

 html {
    height:100%; 
    max-height:100%; 
    padding:0; 
    margin:0; 
    border:0;
    overflow: hidden; 
 }
 body {
    height:100%;
    max-height:100%;
    overflow:hidden;
    padding:0;
    margin:0;
    border:0
    font: 12px Verdana, Helvetica, sans-serif;
    color: #F3F3F3;
 }
 .container {
    width : 100%;
    height: 100%;
    max-height:100%;
 }
 .header {
    position:absolute;
    margin:0;
    top:0;
    display:block;
    width:100%;
    height:80px;
    z-index:5;
    background-color: #656565;
    text-align : center;
    right:18px;
    line-height: 80px;
    font-size:2em;
 }
 .footer {
    position:absolute;
    margin:0;
    bottom:-1px;
    display:block;
    width:100%;
    z-index:4;
    height : 80px;
    background-color: #656565;
    text-align : center;
    right:18px;
    line-height: 80px;
    font-size:2em;
 }
 .content {
    display:block;
    height:100%;
    max-height:100%;
    overflow:auto;
    position:relative;
    z-index:3;
    background-color: #909090;
    text-align : center;
 }
 .gap {height : 80px;}

jQuery ajaxQueue [developed by Corey Frang]

When you are working with AJAX based content, issues may occur due to double click/ frequent clicking. Because AJAX requests are treated as independent thread on server, it does not guaranty the sequence by which the requests will be completed. In this situation most of the developers will just do :

     async:false

And the bug is FIXED !

What these option does is , it will lock the browser until the AJAX call completes. That is not the desirable behaviour on all cases. What you could do in this type of situations is :

  1. Disable the UI/Buttons immediately after the click event – so that User cannot send same requests when one is in progress. (BlockUI is a great help for this).
  2. Show a pre-loader image  to User, until response comes. (preloaders.net is there to help you if you don’t have an animated gif image).
  3. Put all other incoming requests in a  Queue, as in most cases, we want to make ajax sequential NOT synchronous.

Here is a code example about how to en-queue AJAX calls. The ajaxQueue plugin is originally created by gnarf. First add the jQuery library  (1.5+ version needed) followed by ajaxQueue.min.js in your HTML page. Then write a common function for creating ajax requests like :

function createAJAXRequest(actionUrl, params) {
    jQuery.ajaxQueue({
        url:  actionUrl,
        data : params,
        type: "POST",
        success: function(data) {
            //do some thing with the response here
        }
    });
}
Follow

Get every new post delivered to your Inbox.