ADF Mobile with JQuery Mobile

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

Comments:

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

Posted by Java training on April 25, 2014 at 10:30 PM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

This blog is is dedicated to announcements,tips and tricks and other items related to developing, integrating, securing, and managing mobile applications using Oracle's Mobile Platform. It is created and maintained by the Oracle Mobile product development team.

Archive of past entries

Even More Mobile Development Blogs

Oracle A-Team Site - Mobile Related Entries

Code samples from the Community

Fusion Middleware Blogs

Search

Archives
« April 2015
SunMonTueWedThuFriSat
   
1
2
3
4
5
6
8
9
10
11
12
13
14
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
  
       
Today