X

The Mobile & Digital Assistant Blog covers the latest in mobile and conversational AI development and engagement

ADF Mobile with JQuery Mobile

Jeff Davies
Cloud Success Manager

ADF Mobile and JQuery
Mobile

Recently I’ve been looking at
JQuery Mobile. I’ve been using JQuery for quite some time now but I was totally
unaware of JQuery Mobile. Given my background in JQuery, I thought it should be
a snap to create a JQuery app using ADF Mobile.

It turns out that JQuery Mobile is
not exactly the same as straight-up JQuery, but it is close. In a short amount
of time I was able to extend my basic “Hello World” JQuery app (in a Local HTML
feature of my ADF Mobile application) and have it access the contacts on my
device also. This means that I can write functionality in JQuery Mobile and
still take advantage of the other capabilities that you get with ADF Mobile,
like push notifications and security.

To use JQuery Mobile in an ADF
Mobile application, you simply add a Local HTML feature to the ADF Mobile
project, and then edit the local HTML file to contain your JQuery Mobile code.
One caveat here: I recommend that you use the googleapis URLs for JQuery
instead of the links directly to the JQuery site. Why? It was because the
domain for googleapis is already in the domain whitelist for ADF Mobile by
default.

If you really must use the JQuery
Mobile scripts from JQuery.com you will need to add jquery.com to your
applications whitelist. You do this in the Security tab of the
adfmf-application.xml file as shown next.

Whitelist-ing external javascript sources

I named my Local HTML page
mainPage.html and I set its code to be the following:

<!DOCTYPE html> 
<html lang="en">
<head>

 

<title>JQuery Mobile on ADF</title>

 

<meta name="viewport" content="width=device-width, initial-scale=1">

 

<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.2/jquery.mobile.css" />

 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

 

<script src="http://ajax.googleapis.com/ajax/libs/jquerymobile/1.4.2/jquery.mobile.min.js"></script>
<script type="text/javascript">if (!window.adf) window.adf = {}; adf.wwwPath = "../../../../www/";</script>
<script type="text/javascript" src="https:/www/js/base.js"> </script>
<script type="text/javascript" src="https:/www/js/cordova-2.2.0.js"> </script>

<script type="text/javascript">
var contactArray = null; // No contacts have been found yet
// When the Contacts page is shown, load the contact information
$(document).on( 'pageshow', "#contacts", function(event){
//alert('pageshow - contacts');
getContacts();
});
$(document).on( 'pagecreate', "#contacts", function(event){
// Force a refresh now that the list is loaded. This SHOULD fix
// the display problem, but it doesn't
//alert("about to refresh in pagecreate - contacts");
try {
var theList = $("#contactList").listview();
theList.listview('refresh', true);
} catch(err) {
txt="There was an error on this page.\n\n";
txt+="Error description: " + err.message + "\n\n";
txt+="Click OK to continue.\n\n";
alert(txt);
}
// alert("refreshed");
});

// When the ContactDetail page is shown, load the contact information
$(document).on( 'pageshow', "#contactDetail", function(event){
var urlVars = getUrlVars();
var contact = getContact(urlVars["id"]);
// Set the field values
$('#firstName').val(contact.name.givenName);
$('#lastName').val(contact.name.familyName);
$('#note').val(contact.note);
if(contact.organizations.length > 0) {
// Just show the first organization name
$('#company').val(contact.organizations[0].name);
}
});
function onContactSuccess(contacts) {
// Save array for use on the detail page.
contactArray = contacts;
// Clear out any previous contents of the #contactList <ul>
$("#contactList").empty();
// Add each contact to the contactList
for(var i = 0; i < contacts.length; i++) {
$("#contactList").append('<li><a href="contactDetail.html?id=' + contacts[i].id + '"><h2>' + contacts[i].name.formatted +
'</h2><p>' + contacts[i].note + '</p></a></li>');
}
};
function onContactError(contactError) {
alert('onError!');
};

/**
* Gets all contacts from the on-device contact store
*/
function getContacts() {
var options = new ContactFindOptions();
options.filter="";
options.multiple=true;
// Valid fields are:
// id, rawId, displayName, name, nickname, phoneNumbers,
// emails, addresses, ims, organizations, birthday, note, photos, categories,
// urls, remove, clone, save, display
var fields = ["id", "name", "note", "organizations"];
navigator.contacts.find(fields, onContactSuccess, onContactError, options);
}
/**
* Gets the contact by its ID.
* @param contactID
* @return the contact object with the matching ID. May return null if no contact was found
*/
function getContact(contactID) {
var index = -1; // -1 means not found
for(var i = 0; i < contactArray.length; i++) {
if(contactArray[i].id == contactID) {
// Found the contact
index = i;
break;
}
}
if(index != -1)
return contactArray[index];
else
return null;
}

/**
* Utility function to extract query params from a URL and place
* them in an associative array
*/
function getUrlVars() {
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
function showPage(link) {
window.location = link;
}
</script>
</head>
<body>
<div data-role="page" id="main">

 

<div data-role="header">

 

<h1>Hello JQuery Mobile!</h1>

 

</div><!-- /header -->

 

<div role="main" class="ui-content">

 

<p>A simple JQuery Mobile application running in an ADF Mobile application.</p>
<input type="button" id="btnContacts" value="Contacts" onclick="showPage('#contacts')" />

 

</div><!-- /content -->

 

<div data-role="footer" data-position="fixed">

 

<h4>Built with ADF Mobile</h4>

 

</div><!-- /footer -->
</div><!-- /page -->
<!-- Contacts page -->
<div data-role="page" id="contacts">

 

<div data-role="header" data-add-back-btn="true">

 

<h1>Contacts</h1>

 

</div><!-- /header -->

 

<div role="main" class="ui-content">
<ul data-role="listview" id="contactList" data-filter="true">
</ul>

 

</div><!-- /content -->

 

<div data-role="footer" data-position="fixed">

 

<h4>Built with ADF Mobile</h4>

 

</div><!-- /footer -->
</div><!-- /page -->
</body>
</html>

It’s pretty simple. The “main”
page has a button that will take you to the “contacts“ page. The contacts page
shows a list of the contacts on your device. It also provides a filter for that
list. The filtering is done on the javascript side of things, not on the call
to get the list of contacts, so filtering the results is pretty fast and
doesn’t make more than 1 call to the contacts database to get its information.

If you click on a contact the app
will show you a detailed view of that contact. Getting this Master-Detail view
was pretty simple once I figured it out. The problem I had was passing the
specific contact to the detail view. If I kept the contact detail page defined
in the mainPage.html, I couldn’t figure out a good way to pass the information.
I tried appending the array index to the href (i.e. “#contactDetail?id=1”) but when the href was evaluated as a
local target, the query param was truncated.

The solution was to create a
second page that handled the contact details. By using a second page the query
parameter was not truncated. JQuery
Mobile seemed smart enough to just load the content of the contentDetail.html
page, but it ignored the javascript I had. Once I moved all of the javascript
into the mainPage.html, everything worked fine.

<!DOCTYPE html>
<html>
    <head>
        <title>New Contact Detail</title>
    </head>
    <body>
        <!-- Contact Detail page -->
  <div data-role="page" id="contactDetail">

 

<div data-role="header" data-add-back-btn="true">

 

<h1>Contact Detail</h1>

 

</div><!-- /header -->

 

<div role="main" class="ui-content">
<label for="firstName">First Name</label><input type="text" readonly="true" id="firstName" />
<label for="lastName">Last Name</label><input type="text" readonly="true" id="lastName" />
<label for="company">Company</label><input type="text" readonly="true" id="company" />
<label for="note">Note</label><textarea id="note" cols="30" rows="4" readonly="true" ></textarea>

 

</div><!-- /content -->

 

<div data-role="footer" data-position="fixed">
<h4>Built with ADF Mobile</h4>

 

</div><!-- /footer -->
</div><!-- /page -->
</body>
</html> The contact detail page

There is still one little display
bug that I need to figure out though. For some reason the list of contacts does
not display nicely until I enter a character or more in the filter bar. My
research led me to the listview() method, however, I have not been able to get
that to work. I’ve tried several ways of using the operation and place it in
various page event locations, but to no avail. If any of you JQuery experts
know how to resolve this issue, I’d love to hear from you!

Display bug

Follow me on Twitter @JeffDavies_Orlc

Join the discussion

Comments ( 1 )
  • Java training Saturday, April 26, 2014

    This is nice blog and unique information related to jquery. Thanks for sharing such information...


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.

Recent Content