The contacts plugin provides access to the device's contacts database in order to find and create contacts. In order to use the contacts plugin in our Apache Cordova project, we need to use the following cordova plugin add
command:
> cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts.git
In order to access the contacts demo, you can click on the Contacts list item. You will be introduced to the Contacts page. You can search for contacts by typing in the search field (you have to type at least three characters), as shown in the following screenshot:
You can click on any of the filtered contacts, and you will be introduced to the Contact Details page in order to check the contact details, as shown in the following screenshot:
The following code snippet shows the "contacts"
page:
<div data-role="page" id="contacts"> <div data-role="header"> <h1>Contacts</h1> <a href="#" data-role="button" data-rel="back" data-icon="back">Back</a> </div> <div data-role="content"> <ul data-role="listview" id="contactList" data-filter="true" data-filter-placeholder="Enter 3+ chars to search ..."> </ul> </div> </div>
As shown in the preceding "contacts"
page code snippet, it contains the following:
"contactList"
) that is defined by setting the data-role
attribute to "listview"
. Setting the data-filter
attribute to true
tells jQuery Mobile to provide a search field for our list view. Finally, the placeholder
attribute informs the user to enter at least three characters in order to search for contacts.When the user clicks on any of the filtered contacts, the user will be introduced to the "contactDetails
" page. The following code snippet shows the "contactDetails"
page:
<div data-role="page" id="contactDetails"> <div data-role="header"> <h1>Contact Details</h1> <a href="#" data-role="button" data-rel="back" data-icon="back">Back</a> </div> <div data-role="content"> <div id="contactInfo"></div> </div> </div>
As shown in the preceding "contact details"
page code snippet, it contains the following:
"contactInfo"
div to display information on contact detailsThe following code snippet shows the contacts page view controller JavaScript object that includes the event handlers of the page (contacts.js
):
(function() { var contactsManager = ContactsManager.getInstance(); $(document).on("pageinit", "#contacts", function(e) { e.preventDefault(); $("#contactList").on("filterablebeforefilter", function (e, data) { e.preventDefault(); var filterText = data.input.val(); if (filterText && filterText.length > 2) { var callback = {}; callback.onSuccess = function (contacts) { updateContactsList(contacts); }; callback.onError = function (error) { $("#contactList").empty(); $("<li>Error displaying contacts</li>").appendTo("#contactList"); }; contactsManager.getAllContacts(callback, filterText); } }); }); function updateContactsList(contacts) { $("#contactList").empty(); if (jQuery.isEmptyObject(contacts)) { $("<li>No Contacts Available</li>").appendTo("#contactList"); } else { var i; //Display the top 50 elements for (i = 0; i < contacts.length || i < 50; ++i) { if (contacts[i]) { $("<li><a href='#contactDetails?contact=" + encodeURIComponent(JSON.stringify(contacts[i])) + "'>" + contacts[i].name.formatted + "</a></li>").appendTo("#contactList"); } } } $("#contactList").listview('refresh'), } })();
As highlighted in the preceding code snippet, the "pageinit"
event handler registers the "filterablebeforefilter"
event handler on the "contactList"
list view in order to create our custom contacts filter. In the "filterablebeforefilter"
event handler, the current filter text entered by the user is retrieved by calling data.input.val()
. In order to minimize the search space, the filter text has to be at least three characters. If the filter text's length exceeds two characters, then a call to the contactsManager.getAllContacts(callback, filterText)
method is performed in order to get all the contacts that match the entered filter text.
In order to call the contactsManager.getAllContacts(callback, filterText)
method, we specified a callback object that contains two attributes: the onSuccess
attribute (which represents a success callback) and the onError
attribute (which represents a failure callback). The onSuccess
callback receives the filtered contacts list and then calls the updateContactsList()
method in order to update the current contacts list view with the new filtered contacts list. The onError
callback just displays an error message to the user. The second parameter filterText
represents the input filter text.
The updateContactsList(contacts)
method clears the "contactList"
list view, and if the contacts list (contacts
) is not empty, contacts are appended to the "contactList"
list view, and finally, the "contactList"
list view is refreshed with new updates.
You might notice that every contact item in the list view is linked to the "contactDetails"
page and passes the item's contact object as a parameter (after converting the contact object to an encoded JSON string).
Thanks to the jQuery Mobile page parameters plugin (which can be downloaded from https://github.com/jblas/jquery-mobile-plugins/tree/master/page-params) and its inclusion in the index.html
file, we can pass parameters between pages easily using "#pageID?param1=value1¶m2=value2 ...etc
.
However, in our application, in the js/common.js
file (which contains common utilities across all of the app pages and is included after the plugin, that is, the jqm.page.params.js
file), we added a small utility over the plugin in order to retrieve page parameters at any event of the "to"
page. In order to implement this, we create an event handler for the "pagebeforechange"
event in order to get the passed parameter(s), as shown in the following code snippet:
$(document).bind("pagebeforechange", function(event, data) { $.mobile.pageData = (data && data.options && data.options.pageData) ? data.options.pageData : null; });
By checking data.options.pageData
, we can determine whether there are any passed parameters from the "from"
page to the "to"
page, thanks to the page parameters plugin. After getting the passed parameters, we set them in $.mobile.pageData
, which can be accessible from any event in the "to"
page. If there are no passed parameters, then $.mobile.pageData
will be set to null
.
The following code snippet shows
contactDetails.js
, which is the view controller of the "contactDetails"
page:
(function() { $(document).on("pageshow", "#contactDetails", function(e) { e.preventDefault(); var contactDetailsParam = $.mobile.pageData.contact || null; var contactDetails = JSON.parse(decodeURIComponent(contactDetailsParam)); var i; var numbers = ""; if (contactDetails.phoneNumbers) { for (i = 0; i < contactDetails.phoneNumbers.length; ++i) { numbers = "<a href='tel:" + contactDetails.phoneNumbers[i].value + "'>" + contactDetails.phoneNumbers[i].value + "</a><br/>"; } } else { numbers = "NA<br/>"; } $("#contactInfo").html("<p>" + "Name: <strong>" + contactDetails.name.formatted + "</strong><br/><br/>" + "Phone(s): " + "<br/>" + numbers + "</p>"); }); })();
In the "pageshow"
event handler of the "contactDetails"
page, contactDetails
is retrieved using $.mobile.pageData.contact
and then decoded and parsed to be converted to a JavaScript object. Finally, the contact names and numbers are acquired from contactDetails
using contactDetails.name.formatted
and contactDetails.phoneNumbers
and are displayed in the "contactInfo"
div.
The following code snippet shows the contacts manager JavaScript object that wraps the Apache Cordova Contacts API (ContactsManager.js
):
var ContactsManager = (function () { var instance; function createObject() { return { getAllContacts: function (callback, filterText) { var options = new ContactFindOptions(); options.filter = filterText || ""; options.multiple = true; var fields = ["id", "name", "phoneNumbers"]; navigator.contacts.find(callback.onSuccess, callback.onError, fields, options); } }; }; return { getInstance: function () { if (!instance) { instance = createObject(); } return instance; } }; })();
As you can see, ContactsManager
is a singleton object that has a single method as highlighted in the preceding code. The getAllContacts(callback, filterText)
method uses the Cordova navigator.contacts.find()
method to retrieve contacts.
The navigator.contacts.find(contactSuccess, contactError, contactFields, contactFindOptions)
method has the following parameters:
contactSuccess
: This callback will be called if the operation succeeds. It receives the retrieved contacts array as a parameter. In ContactsManager
, contactSuccess
is set to callback.onSuccess
.contactError
: This callback will be called if the operation fails. In ContactsManager
, contactError
is set to callback.onError
.contactFields
: This object specifies the fields of every contact object in the returned result of navigator.contacts.find()
. In ContactsManager
, we specified the ["id", "name", "phoneNumbers"]
contact fields.contactFindOptions
: This is an optional parameter that is used to filter contacts.The contactFindOptions
parameter has the attributes shown in the following table:
We are now done with the Contacts
functionality in the Cordova Exhibition app. However, before exploring the device's API functionality, note that the navigator.contacts.find()
method's contactFields
parameter can have one or more attribute(s) from the Contact
object, whose attributes are specified in the following table:
The ContactName
object has the attributes shown in the following table:
Attribute name |
Description |
---|---|
| |
| |
| |
| |
| |
|
The ContactField
object has the attributes shown in the following table:
The ContactAddress
object has the attributes shown in the following table:
The ContactOrganization
object has the attributes shown in the following table:
The navigator.contacts
object has also the method shown in the following table:
18.226.181.57