Wednesday, November 28, 2012

RequireJs, JQuery, Less, Handlebars, Bootstrap and Jasmine

Attention: This is old stuff. New build instructions here

In the last post we started implementing our photodb backend code. Today we will give some love to our client side. The objective of this first version of the GUI is to provide the code base for new features. We will use RequireJs, JQuery, LessCss, HandlebarsTwitter Bootstrap and Jasmine.

photodb is a single-page application, therefore we won't use any server-side template tool like JSP, JSF or Apache Tapestry. We will use a simple standard "index.html" page and everything else will be loaded from it. The communication between the browser and the application will be entirely via XMLHttpRequest, and the server will send only JSON strings through the wire. Twitter Bootstrap will be the base of our GUI; Handlebars will take care of the templating; LessCss will compile our CSS file; JQuery will manipulate the DOM and trigger the ajax requests; RequireJs will load all the file dependencies for us; Jasmine will test everything.

Let's run this code! Execute the following commands to start the server.

mkdir -p ~/dev/demo2
cd ~/dev/demo2
wget http://people.apache.org/~tveronezi/photodb-day-2.tar.gz
tar -zxvf photodb-day-2.tar.gz
cd photodb
make start-tomee

Once you have your server running, go to http://localhost:8080/photodb-web/. You should see something like this.



Looks dummy, but there is a lot going on behind the scenes. Check what this page is loading.


Now check the "index.html" source code.



You may be asking where did all those requests come from? It is RequireJs doing its job by loading the dependencies for us. We don't need to touch the "index.html" file every time we add a new dependency. We simply need to change the "start.js" file for new "lib" dependencies or follow the module definition used by the RequireJs library. Looking for examples? Check the "start.js" or one of the files under the "photodb/photodb-web/src/main/webapp/app/js" directory. You may also go to their API to learn more about this great framework.

As you have noticed, when the page is loaded it shows a "Welcome to photodb!" message (My version of "Hello world!" :O) ). It is a floating div with an absolute position. The CSS rule of it is managed by LessCss, which generates CSS rules from our "app.less" file. If you want to add a new rule, update this file. Check what LessCss generates from "app.less"...




Handlebars uses the ".handlebars" files to create the templates. If you want to add a new template, create a file with ".handlebars" extension under the "photodb/photodb-web/src/main/webapp/app/js/templates" directory. To load this template, you should call the "get" function of the "ApplicationTemplates" module. Check this code:


In the exemple above, we would have two files: "my-template.handlebars" and "my-template-with-params.handlebars". The second one has a "myParam" value. In your template code it would be something like "<div>{{myParam}}<div>". You need to enumerate the template files the "ApplicationTemplates" module use. All the templates should be in the "files" variable defined in "photodb/photodb-web/src/main/webapp/app/js/ApplicationTemplates.js". Don't forget to check http://handlebarsjs.com/ for more information about templates.

Handlebars and LessCss create the "Welcome to photodb!", but JQuery is the one who adds it to the DOM. To see how JQuery does that, check the "photodb/photodb-web/src/main/webapp/app/js/view/GrowlNotification.js" file.


At the line 38 we get the template; At the line 43 we add it to the DOM; At the line 44 we perform a fancy "fadeIn" transition.

Now we need to test what we have. Jasmine to the rescue! Run the following commands to start Jasmine.

cd ~/dev/demo2/photodb
make run-jasmine

Now open your browser at http://localhost:8234. You should see the unit tests results.


In order to add a new test case, you should create a js file under the "photodb/photodb-web/src/test/javascript/test" directory. Check the "photodb/photodb-web/src/test/javascript/test/I18N.js" file.


It is a RequireJs module. You need to define the dependencies of your test. In this case, our test file depends on the "util/I18N" module implemented by the "photodb/photodb-web/src/main/webapp/app/js/util/I18N.js" file. If you want to test a brand new module, you may need to change the "photodb/photodb-web/src/test/resources/start.js" bootstrap file. Specifically, you may need to change the "require.config" call and the "REQUIREMENTS" object.


This is a javascript application, so there is no need to restart the server to test our code. When you change something under the "photodb/photodb-web/src/main/webapp/app" directory, just run "make up-static" to update the server.

tveronezi@botobox:~/dev/demo2/photodb$ make up-static

If you are just running unit tests, you don't need to run "make". Just refresh the http://localhost:8234 page and you are good to go.

Thats it! Now we have the skeleton of both back-end and front-end codes. We still have a lot to do, but we can be more productive by using these awesome tools.