TypeError: invalid ‘in’ operand obj

A weird JavaScript error that you may face when using Dojo Ajax for retrieving some JSON data from the server to render on the browser. This error happens because Dojo is unable to process the resulted JSON data which is the case when handleAs attribute is set to “text”.

In order to fix this error, set handleAs attribute to “json” instead of “text” as shown below in the example:

xhr.get({
	url: '/SomeServlet',
	handleAs: "json",
	timeout: 3000,
	load: function(data) { /* Success Handling */ },
	error: function(err) { /* Failure Handling */ }
});

This is my today’s two cent advice.

Dojo Ajaxified multi-file upload (including IE7)

One of the most common requirements of business applications is to develop Ajaxified multi-file upload. Thanks to Dojo 1.6 (and later), you can achieve this requirement, however, there are some tricks that you need to do in order to have this feature developed across all the browsers including IE. Let’s start to see the code.

The following listing shows the HTML code part of the file uploader.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
	<title>File Upload POC</title>
	
	<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js">
	</script>
</head>
<body>
	<script type="text/javascript" src="${pageContext.request.contextPath}/js/fileUploader.js"></script>
	<div id="container">
		<form method="post" id="myForm" enctype="multipart/form-data">
		    <fieldset>
		        <legend>Form Files Test</legend>
		        
		        <input id="clearBtn" type="button" value="Clear"></input><br/><br/>
				<div id="uploader"></div><br/>
				<div id="uploaderStatus"></div>
      					
		        <input id="uploadBtn" type="button" value="Submit"></input>
		    </fieldset>
		</form>
	</div>
</body>
</html>

As shown the file upload HTML, the form’s enctype needs to be set to “multipart/form-data”. The form contains “uploader” div that represents the Ajaxified file upload component and “uploaderStatus” div that represents the status panel of the selected files and finally it contains the upload button that will be used for uploading.

Now, Let’s look at the JavaScript file (fileUploader.js) which uses the dojos/form/Uploader module.

require([
        "dojo/parser", "dojox/form/Uploader", "dojo/dom", "dojo/on", "dojo/has", 
        "dojox/form/uploader/FileList", "dojox/form/uploader/plugins/IFrame", 
        "dojo/domReady!"], 
function(parser, Uploader, dom, on, has) {    
    parser.parse(document.getElementById("container"));
    
    var uploaderDIV = document.getElementById("uploader");
    
    var up = new dojox.form.Uploader({
        label: 'Select files',
        style : 'background-color: #ddddff; border: solid 1px;', //Externalize ...
        multiple: true,
        url: "/multifile-ajax-poc/UploaderServlet"
    }).placeAt(uploaderDIV);
    
    on (dom.byId("uploadBtn"), "click", function(evt) {
    	
    	//You can put some validations here ...
        up.submit();
    });  

    on (dom.byId("clearBtn"), "click", function(evt) {
        dom.byId("uploaderStatus").innerHTML = "";
        up.reset();
    });
    
    dojo.connect(up, "onComplete", function(dataArray) {
        var i = 0;
        
        dom.byId("uploaderStatus").innerHTML = "";
        
        if (!dataArray.error) {
            for (i = 0; i < dataArray.length; ++i) {
            	dom.byId("uploaderStatus").innerHTML += "File ID is: " + dataArray[i].id + " is uploaded" + "<br/>";
            }
        } else {
        	dom.byId("uploaderStatus").innerHTML = "Unable to upload the file(s)";
        }
    });    
    
    dojo.connect(up, "onChange", function(evt) {
        var i = 0;
        var content = "";
        var dataArray = up.getFileList();
        
        for (i = 0; i < dataArray.length; ++i) {
            content += dataArray[i].name + "<br/>";
        }
        
        dom.byId("uploaderStatus").innerHTML = content;
    });    
    
    up.startup();     
}
);

As shown in the code, the Dojo Ajaxified file uploader is created using dojox.form.Uploader constructor with specifying the main important attributes:
1. label.
2. multiple attribute is set to true in order to support multi-file uploading.
3. url attribute is set to the Java Servlet which handles the file uploading.

In order to get the uploader working fine, you need to call startup() method of the component.

There are important methods that are needed to be considered:
1. submit() method which allows submitting the selected files to the Java Servlet specified in the url attribute.
2. reset() method which is used to clear the selected files. Note that one of the limitations of this component is that it does not allow removing the selected files individually so the only option you have is ti clear all the files and select them again.
3. getFileList() method which is used to get the list of selected files that you can display for example in the “on change” event of the component as shown by the example.

One important thing to note is dojox/form/uploader/plugins/IFrame plugin which is essential for non-HTML5 browser in order to perform Ajaxified file uploads. Using this plugin will allow file uploading to be done through iframe for poor browsers like IE7.

Finally, let’s come to the most important trick of Ajaxified file uploading which is the server side part. The following code listing shows UploaderServlet Java Servlet.

package servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/UploaderServlet")
public class UploaderServlet extends HttpServlet {
	private static final long serialVersionUID = 1809724554045451657L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		String result = "";
		
		try {
			List<FileItem> items = upload.parseRequest(request);
			Iterator<FileItem> iter = items.iterator();
			int index = 0;

			result += "[";
			
			while (iter.hasNext()) {
			    FileItem item = iter.next();

			    if (!item.isFormField()) {
				    if (index != 0) {
				    	result += ", ";
				    }
				    
			        String feedback = processUploadedFile(item);
			        
			        //Handle IE7 ugly uploading bug
			        if (feedback == null) {
			        	continue;
			        } else {
			        	result += feedback;
			        }
			        
				    ++index;
				    
				    System.out.println(index);
			    }
			}
			
			result += "]";
			
			System.out.println(result);
			
		} catch (FileUploadException e) {
			result = "{'error':'" + e.getLocalizedMessage() + "'}";
			e.printStackTrace();
		}
		
		respondToClient(request, response, result);
	}

	private String processUploadedFile(FileItem item) {
		byte[] data = item.get();
	    String fileName = item.getName();
	    String contentType = item.getContentType();
	    
	    // Handle IE7 file uploading ugly bug ...
	    if (fileName.equals("")) {
	    	return null; //ignore
	    }
	    
		System.out.println(fileName + ", " + contentType + ", " + data.length);	    
	    
	    return "{'fileName':'" + fileName + "', " + 
	    		"'contentType':'" + contentType + "', " + 
	    		"'size':" + data.length + ", " + 
	    		"'id':" + (System.currentTimeMillis() + new Random().nextInt(100)) + "}";
	}
	
	private void respondToClient(HttpServletRequest request, HttpServletResponse response, String result) throws IOException {
        response.setContentType("text/html");
		PrintWriter writer = response.getWriter();		
		String browser = request.getHeader("User-Agent");
		
		if (browser.indexOf("MSIE 9") &gt; 0 || browser.indexOf("MSIE 8") &gt; 0 || browser.indexOf("MSIE 7") &gt; 0 ) {
			
			// For IE 9, 8, and 7 browser, render JSON object inside text area ...
			//String sampleOutput = "<textarea>[{'success':'true', 'id':'123456789'}]</textarea>";
			writer.write("<textarea>" + result + "</textarea>");
		} else {
			
			//For non-IE browsers, render normal JSON objects.
			//String sampleOutput = "[{\"success\":\"true\", \"id\":\"123456789\"}]";
			writer.write(result.replace("'", "\""));
		}		

		writer.flush();		
	}
}

Our UploaderServlet main purpose is to receive the files and if it succeeds to process the files, then it returns a simple array with the basic information of the files that are successfully uploaded.

The most important thing to notice here is for IE7 and IE8 and IE9 (NOT IE 10), a special handling is needed to be taken into consideration in the Servlet response:
1. The response data must be wrapped into textarea field.
2. Do not use double quotes (“) inside the returned JSON array, instead use single quote (‘).

In other modern browsers (which support HTML5 file uploading), you do not need to wrap the content in textarea as it does not use iframe for uploading, and you can freely use the double quotes (“) in the JSON array.

There is an ugly bug that you need to take care about in IE 7 and 8 and also 9 with the Dojo file uploader component, this bug is about having a redundant file with non-name that is always sent in the request of the multiple-file Ajax uploading. In order to handle this bug, just ignore the file which does not have a name (Ugly problem and ugly fix :-)).

This is all about my experience in this component, I wish that it can be helpful to you.

Download the code sample

Resetting dojox.mobile.ScrollableView to top

ScrollableView is a container widget which represents an entire mobile device screen, and has a touch scrolling capability. Sometimes, you may need to reset ScrollableView to the top or to any position in the mobile screen.
In order to achieve this requirement, you need to use its scrollTo() API, for example, scrolling to top can be done by setting x and y to zero as follows:

require(["dojox/mobile/parser", "dijit/registry", ..., "dojo/domReady!"], function(parser, registry) {
	//...
	var view = registry.byId("someViewID");
	view.scrollTo({x:0 ,y: 0});
	//...
});

Following this approach, you can scroll ScrollableView to any position you like by specifying a suitable x and y values.

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
}

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

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.