Bad things that come with AJAX!

This article has been moved to a new home: Disadvantages with AJAX

Thank you

Interceptors in Spring and Struts 2

This article has been moved to new home, the new link is here: Interceptors in Spring

Ways Of Writing Javascript

The way developers write javascript code has changed enormously over the years.

Here are the pros & cons of the three options in the way you can write javascript these days.
  1. Hand code everything:
    • Write all javascript code from scratch.
    • Deal directly with browser compatibility issues.
    • Very flexible (upto the point, you can decide on the name of your temporary variable ;) ).

  2. Use Generic Utilities:
    You get/download the generic javascript utilities written by others (friends, fellow developers), & with little customization use them in your applications.
    • Saves some time to get things working.
    • Browser compatibility issues may be taken care by the generic utilities
    • You should deal with the customization errors
    • Flexible, until you are faced with a bug/error which was not faced by the person who created the utility. (Could be because your application required slightly different behavior)

  3. Use Javascript Toolkits/Frameworks:
    Use the popular javascript toolkits available on internet (for free). Some of the widely used toolkits are jQuery, prototype, YUI, dojo, etc.,
    • Download & use directly in your applications. As simple as including a js file & start using all the wide range of features provided.
    • Little/No javascript experience required.
    • Provides ready to use UI widgets. (like Plug & Play)
    • Provides AJAX facilities
    • Browser compatibility is no more an issue. All toolkits takes care of these internally.
    • Flexibility is less: If you want to change anything for your taste, understanding & changing the core code is time consuming.
    • Most of these toolkits provide a way for developer to extend & create your own widgets

  4. As we can see, using javascript toolkits is the best option.

    In my next article, we'll look into each of these toolkits & compare them.

An Alternate to Auto Increment

No Auto-Increment, Generate Unique Id by own.

Auto-Increment: A column in a database table can be specified as auto-increment, which means the value for that column is auto incremented everytime a new record is inserted. It may be useful for some applications and at the same time pose some issues in some applications.
For eg., Consider a simple schema with tables Person, PersonAddress. Schema as given below
 PERSON
  ID INTEGER(5) AUTO-INCREMENT,
  NAME VARCHAR (50)
 
 PERSON_ADDRESS
  ID  INTEGER (5) AUTO-INCREMENT,
  USER_ID  INTEGER(5) REFERENCES PERSON (ID),
  ADDRESS1 VARCHAR (50),
  CITY  VARCHAR (20),
  COUNTRY  VARCHAR (20)

Consider a use-case where a user is submitting the details, & the code is storing those details into these 2 tables in database.
Storing these details is two step process, i.e., First, create a record in PERSON table, and then create a record in PERSON_ADDRESS table, the issue rises when we are to insert record to PERSON_ADDRESS, how do we get the USER_ID that we just created. Since the ID field in PERSON table is auto-incremented, so in the program we dont have the USER_ID right away. So, How do we get this newly created USER_ID to use for PERSON_ADDRESS table? One way is to make a SQL call to database & get the USER_ID for recently created record, but, this is not efficient way of doing it.
The solution I prefer is to NOT use auto-increment feature of the database. Generate the Unique id's for the ID fields by own. In this article I'll show how this can be done in a simple & generic way for the whole application.

1) Table to store recently Used ID's for each table:
CREATE TABLE SEQUENCE ( 
 TABLE_NAME STRING (40) PRIMARY KEY,
 CURRENT_VALUE INTEGER(10) DEFAULT 0
);
SEQUENCE table stores recently used ID for the TABLE_NAME. Everytime the value is fetched, CURRENT_VALUE is incremented by 1. This is done by the utility method. (Shown below)

2) A Utility Method to generate ID (In sequence)

public class DBUtil {
 
 public int generateNextId (String tableName) {
  /*
   Create connection object & statement objects
   Connection conn = .... ;
   Statement stmt = ... ;
  */
  int nextId = -1;

  String sql = "SELECT CURRENT_VALUE FROM SEQUENCE WHERE TABLE_NAME = '" + tableName + "'";

  ResultSet rs = stmt.executeQuery(sql);
  while(rs.next()) {
   int temp = rs.getInt (CURRENT_VALUE);
   nextId = temp + 1;
  }
  if(nextId == -1) return nextId;

  // INCREMENT the ID & store back in table
  String updateSql = "UPDATE FROM SEQUENCE SET CURRENT_VALUE = ? WHERE TABLE_NAME = '" + tableName + "'";
  PreparedStatement pstatement = connection.prepareStatement(updateSql);

  pstatement.setString(1, nextId);
  int status = pstatement.executeUpdate();

  return nextId;
 }
}
3)Example: Using Utility method while inserting data

 String personId = DBUtil.generateNextId ("PERSON");

 String insertPersonSQL = "INSERT INTO PERSON (ID, NAME) VALUES (?,?)";
 pstatement1 = connection.prepareStatement(insertPersonSQL);
 pstatement1.setString(1, personId);
 pstatement1.setString(2, name);

 // Now we still have person id handle, can use the same for Person Address record
 String addressId = DBUtil.generateNextId ("PERSON_ADDRESS");

 String insertAddressSQL = "INSERT INTO PERSON_ADDRESS (ID, PERSON_ID, ADDRESS, CITY) VALUES (?,?,?,?)";
 pstatement2 = connection.prepareStatement(insertPersonSQL);
 pstatement2.setString(1, addressId);
 pstatement2.setString(2, personId);
 .
 .
Here, in this example, when inserting new records, we generate ID for person table using the utility as DBUtil.generateNextId ("PERSON");, and we have handle for this new Id, which we use for further insertions when required. This wouldn't be possible with default auto-increment feature that database provides.

Hope this makes sense & it's useful. Any suggestions/query, feel free to contact me.

A Generic database schema design for UserContact details

Most of the business application that deals with a User entity, will have contact details for the user.
Contact details may be Email, Phone, Address (Home, office), Fax etc., There are various types of contacts.
Rather having to design/create the schema for user/user contacts for every application we design from scratch. It helps to have a generic model which we can just refer & use in our applications. In this article i'll show the simple & efficient schema for the same.
Source: This schema idea is taken from OfBiz framework (Database schema design of Ofbiz is considered one of the best schema design).

Basic User schema
1) USER Entity
 USER_ID  Integer(10) primary key,
 NAME  Varchar (30)
For simplicity sake, we just have 2 fields for User entity. You can add more columns when required.
2) CONTACT_MECH Entity
 CONTACT_MECH_ID  Integer(10) primary key,
 TYPE   Varchar (10),
 VALUE   Varchar (50)
'Type' field holds a constant string values like 'PHONE', 'EMAIL', 'ADDRESS', etc., 'Value' field will be used for holding values when the value is a single value like EMAIL, WEBSITE etc.,
3) USER_CONTACT_MECH
 USER_ID   Integer(10) Foreign key,
 CONTACT_MECH_ID  Integer(10) Foreign key,
 unique (USER_ID, CONTACT_MECH_ID)
This entity is the link between User & ContactMech tables.
4) ADDRESS
 CONTACT_MECH_ID  Integer(10) Foreign key,
 ADDRESS_LINE1  Varchar(40),
 ADDRESS_LINE2  Varchar(40),
 CITY   Varchar(20),
 STATE   Varchar(20),
 COUNTRY   Varchar(20),
 ZIP_CODE  Varchar(10)
If contact mech type is ADDRESS (HOME_ADDRESS, SHIPPING_ADDRESS etc.,), this table is looked up to get the details.

In this example, ADDRESS entity is kept separate, but Phone, email is kept as part of CONTACT_MECH. If necessary even phone can be kept as separate entity.

Using The Schema
In the application, when storing the details, based on the contact mech type, the values is stored in ContactMech and Address entity. For eg., If a webapplication has a form for user to fill in the details like Name, Email, phone & address (address1, city,country etc.,) fields. When data is submitted, the backend code will add an entry in User entity, then create Contact mech records for each of the type, i.e., Email, phone & address and store the values of email & phone in ContactMech table, and create a entry in Address entity to store address details. Finally create entries in UserContactMech to map between User & ContactMech records.

Sample Java (jsp) code for Storing details would be something like this:

 String name = request.getParameter("name");
 String email = request.getParameter("email");
 String phone = request.getParameter("phone");
 String address1 = request.getParameter("address1");
 String city = request.getParameter("city");
 String country = request.getParameter("country");
 String zipcode = request.getParameter("zipcode");
 
 int status = 0;
 // Insert new record for User table
 String userId = DBUtil.getNextId ("USER");

 String insertUserSQL = "INSERT INTO USER (USER_ID, NAME) VALUES (?,?)";
 
 pstatement1 = connection.prepareStatement(insertUserSQL);
 pstatement1.setString(1, userId);
 pstatement1.setString(2, name);
 
 status = pstatement.executeUpdate();

 String nextContactMechId = "";

 // Create entry in Contact Mech for Email

 nextContactMechId = DBUtil.getNextId ("CONTACT_MECH");
 String insertEmailSQL = "INSERT INTO CONTACT_MECH (CONTACT_MECH_ID, TYPE, VALUE) VALUES (?, ?, ?)";
 pstatement2 = connection.prepareStatement(insertEmailSQL);
 pstatement2.setString(1, nextContactMechId);
 pstatement2.setString(2, "EMAIL");
 pstatement2.setString(1, email);
 status = pstatement2.executeUpdate();
 
 String insertUserContactMechSQL = "INSERT INTO USER_CONTACT_MECH (USER_ID, CONTACT_MECH_ID) VALUES (?, ?)";
 pstatement2a = connection.prepareStatement(insertUserContactMechSQL);
 pstatement2a.setString(1, userId);
 pstatement2a.setString(2, nextContactMechId);
 status = pstatement2a.executeUpdate();

 // Create entry in Contact Mech for Address
 nextContactMechId = DBUtil.getNextId ("CONTACT_MECH");
 String insertAddressSQL = "INSERT INTO ADDRESS (CONTACT_MECH_ID, ADDRESS_LINE1, CITY, COUNTRY, ZIPCODE) ";
 insertAddressSQL += " VALUES (?, ?, ?, ?, ?) ";
 pstatement3 = connection.prepareStatement(insertAddressSQL);
 pstatement3.setString(1, nextContactMechId);
 pstatement3.setString(2, address1);
 pstatement3.setString(3, city);
 pstatement3.setString(4, country);
 pstatement3.setString(5, zipcode);
 status = pstatement3.executeUpdate();
 
 String insertContactMechSQL = "INSERT INTO CONTACT_MECH (CONTACT_MECH_ID, TYPE, VALUE) VALUES (?, ?)";
 pstatement3a = connection.prepareStatement(insertContactMechSQL);
 pstatement3a.setString(1, nextContactMechId);
 pstatement3a.setString(2, "HOME_ADDRESS"); 
 status = pstatement3a.executeUpdate();
 // Value field is left empty

 pstatement3b = connection.prepareStatement(insertUserContactMechSQL);
 pstatement3b.setString(1, userId);
 pstatement3b.setString(2, nextContactMechId);
 status = pstatement3b.executeUpdate();
 
 // Create entry for Phone
 /* Is similar to creating for EMAIL as above */
 
DBUtil.getNextId() is a utility method, which gets the next id to use for the specified entity name. (See my other post on How to generate unique ID by own, rather using Auto-increment.)

Similary, when retrieving the details for displaying, based on the type, the data is fetched from appropriate table.
Example Java code for retrieving is as below: (Get details for userId passed as parameter)

 String userId = request.getParameter("user_id");
 
 // Values for these will be populated from database
 String name = null;
 String email = null;
 String phone = null;
 String address1 = null;
 String city = null, country = null, zipcode = null;

 String sql = "SELECT USER_ID, NAME FROM USER WHERE USER_ID = '" + userId + "'";
 stmt=con.createStatement();
 rs=stmt.executeQuery(sql);
 
 while(rs.next()) {
  name = rs.getString("NAME"); 
 } 
 
 // Get list of contact mech id's
 sql = "SELECT CONTACT_MECH_ID FROM USER_CONTACT_MECH WHERE USER_ID = '" + userId + "'";
 stmt1 = con.createStatement();
 rs1 = stmt.executeQuery(sql);
 while (rs1.next()) {
  String contactMechId = rs1.getString ("CONTACT_MECH_ID");

  // Get ContactMech for this contactMechId
  String sql_temp = "SELECT CONTACT_MECH_ID, TYPE, VALUE FROM CONTACT_MECH WHERE CONTACT_MECH_ID = '" + contactMechId + "'";
  stmt2 = con.createStatement();
  rs2 = stmt.executeQuery(sql_temp);
  
  while (rs2.next()) {
   String type = rs2.get("TYPE");
   if("EMAIL".equalsIgnoreCase (type)) {
    email = rs2.get("VALUE");
   } else if("PHONE". equalsIgnoreCase (type) ) {
    phone = rs2.get("VALUE");
   } else if ("HOME_ADDRESS".equalsIgnoreCase (type) || "SHIPPING_ADDRESS".equalsIgnoreCase (type) ) {
    sql_temp = "SELECT ADDRESS_LINE1, CITY, COUNTRY, ZIPCODE FROM ADDRESS WHERE  CONTACT_MECH_ID = '" + contactMechId + "'";
    stmt3 = con.createStatement();
    rs3 = stmt.executeQuery(sql_temp);
    while(rs3.next()) {
     address1 = rs3.getString ("ADDRESS_LINE1");
     city = rs3.getString ("CITY");
     country = rs3.getString ("COUNTRY");
     zipcode = rs3.getString ("ZIPCODE");
     
    }
   }
  } // End of rs2 loop
 }
 
 // Display the details.

 out.println ("Name: " + name );
 out.println ("Phone: " + phone );
 out.println ("Email: " + email );
 out.println ("Address: " + address1 + ", " +  city + ", " + country + "," + zipcode);


Note: If you use any ORM like Hibernate, the storage/retrieval process will be even easier. Only the mapping between bean & database tables should be done properly.

Lazy loading data in dojo tree

In dojo tree, the data to be shown will normally be fetched from a json file. Though the data can be in any format: an array, a txt file, or a http request. Dojo tree just needs a dojo's data store object to display the data.
Anyone who has worked in dojo for a while, will know how to create a store & use it in tree.
How to load data lazily, i.e., how to load data only when a node is expanded.

In this article, I will show an simple way of loading data when a node is expanded, and data will be loaded from ajax call to server. (Using DWR to get data from server).

A new widget "TreeCustom" be created, extending from default dojo tree, and make changes to expandNode function to allow an option of loading the child items lazily. This is done by checking the state of the node being expanded & if it's UNCHECKED, then call "lazyloadItems" method, which will be overriden by the user to add new child items to that node.

Here is the extended Tree source code:

dojo.provide("dijit.TreeCustom");

dojo.require("dijit.Tree");

dojo.declare("dijit.TreeCustom", dijit.Tree, {
 
 _expandNode: function (node) {
  if(node.state == "UNCHECKED") {
   this.lazyLoadItems(node , function() {
    node.unmarkProcessing();
   });
  }
  this.inherited(arguments); 
 },
  
 lazyLoadItems: function(node, callback_function) {
  // Default implementation. User overridable function.
  callback_function();
 }
});


That's it for custom tree widget code.
The real job of lazy loading items is done in the function which overrides lazyLoadItems method. As shown below.

1) Create a tree (Custom tree)

 var myTree_Data = {
    identifier: 'name',
    label: 'name',
    items: [
    {name: 'World', type:'world',
    children:[{_reference:'India'}, {_reference:'Australia'} , {_reference:'United States'} ]},
    {name: 'India', type:'country', isStub:'true'},
    {name: 'Australia', type:'country', isStub:'true'},
    {name: 'United States', type:'country', isStub:'true'}
    ] 
 };


 var myTree_Store = null;

 dojo.addOnLoad(function(){
  myTree_Store = new dojo.data.ItemFileWriteStore({data: myTree_Data});
  createTree();
 });

 function createTree () {
  var newModel  = new dijit.tree.TreeStoreModel({
   store: myTree_Store,
   query: {type:'world'},
   childrenAttrs: ["children"]
  });

  if(dijit.byId("myTree") != null) dijit.byId("myTree").destroy();
  myTree = new dijit.TreeCustom({
   id: "myTree",
   model: newModel,
   lazyLoadItems: loadCities
  });

  dojo.byId("treecontainer").appendChild(myTree.domNode);
 }
 function loadCities(node, callback_function) {
  // Load cities for this 'node'
 }

Notice isStub property in the data for country items. Only the nodes with isStub set to true requires the data be still loaded from server.
And the data is loaded only when user wants it, i.e., when user expands that particular node.

2) Code for loadCities method (lazy load data for this node):
 function loadCities(node, callback_function) {
  // Load cities for this 'node'
  var store = this.tree.model.store;
  
  var isStub = store.getValue(node.item, "isStub");
  var country = store.getValue(node.item, "name");
  if(isStub) {
   store.setValue(node.item, "isStub", false); // Make stub as false
   
   // make DWR call to server to the cities for this country.
   CitiesHandler.getCities(country, { callback:function(datafromServer) {
    dwrCallbackMethod(datafromServer, node, callback_function); }
   });
  }

 }
 
 // Assuming the DWR method from server returns list of city names.
 function dwrCallbackMethod(data, parentNode, callback_function) {
  if(data == null) {
   callback_function();
   return;
  }

  // add the cities to the parentNode.
  var parentItem = parentNode.item;
  var store = this.tree.model.store;

  for(i=0; i < data.cities.length; i++) {
   var cityInfo = {name: data.cities[i], type:'city'};
   var cityItem = store.newItem(relationshipNode, {parent: parentItem, attribute:"children"} );
  }
  callback_function();
 }

In loadCities method, isStub property of the node is checked if its true/false. If true, a request to server is made to get the data from server. DWR callback method gets the list of city names as array. All the items in the array is added to the store, which directly reflects in the tree view.

This example assumes that user is aware of configuring DWR in server side, and how to use dwr. If not, check directwebremoting.org to download DWR & also for instructions on setting up DWR.
Any suggestions/queries, i will be happy to help. :)

Multi Select in Dojo Tree

Dojo comes with a very nice widget "Tree".
Tree is bundled in dijit, it allows programmer to represent data in a tree view.
With dojo 1.2, creating an tree is quite easy. The 3 simple steps to create a simple tree are:
1) Create a data store
2) Create a model from this store
3) Create a tree, and assign the model to pick up the data from.

Using the default tree, user can expand/collapse a node, click on the node, and with just a little change in code have the ability to drag and drop nodes. But one thing that the default tree lacks is the ability to select multiple nodes in the tree. In this article, i'll show the simple way of customizing the dojo tree to have the ability to multi select nodes.

The best way to customize an existing widget is to extend the widget & create a new widget from it.
In this article, we'll create a new widget "dijit.TreeCustom", which extends from dijit.Tree.
In the custom widget, following four methods of dijit.Tree should be overridden

1) postCreate
2) _onClick
3) focusNode
4) blurNode

Custom Tree Widget:
Here is the skeleton code for custom tree widget, extending from default dojo tree.
dojo.provide("dijit.TreeCustom");

dojo.require("dijit.Tree");
dojo.require("dojo.dnd.Manager");

dojo.declare("dijit.TreeCustom", dijit.Tree, {
});
(If you need more details on creating an widget, refer my previous article "Creating custom widgets in DOJO")

Adding new properties for Custom tree widget
	lastFocusedNode: null, // To store the currently focused node in the tree.

	allFocusedNodes: [], // array of currently focused nodes. eg., user holds cntrl key and selects multiple nodes.

	ctrlKeyPressed: false, // Flag to find out if ctrl key was pressed, when click happened.
The properties are self-explanatory.

Overriding postCreate:
When dojo engine has finished creating & parsing the TreeCustom widget on browser, postCreate method is called, where in the initilization stuffs can take place. Here is the postCreate method for TreeCustom widget, initializing the properties to proper values.
	postCreate: function(){
		this.inherited(arguments); // Call parent's postCreate
		this.onClick = this.onClickDummy;
		this.allFocusedNodes = [];
		this.lastFocusedNode = null;
	},
Notice that, default onClick is dummied out, since the new tree widget will have to send out array of selected nodes for onClick event, rather than just one selected node. So, a new customOnClick event will be added for this purpose. (See below)

Dummy onclick method (Does nothing)
	onClickDummy: function(item, node) {
	},

Overriding _onClick:
_onClick is the method called by default tree whenever user clicks on the tree node.
	_onClick: function(/*Event*/ e){
		if(e.ctrlKey) {
			this.ctrlKeyPressed = true;
		} else {
			this.ctrlKeyPressed = false;
		}
		this.inherited(arguments); 
		dojo.stopEvent(e);
	},
This method, stores the state of ctrl key pressed, and passes on to default tree's _onClick, which inturn calls focusNode method, which is also one of the method that will be overridden for custom tree widget.

Overriding focusNode:
	focusNode: function(/* _tree.Node */ node){
		this.inherited(arguments); 
		
		this.lastFocusedNode = node;
		if(this.ctrlKeyPressed) {
			// Ctrl key was pressed
		} else {
			// Ctrl key was not pressed, blur the previously selected nodes except the clicked node.
			for(i=0; i < this.allFocusedNodes.length; i++) {
				var temp = this.allFocusedNodes[i];
				if(temp != node)
					this._customBlurNode(this.allFocusedNodes[i]);
			}
			this.allFocusedNodes = [];
		}
		var isExists = false; // Flag to find out if this node already been selected
		for(i=0;i < this.allFocusedNodes.length; i++) {
			var temp = this.allFocusedNodes[i];
			if(temp.item.id == node.item.id) isExists = true;
		}
		if( ! isExists)
			this.allFocusedNodes.push(node);
		this.customOnClick (node.item, node, this.getSelectedItems() );
		this.ctrlKeyPressed = false;
	},
_customBlurNode method:
	_customBlurNode: function(node) {
		var labelNode = node.labelNode;
		dojo.removeClass(labelNode, "dijitTreeLabelFocused");
		labelNode.setAttribute("tabIndex", "-1");
		dijit.setWaiState(labelNode, "selected", false);
	},
customOnClick method: An event handler, that must be overriden by page using this widget. This method is called when user clicks on any node in the tree.
Passes node, item & array of all selected items to the method.
Here is the default implementation. (to avoid runtime exceptions)
	customOnClick: function (item, node, allSelectedItems) {
		//User overridable method.
	},
Overriding blurNode: Since a custom blur node method was used, the default blurNode is no more required. Overriding to cover the default behavior.
	blurNode: function(){
		// Not using, we've our own custom made blur method. See _customBlurNode
	},
Extra method to get all selected items
An utility method for the custom tree, which can be used to get list of all the selected items in the tree.
	// Returns array of currently selected items.
	getSelectedItems: function() {
		var selectedItems = [];
		for(i=0;i < this.allFocusedNodes.length; i++) {
			var iNode = this.allFocusedNodes[i];
			selectedItems.push(iNode.item);
		}
		return selectedItems ;
	},
Final dijit.TreeCustom JS: Put this in TreeCustom.js file under dijit folder. (DOJO_HOME/dijit).
dojo.provide("dijit.TreeCustom");

dojo.require("dijit.Tree");
dojo.require("dojo.dnd.Manager");


dojo.declare("dijit.TreeCustom", dijit.Tree, {
	
	lastFocusedNode: null, // To store the currently focused node in the tree.

	allFocusedNodes: [], // array of currently focused nodes. eg., user holds cntrl key and selects multiple nodes.

	ctrlKeyPressed: false, // Flag to find out if ctrl key was pressed, when click happened.

	postCreate: function(){
		this.inherited(arguments);
		this.onClick = this.onClickDummy;
		this.allFocusedNodes = [];
		this.lastFocusedNode = null;
	},

	focusNode: function(/* _tree.Node */ node){
		this.inherited(arguments); 
		
		this.lastFocusedNode = node;
		if(this.ctrlKeyPressed) {
			// Ctrl key was pressed
		} else {
			// Ctrl key was not pressed, blur the previously selected nodes except the clicked node.
			for(i=0;i < this.allFocusedNodes.length; i++) {
				var temp = this.allFocusedNodes[i];
				if(temp != node)
					this._customBlurNode(this.allFocusedNodes[i]);
			}
			this.allFocusedNodes = [];
		}
		var isExists = false; // Flag to find out if this node already been selected
		for(i=0;i < this.allFocusedNodes.length; i++) {
			var temp = this.allFocusedNodes[i];
			if(temp.item.id == node.item.id) isExists = true;
		}
		if( ! isExists)
			this.allFocusedNodes.push(node);
		this.customOnClick (node.item, node, this.getSelectedItems() );
		this.ctrlKeyPressed = false;
	},

	blurNode: function(){
		// Not using, we've our own custom made blur method. See _customBlurNode
	},
	
	_onBlur:function () {
	},

	_onClick: function(/*Event*/ e){
		if(e.ctrlKey) {
			this.ctrlKeyPressed = true;
		} else {
			this.ctrlKeyPressed = false;
		}
		this.inherited(arguments); 
		dojo.stopEvent(e);
	},

	_customBlurNode: function(node) {
		var labelNode = node.labelNode;
		dojo.removeClass(labelNode, "dijitTreeLabelFocused");
		labelNode.setAttribute("tabIndex", "-1");
		dijit.setWaiState(labelNode, "selected", false);
	},
	
	// Returns array of currently selected items.
	getSelectedItems: function() {
		var selectedItems = [];
		for(i=0;i < this.allFocusedNodes.length; i++) {
			var iNode = this.allFocusedNodes[i];
			selectedItems.push(iNode.item);
		}
		return selectedItems ;
	},

	onClickDummy: function(item, node) {
	},

	customOnClick: function (item, node, allSelectedItems) {
		//User overridable method.
	}

});



Example of using the Custom Tree
Put this html file under dijit/tests/tree.


	Dijit Tree Test

	

	
	

	
	

	
	

	







Let me know of any suggestion/changes for this custom tree code.

In next article, I'll show how to lazy load data in tree using DWR (Ajax).

Creating a Custom Dojo Widget

A Typical pagination widget should have links to navigate between pages. Generally First, Next, Previous & Last are the four links that will be present in a pagination widget.

Custom Widget - First Step
Create a Javascript file, named Paginator.js (For simplicity sake, keep this file under dijit folder)
Skeleton code for Paginator.js
dojo.provide("dijit.Paginator");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");

dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{
});


The above code creates a widget by name dijit.Paginator, and tells dojo that a widget by this name is now available.

Adding functionality to the widget.
Creating the required HTML snippet for the widget.


This is the HTML code that the widget will use to display on the browser.
There are two ways of letting dojo engine know about using this HTML code for rendering on browser. Using templateString property, or templatePath property of the widget.
For this example, templateString is used to provide the HTML code for the widget.
dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{
	templateString: '
' + '
' + ' ' + ' |<' + '   ' + ' ' + ' <<' + '   ' + '  ' + ' ' + ' >> ' + '  ' + ' ' + ' >|' + ' ' + '
' + '
' });

The html required by the widget is assigned to a property templateString, this property is the one used by dojo when rendering/parsing the widget on the browser. (templatePath can also be used, by providing path for HTML file) dojoAttachEvent is the way of attaching an event handler for any node (HTML node/tag).
Adding the required properties for the widget.
	currentPage: 1,
	totalPages: 0,

These are two properties that will be initiated by the pages using the widget.
Adding a method for refreshing the widget according to the current state of the widget. Meaning, the first/prev links should be hidden when the page shown is the first page, and similar case with last/next links. Here is the code for refresh method.
	refresh: function () {
		if(this.currentPage <= 0) this.currentPage =1;
		this.pageNumInfoNode.innerHTML = this.currentPage + " of " + this.totalPages;

		if(this.currentPage == 1) {
			this.prevNode.style.display = "none";
			this.firstNode.style.display = "none";
		} else {
			this.prevNode.style.display = "";
			this.firstNode.style.display = "";
		}

		if(this.currentPage >= this.totalPages) {
			this.nextNode.style.display = "none";
			this.lastNode.style.display = "none";
		} else {
			this.nextNode.style.display = "";
			this.lastNode.style.display = "";
		}
		
	}

pageNumInfoNode points to the node in the widget, which displays the current page number. It shows the information, something like "1 of 5", "3 of 10" etc.,
Whenever a dojo widget has been rendered & created on browser, dojo engine calls the postCreate method of the widget to perform any operations upon creation of the widget. This method can be generally used for initializing state of the widget. Use this method for refreshing/initializing the widget for the initial view.
	postCreate: function(){
		this.refresh();
		this.inherited(arguments);
	}

this.inherited(arguments) calls the super/parent widgets postCreate up the hierarchy. (Similar to super in java).
Add event handlers for each of the pagination links.
	firstClick: function () {
                if(this.currentPage <= 1) return;
		this.currentPage = 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},
	prevClick : function() {
                if(this.currentPage <= 1) return;
		this.currentPage = this.currentPage - 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},
	nextClick : function() {
                if(this.currentPage >= this.totalPages) return;
		this.currentPage = this.currentPage + 1;
		this.refresh();
		this.onPageChange(this.currentPage);
	},	
	lastClick: function () {
                if(this.currentPage >= this.totalPages) return;
		this.currentPage = this.totalPages;
		this.refresh();
		this.onPageChange(this.currentPage);
	},

onPageChange will be the way of the widget to communicate with outer world. Whenever user does any activity on the widget, like changing the page, onPageChange event will be triggered and it passes the current page number as the parameter. Then the page can take required actions to show the data appropriate for that page number.
Anyway, there should be a default implementation for this onPageChange method in the widget.
So, here is the default implementation of onPageChange, which should and must be overridden by page using the widget to get any meaningful functionality.
	onPageChange: function (currPage) {
		// User should override this method to communicate with the widget & perform required actions for particular page.

	},

Putting it all together, Here is the complete code for Paginator.js
dojo.provide("dijit.Paginator");

dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");

dojo.declare("dijit.Paginator",
	[dijit.layout.ContentPane, dijit._Templated], 
{

	
	templateString: '
' + '
' + ' ' + ' First ' + '   ' + ' ' + ' Prev ' + '   ' + '  ' + ' ' + ' Next ' + '  ' + ' ' + ' Last ' + ' ' + '
' + '
', currentPage: 1, totalPages: 0, firstClick: function () { this.currentPage = 1; this.refresh(); this.onPageChange(this.currentPage); }, prevClick : function() { this.currentPage = this.currentPage - 1; this.refresh(); this.onPageChange(this.currentPage); }, nextClick : function() { this.currentPage = this.currentPage + 1; this.refresh(); this.onPageChange(this.currentPage); }, lastClick: function () { this.currentPage = this.totalPages; this.refresh(); this.onPageChange(this.currentPage); }, onPageChange: function (currPage) { // User function called. passes the currentPage }, refresh: function () { if(this.currentPage <= 0) this.currentPage =1; this.pageNumInfoNode.innerHTML = this.currentPage + " of " + this.totalPages; if(this.currentPage == 1) { this.prevNode.style.display = "none"; this.firstNode.style.display = "none"; } else { this.prevNode.style.display = ""; this.firstNode.style.display = ""; } if(this.currentPage >= this.totalPages) { this.nextNode.style.display = "none"; this.lastNode.style.display = "none"; } else { this.nextNode.style.display = ""; this.lastNode.style.display = ""; } }, postCreate: function(){ this.refresh(); this.inherited(arguments); } });
Example of using the newly created widget.




In this example, whenever the user clicks on any of the links on the widget, notification is sent to myFunction which notifys the page change.