Preventing backspace from navigating back in all the browsers

One of the requirements which you may face is preventing the backspace key from navigating back in the browser. This requirement can be achieved by listening on the keyboard keys in the browser and acting when the backspace key is pressed under the condition that the mouse cursor is NOT inside an input or a text area elements. Actually, you have to take care of the IE broken event model when you are implementing this feature. for example, the event.stopPropagation() method is not working in IE, adding to this, you have to get the keycode from the window.event not from the passed event object to the event handler.

I wrote the following code which works on all the common browsers (IE, Safari, Chrome, and Firefox) perfectly, and I wish it can be useful for you:

document.onkeydown = function (event) {
	
	if (!event) { /* This will happen in IE */
		event = window.event;
	}
		
	var keyCode = event.keyCode;
	
	if (keyCode == 8 &&
		((event.target || event.srcElement).tagName != "TEXTAREA") && 
		((event.target || event.srcElement).tagName != "INPUT")) { 
		
		if (navigator.userAgent.toLowerCase().indexOf("msie") == -1) {
			event.stopPropagation();
		} else {
			alert("prevented");
			event.returnValue = false;
		}
		
		return false;
	}
};	

Using this code inside a <script> tag of the HTML <body> element can do this job for you.

JsTestDriver integration with Hudson

Abstract

JsTestDriver is one of the most efficient JavaScript unit testing tools. Integrating JsTestDriver with continuous integration tools is a mandatory step for ensuring the web application quality. In this article, I will illustrate how this sort of integration can be done between JsTestDriver and Hudson.

Installing Hudson

To install Hudson on your machine, you need to download it from http://hudson-ci.org/.

Run the following command to start Hudson:

java -jar hudson-2.2.0.war

You can start launching Hudson by typing the following address in your browser:

http://localhost:8080/

You should now be redirected to the Hudson home page.

Creating Hudson Job

First of all, you need to create a new Job in Hudson. You can do this by clicking on “New Job” and entering the Job name and selecting “Build a free-style software project” as shown in the figure below:

Configuring JsTestDriver with Hudson

Click the “Configure” link of the project. In the configuration page, enter the project description. In order to run the job periodically, you need to configure the “Build Triggers”. Check the “Build periodically” option and enter the cron-like expression. To run the job every 5 mins past the hour (for example), enter the following expression 5 * * * * as shown below in the figure:

In order to execute the JsTestDriver test command, you need to configure the “Build” section. There are many ways to do so, you can either add “Execute Shell”, “Invoke Ant or Maven2 or Maven3”, or “Execute Windows Batch command”. The latter case can be used when you are working on Windows environment. For the case of this example, I use the “Execute Windows Batch command” option and specify the path of the batch file as shown in the screenshot below:

The batch file has the following content:

java -jar JsTestDriver-1.3.4.b.jar 
      --config jsTestDriver.conf 
      --tests all 
      --testOutput c:/outputFolder 
      --reset

For the matter of simplicity, I assume that the JsTestDriver server is already started and some browsers are already captured. This step is not included in this post, however, This step also can be automated if required.

Testing the integration of JsTestDriver with Hudson

In order to test the integration of JsTestDriver with Hudson, this can be done by manually or automatically (as indicated in the “Build periodically” option). To test the integration manually, click on the “Build Now” link as shown in the screenshot below:

Click the “console output” link to check the output of the results:

setting runnermode QUIET
Firefox: Reset
...
Total 3 tests (Passed: 3; Fails: 0; Errors: 0) (3.00 ms)
  Firefox 12.0 Windows: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (3.00 ms)

Notices

You may face this error while trying to run a new Job:

hudson java.io.IOException: Cannot run program "sh"

In order to fix this error, check this post:
http://www.technicaladvices.com/2012/05/04/hudson-java-io-ioexception-cannot-run-program-sh-resolution/.

More Information about JsTestDriver

Efficient JavaScript unit testing

Generating Test Reports using JsTestDriver

Running Jasmine on the top of the JsTestDriver test runner

Modern Web Architecture: The HTML5 Web Storage

Abstract

One of the most important features of HTML5 is the Web Storage feature. Using the Web Storage feature, the client state can be saved on the browser level without consuming the network bandwidth or the server memory. The Web Storage increases the scalability of the web applications on the server level and on the network level. In this article, I will show you how to work with the HTML5 Web Storage feature.

Difference between the old cookies and the HTML5 Web Storage

Unlike cookies, the HTML5 Web Storage is more scalable. The HTML5 Web Storage content is not transferred between the client and the server per every request. This means using the HTML5 Web Storage, you can store unlimited amount of information on the browser without affecting the network bandwidth. While the web cookies have a limited size, and are transferred between the server and the client per every request.

Checking if the browser is supporting the HTML5 Web Storage

HTML5 Web Storage is supported in most of the modern browsers (IE8, Firefox, Safari, Chrome, and Opera). To check if the Web Storage is supported, check if the web storage objects are defined as follows.

function isStorageSupported() {
	if (typeof(localStorage) === "undefined" || typeof(sessionStorage) === "undefined") {
		alert("Web Storage is no suppored ...");
		return false;
	}
	
	return true;
}

The HTML5 Web Storage Objects

The Web Storage is represented by two main objects the localStorage object and the sessionStorage object. The main difference between them is that the localStorage object is stored in the browser with no expiration date, however, the sessionStorage object is stored in the browser and is removed once the user session ends (i.e., its life time is the user session). It is important to know that there is another difference which is localStorage can work in local mode while the sessionStorage can work only inside a hosted page on the server.

If you try to run the sessionStorage in local mode, you will face an error. For example, the error message in Firefox is:

Operation is not supported

I created an example that illustrates how to use the HTML5 Web Storage objects. In this example, there is a text area “information” field and four buttons for (saving the “information” field value in localStorage, retrieving the stored “information” field value from localStorage, saving the “information” field value in sessionStorage, retrieving the stored “information” field value from sessionStorage).

To store any data in the localStorage object, just add the information in the (key, value) form as follows:

localStorage.key = value;

In the example to store the “information” field data in the localStorage object:

localStorage.information = document.getElementById("information").value;

To retrieve the data from the localStorage object, you can retrieve it using the key as follows:

alert(localStorage.key);

In the example to get the “information” data from the localStorage object:

alert("Data from local storage is: " + localStorage.information);
document.getElementById("information").value = localStorage.information;

Using the sessionStorage object is pretty the same as localStorage. In the example to store the “information” field data in the sessionStorage object:

sessionStorage.information = document.getElementById("information").value;

To get the “information” data from the sessionStorage object:

alert("Data from session storage is: " + sessionStorage.information);
document.getElementById("information").value = sessionStorage.information;

I attach below, the complete example code:

<!DOCTYPE html>
<HTML>
<HEAD>
	<TITLE>Welcome to the WebStorage test</TITLE>
	
	<SCRIPT type="text/javascript">
	
		function isStorageSupported() {
			if (typeof(localStorage) === "undefined" || typeof(sessionStorage) === "undefined") {
				alert("Web Storage is no suppored ...");
				return false;
			}
			
			return true;
		}
	
		function storeInformationInLocalStorage() {
			if (isStorageSupported()) {
				localStorage.information = document.getElementById("information").value;
			}
		}
		
		function readInformationFromLocalStorage() {
			if (isStorageSupported()) {
				alert("Data from local storage is: " + localStorage.information);
				document.getElementById("information").value = localStorage.information;
			}			
		}		
	
		function storeInformationInSessionStorage() {
			if (isStorageSupported()) {
				sessionStorage.information = document.getElementById("information").value;
			}
		}
		
		function readInformationFromSessionStorage() {
			if (isStorageSupported()) {
				alert("Data from session storage is: " + sessionStorage.information);
				document.getElementById("information").value = sessionStorage.information;
			}				
		}	
	
	</SCRIPT>
</HEAD>
<BODY>
	<label for="information">Enter some information in the textArea: </label><br/>
	<textarea id="information" rows="2" cols="20"></textarea>	
	<br/><br/>

	<INPUT TYPE="button" value="Store in the localStorage" onclick="javascript:storeInformationInLocalStorage()"/>
	<INPUT TYPE="button" value="Read from the localStorage" onclick="javascript:readInformationFromLocalStorage()"/>

	<br/>

	<INPUT TYPE="button" value="Store in the sessionStorage" onclick="javascript:storeInformationInSessionStorage()"/>
	<INPUT TYPE="button" value="Read from the sessionStorage" onclick="javascript:readInformationFromSessionStorage()"/>	
</BODY>
</HTML>

You can delete any of the key/value pairs in the Web Storage using the sessionStorage.removeItem(key) and the localStorage.removeItem(key). If you want to delete all of the key/value pairs, you can use the sessionStorage.clear() and localStorage.clear().

I attach the example for your reference here.

Detecting the Page Leave event in JavaScript

You may need to detect if the user is leaving your web page for displaying a warning message to the user mentioning that he may not leave the page and the form is containing data filled by him. To be able to detect this event in JavaScript, you need to deal with the "onbeforeunload" event. The following example explains the idea.

In this example, there is a simple form that contains an input text. When the user enters something in the input text, a warning message appears.

<HTML>
<HEAD>
	<TITLE>Welcome to the test Page</TITLE>
	<SCRIPT type="text/javascript">
		window.onbeforeunload = function(event) {
			
			if (hasData()) {
				return "You entered information in the page. Are you sure you want to leave now?"; // Very important
			}
		}
		
		function hasData() {
			var someThing = document.getElementById("someThing");
			
			if (someThing.value != "") {
				return true;
			}		
			
			return false;
		}
	</SCRIPT>
	
</HEAD>
<BODY>
	<H1>Welcome to the test page</H1>
	
	<FORM>
		<LABEL for="someThing">Enter something here:</LABEL>
		<INPUT type="text" id="someThing"/>
	</FORM>
</BODY>
</HTML>

The "onbeforeunload" event is called when the user tries to leave the page. As shown in the code, to display the interruption message "You entered information in the page. Are you sure you want to leave now?", you have to specify the interruption message in the return of the event. The interruption message is displayed as shown in the figure below.
IE Preview

This code works with me on IE, Firefox, and Safari. I wish that this tip can be useful for you.

Ajax file upload to a Java Servlet in HTML5

HTML5 comes with a great feature which is the ability to upload files using the XMLHttpRequest version 2.
Modern Gecko and WebKit browsers include a wonderful object FormData that allows combining both simple and complex form data (text and files) in the Ajax request object.

Let's show you how to do this.

In the example, we are having a form with two fields, one field represents a simple text field, and the other one represents a file field as shown in the code below.

<form id="form1">    

    <label for="sampleText">Please enter a text</label>

    <input id="sampleText" name="sampleText" type="text" /> <br/>

    <label for="sampleFile">Please select a file

    <input id="sampleFile" name="sampleFile" type="file" /> <br/>

    <input id="uploadBtn" type="button" value="Ajax Submit" onClick="performAjaxSubmit();"></input>

</form>

<script type="text/javascript">

    function performAjaxSubmit() {

        var sampleText = document.getElementById("sampleText").value;

        var sampleFile = document.getElementById("sampleFile").files[0];

        var formdata = new FormData();

        formdata.append("sampleText", sampleText);

        formdata.append("sampleFile", sampleFile);

        var xhr = new XMLHttpRequest();       

        xhr.open("POST","/fileUploadTester/FileUploader", true);

        xhr.send(formdata);

        xhr.onload = function(e) {

            if (this.status == 200) {

               alert(this.responseText);

            }

        };                    

    }   

</script>

As we see in the listed code, it is a normal old XHR code, but it has two differences:
1. The files property in the HTML5 input file, which gives you the ability to get the file(s) object(s).
2. The FormData object, which has one method called append, that allows adding any form data (text and file) to the object. The FormData object has another big advantage which is making the Ajax request “multipart/form-data” without writting any special code.

Now, Let's move to the Servlet code (Iam using Apache Commons File Upload for handling the multipart form request parsing).

public class FileUploader extends HttpServlet {

    protected void doPost(HttpServletRequest request,

                          HttpServletResponse response)

                          throws ServletException, IOException {

        String ajaxUpdateResult = "";

        try {

            List items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);            

            for (FileItem item : items) {

                if (item.isFormField()) {

                    ajaxUpdateResult += "Field " + item.getFieldName() + 

                    " with value: " + item.getString() + " is successfully read\n\r";

                } else {

                    String fileName = item.getName();

                    InputStream content = item.getInputStream();

                    response.setContentType("text/plain");

                    response.setCharacterEncoding("UTF-8");

                    // Do whatever with the content InputStream.

                    System.out.println(Streams.asString(content));

                    ajaxUpdateResult += "File " + fileName + " is successfully uploaded\n\r";

                }

            }

        } catch (FileUploadException e) {

            throw new ServletException("Parsing file upload failed.", e);

        }

        response.getWriter().print(ajaxUpdateResult);

    }
}

The Servlet simply parses the multipart form request and then constructs a message with the result.

Please keep in mind that this code will work with Chrome 5 and Safari 5, Firefox 4 but unfortunately will not work with IE9 because miserably IE9 does not have the FormData object, I will show later how you can achieve the same behaviour in IE9 “Iam sure you will not like it because it is much harder ;-)”.

Download the complete code from here.