JavaScript Variable Scope confusion for Java Developers

Sometimes, the Java developers that are new to the JavaScript world have a confusion regarding the variable scoping in JavaScript. Let’s see an example that will illustrate this confusion, consider that we are having the following Simple JavaScript code:

<script>
var someVar = 0;

{
    var someVar = 100;
}

alert(someVar);
</script>

Some of the new JavaScript developers (from Java background) will expect that the result of the someVar will be 0, because the defined someVar variable inside the inline block will be ignored once the inline block ends.

In fact, the end result will be 100, This is because JavaScript does not have the concept of Java block scopes, JavaScript has only two scopes:
1. Global Scope.
2. Local Scope which is applied ONLY on the function(s) level (A single function or functions inside function) NOT on any other type of block(s) level (such as loops and inline blocks).

To be able to understand JavaScript local scope, Let’s introduce a new function to our original example:

{
    var someVar = 100;
    //someVar will be visible everyWhere ...
}

function someFunction() {
    var someVar = 10; 
	
    //someVar will be visible only here as 10 ...
}

alert(someVar);
someFunction();
alert(someVar);

The result will be:

100
100

someFunction defines a someVar variable and initializes it to 10, the someVar variable will be visible as long as we are in the someFunction‘s scope, when the someFunction ends, the someVar‘s function variable will not be available anymore, this is why the second alert will produce 100 which is the original value of someVar that is defined in the Global scope.

Checking the Local Storage limits across the browsers

One of the issues you may face during your daily job (if you are a web developer) is how to check the limits of the Local Storage across the different browsers. This is because there is no unified fixed storage quota for local storage across all the browsers, for example, Chrome local storage quota is 2.5 MB. In Firefox, it is 5 MB and in IE, it is 10 MB.

In order to check if the local storage reaches its maximum quota, it will not be efficient to depend on the mentioned quota sizes on every browser, other than this, I prefer to do this programmatic-ally as shown in the following JavaScript function:

function saveInLocalStorage(name, value) {
    try {
        localStorage.name = value;
        return true;
    } catch (e) {
        return false;
    }
}

Using saveInLocalStorage method, you can safely store your local storage entry, and if saveInLocalStorage method returns false, this is an indicator that the browser’s local storage maximum quota is reached, and you will need to show the user an error message asking him to free some of the saved entries in the local storage.

These are my thoughts regarding how to implement this requirement, if you have other thoughts, let me know.

Changing the moveTo attribute in “dojox/mobile/Heading” dynamically

One of the known issues of the Dojo mobile is that when the Dojo mobile heading dojox.mobile.Heading has a moveTo attribute, the value of the moveTo attribute cannot be changed once the widget is created. This means that the moveTo attribute will cause the back button to be always going to the initial view id that is binded to the attribute.

In order to resolve this issue (to support, for example, dynamic back navigation), you can destroy the widgets inside the dojox.mobile.Heading and then re-create the widgets again. Let’s see how to do this. The following code snippet shows the mobile heading element in the HTML file:

<div>
    <h1 data-dojo-type="dojox/mobile/Heading" data-dojo-attach-point="dynamicHeading">
    </h1>
    <!-- Other elements -->
</div>			

And in the "onBeforeTransitionIn" of the view, you can call the buildHeadingDynamic("someView") function which destroys the descendants of the heading and then re-create it again with the new moveTo value.

buildHeadingDynamic : function(backView) {
  var dynamicHeading = this.dynamicHeading;
  dynamicHeading.destroyDescendants();

  var heading = new dojox.mobile.Heading ({label:"Heading", fixed:"top", back:"Back", moveTo:"#" + backView});
  dynamicHeading.addChild(heading);		
}

Overriding Android back button behavior in Apache Cordova

If you are using Apache Cordova for building a native application on mobiles using HTML, CSS, and JavaScript. You may need to override the default behavior of the back button on the Android mobiles to implement your application specific back button behavior.

In order to do this, you can register an event handler on the "backbutton" event on the document object but before you do this, you need to make sure that the device is ready using the "deviceready" event as follows.

// In the initialization ...
document.addEventListener("deviceready", deviceReadyHandler, false);  


function deviceReadyHandler () {
    document.addEventListener("backbutton", backButtonHandler, false);
}


function backButtonHandler(e) {
    //Here implement the back button handler
}

What the JavaScript Unit Testing book covers?


The JavaScript Unit Testing book is a comprehensive practical guide that illustrates in details how to efficiently perform and automate JavaScript testing for web applications using the most popular JavaScript unit testing frameworks.

The book starts by explaining the concept of JavaScript unit testing and by exploring the bits of an interactive Ajax web application. Throughout the book chapters, the JavaScript part of the web application is tested using popular JavaScript unit testing frameworks (Jasmine, YUITest, QUnit, and JsTestDriver). The book illustrates how to generate JavaScript test reports, how to automate running the tests in the build and the continuous integration environments, and how to make all of the mentioned JavaScript unit testing frameworks work together in order to test the web applications in the most efficient way.

After reading this book, you will learn everything you need to know in order to make efficient JavaScript tests for the web applications. You will learn how to generate test and code coverage reports, how to automate running the JavaScript tests, and the bits of the JavaScript testing by following the book practical hands-on detailed examples.

You can order the book from: http://www.amazon.com/dp/1782160620/.

Finally, I would like to thank all of the persons that worked with me in order to produce this book (Acquisition Editor, Commissioning Editors, Technical Editors, Copy Editors, Project Coordinator, Proofreaders, Graphics Designers, Production Coordinator) and certainly the technical reviewer of this book Allan Lykke Christensen.

The Easiest way to check empty Objects in JavaScript

It is a very common requirement that is needed by many JavaScript developers to check if an object is empty in JavaScript without having to write more than one line of code. In the old days, you usually had to make the following for … loop in a common function isEmpty in order to check if the object is empty:

function isEmpty(myObject) {
    for(var key in myObject) {
        if (myObject.hasOwnProperty(key)) {
            return false;
        }
    }

    return true;
}

Thanks to ECMAScript 5, you can now just use the Object.keys() function to check the object keys, so you can check if the myObject (for example) is empty as follows:

Object.keys(myObject).length == 0

I wish that this tip can be useful for you.

java.lang.RuntimeException: Oh Snap! No server defined!

You may face this problem when you try to run the JsTestDriver (JSTD) tests. The reason behind this error is that JsTestDriver is unable to find the configuration file that declares the server directive. In order to solve this error, you need to specify the configuration file path using the --config parameter in the test running command as follows:

java -jar JsTestDriver.jar --config jsTestDriver.conf --tests all

Parsing ATOM/RSS feeds from JavaScript code using Dojo

One of the most common requirements is to parse RSS and ATOM feeds from the JavaScript code. In this post, I show you how to parse both RSS and ATOM feeds from your JavaScript code using Dojo.

Parsing ATOM feed

The next code listing is an example which loads and parses the ATOM feed from the "atom.xml" file that contains an ATOM XML.

<script type="text/javascript">
dojo.addOnLoad(function() {
	  var resultPanelID = "resultPanel";
	  
	  // Parse ATOM feed
	  dojo.xhrGet({
	     url: "atom.xml",
	     preventCache: true,
	     handleAs: "xml",
 	     load: function(xmlDoc, ioArgs){		 
	         var i = 0;
	         var output = "";
	      
	         var node = xmlDoc.getElementsByTagName("feed").item(0);
	     
	         if (node == null) {
		         console.debug("ATOM XML format is corrupted ...");		    	     
	    	     return;
	         }
	     
	         var entriesLength = node.getElementsByTagName("entry").length;
	     
			 for (i = 0; i < entriesLength; ++i) {
				var entry = node.getElementsByTagName('entry').item(i);
			 	
				var title = entry.getElementsByTagName('title').item(0).firstChild.data;
			 	var published = entry.getElementsByTagName('published').item(0).firstChild.data;			
			 	var summary = entry.getElementsByTagName('summary').item(0).firstChild.data;
			 	var link = entry.getElementsByTagName('link').item(0).getAttribute("href");
			 	
				output += '<hr><p><a target="_blank" href="' + link +'">' + title + '</a><br/>' + 
					      '<span class="smaller">' + published + '</span><br/>' + 
					      summary +
					      '</p>';
			 }
			 
		     document.getElementById(resultPanelID).innerHTML = output; 	    	
         },
         error: function(error, ioArgs){		         
	         dojo.byId(resultPanelID).innerHTML = "Error loading atom feed";
	         console.debug("failed xhrGet for ATOM URL: ", error, ioArgs);	         
    	 }
	});
});	
</script>

<div id="resultPanel"></div>

The code listing gets all the <entry> elements in the ATOM feed then gets some of the child elements of the <entry> element which are the <title>, <published>, <summary>, and <link> elements and then displays their values in the "resultPanel" DIV element.

Parsing RSS feed

The next code listing is an example which loads and parses the RSS feed from the "rss.xml" file that contains an RSS XML.

<script type="text/javascript">
dojo.addOnLoad(function() {
	  var resultPanelID = "resultPanel";
	  
	  // Parse Rss Feed
	  dojo.xhrGet({
	     url: "rss.xml",
	     preventCache: true,
	     handleAs: "xml",
	     load: function(xmlDoc, ioArgs){		 
	         var i = 0;
	         var output = "";
	      
	         var node = xmlDoc.getElementsByTagName("channel").item(0);
	     
	         if (node == null) {
		         console.debug("RSS XML format is corrupted ...");	  		    	     
	    	     return;
	         }
	     
	         var entriesLength = node.getElementsByTagName("item").length;
			 
			 for (i = 0; i < entriesLength; ++i) {
				var entry = node.getElementsByTagName('item').item(i);
			 	
				var title = entry.getElementsByTagName('title').item(0).firstChild.data;
			 	var published = entry.getElementsByTagName('pubDate').item(0).firstChild.data;			
			 	var description = entry.getElementsByTagName('description').item(0).firstChild.data;
			 	var link = entry.getElementsByTagName('link').item(0).firstChild.data;
			 	
				output += '<hr><p><a target="_blank" href="' + link +'">' + title + '</a><br/>' + 
					      '<span class="smaller">' + published + '</span><br/>' + 
					      description +
					      '</p>';
			 }
			 	
		     document.getElementById(resultPanelID).innerHTML = output; 	    	
       },
       error: function(error, ioArgs){	         
	         dojo.byId(resultPanelID).innerHTML = "Error loading Rss feed";
	         console.debug("failed xhrGet for Rss URL: ", error, ioArgs);	  	         
  	   }	  
	});
});	
</script>

<div id="resultPanel"></div>

The code listing gets all the <item> elements in the RSS feed then gets some of the child elements of the <item> element which are the <title>, <pubDate>, <description>, and <link> elements and then displays their values in the "resultPanel" DIV element.

Ajax Error Handling

In Order to return an Ajax error from the server, you need to set the response status to 500, For example if you are working with Java Servlets, your Java Servlet will return the error as follows:

public class AjaxServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		try {
			// Do whatever you want to do
		} catch (Exception exception) {
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
	                response.getWriter().write(exception.getMessage());
	                response.flushBuffer();			
		} finally {
			// Clean up ...
		}
	}
	
}

In the client side, you can get the server error message (after checking that the readyState of the XML HTTP Request (XHR) is 4, and the status of the XHR object is 500) from the responseText of the XHR object.

If you are using a JavaScript framework (the Dojo for example): In the Dojo xhrPost API, in order to get the error message, you can get it from the ioArgs parameter of the error callback as follows:

dojo.xhrPost( {
	url: 'service URL',
	content: {},
	handleAs: 'text',
	load: function(response, ioArgs) {
		// Do something
	},
	error: function(response, ioArgs) {
		alert("Failed while doing the operation: " + ioArgs.xhr.response);
	}
});

Using the ioArgs.xhr.response, you can get the full error message from the server response, you can also get the status code from the ioArgs.xhr.status.

I wish that this advice can be useful for you in order to make Ajax error handling correctly.

Could not convert JavaScript argument arg 0 [nsIDOMHTMLDivElement.appendChild]

You may face this error when you add a Dojo component to a normal DOM element using appendChild as follows:

<div id="container"></div>

<script type="text/javascript">
	dojo.addOnLoad(function(){
		var dojoInputField = new dijit.form.TextBox({id: "txtName"});
		document.getElementById("container").appendChild(dojoInputField);
	});
</script>

This error appears because you try to add the Dojo element itself not the DOM node that it wraps. In order to fix this issue, you can do this by adding the component DOM node as follows:

<div id="container"></div>

<script type="text/javascript">
	dojo.addOnLoad(function(){
		var dojoInputField = new dijit.form.TextBox({id: "txtName"});
		document.getElementById("container").appendChild(dojoInputField.domNode);
	});
</script>