Info tech mobileapp week7 assignment

profilekarthikrao0207
DerbyInPhoneGap.pdf

330 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

} });

To make the call to an outside service for iPhone, you need to add the service to the external hosts in the PhoneGap.plist fi le. The easiest way to enable the external service for debugging is to add the * wildcard to the external hosts, as shown in Figure 11-26.

The data from the request string is placed on the responseText variable in the success callback. This can then be parsed with JavaScript’s eval function, which turns the XML into an array of items that can be used to get the items from the JSON response:

function successFunction(){ var dataItems = eval(“(“+this.responseText +”)”).d; for (var i = 0; i < dataItems.length; i++) { console.log(dataItems[i].Name); } }

LawnChair LawnChair is a JavaScript library that was built to allow persistent storage of data in a lightweight application. The primary target for LawnChair is mobile HTML5 applications, due to LawnChair’s lightweight nature. To use LawnChair you need to set up a data store:

var store = new Lawnchair({name:’testing’}, function(store) {});

Once you have the store, you can create an object with a key, and then place that object in the store:

var me = {key:’adam’, lastName:’Ryder’}; store.save(me);

Now that the object is stored, you can retrieve it from the store using the key:

store.get(‘adam’, function(item) { alert(item.lastName); });

This would get the object and alert the lastName item from the object. LawnChair is small; only 8 K in size. This lends itself well to being packaged in PhoneGap, because it won’t take much space on the device.

BUILDING THE DERBY APP IN PHONEGAP The idea of the Derby App is to build the same app over all of the mobile platforms covered in this book. The PhoneGap version is very similar to the other versions that you have built thus far or will build in future chapters.

FIGURE 11!26: External hosts with Item 0 Set to *

c11.indd 330c11.indd 330 28/07/12 6:08 PM28/07/12 6:08 PM

Building the Derby App in PhoneGap ! 331

The requirements are to provide two pages: one that lists all the teams/leagues and one that lists all the players. When a league/team is selected, the application shows the roster for the team. When a player is selected, it shows which team the player belongs to and her number.

The fi rst thing that you want to do in the Derby App is to create a placeholder which will hold the list of all the derby teams. You set this up on the index.html page:

<div id=”wrapper”> <div id=”scroller”> <ul> </ul> </div> </div>

You have set up the wrapper with an unordered list inside of the scroller. You need to add the listener for PhoneGap’s device ready event, and make a callback to the onDeviceReady function inside the onLoad function.

You also need to add a listener to the touchmove event to prevent the default touchmove behavior. Then you can use the iScroll library to control the movement of the screen:

function onLoad() { document.addEventListener(‘touchmove’, function (e) { e.preventDefault(); }, false); document.addEventListener(“deviceready”, onDeviceReady, false); }

With the ondevice events wired up you can now request data from the derby name service. To accomplish this, create a fi le named OData.js to handle all requests to the oData Derby Names web service. This OData.js fi le will need to be included in your index.html header. The OData.js fi le has a getData function that takes a request string and a successFunction callback. The actual request is made using XUI’s XHR function, which calls the success function and passes the results from the request string to the function.

function OData() { this.getData = function (requestString, successFunction) { x$().xhr(requestString, { callback: successFunction, headers: [{name:”Accept”, value: “application/json”}], error: function(){alert(‘Error ‘); }}); };

Next, set up a DerbyService function that contains all of the service calls and builds the request strings and sends them to the OData function. The calls in the DerbyService contain functions to get the leagues and take a callback.

function DerbyService() {

this.HostName = ‘http://derbynames.gravityworksdesign.com’; this.BaseServiceUrl = this.HostName + ‘/DerbyNamesService.svc/’; this.odataService = new oData();

this.searchAllLeagues = function (successFunction) { var serviceString = this.BaseServiceUrl + “Leagues?$top=50”;

c11.indd 331c11.indd 331 28/07/12 6:08 PM28/07/12 6:08 PM

332 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

odataService = new oData(); odataService.getData(serviceString, successFunction); }; }

The onDeviceReady function calls setHeight, which is a function in your helper.js fi le and the searchAll function, which is a local function with a callback to an anonymous function that sets up the scrollView for your iScroll implementation:

setHeight(); searchAll( function(){ setTimeout(function () { scrollView = new iScroll(‘wrapper’, {desktopCompatibility:true}); }, 500); });

The searchAll function creates an instance of the DerbyService, and then calls the searchAllLeagues function of the derby service with an anonymous callback function. The anonymous callback will call another helper function to display the league data on the screen. The displayAllLeagueDataOnScreen function takes a parameter for the response from the OData service, the search string (currently empty string), and the ID of the div that will hold the results.

function searchAll(callback){ var service = new DerbyService(); service.searchAllLeagues(function(){ displayAllLeagueDataOnScreen(this.responseText, “”, “scroller”); } });

callback(); }

The displayAllLeagueDataOnScreen function uses jQuery to fi nd the list name, and removes any list items that are currently in the list. It then calls the appendAllLeagueDataOnScreen function, passing it the data, search term, and the list name:

function displayAllLeagueDataOnScreen(data, searchTerm, listName){ jQuery(“#” + listName).find(‘li’).remove(); appendAllLeagueDataOnScreen(data, searchTerm, listName); }

The appendAllLeagueDataOnScreen function calls the JavaScript eval function on the data to get an array of dataItems to work with. You also create a temporary singleItem to hold the league list item. You use jQuery again to fi nd the unordered list inside of the listName that was passed in. For every dataItem, you create a link that will go to the leagues page, league.html, which shows all of the players for that league.

After the item is created you append those items to the list. If the data item’s length is the same as the number of records you asked for, you also add a link to get more items when you scroll to the bottom of the list.

c11.indd 332c11.indd 332 28/07/12 6:08 PM28/07/12 6:08 PM

Building the Derby App in PhoneGap ! 333

function appendAllLeagueDataOnScreen(data, searchTerm, listName){ var dataItems = eval(“(“+ data +”)”).d; var singleItem = “”; var list = jQuery(“#” + listName).find(‘ul’);

for (var i = 0; i < dataItems.length; i++) { singleItem = “<a href=’league.html?League=” + dataItems[i].LeagueName + “’> <li title=”; singleItem = singleItem + dataItems[i].LeagueName +” >”; singleItem = singleItem + dataItems[i].LeagueName + “</li></a>”;

list.append(singleItem); }

if(dataItems.length == 50){ if(searchTerm == “”){ singleItem = “<a href=’#’ id=’btnGetMore’ onclick=’LoadMorePushed()’>” singleItem = singleItem + “<li id=’liAddMore’>Load More</li></a>”; } else{ singleItem = “<a href=’#’ id=’btnGetMore’ onclick=’LoadMoreSearchPushed(&quot;”; singleItem = singleItem + searchTerm + “&quot;)’><li id=’liAddMore’>Load More</li></a>”; }

list.append(singleItem); } }

Figure 11-27 shows the index page rendering a list of roller derby teams.

Now that you have the leagues set up as a list of links to a league.html page, you can use CSS to change the links to look more like the native OS list items. You can set the list-style to none and the list-type to none, which will remove the bullets. When you set text-decorations to none for the anchor tabs, the links will no longer be underlined.

ul { list-style:none; padding:0; margin:0; width:100%; text-align:left; }

li { margin:5px 0; padding:3px 7px 7px 7px; border-bottom:1px solid #ddd; list-style-type:none; font-size:15px; font-weight:bold; margin-right:5px; }

FIGURE 11!27: List of derby teams rendered on an iPhone

c11.indd 333c11.indd 333 28/07/12 6:08 PM28/07/12 6:08 PM

334 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

a:link, a:visited { text-decoration:none; color:#000; font-weight:bold; }

Figure 11-28 shows what the Derby app looks like after this small amount of CSS has been added.

With the scrolling working and the list looking like a list, you can add a header to the league page. The header consists of two links with classes, which will become image links through CSS. This header will also be used on the individualList.html page, just with different classes, so that the links look different.

<div class=”header”> <a id=”btnLeague” href=’index.html’ class=”btnTwoLeft”>Leagues</a> <a id=”btnIndividuals” href=’individualList.html’ class=”btnTwoRightSelected” >Players</a> </div>

Here is the CSS for the buttons; the images are stored inside the images directory within the www directory:

.btnTwoLeft { height:23px; width:150px; background:url(images/btn-two-left.png) no-repeat; float:left; text-align:center; font-size:14px; font-weight:200!important; color:#fff!important; font:Georgia, “Times New Roman”, Times, serif; padding:7px 0 0 0; margin:2px 0; }

.btnTwoLeftSelected { height:23px; width:150px; background:url(images/btn-two-left-selected.png) no-repeat; float:left; text-align:center; font-size:14px; font-weight:200!important; color:#fff!important; font:Georgia, “Times New Roman”, Times, serif; padding:7px 0 0 0; margin:2px 0; }

With the header added, the league screen is now starting to look like a mobile app. Figure 11-29 shows the header added to the league screen.

FIGURE 11!28: Formatted league list displayed on an iPhone

FIGURE 11!29: Derby App with header added

c11.indd 334c11.indd 334 28/07/12 6:08 PM28/07/12 6:08 PM

Other Useful PhoneGap Things ! 335

There is another useful option for a list this long, and that is the ability to search. To search, you need a text box for the search term, a button to search with, and another service call for searching:

<input id=”txtSearch” type=”search” placeholder=”Search” class=”searchbar”> <button id=”btnSubmit” type=”button” class=”gobtn” label=”Go” >GO</button>

Wire up the button click event in the onDeviceReady function. This click function gets the searchCriteria from the search text box and passes that to the searchLeagues function:

jQuery(“#btnSubmit”).click(function(){ var searchCriteria = jQuery(“#txtSearch”).val(); skipCount = 50; searchLeagues(searchCriteria); });

The searchLeagues function creates a new instance of the DerbyService and calls the searchLeagues function in the service with a callback to displayAllLeagueDataOnScreen. This is the same function that you called when you displayed the unfi ltered list.

function searchLeagues(searchCriteria){ var service = new DerbyService();

service.searchLeagues(searchCriteria, function(){ displayAllLeagueDataOnScreen(this.responseText, searchCriteria, “scroller”); }); }

The searchLeagues function in the service calls the OData object with a fi lter that looks for a sub- string of the searchString that is passed in the LeagueName property:

this.searchLeagues = function (searchString, successFunction) { var serviceString = this.BaseServiceUrl + “Leagues?$top=50&$filter=\ substringof(‘” + searchString + “’,LeagueName)”;

this.odataService.getData(serviceString, successFunction); };

With the search in place, Figure 11-30 shows the completed UI for the Leagues screen in the Derby App.

With the Derby App completed, now you can take a look at some of the other useful functions in PhoneGap.

OTHER USEFUL PHONEGAP THINGS Thus far, the examples in this chapter have provided the basics for creating a PhoneGap application. This application will go out to a web service and render the data on the screen. This does not cover every possible situation you will encounter as a PhoneGap mobile developer, so we will fi nish this

FIGURE 11!30: Derby App with league search added

c11.indd 335c11.indd 335 28/07/12 6:08 PM28/07/12 6:08 PM

336 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

chapter by providing a few short examples of other common tasks you may need to accomplish when working with PhoneGap.

Pickers Pickers in PhoneGap come in two fl avors. The fi rst type of picker is a date-style picker. These pickers rely on plug-ins to function, because there isn’t a uniform date picker available to the different platforms yet. iOS 5 does support the HTML date input type. You can get the code for the date picker from https://github.com/phonegap/phonegap-plugins/tree/master/ iPhone/DatePicker. This will have the .js, .h, and .m fi les. The .h and .m fi les go into your Plugins directory. The DatePicker.js fi le belongs in your www directory. You also need to add a DatePicker key and value to the plugins section of your phonegap.plist fi le. You need to create a callback and a function that will be called during the onclick of a link.

var callbackFunction = function(date) { console.log(date.toString()); document.getElementById(“date”).innerHTML = date.toString(); } var showDatePicker = function(mode) { plugins.datePicker.show({ date: new Date(), mode: mode, //date or time or blank for both allowOldDates: false }, callbackFunction); }

The other way to create a picker, which is our recommended way, is to create a page that lists the items you want to pick from as links back to your selector. In your HTML you could have a link to a pickList page:

<a href=’pickList.html’>Choose Your Favorite Color</a>

On the pickList page you can set up the list as a series of links back to the index with the choices differentiated by the query string parameter that is passed back:

<html> <ul> <li><a href=’index.html?color=blue’>Blue</a> <li><a href=’index.html?color=green’>Green</a> <li><a href=’index.html?color=red’>Red</a> </ul> </html>

Once back on the index page you can read the query string and take action based on what it con- tains. You can use regular expressions in JavaScript to decode the query string and return the value of the query string parameter. You could add another JavaScript library to handle this, but it is quicker and easier to just write the function yourself:

function getParameterByName( name ){ name = name.replace(/[\[]/,”\\\[“).replace(/[\]]/,”\\\]”);

c11.indd 336c11.indd 336 28/07/12 6:08 PM28/07/12 6:08 PM

Other Useful PhoneGap Things ! 337

var regexS = “[\\?&]”+name+”=([^&#]*)”; var regex = new RegExp( regexS ); var results = regex.exec( window.location.href ); if( results == null ) return “”; else return decodeURIComponent(results[1].replace(/\+/g, “ “)); }

Once you make the call to getParameterByName you can use the information that you have in the query string:

var color = getParameterByName(‘color’); if (color != ‘’) { alert(‘You Chose: ‘ + color); }

Figure 11-31 is an example of the color picker view.

O" ine Storage Sometimes you will need to store data on the device. This could be because the business rules for your app require offl ine usage, or it could be just a matter of saving a few settings such as username and password. This section shows you the different techniques you can use to store data offl ine so that it can be retrieved when the user is not connected to the web. Offl ine storage also allows you to store settings on the device for your user.

Web SQL If you have a lot of data that needs to be stored, one of the better ways to store that data is in a database. PhoneGap provides a mechanism to create, maintain, and retrieve records from an internal database. The fi rst thing you need to do to use the database is to open it. You must do this after PhoneGap’s deviceready event has been fi red. The following code creates or opens a database named PlayerDemo with a version of 1.0 and a display name of Player Demo. The 10000 is the size of the database in bytes.

function onDeviceReady() { var db = window.openDatabase(“PlayerDemo”, “1.0”, “Player Demo”, 10000); }

Now that you have a database you can run transactions against it. You do that by calling the transaction function on the database, and passing in a callback function, an error callback, and a success callback. The callback function gets called with a transaction object. The fi rst thing you do is populate the database:

db.transaction(populateDB, onDBError, onDBSuccess);

FIGURE 11!31: Color picker view

c11.indd 337c11.indd 337 28/07/12 6:08 PM28/07/12 6:08 PM

338 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

This calls the populateDB function and passes the function its transaction. This means that if any of the commands in the transaction fail, the entire transaction will be rolled back. The following function creates a players table:

function populateDB(tx){ tx.executeSql(‘DROP TABLE IF EXISTS PLAYERS’); tx.executeSql(‘CREATE TABLE IF NOT EXISTS PLAYERS (id unique, number, name)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (1, 6, “Adam”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (2, 1, “Jeff”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (3, 4, “Scott”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (4, 2, “Amelia”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (5, 5, “Dave”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (6, 3, “Lauren”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (7, 7, “Ashley”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (8, 9, “Nathan”)’); tx.executeSql(‘INSERT INTO PLAYERS (id, number, name) VALUES (9, 8, “Heather”)’); }

Now that you have the database populated you can create another transaction that you can use to retrieve the data from the players table that you just created. To get the data back from a query, you call executeSQL and pass it the query, arguments, the success callback, and the error callback:

tx.executeSql(‘SELECT * FROM PLAYERS ORDER BY name’, [], onQuerySuccess, onDBError);

You can use the onQuerySuccess callback to iterate through the results and display them to the screen, as shown in Figure 11-32:

FIGURE 11!32: SQL returned to screen

c11.indd 338c11.indd 338 28/07/12 6:08 PM28/07/12 6:08 PM

Other Useful PhoneGap Things ! 339

function onQuerySuccess(tx, results){

try{ var playerInfo = ‘<ul>’; var len = results.rows.length; for (var i=0; i<len; i++){ playerInfo += ‘<li><b>’ + results.rows.item(i).name + ‘</b>(‘ + results.rows.item(i).number + ‘)</li>’; } playerInfo += ‘</ul>’; jQuery(‘#divPlayers’).html(playerInfo); } catch(err){ alert(err); } }

Filesystem Storage Local storage is also available. The local storage is available as key-value pairs. To store Lansing as a favorite, you would call setItem, passing in the key (favorite) and the value (Lansing):

window.localStorage.setItem(“favorite”, “Lansing”);

This storage is persistent and will be available the next time the applica- tion is run. To retrieve the data you call getItem with the key that you are looking for. The following code retrieves the favorite item and then alerts that item, as shown in Figure 11-33:

var fav = window.localStorage.getItem(“favorite”); alert(fav);

GPS You access the GPS through PhoneGap by calling the geolocation function with a callback:

function onDeviceReady() { navigator.geolocation.getCurrentPosition(gpsSuccess, gpsFailure); }

As with all of the PhoneGap functions, the GPS functions cannot be called until the deviceready event has been fi red. The success callback returns a position object, which has a coordinates object that contains properties for latitude, longitude, altitude, accuracy, heading, and speed:

function gpsSuccess(location){ var gpsinfo = ‘<ul><li>Latitude: ‘ + location.coords.latitude + ‘</li>’; gpsinfo += ‘<li>longitude: ‘ + location.coords.longitude + ‘</li>’;

FIGURE 11!33: Local storage alert

c11.indd 339c11.indd 339 28/07/12 6:08 PM28/07/12 6:08 PM

340 ! CHAPTER 11 GETTING STARTED WITH PHONEGAP

gpsinfo += ‘<li>Altitude: ‘ + location.coords.altitude + ‘</li>’; gpsinfo += ‘<li>Accuracy: ‘ + location.coords.accuracy + ‘</li>’; gpsinfo += ‘<li>Speed: ‘ + location.coords.speed + ‘</li></ul>’;

jQuery(‘#GPSInfo’).html(gpsinfo); }

There is also a failure callback that returns a positionError object. The positionError object has a code and a message property:

function gpsFailure(PositionError){ alert(PositionError.code); alert(PositionError.message); }

Accelerometer You can access the accelerometer using the accelerometer’s watchAcceleration function with a callback for the success and for errors. watchAcceleration is set to a variable and fi res on the frequency that is set in the options. The iPhone simulator does not transmit accelerometer data; however, the Android simulator does, so if you are testing without a device, the accelerometer needs to be tested on Android.

var options = { frequency: 3000 }; watch = navigator.accelerometer.watchAcceleration(successFunction, errorFunction, options); //The success function takes an acceleration object. //This object has the x, y and z change, //as well as the timestamp from when the acceleration was gathered. function successFunction(acceleration){ try{ x$(“#spanX”).html(acceleration.x); x$(“#spanY”).html(acceleration.y); x$(“#spanZ”).html(acceleration.z); x$(“#spanTime”).html(acceleration.timestamp); } catch(err) { alert(err); } }

To stop the watch from fi ring constantly, you can call the clearWatch function and pass it the watch variable to stop the watch from fi ring:

x$(‘#btnStop’).click(function(){ navigator.accelerometer.clearWatch(watch); });

Now that you have a working app you can connect the application to the markets.

c11.indd 340c11.indd 340 28/07/12 6:08 PM28/07/12 6:08 PM

Summary ! 341

CONNECTING PHONEGAP TO THE MARKETS If you have been following through the book chapter by chapter, you have seen how to connect to the different markets. Because PhoneGap applications are compiled with their native frameworks, they are released to the markets in the same manner as their true native counterparts are released. Refer to the corresponding section of Chapters 6–9 for more information on connecting to the vari- ous markets.

SUMMARY PhoneGap is an easy-to-learn framework for creating cross-platform mobile applications. Everything in PhoneGap derives from the onDeviceReady listener. Once onDeviceReady fi res, you have access to the device’s native components, like the GPS, camera, or accelerometer. Leveraging your current HTML, CSS, and JavaScript knowledge also enables you to create these applications with a lower learning curve.

Because PhoneGap is cross platform, you don’t need to learn four different languages to be able to deploy your application across iPhone, Android, BlackBerry, and Windows Phone 7. Having the same codebase for all platforms can also give you a sense of parity through the different device platforms.

Now that you have created mobile applications with PhoneGap, the next chapter will show how to create Android and iPhone applications using .NET and the Mono framework.

c11.indd 341c11.indd 341 28/07/12 6:08 PM28/07/12 6:08 PM