“JavaScript Mobile Application Development” book is published

I’m pleased to announce the release of my new Book “JavaScript Mobile Application Development” using Apache Cordova:
http://www.amazon.com/JavaScript-Native-Mobile-Apps-Development/dp/1783554177

Book Cover

What this book is about

Mobile development is one of the hottest trends and a staple in today’s software industry. Almost every popular website today has its own equivalent mobile application version to allow its current users to access its functions from a mobile device. However, developing mobile applications requires a lot of effort and a wide skill set from mobile developers. Whether you are developing a mobile app for an iPad or on a Windows Phone, there is a requirement to learn the specific languages and technologies for that device. This is where the glory of Apache Cordova shines. As a set of device APIs for building cross-platform mobile applications using HTML, CSS, and JavaScript, the apps developed using JavaScript APIs are easily portable to other device platforms, as well as being consistent across devices and built on web standards. As a result of this, you will find that your development costs and efforts are sharply reduced, whilst increasing the readability and maintainability of your code, as you make use of only one popular programming language: JavaScript.

This is the learning resource to use when you want to efficiently develop your own native mobile applications using Apache Cordorva as the platform that uses HTML, CSS, and JavaScript. In order to develop neat-looking mobile applications, this book also utilizes jQuery mobile. jQuery mobile is one of the best mobile web application frameworks that allows web developers to develop web applications that are mobile friendly.

We start by developing a simple sound recorder mobile app. We then configure this app to work on Android, Windows, and iOS. Then you will learn how to use the different APIs provided by Apache Cordova and how to develop your Apache Cordova custom plugins.

You will then learn how to develop, run, and automate tests using Jasmine. At the end, you develop a “Mega App” where you will learn in details how to design, develop, and deploy a real cross-platform Apache Cordova application that works in Android, iOS, and Windows Phone 8.

After finishing this book, you should be able to develop your mobile application on the different mobile platforms, using only JavaScript, without having to learn the native programming languages of every mobile platform.

What this book covers

Chapter 1, An Introduction to Apache Cordova, teaches what Apache Cordova is and the differences between mobile web, mobile hybrid, and mobile native applications. You will also know why we should use Apache Cordova, along with the current Apache Cordova architecture, and finally, the chapter offers an overview of Apache Cordova APIs.

Chapter 2, Developing Your First Cordova Application, explains how to develop, build, and deploy your first Sound Recorder mobile application on the Android platform.

Chapter 3, Apache Cordova Development Tools, explains how to configure your Android, iOS, and Windows Phone development environments. You will also learn how to support and run your Sound Recorder mobile application on both iOS and Windows Phone 8 platforms.

Chapter 4, Cordova API in Action, dives deep into Apache Cordova API, and you will see it in action. You will learn how to work with the Cordova accelerometer, camera, compass, connection, contacts, device, Geolocation, globalization, and InAppBrowser API by exploring the code of the Cordova Exhibition app. The Cordova Exhibition app is designed and developed to show complete usage examples of the Apache Cordova core plugins. The Cordova Exhibition app supports Android, iOS, and Windows Phone 8.

Chapter 5, Diving Deeper into the Cordova API, continues to dive into Apache Cordova API by exploring the remaining main features of the Cordova Exhibition app. You will learn how to work with Cordova media, file, capture, notification, and storage API. You will also learn how to utilize the Apache Cordova events in your Cordova mobile app.

Chapter 6, Developing Custom Cordova Plugins, dives deep into Apache Cordova and lets you create your own custom Apache Cordova plugin on the three most popular mobile platforms: Android, which uses the Java programming language, iOS, which uses the Objective-C programming language, and Windows Phone 8, which uses the C# programming language.

Chapter 7, Unit Testing Cordova Apps Logic, explains how to develop JavaScript unit tests for your Cordova app logic. You will learn the basics of the Jasmine JavaScript unit testing framework and understand how to use Jasmine in order to test both the synchronous and asynchronous JavaScript code. You will learn how to utilize Karma as a powerful JavaScript test runner in order to automate the running of your developed Jasmine tests. You will also learn how to generate the test and code coverage reports from your developed tests. Finally, you will learn how to fully automate your JavaScript tests by integrating your developed tests with Continuous Integration tools.

Chapter 8, Applying it All – the Mega Application, explores how to design and develop a complete app (Mega App) using Apache Cordova and jQuery Mobile API. Mega App is a memo utility that allows users to create, save, and view audible and visual memos on the three most popular mobile platforms (Android, iOS, and Windows Phone 8). In order to create this utility, Mega App uses jQuery Mobile to build the user interface and Apache Cordova to access the device information, camera, audio (microphone and speaker), and filesystem. In this chapter, you will learn how to create a portable app that respects the differences between Android, iOS, and Windows Phone 8.

Where to buy this book

You can buy JavaScript Mobile Application Development Book from:

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

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.

Developing Weather Application using Dojo Mobile

Abstract

Dojo mobile (dojox/mobile) is one of the most powerful JavaScript frameworks that enable you to build cross mobiles web applications. It does not only contain mobile components but also it mimics the interface of the different mobile devices. Adding to this it responds to the mobile orientations. In this article, I will illustrate how to use the framework for building a weather application on the iPhone mobile.

Application Story

The application story is simple. In the weather mobile application, the user can get the current weather forecasting of a specific location. The user can do this by selecting one city from a list of available cities in the drop down and then click the “Get Information” button to get the weather information as shown in the screenshot below.

Building the weather application

In order to create the weather forecasting page, we need to know the main parts of the Dojo mobile page:

  • The Doc Type and META tags.
  • The mobile script and style includes.
  • The application pages.

The Doc Type and META Tags

The Doc type that is recommended to be used is the HTML5 doctype as shown below:

<!DOCTYPE html>

For the META tags, it is important to use the "viewport" META tag to setup cross-device layout as shown below:

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/>

The other important META tag is an iPhone specific one which is the “apple-mobile-web-app-capable”. It is recommend to be set to “yes” to make the web application runs in full-screen mode as shown below:

<meta name="apple-mobile-web-app-capable" content="yes"/>

The script and style includes

Now, we come to the script and style includes. I’m using Dojo 1.7.1 for this application; in order to include the script and the style files; this can be done as shown below:

<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojox/mobile/themes/iphone/iphone.css" rel="stylesheet"></link>

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js" data-dojo-config="async: true"></script>

I only included the iPhone CSS file, and the dojo.js file which is loaded asynchronously for including only the resources we need to keep the application optimized.

After including the script and the style, we need to use the require statements for including the Dojo modules. I use the new Asynchronous Modules (AMD) convention for making asynchronous loading of the modules as shown below:

require(["dojox/mobile/parser", "dojo/_base/xhr", "dojox/mobile", "dojox/mobile/deviceTheme",
         "dojox/mobile/TextBox", "dojox/mobile/Button", "dojox/mobile/compat", 
	 "dijit/form/DataList", "dojox/mobile/ComboBox",
         "dojo/domReady!"], function(parser) {
			
		//...			
		parser.parse();
	});

The following modules are loaded:

  • The Dojo mobile parser "dojox/mobile/parser" for converting the HTML elements to Dojo mobile components.
  • The Dojo XHR module "dojo/_base/xhr" for allowing performing Ajax requests.
  • The Dojo mobile device theme "dojox/mobile/deviceTheme", for allowing detecting the mobile type and loading the proper theme correctly.
  • "dojox/mobile/TextBox", "dojox/mobile/Button", "dijit/form/DataList", "dojox/mobile/ComboBox", for loading the mentioned components.
  • The "dojox/mobile/compat" module is required for allowing having cross mobiles CSS3 animations.
  • "dojo/domReady!" module is a replacement for the old dojo.ready API. The exclamation mark is required to tell Dojo not to execute the callback until the DOM is ready.

Finally in the callback, I’m using only the first parameter which is the parser object. The parser.parse statement is called for allowing the Dojo mobile parser to convert the HTML elements to Dojo mobile components.

The Application Pages

In our weather application, we have mainly two pages; the weather forecasting page and the about page. In order to make the pages scroll to the left and the right while navigation, we need to use the Dojo mobile views. The Dojo mobile views are normal HTML elements with the dojo type "dojox.mobile.View". To define the two views, we can do this as shown below:

<div id="weather" dojoType="dojox.mobile.View" selected="true">
	...
</div>
			
<div id="about" dojoType="dojox.mobile.View">
	...
</div>		

The main view should be marked as selected by setting the selected attribute to "true".

In the weather forecasting page, there are three main elements:

  • Heading element.
  • Combo Box of the available cities.
  • The “Get Information” button.

In order to create the heading element, you can mark an HTML element h1 with the “dojox.mobile.Heading” dojo type as follows:

<h1 dojoType="dojox.mobile.Heading">Weather
	<div dojoType="dojox.mobile.ToolBarButton" moveTo="about">About</div>		
</h1>

I included a toolbar button for moving to the other view. The moveTo attribute can have the id of the view to switch to, in our case it is the about view id.

In order to create the combo box element, we need to use two tags, one for the data which is the dijit.form.DataList, and the other for the widget itself which is the dojox.mobile.ComboBox as follows:

<select data-dojo-type="dijit.form.DataList" data-dojo-props="id:'locationList'" >
  <option selected>Cairo, Egypt</option>
  <option>Stockholm, Sweden</option>	
  <option>Vienna, Austria</option>
  <option>Madrid, Spain</option>	
  <option>Paris, France</option>
  <option>New York, USA</option>
  <option>Lima, Peru</option>
</select>

<input id="location" class="ninety" type="text" data-dojo-type="dojox.mobile.ComboBox" data-dojo-props="list:'locationList'" />

The “location” combo box is referring to the “locationList” using the list attribute.

The “Get Information” button calls the getWeatherInformation function to get the weather information as follows:

<button class="mblBlueButton full" dojoType="dojox.mobile.Button" onClick="getWeatherInformation();">Get Information</button>

The getWeatherInformation JavaScript function is calling a proxy Java Servlet that interacts with the Yahoo weather service API using dojo xhrGet.

function getWeatherInformation() {
	var selectedCode = cityMap[dijit.byId("location").value];
	
	dojo.xhrGet({
		url: "/mobileSamples/weatherProxyServlet?w=" + selectedCode,
		handleAs: "text",
		load: function(data) {
			document.getElementById("weatherResult").innerHTML = data;
		}
	});
}

The location value is read from the “location” combo box and the code of the location is retrieved from a custom JavaScript Map that I created for mapping the WOEID (Where on earth identification) to the locations.

When the HTML response is returned from the server, it is displayed directly in the "weatherResult" span.

Finally in the weather forecasting view, I embed the combo box and the button in the "dojox.mobile.RoundRect" div as follows:

<div dojoType="dojox.mobile.RoundRect" shadow="true">
	<label for="txtLocation">Select location</label> <br/>
	
	<select data-dojo-type="dijit.form.DataList" data-dojo-props="id:'locationList'" >
	  <option selected>Cairo, Egypt</option>
	  <option>Stockholm, Sweden</option>	
	  <option>Vienna, Austria</option>
	  <option>Madrid, Spain</option>	
	  <option>Paris, France</option>
	  <option>New York, USA</option>
	  <option>Lima, Peru</option>
	</select>
	
	<input id="location" class="ninety" type="text" data-dojo-type="dojox.mobile.ComboBox" data-dojo-props="list:'locationList'" /><br/><br/>
	
	<button class="mblBlueButton full" dojoType="dojox.mobile.Button" onClick="getWeatherInformation();">Get Information</button><br/><br/>
	
	<span id="weatherResult"/>
</div>

The other “about” view element is a simple one that contains description for the sample as follows:

<div id="about" dojoType="dojox.mobile.View">
	<h1 dojoType="dojox.mobile.Heading" back="back" moveTo="weather">About</h1>
	<div dojoType="dojox.mobile.RoundRect">This sample is developed by TechnicalAdvices.COM. It is powered by Dojo Mobile.</div>
</div>

It contains a heading that includes a back button using the back attribute. The back attribute should be set to id of the view element that the application navigates to when the back button is clicked.

The next code listing shows the complete code of the weather forecasting page:

<!DOCTYPE html>
<html>

<head>
	<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/>
	<meta name="apple-mobile-web-app-capable" content="yes"/>
	<title>Welcome to the weather application</title> 
	
	<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojox/mobile/themes/iphone/iphone.css" rel="stylesheet"></link>
	<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.1/dojo/dojo.js" data-dojo-config="async: true"></script>
	
	<script type="text/javascript">
		var cityMap = {};
		
		require(["dojox/mobile/parser", "dojo/_base/xhr", "dojox/mobile", "dojox/mobile/deviceTheme",
		         "dojox/mobile/TextBox", "dojox/mobile/Button", "dojox/mobile/compat", 
		         "dijit/form/DataList", "dojox/mobile/ComboBox",
		         "dojo/domReady!"], function(parser) {
			
					// initialize WOIDs ...
					cityMap["Cairo, Egypt"] = "1521894";
					cityMap["Stockholm, Sweden"] = "906057";
					cityMap["Vienna, Austria"] = "551801"
					cityMap["Madrid, Spain"] = "766273";
					cityMap["Paris, France"] = "615702";
					cityMap["New York, USA"] = "2459115";
					cityMap["Lima, Peru"] = "418440";
			
					parser.parse();
				});


		function getWeatherInformation() {
			var selectedCode = cityMap[dijit.byId("location").value];
			
			dojo.xhrGet({
			    url: "/mobileSamples/weatherProxyServlet?w=" + selectedCode,
			    handleAs: "text",
			    load: function(data) {
			    	document.getElementById("weatherResult").innerHTML = data;
			    }
			});
		}
	</script> 
	
	<style>
		.full {
			width:100%
		}
		
		.ninety {
			width:90%
		}		
	</style>
</head>

<body>
	<div id="weather" dojoType="dojox.mobile.View" selected="true">
		<h1 dojoType="dojox.mobile.Heading">Weather
			<div dojoType="dojox.mobile.ToolBarButton" moveTo="about">About</div>		
		</h1>
		
		<div dojoType="dojox.mobile.RoundRect" shadow="true">
			<label for="txtLocation">Select location</label> <br/>
			
			<select data-dojo-type="dijit.form.DataList" data-dojo-props="id:'locationList'" >
			  <option selected>Cairo, Egypt</option>
			  <option>Stockholm, Sweden</option>	
			  <option>Vienna, Austria</option>
			  <option>Madrid, Spain</option>	
			  <option>Paris, France</option>
			  <option>New York, USA</option>
			  <option>Lima, Peru</option>
			</select>
			
			<input id="location" class="ninety" type="text" data-dojo-type="dojox.mobile.ComboBox" data-dojo-props="list:'locationList'" /><br/><br/>
			
			<button class="mblBlueButton full" dojoType="dojox.mobile.Button" onClick="getWeatherInformation();">Get Information</button><br/><br/>
			
			<span id="weatherResult"/>
		</div>
	</div>
				
	<div id="about" dojoType="dojox.mobile.View">
		<h1 dojoType="dojox.mobile.Heading" back="back" moveTo="weather">About</h1>
		<div dojoType="dojox.mobile.RoundRect">This sample is developed by TechnicalAdvices.COM. It is powered by Dojo Mobile.</div>
	</div>					

</body>
</html>

The Backend Java Servlet

Finally, the backend Java Servlet reads the WOEID parameter and opens a URL connection to the yahoo API weather forecasting URL for getting the weather forecasting of the location as shown in the code listing below.

package servlets;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;

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

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;

/**
 * <code>WeatherProxyServlet</code> is a proxy servlet that wraps Yahoo weather REST service.
 * @author hazems
 *
 */
public class WeatherProxyServlet extends HttpServlet {
	private static final long serialVersionUID = 8732370454506907957L;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		String WOEID = request.getParameter("w");
		HttpURLConnection connection = null;
		
		response.setContentType("text/html");

		PrintWriter writer = null;
		
		try {
			URL url = new URL("http://weather.yahooapis.com/forecastrss?u=c&w=" + WOEID);
			
			connection = createHTTPConnection(url);
			
			String output = getHTTPOutputResponse(connection);
			
			SyndFeedInput input = new SyndFeedInput();
			SyndFeed feed = input.build(new InputStreamReader(new ByteArrayInputStream(output.getBytes("UTF-8"))));  		
			
		    if (feed.getEntries() != null && feed.getEntries().size() > 0) {
	            SyndEntry entry = ((SyndEntry) feed.getEntries().get(0));
	                        
	            String title = entry.getTitle();
	            String description = entry.getDescription().getValue();
	            
	            if (description.contains("Invalid")) {
	            	throw new Exception(description);
	            }
	    		
	    		writer = response.getWriter();	            
	            writer.print(title + "<br/>" + description);
	        }	
		} catch (Exception exception) {
			throw new ServletException(exception.getMessage());
		} finally {
			if (connection != null) {
				connection.disconnect();
			}
			
			if (writer != null) {
				writer.flush();
	        	writer.close();		
			}
		}
	}
	
	private static HttpURLConnection createHTTPConnection(URL url) throws IOException, ProtocolException {
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setRequestMethod("GET"); 
		conn.setRequestProperty("Accept", "text/html"); 
		conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
		
		return conn;
	}

	private static String getHTTPOutputResponse(HttpURLConnection conn) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

		String httpOutputResponse = ""; 
		String outputLine;
		
		while ((outputLine = br.readLine()) != null) {
			httpOutputResponse += outputLine;
		}
		
		return httpOutputResponse;
	}
}

You can try the application from your iPhone by going to the following URL:
http://www.mashups4jsf.com/mobileSamples/weather.jsp

You can download the complete Eclipse project from the following URL:
https://www.ibm.com/developerworks/mydeveloperworks/blogs/hazem/resource/29052012/mobileSamples.zip

Conclusion

In this article, you learned how to build a mobile application using the Dojo mobile APIs. You know how to use the framework views, headings, and components for building the weather forecasting application.

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.

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.