Imediava's Blog

Just another WordPress.com site

Tag Archives: javascript

Tutorial on ember states and routing

Single page apps, states

In the quest for improving web applications many developers are starting to consider single-page apps as a way to offer a better user experience, more similar to native applications, without the nuances of having to wait after every server request [see single apps challenges and benefits].

Even if we call them single-page apps, they are composed of different steps that would correspond to different pages in a normal app. If we imagine a blog, a list of all the posts can be a step and a post with all its comments another.

In this post we will see ember’s approach to define apps based on steps through the construction of an extremely simple single page app.

Ember’s approach

States

The different steps of an application, are called  states  in ember and are organized in layers. At any moment an application can only be in one of its leaf states. Being in a state implies being in all its direct ancestors. If we take the following example:

Hierarchy of states

An application can only be in states 1.a, 1.b and 2. However if an application is in state 1.a, it means it is also in state 1 and 0 because they are both direct ancestors of 1.a.

Ember basics

We also need to understand that ember apps are based on three main building blocks:

  • Templates:  Strings that contain variables that are replaced by values when they are evaluated. Ember uses handlebars template engine.
  • Controllers: Objects used to manipulate data in the application
  • Views: Elements responsible for: “combining templates with data to render as sections of a page’s DOM, and … responding to user-initiated events.”  Basically a view has an associated template and uses a controller to access the data it needs to render it.

I’ll call the combination of this three elements a section.

Elements that form a section

Ember tools to build multi-state apps

Apart from the main building blocks, ember provides two tools that are extremely useful when building an app based on states: the {{outlet}} tag and the Router.

  • The {{outlet}} tag allows to build a hierarchy of sections by providing a mean for a container template to include a child template
  • The Router allows to specify all the possible states of an app and map them to urls.

Joining them together we can create a tree of states, where every state has an associated section. This makes possible the construction of really complex apps where the sates are decoupled from each other while the acceptable combination of states is well defined.

Hierarchy of states associated to sections

Our simple application

Once we know the concepts behind the approach we’ll show an example of how it works with our basic application. Our example will only have a master section with a child. We will build the master section and then we will see how we can add a child section with its corresponding state. Adding subsequent children will only mean repeating the same steps adapting them to our new states.

The master view

For our master section of the application will use the following handlebar template:


<script type="text/x-handlebars" data-template-name="master">
This is the master.
  {{outlet}}
</script>

The {{outlet}} helper is the container for the child template, it will server to render the main section inside the master.

To define the controller and the view for the master section we need to pass them as the ApplicationController and ApplicationView parameters when we build Ember.Application. The need to be called like that to conform with ember’s convention:


App = Ember.Application.create({

  ApplicationController : Ember.Controller.extend({
  }),

  ApplicationView : Ember.View.extend({
    templateName: "master" // We use the master template for this view
  }),

});

To add the states we will pass a Router property of type Ember.Router to our application. The router will be in charge of representing the different application’s states and matching them to urls (see Ember.Router for a deeper explanation on how this type works). It needs a root parameter that represents the app’s root state and as we’ve said before is associated to ApplicationView and ApplicationController.


App = Ember.Application.create({

  //......

  Router : Ember.Router.extend({
    // Every rooter must have a root state
    // whose controller and view are ApplicationController and ApplicationView
    root: Ember.Route.extend({
	// here will have all the states accessible by the user
    })
  })
});

The main state

With this simple code we already have our master section working. Now we need a child section that will render inside the master.

Again we need to define a template for it:


<script type="text/x-handlebars" data-template-name="main">
My main with its context:  {{ variable }}.
</script>

We also create the controller and the view for the state. We will call them, according to ember’s convention, with the state’s name with a capital letter.


App = Ember.Application.create({

  //......

  MainView : Ember.View.extend({
    templateName: "main"
  }),

  MainController : Ember.Controller.extend({
    variable: "my main",
  }),

  //......

});

We still need to add the main section’s state to the rooter. Since the main is inside the master we will place our main state inside the root state.


  root: Ember.Route.extend({
     // here will have all the states accessible by the user
     main: Ember.Route.extend({
     }),
  })

Old single page apps didn’t allow to bookmark a state or go back to a previous state by clicking on the back button because states where not represented by an url. However this is not a problem with ember that allows assigning a mapping between an state and a url.

To make our main state available at ‘#/main’ we add the following to the state:


  root: Ember.Route.extend({
     // here will have all the states accessible by the user
     main: Ember.Route.extend({
        //main => /main/ - will be accessible at #/main/
        route: '/main/',
     })
  })

Finally we want to tell ember that when we are in the main state, the main view should be rendered inside the master. For that we need to add a callback with the connectOutlets property passed to the state. This callback must contain the following method call:


router.get('applicationController').connectOutlet('main')

Since we have followed ember’s convention this method internally creates the instance of MainView, assigns it to the MainController singleton and then passes it to the ‘applicationController’. The framework knows that it has to take MainView and MainController because they follow the naming convention for the ‘main’ state.


  root: Ember.Route.extend({
     // here will have all the states accessible by the user
     main: Ember.Route.extend({
        route: '/main/',
	connectOutlets: function(router, event) {
          router.get('applicationController').connectOutlet('main');
        }
     }),

   //........

   });

With this we finally have our final app based on ember states, with our main page accessible at http://whatevertherootis/#/main:

App = Ember.Application.create({

  ApplicationController : Ember.Controller.extend({
  }),

  ApplicationView : Ember.View.extend({
    templateName: "master"
  }),

  MainView : Ember.View.extend({
    templateName: "main"
  }),

  MainController : Ember.Controller.extend({
    variable: "my main",
  }),

  Router : Ember.Router.extend({
    root: Ember.Route.extend({
      main: Ember.Route.extend({
        route: '/main/',
        connectOutlets: function(router, event) {
          router.get('applicationController').connectOutlet('main');
        }
      })
    })
  })
});

The source code for the full application with and index.html page can be downloaded from here.In later posts I will show how to add another state and link it from our main, how to redirect the root of our app to the main state and how to add nested states to our app.

Introduction to Require.js

In a programming language like Java you normally don’t need to pay attention to how dependencies are loaded. All you need to do is define your dependencies with a fully qualified name (e.g. import java.utils.Collection) and the loading is done transparently by the JVM.

However when you move to JavaScript the landscape changes and you realize that loading dependencies is not a simple process. JavaScript doesn’t initially define a smart module system, what means that the programmer needs to take care of it by himself, making modularisation difficult.

Let’s have a look at an example of a project and the dependencies that are defined within its modules. The dependencies are represented as arrows from the client module on the left to the required module on the right:

module1 → module 2 → module3, module4

With this system in JavaScript, every time you need to use the module1, all the other modules need to be imported in the right order in the following manner:

<script type="text/javascript" src="module4”></script
<script type="text/javascript" src="module3”></script>
<script type="text/javascript" src="module2"></script>
<script type="text/javascript" src="module1"></script>

Whereas in Java a similar system could be defined like this:

//Module 1
import module2; 

class Module1 { .. }

//Module 2
import module3;
import module4;

class Module2 { .. }

// And a client module would only need to import module1
import module1;

class Client { .. }

Disadvantages of Javascript

We can see that JavaScript’s approach is less adequate:

  • It means that every time we want to use module1 we have to first have a look at which are its dependencies recursively.
  • What makes it even worst those dependencies need to be defined every time the module is used.
  • If the dependencies change, they need to be redefined in every module that imports module1. If someone is using module1 and forgets or is not informed of the changes, its code would stop working without any previous notice regardless of if there have been any changes in module1’s public API.

CommonJS and Require.js

The good news are that there are ways on JavaScript of defining hierarchies of dependencies in a way pretty similar to that of languages like Java.

In platforms like Node and Rhino, you can use the “require” function that allows to load dependencies of modules that have been defined using the CommonJS specification. However this loading mechanism is not specially suited for JavaScript on the browser where loading synchronously is not the more appropriate mechanism. Luckily Require.js exists, a library that allows defining dependencies between modules in a way that is appropriate for the browser.

Applying Require.js to our initial example

To allow a module to be imported with requirejs you need to wrap your javascript in a module format defined by the library. Fortunately the format is really simple. Let’s start applying it to the leafs of our hierarchy, the modules 3 and 4.

define(function(){

     // Code defining the module (private code)
     ....

     // It returns the properties that form the module's public API
     return {
         myMethod1: function(){ .. } 
         myProp1: value
     };
});

All we need to do is wrap our code in a call to define and pass it a callback function. The callback function must return the methods and properties of the module that you want to make available to its clients , it’s public API . This is done in a way that follows the Module Pattern a pattern that has as purpose to preserve the encapsulation of modules. Despite of wether or not you’re interested in using requirejs you should definitely use the Module Pattern when programming in Javascript to protect the clients of your module and to avoid polluting the namespace.

When you’re defining modules that have dependencies on other modules like module1 and module2, the definition doesn’t change that much. The only modification requires to provide as the first argument to the define function an array with the dependencies of the modules (the imports) and as many parameters as imported modules to the callback function. Taking as an example module2 the definition would be the following.

define([“module3”, “module4”], function(module3, module4){

   // Any code 
   ...

   // Accessing the methods of the imported modules is done
   // through the parameters of the callback function

   module3.myMethod1();
});

Loading any module would follow the same pattern keeping the benefit of only having to define direct dependencies.

Finally defining the starting point

Any Javascript application that uses requirejs needs to have a starting point. It is something similar to how an application in Java has to have a class with a main method. This starting point uses the require function to define its dependencies. This function works just like define by passing an array of dependencies and a callback function with the code that will run when the dependencies are loaded.

require([“module1”], function(module1){
   // Code to run as a main method
   ....
});

Best Javascript Tools

I remember when I started creating webpages coming from a background in Java that I looked at Javascript and I really didn’t get it. I guess it didn’t help the fact that the critics about the language were spread all over the internet. It gave me the impression of a really old language, the legacy of a list of wrong design decisions. Overall I felt like it was something I had to deal with but I should avoid, trying to do as much as possible on the server.

However, now after I’ve had some experience with it I realize that it was just a prejudiced impression. It’s a fact that Javascript is an old language and there are some things that have been done wrong over its history.

Nonetheless, Javascript is living a renaissance. There is a really active community backing it and many innovations going on. Many of the mistakes in its design have been addressed and overall it is just a matter of having the expertise to be able to avoid them. As with any programming language, it is a matter of using it well. The great news with Javascript are that thanks to its community there are many available tools that make this task of “programming well” easier.

This is the list of my favourite Javascript libraries for this task:

  • Underscore – A really interesting library of useful functions to operate with collections, arrays, objects or other functions.
  • Coffeescript – A language that takes influences from ruby and provides among other things list comprehensions, a smarter way of dealing with variables without polluting the namespace and many other useful tricks that can make Javascript development simple. Coffeescript compiles to a well formated Javascript, thus allowing for easy debugging.
  • Require.js – A library for defining dependencies between Javascript files, Require.js facilitates a better modularization of code. It also allows smart resource loading and resource compression, making page loading faster. (See an introduction to the library here)
  • Backbone – An MVC-like framework for defining complex one page web applications.
  • Mustache: A logic-less template engine that is available for many languages including Javascript. Its markup is powerful while keeping developers from cluttering templates with complexity. It can be replaced by handlebars whose templates are fully compatible with Mustache but provides even more powerful features. Both can be plugged into Backbone’s template-agnostic views system.

  • My intention is that this article serves as an introduction for a list of posts where I delve into each of this tools features, advantages/shortcomings and alternatives.

Selecting a row from a table with JQuery

In this post, I am going to describe how to set up an html table so that the user can select one and only one row from that table. The selection only means that the row selected is going to be highlighted.

First we need to establish with CSS the colour the highlighted row is going to have. In this case we chose red:

tbody tr.hilite td {
    background: none repeat scroll 0 0 red;
}

The last snippet means that all table cells (td) whose parent is a row that belongs to the class hilite will have a red background colour.

Now using JQuery we link the click event for every table row in the page to a function that removes the class hilite for every row first, this way we make sure that there is only going to be one cell highlighted at the same time. Then we add the class to the row that has actually been click.

$(document).ready(function() {
   $('tr').click(function () {
      $(this).siblings('tr').removeClass('hilite');
      $(this).toggleClass('hilite');
   });
}); 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: