Tuesday, March 8, 2011

Creating classes in Javascript

Creating Classes in JavaScript:-

We can use dojo.declare to create new classes in JavaScript. This is similar to creating classes in Java.

A simple example on creating classes using dojo.


dojo.declare(/*ClassName*/"com.org.Employee",/*SuperClassName*/null,{
            /* Declare any variables if you have */
            company:"MT",
            constructor:function(/*EmployeeName*/empName,/*ProjectName*/projectName){
                  this.employeeName=empName;
                  this.projectName=projectName;
            },
            displayProjectInfo: function(){
                  console.log(this.employeeName +" works in "+this.projectName);
            },
            moveToNewProject:function(/*New ProjectName*/projectName){
                  console.log("About to change Project Name. New Project Name is ["+projectName+"].Company Name is ["+this.company+"]");
                  this.projectName=projectName;
            }
});

//Create an object of "com.org.Employee" Class. The constructor will be invoked when the Object is created
var empObj=new com.org.Employee("Se","BP");
empObj.displayProjectInfo();
empObj.moveToNewProject("Kn");
empObj.displayProjectInfo();


In the above example, com.org.Employee is the name of the class. It does not have a super class. It has got a constructor, which will be called when an object of Employee class is created.(similar to Java). This class has a method moveToNewProject which can be invoked only on an instance of Employee class.

This makes the JavaScript code easy to read. There is no need to create any JS variable with global scope.
For example, in the above code, JS variable company’s scope is within Employee class. There is a method moveToNewProject whose scope is also within the class. Had we not used this approach, the scope of the above variable and method is GLOBAL. So anyone can invoke it. But in this case com.org.Employee object is required to access company variable and invoke moveToNewProject function. So there will not be any issues even if we have the same method in another Class.
This is really useful when we develop portlets. Developer of one portlet need not worry about the methods and variables that are created in another project. When we consider very generic JS methods like “hideMe(), showMe()”,this approach becomes very useful J
It is also possible to organize the Classes to packages (like we have in Java).

Another advantage is you can move your JavaScript code which is written in JSP to a new JS file.

What are the advantages of moving JavaScript code written in JSP to a new JS file?

  1. Performance can be improved a lot. Browsers only caches JavaScript in JS files. JavaScript code written inside JSP is not cached by the Browser. So each time you load the page, the JavaScript code in JSP has to be fetched from server and then rendered. This makes the HTML source code very heavy and consumes network bandwidth. If you save Dashboard page (from Browser File > Save As), it’s size is about 260 KB. If we had removed all the JavaScript code to a separate JS file, this size can be reduced. Obviously Browser has to download this JS file, but this file can be compressed using Shriksafe.

  1. Improves AJAX Performance. We are using IBM-JSF’s AJAX in almost all the Portlets. Unlike the normal AJAX which returns on the response, JSF’s AJAX always returns updated complete Portlet’s markup as the response. If there are lot of JavaScript code written in JSP it increases the response size.

  1. JSP code looks cleaner and easy to read.

How to use this approach in a JSF Portlet?

One concern that we have is how to get the Portlet Namespace in a JS file? We do not have access to Portlet context in a JS file. constructor method will help us. Consider the below example,

dojo.declare("com.org.RA",null,{
            constructor:function(/*PortletWindowId*/portletWindowId){
            this.portletNameSpace=portletWindowId;
      },
           
});

The above code is in a JS file. Now in my RA Portlet’s JSP, I create an instance of “com.org.RA” Class.

var riskAppObj=new com.org.RA("view<%=renderResponse.getNamespace()%>");
(/*Calls the constructor and sets the portletWindowId to portletNameSpace. All the methods in "com.org.RA" have access to portletNameSpace */

.

dojo.declare("com.org.RA",null,{

    riskProductDescriptionStatus:false,

         constructor:function(/*PortletWindowId*/portletWindowId){
           this.portletNameSpace=portletWindowId;
     },
         initiateAjaxOnLinkClick:function(source,formName){
           if(this.riskProductDescriptionStatus==true){
                 this.riskAppHideProductsSection();
           }          
           dojo.byId(this.portletNameSpace+":"+formName+":inputSicCodeSelectedSicCd").value = source.childNodes[0].childNodes[0].nodeValue;
          dojo.byId(this.portletNameSpace+":"+formName+":inputSicCodeSelectedIndustryName").value = source.childNodes[1].childNodes[0].nodeValue;     
           var button = dojo.byId(this.portletNameSpace+":"+formName+":getProductLinesButton");
           button.click();  
     }
});

No comments:

Post a Comment