Creating Cross-Device Compatible Mobile Applications that Integrate with SharePoint
Create applications that work with SharePoint LOB systems
April 26, 2012
![Creating Cross-Device Compatible Mobile Applications that Integrate with SharePoint Creating Cross-Device Compatible Mobile Applications that Integrate with SharePoint](https://eu-images.contentstack.com/v3/assets/blt07f68461ccd75245/blt91d30193c99b59f8/661cf9a9a4e1ff6678e3259f/women-computers-680x340_0_3.jpg?width=1280&auto=webp&quality=95&format=jpg&disable=upscale)
Today, more than ever before, businesses are creating mobile applications to extend their line of business (LOB) systems to internal employees, business partners, and consumers. The odds are that you work in an organization that has LOB applications built on the Microsoft SharePoint platform; perhaps you've built them yourself. Throughout this article, I'll show you various approaches that you can take to build mobile applications that integrate with SharePoint LOB systems. I'll also provide the information that you need to choose the right approach for your mobile application development.
Native Applications vs. HTML5 Applications
The first things that you need to consider when building a mobile application are the target platforms and devices on which the applications need to run and the level of functionality that the applications should provide. For example, suppose that only internal employees, all of whom have the same type of company-issued mobile device, use an application. In that case, writing the application in the native language for that particular device might make sense. However, it's less likely that you'll be able to target a specific platform and device if the application will be used by internal employees, business partners, and consumers. In the latter scenario, you could write the application in native code for each platform and device that you're targeting, but this approach is costly and takes more time to develop. Plus, the associated costs of maintaining separate native codebases for each device are higher in the long run.
Another approach would be to develop the application with HTML5 and JavaScript, then host the application in a wrapper that uses the mobile devices' web browser to display and run the application. With this approach, you have only one codebase to create and maintain. Thankfully, you can use the open-source PhoneGap technology (currently hosted by Adobe Systems) to facilitate this solution.
PhoneGap Applications
PhoneGap provides the ability to quickly create the wrapper applications that host your HTML5-and-JavaScript applications. PhoneGap also provides a JavaScript library that allows you to call into the APIs that are specific to each phone platform you target. By doing so, you can write your applications one time and make them work on multiple mobile platforms. PhoneGap currently supports 10 mobile OS platforms to various degrees.
For example, suppose you want to provide the ability to take a picture from a mobile device. If you write the code natively, you'll end up writing the code to take the picture in each native platform language. As I mentioned before, this approach takes more time and costs more to develop and maintain. But the PhoneGap JavaScript library allows you to do the same thing with one consistent approach.
In this code sample, the captureImage function is invoked by a button's Click event. The captureImage function uses the PhoneGap JavaScript library to invoke the appropriate APIs, specific to the device, to launch the appropriate functionality. In this example, after you take a picture with the camera of a mobile device, the data is returned to the JavaScript success callback function, from where you can process it.
function captureImage() {navigator.camera.getPicture(captureSuccess,captureError,{ sourceType: Camera.PictureSourceType.CAMERA });}function captureSuccess(pictureData) {navigator.notification.alert("Picture captured!");}function captureError(error) {var msg = 'An error occurred during capture: ' + error.code;navigator.notification.alert(msg, null, 'Picture Not Captured!');}
You might be wondering how the PhoneGap JavaScript library calls into the native APIs on the target mobile device to execute the functionality. The library calls into the appropriate PhoneGap native library for each device. When you create the PhoneGap wrapper application specific to each device, you include the PhoneGap native library so that it is available.
For example, in a Windows Phone 7 PhoneGap application, the PhoneGap JavaScript library calls the WP7CordovaClassLib.dll assembly. In Figure 1, you can see that this assembly has been added as a reference is in the Visual Studio (VS) 2010 Solution Explorer. Figure 2 shows the phonegap-1.5.0.jar Java Archive that the PhoneGap JavaScript library calls in an Android PhoneGap application.
Figure 1: WP7CordovaClassLib.dll assembly in VS
![Figure 2: The phonegap-1.5.0.jar Java Archive in an Android PhoneGap Figure 2: The phonegap-1.5.0.jar Java Archive in an Android PhoneGap](https://www.windowsitpro.com/content/content/142911/Baginski-SPC314-Figure2-sm.jpg?width=700&auto=webp&quality=80&disable=upscale)
Figure 2: The phonegap-1.5.0.jar Java Archive in an Android PhoneGap
Pros and Cons of Each Approach
As you decide which approach to take, carefully consider the pros and cons to ensure that you use the right technology to meet your mobile application needs. Table 1 summarizes the main pros and cons that are associated with each approach. At the end of the day, if you're targeting multiple device platforms, PhoneGap will usually bubble to the top because it saves so much time and money compared to writing the same application in native code.
One fantastic aspect of PhoneGap development is the PhoneGap build service. You can create a PhoneGap application in any IDE and emulator you want and then upload the source files to the PhoneGap build service. The service creates the versions of the applications that you need to deploy to each target device that you specify.
Native Mobile Device Code SharePoint Integration
Writing native code to target multiple device platforms is a cumbersome task, and showing all the code samples to facilitate this approach is outside the scope of this article. However, you can download the SharePoint 2010 and Windows Phone 7 Training Course from MSDN and quickly get up to speed on the approach for writing a native Windows Phone 7 application to authenticate to SharePoint and interact with SharePoint APIs.
Because NTLM is unsupported in the current version of Microsoft Silverlight, you can take one of two approaches in Windows Phone 7 to authenticate to SharePoint. You can use the Authentication SharePoint Web service in a Forms Based Authentication (FBA)-enabled SharePoint environment, or you can front your SharePoint server with a Unified Access Gateway (UAG) Server and inject your credentials into the headers for the requests that you make. In Module 6 of the training course, Lab 1 shows how to use the FBA approach; Lab 2 shows how to use the UAG approach. For more information about how to set up a UAG server to front SharePoint and call into it from Windows Phone 7 applications, see the whitepaper " Building Windows Phone 7 Applications with SharePoint 2010 Products and Unified Access Gateway (UAG) ."
What about other devices, such as the Apple iPhone or iPad or Android devices? Although no official Microsoft training kits demonstrate how to use native code to integrate these device platforms with SharePoint, you can take the same approaches that you find in the SharePoint 2010 and Windows Phone 7 Training Course. You just need to wrap the service calls in the native code that is specific to the device that you're targeting.
Keep in mind that you can build a service layer between SharePoint and your mobile applications. You might build such a service layer to overcome authentication limitations or to provide the ability to remotely invoke functions that are unavailable in the out-of-the-box services that SharePoint provides.
PhoneGap SharePoint Integration
As I've developed PhoneGap applications that integrate with SharePoint, I've learned a few tips and tricks along the way. First, there's a big difference in the way that the different emulators resolve host names. When you call into a SharePoint server from the Windows Phone 7 emulator, the emulator uses the DNS settings and HOSTS file on the host machine to resolve addresses. However, the Android emulator doesn't use the HOSTS file on the host machine. You can find several Internet posts that describe how to edit the HOSTS file on the Android emulator so that you can resolve hosts that are not registered in DNS. I was unable to get any of these methods to work with the Android emulator running on a Windows host machine. To get my Android emulator to resolve my SharePoint development server, I eventually registered the server name in DNS and used a command-line switch to supply the DNS server name to the emulator at startup.
In my experience, the Android emulator is much slower and less reliable than the Windows Phone 7 emulator. For example, the initial process of loading the Android emulator and deploying an application to it for testing can take several minutes. Also, the Android emulator frequently fails to deploy the applications on the first try. You often need to close the Android Debug Bridge (adb.exe) and the Eclipse IDE, check to make sure they aren't running in Task Manager, and then restart them for a deployment to succeed. If you look around on the Internet, you'll find that this behavior is common. On the flip side, the Windows Phone 7 emulator starts and deploys new applications in under a minute and doesn't experience the intermittent deployment issues that the Android emulator exhibits. (Keep in mind, I run both development environments on Windows machines. The Android emulator behavior that I describe might not manifest itself on a UNIX host.) For these reasons, I find it faster to develop with VS 2010 and then copy the HTML5 and JavaScript code to other projects when I'm ready to test on other platforms.
Another consideration is that the PhoneGap JavaScript library has a few quirks that appear between device platforms. For example, in PhoneGap versions earlier than 1.5, request headers aren't set properly when you make AJAX calls from jQuery in a Windows Phone 7 device. (The Android and Apple iOS devices properly set the headers.) Because PhoneGap is so new, these issues are bound to appear from time to time as the library matures. The good news is that when you post an issue such as this one to the PhoneGap support forum, the developers quickly triage the issue, and fixes are rolled out very quickly. In the example I mention here, the issue was resolved within two weeks of a few people posting the issue.
Sample Application
In the following example, I'll demonstrate how to use PhoneGap, jQuery, jQuery Mobile, JavaScript, and HTML5 to create a simple mobile application that authenticates a user to an FBA-enabled SharePoint site and performs create, read, update and delete (CRUD) operations on SharePoint list data. In this example, I'll demonstrate how to target Windows Phone 7 and Android devices; you can also use the code for iPhone, iPad, or other devices.
First, I created a PhoneGap development environment on my Windows 7 host machine for both Windows Phone 7 and Android development. To get started with PhoneGap development, visit the Getting Started Guide on the PhoneGap web site. The guide walks you through the hardware requirements and how to install the various tools and SDKs to develop PhoneGap applications. After the development environments were up and running, I created a simple Hello world application for each target device.
Next, I began to write the code to authenticate to the FBA-enabled SharePoint server. In this code, I define an HTML5 page to load all the necessary script and CSS files. Notice that I include the phonegap-1.5.0.js file in the page source, jQuery, jQuery Mobile, and a couple JavaScript files that I created and used to set up the page.
You will notice that I include the PhoneGap JavaScript library in each HTML page, to prep the application for interaction with the device-specific APIs. To keep the demo application and code pattern simple, I didn't include PhoneGap functionality into this application. In a subsequent article, I'll demonstrate how to use the PhoneGap APIs to provide more functionality with the application.
Note that the PhoneGap JavaScript library isn't required to facilitate the communication with the SharePoint server. But as I mentioned earlier, it is if you want to interact with the native APIs on the mobile device via JavaScript. In this example application, I use the PhoneGap wrapper application for both the Windows Phone 7 and Android devices. This application loads a web browser, which displays the HTML pages that make up the application.
You might also wonder why I don't use the SharePoint ECMA (JavaScript) client-side object model (CSOM) to query the data in the SharePoint site. The SharePoint ECMA CSOM isn't supported and won't work in this context because the CSOM relies on the FormsDigest control <SharePoint:FormDigest runat="server"/>. This control is unavailable outside of a SharePoint page. (See the MSDN article "Differences Between Managed and JavaScript ObjectModels" for more information.) Although you can find some instances of folks hacking this control into non-SharePoint web pages in ASP.NET web sites, such a hack introduces a fragile element into your code.
Also, in the Windows Phone 7 version of the application, you need to add additional code to handle the hardware back-button Click event, to make sure that the application doesn't exit but navigates to the previous web page in the mobile application. You can find an approach for implementing this code at the Scott Logic site.
<!DOCTYPE html><html ><head><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><title>PhoneGap SharePoint List Reader</title><link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8" /><link rel="stylesheet" href="jquery.mobile-1.0.1.min.css" /><script type="text/javascript" src="jquery-1.7.1.min.js"></script><script type="text/javascript" src="jquery.mobile-1.0.1.min.js"></script><script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script><script type="text/javascript" charset="utf-8" src="init.js"></script><script type="text/javascript" charset="utf-8" src="spauth.js"></script></head><body><div data-role="page" data-theme="a" data-content-theme="a"><div data-role="header">Phonegap SharePoint List Data Editor</div><div data-role="content" id="topnavcontent"></div><div data-role="content" id="errorContent"></div></body></html>
When the application loads, first, the following init.js file registers an event that listens for the DeviceReady event. The PhoneGap JavaScript library fires this event when the PhoneGap library is initialized and ready for use.
$(document).ready(function () {document.addEventListener("deviceready", onDeviceReady, false);});
If you need to debug the application inside of a web browser, you can replace the previous function with the following one. This function allows you to attach a JavaScript debugger directly to the web page.
$(window).load(function () {setTimeout(onDeviceReady, 100);});
When the onDeviceReady event fires, I set support.cors and mobile.allowCrossDomainPages equal to true, to allow the application to communicate with the SharePoint Web services. jQuery is then used to add the Authenticate button to the page. I chose to add the button after initializing PhoneGap, to ensure that no timing issues occur when the button is clicked. Note that the Authenticate function is registered for the onClick event for the Authenticate button.
function onDeviceReady() {$.support.cors = true;$.mobile.allowCrossDomainPages = true;$("#topnavcontent").append("<a href=\"#\" data-role=\"button\" data-icon=\"check\" onclick=\"Authenticate(); return false;\">Authenticate</a>");$("#topnavcontent").trigger("create");}
Figure 3 shows what the page looks like when it loads.
Figure 3: The authentication page
When the Authenticate button is clicked, the Authenticate function is called. This function is defined in the spauth.js file that I include in the page source. Inside this function, which the following code shows, I assemble a Simple Object Access Protocol (SOAP) envelope and use jQuery AJAX to call the Authentication SharePoint Web service. I pass the user credentials inside the SOAP envelope.
function Authenticate() {$("#topnavcontent").append("Creating SOAP envelope...</br>");var soapEnv = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soap:Body>" +"<Login xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +"<username>username</username>" +"<password>password</password>" +"</Login>" +"</soap:Body>" +"</soap:Envelope>";$("#topnavcontent").append("Calling authenticate.asmx...</br>");$.ajax({url: "http://ski.canviz.com/_vti_bin/authentication.asmx",type: "POST",dataType: "xml",data: soapEnv,complete: authenticationResultSuccess,contentType: "text/xml; charset=\"utf-8\"",error: authenticationResultError});}
The following functions are used to handle the callback from the AJAX request to the Authentication SharePoint Web service. When the request completes successfully, a cookie is stored in the browser. This cookie is used to keep track of who logged in and to authenticate subsequent requests to the SharePoint server. This authentication process is much more streamlined than a native code approach would be because you don't need to keep track of the cookie or attach it to subsequent requests that you make to the SharePoint server. The authenticationResultSuccess function redirects the user to the main.html web page inside the browser on the mobile device.
function authenticationResultSuccess(xData, status) {if (status != "error") {$("#topnavcontent").append("Authentication Result: " + status + "</br>");window.location = "main.html";}else {$("#errorContent").empty();$("#errorContent").append("Authentication Result:" + status + "</br>");$("#errorContent").trigger("create");}}
The authenticationResultError function is used to handle errors and displays the error to the screen.
function authenticationResultError(xData, status) {$("#errorContent").empty();$("#errorContent").append("Authentication Result:" + status + "</br>");$("#errorContent").trigger("create");}
After the authentication is successful, the main.html page queries the SharePoint server and returns all the items in a list that I created, named Ski Resorts. This list is based on the out-of-the-box custom list template and contains only the Title column. (I chose to keep this example simple to reduce the amount of code in the article.)
Figure 4 shows what the data looks like in the Ski Resorts SharePoint list. Figure 5 shows the main page in the Windows Phone 7 emulator displaying this data. Figure 6 shows the main page in the Android emulator displaying the data. Notice the common look and feel that is applied to both applications with the jQuery Mobile framework.
Figure 4: Data in the Ski Resorts SharePoint list
Figure 5: Main page in the Windows Phone 7 emulator displaying the data from the Ski Resorts SharePo
In the mainpage.html file, you'll see that two JavaScript files are loaded to support the operations in the page. A jQuery Mobile listview is placed on the page to display the items from the SharePoint list, and two buttons are created to refresh the list and to create a new item in the list.
<!DOCTYPE html><html ><head><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><title>Phonegap SharePoint List Data Editor</title><link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8" /><link rel="stylesheet" href="jquery.mobile-1.0.1.min.css" /><script type="text/javascript" src="jquery-1.7.1.min.js"></script><script type="text/javascript" src="jquery.mobile-1.0.1.min.js"></script><script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script><script type="text/javascript" charset="utf-8" src="maininit.js"></script><script type="text/javascript" charset="utf-8" src="spqueries.js"></script></head><body><div data-role="page" data-theme="a" data-content-theme="a"><div data-role="header">Phonegap SharePoint List Data Editor</div><div data-role="content" id="topnavcontent">Ski Resorts</div><ul data-role="listview" data-inset="true" id="listview" ></ul><div data-role="content" id="footercontent"><a href="#" data-role="button" data-icon="refresh" onclick="GetItems(); return false;">Refresh</a><a href="#" data-role="button" data-icon="plus" onclick="ShowCreate(); return false;">Add New Resort</a></div><div data-role="content" id="errorContent"></div></body></html>
The maininit.js file fires the GetItems function that's defined in the spqueries.js file.
$(window).load(function () {setTimeout(init, 100);});function init() {$.support.cors = true;$.mobile.allowCrossDomainPages = true;GetItems();}
The GetItems function works much like the Authenticate function. GetItems assembles a SOAP envelope and calls the SharePoint Lists Web service to retrieve the items from the Ski Resorts list.
function GetItems() {var soapEnv ="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soapenv:Body>" +"<GetListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +"<listName>Ski Resorts</listName>" +"<viewFields>" +"<ViewFields>" +"<FieldRef Name=\"Title\" />" +"</ViewFields>" +"</viewFields>" +"</GetListItems>" +"</soapenv:Body>" +"</soapenv:Envelope>";$.ajax({url: "http://ski.canviz.com/_vti_bin/lists.asmx",type: "POST",dataType: "xml",data: soapEnv,complete: processGetItemsResultSuccess,contentType: "text/xml; charset=\"utf-8\"",error: processGetItemsResultError});}function processGetItemsResultError(xData, status) {$("#errorContent").empty();$("#errorContent").append("Get Items Result:" + status + "</br>");$("#errorContent").trigger("create");
After the request to the Lists SharePoint Web service completes, the processGetItemsResultSuccess function loops through the results and adds them to the jQuery Mobile listview. The ShowDetails function in the maininit.js file is registered with the onClick event for each item that is added to the listview.
function processGetItemsResultSuccess(xData, status) {$("#listview").empty();$(xData.responseXML).find("z\\:row, row").each(function () {var output = "<li>" +"<a href=\"#\" data-theme=\"b\" data-icon=\"gear\" " +"onclick=\"ShowDetails('" +$(this).attr("ows_ID") + "','" + $(this).attr("ows_Title") +"'); return false;\">" +$(this).attr("ows_Title") +"</a>" +"</li>";$("#listview").append(output);});$("#listview").listview("refresh");}
When a user clicks an item in the listview, the following ShowDetails function uses HTML5 localStorage to store the ID and Title for the current list item, then redirects the user to the itemdetail.html page. Storing values in localStorage and retrieving them from other pages in your application is a great way to pass data from one page to another. If you try to use a query string approach (as I initially did), you'll encounter JavaScript errors.
function ShowDetails(ID, Title) {localStorage.setItem("currentItemID", ID);localStorage.setItem("currentItemTitle", Title);window.location = "itemdetail.html";}
The itemdetail.html page displays the Title for the selected list item and allows the user to update the value. Figure 7 shows the item detail page in the Windows Phone 7 emulator. Notice the glowing effect that jQuery Mobile applies around the text box when it has been selected for input.
Figure 7: Item detail page in the Windows Phone 7 emulator
Figure 8 shows the item detail page in the Android emulator. In this figure, the text box has not been selected for input, so the glowing effect is absent.
Figure 8: Item detail page in the Android emulator
The following itemdetail.html page loads the itemdetailinit.js file and defines a text box to display and edit the Title column value.
<!DOCTYPE html><html ><head><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><title>Phonegap SharePoint List Data Editor</title><link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8" /><link rel="stylesheet" href="jquery.mobile-1.0.1.min.css" /><script type="text/javascript" src="jquery-1.7.1.min.js"></script><script type="text/javascript" src="jquery.mobile-1.0.1.min.js"></script><script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script><script type="text/javascript" charset="utf-8" src="itemdetailinit.js"></script><script type="text/javascript" charset="utf-8" src="spqueries.js"></script></head><body><div data-role="page" data-theme="a" data-content-theme="a"><div data-role="header" >Phonegap SharePoint List Data Editor</div><div data-role="content" id="topnavcontent">Resort Details</div><div data-role="content" id="resultscontent"><label for="ItemTitle">Name:</label><input type="text" name="ItemTitle" id="ItemTitle" value="" /></div><div data-role="content" id="footercontent"></div><div data-role="content" id="errorContent"></div></body></html>
In the following itemdetailinit.js file, the ID and the Title for the item that was selected in the previous page are retrieved from localStorage. jQuery is used to display the Title in the text box, and the ID is used to set up the Click event for the Delete button.
$(window).load(function () {setTimeout(init, 100);});function init() {$.support.cors = true;$.mobile.allowCrossDomainPages = true;$("#ItemTitle").val("");$("#ItemTitle").trigger("create");var ID = localStorage.getItem("currentItemID");var Title = localStorage.getItem("currentItemTitle");$("#ItemTitle").val(Title);$("#footercontent").append("<a href=\"#\" data-role=\"button\" data-icon=\"gear\" onclick=\"Update(); return false;\">" + "Save</a>");$("#footercontent").append("<a href=\"#\" data-role=\"button\" data-icon=\"delete\" onclick=\"DeleteItem('" + ID + "'); return false;\">" +"Delete</a>");$("#footercontent").trigger("create");}
When the Save button is clicked, the Update function is fired. This function uses the ID that's retrieved from localStorage and the value in the text box to update the list item by calling the UpdateItem function that's defined in the spqueries.js file.
function Update() {UpdateItem(localStorage.getItem("currentItemID"), $("#ItemTitle").val());}
As you can see, the code pattern here is similar to the other calls to the Lists Web service. Note the beforeSend values that are set on the jQuery AJAX request. If you don't set these values appropriately, then the server returns a 500 error, which makes debugging difficult.
function UpdateItem(ID, Title) {var soapEnv ="<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soapenv:Body>" +"<UpdateListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +"<listName>Ski Resorts</listName>" +"<updates>" +"<Batch OnError=\"Continue\">" +"<Method ID=\"2\" Cmd=\"Update\">" +"<Field Name=\"ID\">" + ID + "</Field>" +"<Field Name=\"Title\">" + Title + "</Field>" +"</Method>" +"</Batch>" +"</updates>" +"</UpdateListItems>" +"</soapenv:Body>" +"</soapenv:Envelope>";$.ajax({url: "http://ski.canviz.com/_vti_bin/lists.asmx",type: "POST",dataType: "xml",data: soapEnv,beforeSend: function (xhr) {xhr.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/UpdateListItems");},complete: processUpdateItemResultSuccess,contentType: "text/xml; charset=\"utf-8\"",error: processUpdateItemResultError});}function processUpdateItemResultError(xData, status) {$("#errorContent").empty();$("#errorContent").append("Update Item Result:" + status + "</br>");$("#errorContent").trigger("create");}
After a successful update, the processUpdateItemResultSuccess function returns the user to the main page.
function processUpdateItemResultSuccess(xData, status) {window.location = "main.html";}
When the Delete button is clicked, the Delete function in the spqueries.js file fires. This function uses the SharePoint Lists Web service to delete the item from the SharePoint list. The Delete function uses the item's ID to locate it inside the SharePoint list.
function DeleteItem(ID) {var soapEnv ="<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soapenv:Body>" +"<UpdateListItems xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +"<listName>Ski Resorts</listName>" +"<updates>" +"<Batch OnError=\"Continue\">" +"<Method ID=\"3\" Cmd=\"Delete\">" +"<Field Name=\"ID\">" + ID + "</Field>" +"</Method>" +"</Batch>" +"</updates>" +"</UpdateListItems>" +"</soapenv:Body>" +"</soapenv:Envelope>";$.ajax({url: "http://ski.canviz.com/_vti_bin/lists.asmx",type: "POST",dataType: "xml",data: soapEnv,beforeSend: function (xhr) {xhr.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/UpdateListItems");},complete: processDeleteResultSuccess,contentType: "text/xml; charset=\"utf-8\"",error: processDeleteResultError});}function processDeleteResultError(xData, status) {$("#errorContent").empty();$("#errorContent").append("Delete Item Result:" + status + "</br>");$("#errorContent").trigger("create");}
After the item is successfully deleted, the processDeleteResultSuccess function removes the values from localStorage and returns the user to the main page.
function processDeleteResultSuccess(xData, status) {localStorage.removeItem("currentItemID");localStorage.removeItem("currentItemTitle");window.location = "main.html";}
As the following code shows, the Add New Resort button on the main page calls the ShowCreate function, which is defined in the maininit.js file. This function redirects the user to the creatitem.html page.
function ShowCreate() {window.location = "createitem.html";}
Figure 9 shows the createitem.html page in the Windows Phone 7 emulator. Figure 10 shows the createitem.html page in the Android emulator.
Figure 9: Create item page in the Windows Phone 7 emulator
Figure 10: Create item page in the Android emulator
The following createitem.html page creates a text box to accept the value for the Title column for the new SharePoint list item. Note that the createitem.js file and the spqueries.js file are also included, to facilitate the interaction with SharePoint.
<!DOCTYPE html><html ><head><meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /><meta http-equiv="Content-type" content="text/html; charset=utf-8" /><title>Phonegap SharePoint List Data Editor</title><link rel="stylesheet" href="master.css" type="text/css" media="screen" title="no title" charset="utf-8" /><link rel="stylesheet" href="jquery.mobile-1.0.1.min.css" /><script type="text/javascript" src="jquery-1.7.1.min.js"></script><script type="text/javascript" src="jquery.mobile-1.0.1.min.js"></script><script type="text/javascript" charset="utf-8" src="cordova-1.5.0.js"></script><script type="text/javascript" charset="utf-8" src="createiteminit.js"></script><script type="text/javascript" charset="utf-8" src="spqueries.js"></script></head><body><div data-role="page" data-theme="a" data-content-theme="a"><div data-role="header">Phonegap SharePoint List Data Editor</div><div data-role="content" id="topnavcontent">Add A New Resort</div><div data-role="content" id="resultscontent"><label for="ItemTitle">Name:</label><input type="text" name="ItemTitle" id="ItemTitle" value="" /></div><div data-role="content" id="footercontent"><a href="#" data-role="button" data-icon="plus" onclick="Create(); return false;">Add</a></div><div data-role="content" id="errorContent"></div></body></html>The following createitem init.js file ensures that the localStorage values are removed and resets the form.$(window).load(function () {setTimeout(init, 100);});function init() {$.support.cors = true;$.mobile.allowCrossDomainPages = true;localStorage.removeItem("currentItemID");localStorage.removeItem("currentItemTitle");$("#ItemTitle").val("");}function Create() {CreateItem($("#ItemTitle").val());}
When the Add button is clicked in the createitem.html page, the Create function fires. This function calls the CreateItem function in the spqueries.js file and uses jQuery to retrieve the value from the text box so that the value can be passed as a parameter.
The following CreateItem function uses the SharePoint Lists Web service to create the new item in the Ski Resorts SharePoint list.
function CreateItem(Title) {var soapEnv ="<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +"xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">" +"<soapenv:Body>" +"<UpdateListItemsxmlns=\"http://schemas.microsoft.com/sharepoint/soap/\">" +"<listName>Ski Resorts</listName>" +"<updates>" +"<Batch OnError=\"Continue\">" +"<Method ID=\"1\" Cmd=\"New\">" +"<Field Name=\"ID\">New</Field>" +"<Field Name=\"Title\">" + Title + "</Field>" +"</Method>" +"</Batch>" +"</updates>" +"</UpdateListItems>" +"</soapenv:Body>" +"</soapenv:Envelope>";$.ajax({url: "http://ski.canviz.com/_vti_bin/lists.asmx",type: "POST",dataType: "xml",data: soapEnv,beforeSend: function (xhr) {xhr.setRequestHeader("SOAPAction","http://schemas.microsoft.com/sharepoint/soap/UpdateListItems");},complete: processCreateResultSuccess,contentType: "text/xml; charset=\"utf-8\"",error: processCreateResultError});}function processCreateResultError(xData, status) {$("#errorContent").empty();$("#errorContent").append("Create Item Result:" + status + "</br>");$("#errorContent").trigger("create");}
When the item is created, the success callback function returns the user to the main page.
function processCreateResultSuccess(xData, status) {window.location = "main.html";}
The code samples in this application are designed to be as simple as possible, to illustrate the concepts that this article discusses. You can call into many SharePoint ASMX Web services to do a variety of things with SharePoint. You can also consume RSS feeds from SharePoint lists or use the Open Data Protocol (OData) APIs.
Other ways of creating pages with jQuery Mobile involve using a single .html file to hold all the pages, as well as other ways to create buttons and links in your HTML5 applications. To learn more about these options, visit the jQuery Mobile Framework site. There are also many JavaScript utility libraries that you can use to simplify your JavaScript code and to bind data to templatized HTML. Take some time to research these libraries to determine whether they make sense in your mobile applications.
The Right Approach
As you can see, there are multiple ways to go about building mobile applications that integrate with SharePoint. Understanding the available options and their pros and cons will help you to determine the right approach for your organization. PhoneGap is an emerging technology that speeds application development for multiple mobile target platforms and reduces the maintenance costs that are associated with the applications.
Table 1: Pros and Cons of Mobile App Development Approaches
Approach |
---|
Native |
HTML5/JavaScript/PhoneGap |
About the Author
You May Also Like