This section presents the full source code of a working sample widget
for the Contacts Service.
You can download the wgz
package for this widget from
section Example widgets.
For general information about creating widgets, see section Widget component files.
For widget development and debugging purposes, this example writes its
output to c:\data\jslog_widget.log
using console.info
.
For instructions on how to enable logging in the Web browser for S60, see
section JavaScript console.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Nokia//DTD PLIST 1.0//EN" "http://www.nokia.com/NOKIA_COM_1/DTDs/plist-1.0.dtd"> <plist version="1.0"> <dict> <key>DisplayName</key> <string>ContactSample</string> <key>Identifier</key> <string>com.nokia.widget.sapi.contact.sample</string> <key>Version</key> <string>1.0</string> <key>MainHTML</key> <string>contact-sample.html</string> </dict> </plist>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <script type="text/javascript" src="js/common.js"></script> <script type="text/javascript" src="js/contact-sample.js"></script> </head> <body id='docBody' bgcolor="#ddeeff" onload="setup()" style=width:100%;height:100%;> <form name="frm"> <h3>Contact API Sample Widget</h3> Async<input type="checkbox" id="async_check" onClick="check_async()"> Cancel<input type="checkbox" id="cancel_check" onClick="check_cancel()"><br/> <hr> <input type="button" onclick="addContact('img1')" value="AddContact"><img id="img1" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="delContact('img2')" value="DeleteContact"><img id="img2" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="getContactList('img3')" value="GetContactList"><img id="img3" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="importContact('img4')" value="ImportContact"><img id="img4" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="exportContact('img5')" value="ExportContact"><img id="img5" src="pic/blank.png" width="25" height="25" align="center"><br> <hr> <input type="button" onclick="addGroup('img6')" value="AddGroup"><img id="img6" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="delGroup('img7')" value="DeleteGroup"><img id="img7" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="getGroupList('img8')" value="GetGroupList"><img id="img8" src="pic/blank.png" width="25" height="25" align="center"><br> <input type="button" onclick="organiseGroup('img9')" value="OrganiseGroup"><img id="img9" src="pic/blank.png" width="25" height="25" align="center"><br> <hr> <div class='contactsample' id='contactsample' bgcolor="#ddeeff" style=width:100%;height:100%;overflow:auto></div> </form> </body> </html>
// common.js // // This file contains some utility functions // Check the error code and show the information to users function checkError(message, resultList, divId, imgId) { var errCode = resultList.ErrorCode; var msg = ""; if (errCode) { msg = message + "<BR>" + "Failed Error: " + errCode + "<BR>"; if(resultList.ErrorMessage != undefined) msg += "Error Message: " + resultList.ErrorMessage; showIMG(imgId,"no"); } else { showIMG(imgId,"yes"); } //print error message if(divId != null && divId != undefined) document.getElementById(divId).innerHTML = msg; console.info(msg); return errCode; } // Build the message by reading a iteratorable list in a recursive manner function showIterableList(iterator) { var msg = ""; try { iterator.reset(); var item; while (( item = iterator.getNext()) != undefined ){ msg += showObject( item ); } } catch(e) { alert('<showIterableList> ' + e); } return msg; } // Build the message by reading a JS object in a recursive manner function showObject( obj ) { var txt = ""; try { if ( typeof obj != 'object' ) return "" + obj + '<BR/>'; else { for(var key in obj) { txt += key + ":"; txt += showObject( obj[key] ); txt += '<BR/>'; } txt += '<BR/>'; } } catch (e) { alert("showObject: " + e); } return txt; } // Show the image to indicate the test result function showIMG(imgId, isOK) { if(imgId == null || imgId == undefined) return; if(isOK == "yes") document.getElementById(imgId).src = "pic/yes.png"; else if(isOK == "no") document.getElementById(imgId).src = "pic/no.png"; else document.getElementById(imgId).src = "pic/blank.png"; } // Show elements in object by using 'alert' function testObject(obj) { var msg = ""; for(var key in obj) { msg = msg + ":" + key + "=" + obj[key]; } alert(msg); } // Test whether the input is numeric function IsNumeric(sText) { var ValidChars = "0123456789."; var IsNumber=true; var Char; for (i = 0; i < sText.length && IsNumber == true; i++) { Char = sText.charAt(i); if (ValidChars.indexOf(Char) == -1) { IsNumber = false; } } return IsNumber; }
// contact-sample.js // // In this sample Contact and Group will be added, deleted, and listed from // default database; Contact will be imported and exported; Group will be // organised; Also, async operation will be canceled // //SAPI Error Codes // 0 - Success // 1000 - InvalidServiceArgument // 1001 - UnknownArgumentName // 1002 - BadArgumentType // 1003 - MissingArgument // 1004 - ServiceNotSupported // 1005 - ServiceInUse // 1006 - ServiceNotReady // 1007 - NoMemory // 1008 - HardwareNotAvailable // 1009 - ServerBusy // 1010 - EntryExists // 1011 - AccessDenied // 1012 - NotFound // 1013 - UnknownFormat // 1014 - GeneralError // 1015 - CancelSuccess // 1016 - ServiceTimedOut // 1017 - PathNotFound // declare the service object var so; // async Test Mode var asyncMode; // cancel Test Mode var cancelMode; // imgid for callback1 function var imgid_callback1; // imgid for callback2 function var imgid_callback2; // imgid for callback3 function var imgid_callback3; // imgid for callback4 function var imgid_callback4; // imgid for callback5 function var imgid_callback5; // imgid for callback6 function var imgid_callback6; // imgid for callback7 function var imgid_callback7; // id of the div used to display information const DIV_ID = 'contactsample'; // Called from onload() function setup() { try { so = device.getServiceObject("Service.Contact", "IDataSource"); console.info("setup: so: %s", so); } catch (e) { alert('<setup> ' +e); } } // Async checkbox handler function check_async() { var asyncChk = document.getElementById("async_check"); asyncMode = asyncChk.checked; if (!asyncMode) { var cancelChk = document.getElementById("cancel_check"); cancelChk.checked = false; cancelChk = false; } } // cancel checkbox handler function check_cancel() { var cancelChk = document.getElementById("cancel_check"); cancelMode = cancelChk.checked; // if cancel checkbox is selected, the async checkbox should be // selected automatically if(cancelMode) { var asyncChk = document.getElementById("async_check"); asyncChk.checked = true; asyncMode = true; } } // Add Contact function addContact(imgId) { var last = new Object(); last.Label = "Last name"; last.Value = "Shen"; var first = new Object(); first.Label = "First name"; first.Value = "Yi"; var contactdata = new Object(); contactdata.LastName = last; contactdata.FirstName = first; var criteria = new Object(); criteria.Type = "Contact"; criteria.Data = contactdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Add(criteria); checkError("IDataSource::addContact",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback1 function imgid_callback1 = imgId; result = so.IDataSource.Add(criteria, callback1); if(!checkError("IDataSource::addContactAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback1 function imgid_callback1 = imgId; result = so.IDataSource.Add(criteria, callback1); if(!checkError("IDataSource::cancelAddContactAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelAddContactAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("addContact: " + e); } } // Delete Contact function delContact(imgId) { // using the getFirstId to get the Contact Id // it is impossible to ask user to type the Contact Id because // the id is in binary and hard to be displayed by javascritp var contactId = getFirstId("Contact"); if(contactId == null) { alert("No contact exists!"); return; } var contactdata = new Object(); contactdata.IdList = new Array(); contactdata.IdList[0] = contactId; var criteria = new Object(); criteria.Type = "Contact"; criteria.Data = contactdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Delete(criteria); checkError("IDataSource::delContact",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback2 function imgid_callback2 = imgId; result = so.IDataSource.Delete(criteria, callback2); if(!checkError("IDataSource::delContactAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback2 function imgid_callback2 = imgId; result = so.IDataSource.Delete(criteria, callback2); if(!checkError("IDataSource::cancelDelContactAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelDelContactAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("delContact: " + e); } } // Show Contact List // find the property names in AddContact() // Note, the contact id cannot be display correctly by javascript because // it is a binary number function showContactList(iterator) { var msg = ""; try { iterator.reset(); var item; while (( item = iterator.getNext()) != undefined ){ var lastName = item['LastName']; var firstName = item['FirstName']; msg += lastName['Label'] + ":" + lastName['Value'] + "<br>"; msg += firstName['Label'] + ":" + firstName['Value'] + "<br>"; msg += "<br>"; } } catch(e) { alert('<showContacList> ' + e); } return msg; } // Get the first Id function getFirstId(type) { var criteria = new Object(); criteria.Type = type; var result; var firstId = null; result = so.IDataSource.GetList(criteria); if(!result.ErrorCode) { var iterator = result.ReturnValue; var item = iterator.getNext(); firstId = item['id']; } return firstId; } // Get Contact List function getContactList(imgId) { var criteria = new Object(); criteria.Type = "Contact"; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.GetList(criteria); if(!checkError("IDataSource::getContactList",result,DIV_ID,imgId)) { document.getElementById(DIV_ID).innerHTML = showContactList(result.ReturnValue); } } else if (asyncMode && !cancelMode) {// async // set the image id for callback7 function imgid_callback7 = imgId; result = so.IDataSource.GetList(criteria, callback7); if(!checkError("IDataSource::getContactListAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback7 function imgid_callback7 = imgId; result = so.IDataSource.GetList(criteria, callback7); if(!checkError("IDataSource::cancelGetContactListAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelGetContactListAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("getContactList: " + e); } } // Import Contact function importContact(imgId) { var impFileName = prompt("Please enter the file name", "contact-export.txt"); if (impFileName == "") return; var contactdata = new Object(); contactdata.SourceFile = impFileName; var criteria = new Object(); criteria.Type = "Contact"; criteria.Data = contactdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Import(criteria); checkError("IDataSource::Import",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback4 function imgid_callback4 = imgId; result = so.IDataSource.Import(criteria, callback4); if(!checkError("IDataSource::ImportAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback4 function imgid_callback4 = imgId; result = so.IDataSource.Import(criteria, callback4); if(!checkError("IDataSource::cancelImportAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelImportAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("importContact: " + e); } } // Export Contact function exportContact(imgId) { // using the getFirstId to get the Contact Id // it is impossible to ask user to type the Contact Id because // the id is in binary and hard to be displayed by javascritp var contactId = getFirstId("Contact"); if(contactId == null) { alert("No contact exists!"); return; } var expFileName = prompt("Please enter the file name", "contact-export.txt"); if (expFileName == "" || expFileName == null) return; var contactdata = new Object(); contactdata.id = contactId; contactdata.DestinationFile = expFileName; var criteria = new Object(); criteria.Type = "Contact"; criteria.Data = contactdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Export(criteria); checkError("IDataSource::Export",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback5 function imgid_callback5 = imgId; result = so.IDataSource.Export(criteria, callback5); if(!checkError("IDataSource::ExportAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback5 function imgid_callback5 = imgId; result = so.IDataSource.Export(criteria, callback5); if(!checkError("IDataSource::cancelExportAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelExportAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("exportContact: " + e); } } // Add Group function addGroup(imgId) { var groupdata = new Object(); groupdata.GroupLabel = "TestGroupName" var criteria = new Object(); criteria.Type = "Group"; criteria.Data = groupdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Add(criteria); checkError("IDataSource::addGroup",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback1 function imgid_callback1 = imgId; result = so.IDataSource.Add(criteria, callback1); if(!checkError("IDataSource::addGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback1 function imgid_callback1 = imgId; result = so.IDataSource.Add(criteria, callback1); if(!checkError("IDataSource::cancelAddGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelAddGroupAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("addGroup: " + e); } } // Delete Group function delGroup(imgId) { // using the getFirstId to get the Group Id // it is impossible to ask user to type the Group Id because // the id is in binary and hard to be displayed by javascritp var groupId = getFirstId("Group"); if(groupId == null) { alert("No Group exists!"); return; } var groupdata = new Object(); groupdata.IdList = new Array(); groupdata.IdList[0] = groupId; var criteria = new Object(); criteria.Type = "Group"; criteria.Data = groupdata; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Delete(criteria); checkError("IDataSource::delGroup",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback2 function imgid_callback2 = imgId; result = so.IDataSource.Delete(criteria, callback2); if(!checkError("IDataSource::delGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback2 function imgid_callback2 = imgId; result = so.IDataSource.Delete(criteria, callback2); if(!checkError("IDataSource::cancelDelGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelDelGroupAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("delGroup: " + e); } } // Show Group List // find the property names in AddGroup() // Note, the group id cannot be display correctly by javascript because // it is a binary number function showGroupList(iterator) { var msg = ""; try { iterator.reset(); var item; while (( item = iterator.getNext()) != undefined ){ msg += item['GroupLabel'] + "<br>"; var groupList = item['Contents']; if(groupList == null || groupList == undefined) msg += "No group member.<br>"; else { var i = 0; for (var key in groupList) i++; msg += "There are " + i +" contacts in this group.<br>"; } msg += "<br>"; } } catch(e) { alert('<showGroupList> ' + e); } return msg; } // Get Group function getGroupList(imgId) { var criteria = new Object(); criteria.Type = "Group"; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.GetList(criteria); if(!checkError("IDataSource::getGroupList",result,DIV_ID,imgId)) { document.getElementById(DIV_ID).innerHTML = showGroupList(result.ReturnValue); } } else if (asyncMode && !cancelMode) {// async // set the image id for callback3 function imgid_callback3 = imgId; result = so.IDataSource.GetList(criteria, callback3); if(!checkError("IDataSource::getGroupListAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback3 function imgid_callback3 = imgId; result = so.IDataSource.GetList(criteria, callback3); if(!checkError("IDataSource::cancelGetGroupListAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelGetGroupListAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("getGroupList: " + e); } } // Organise Group function organiseGroup(imgId) { // using the getFirstId to get the Group Id // it is impossible to ask user to type the Group Id because // the id is in binary and hard to be displayed by javascritp var groupId = getFirstId("Group"); if(groupId == null) { alert("No Group exists!"); return; } // using the getFirstId to get the Contact Id // it is impossible to ask user to type the Contact Id because // the id is in binary and hard to be displayed by javascritp var contactId = getFirstId("Contact"); if(contactId == null) { alert("No contact exists!"); return; } //"Associate" //"Disassociate" var msg = "Please enter the operation type ['Associate' or 'Disassociate']"; var optype = prompt(msg, "Associate"); if (optype == "" || optype == null) return; var groupdata = new Object(); groupdata.id = groupId; groupdata.IdList = new Array(); groupdata.IdList[0] = contactId; var criteria = new Object(); criteria.Type = "Group"; criteria.Data = groupdata; criteria.OperationType = optype; try { var result; if (!asyncMode && !cancelMode) { // sync result = so.IDataSource.Organise(criteria); checkError("IDataSource::organiseGroup",result,DIV_ID,imgId); } else if (asyncMode && !cancelMode) {// async // set the image id for callback6 function imgid_callback6 = imgId; result = so.IDataSource.Organise(criteria, callback6); if(!checkError("IDataSource::organiseGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); } } else if (cancelMode){ // cancel // set the image id for callback6 function imgid_callback6 = imgId; result = so.IDataSource.Organise(criteria, callback6); if(!checkError("IDataSource::cancelOrganiseGroupAsync",result,DIV_ID,imgId)) { showIMG(imgId,""); var criteria2 = new Object(); criteria2.TransactionID = result.TransactionID; var result2 =so.IDataSource.Cancel(criteria2); checkError("IDataSource::cancelOrganiseGroupAsync",result2,DIV_ID,imgId); } } } catch (e) { showIMG(imgId,"no"); alert ("organiseGroup: " + e); } } // This is the asynchronous callback handler function callback1(transId, eventCode, result) { console.info("addAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); checkError("IDataSource::addAsync",result,DIV_ID,imgid_callback1); } // This is the asynchronous callback handler function callback2(transId, eventCode, result) { console.info("delAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); checkError("IDataSource::delAsync",result,DIV_ID,imgid_callback2); } // This is the asynchronous callback handler function callback3(transId, eventCode, result) { console.info("getListAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); if(!checkError("IDataSource::getListAsync",result,DIV_ID,imgid_callback3)) { document.getElementById(DIV_ID).innerHTML = showGroupList(result.ReturnValue); } } // This is the asynchronous callback handler function callback4(transId, eventCode, result) { console.info("importAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); checkError("IDataSource::importAsync",result,DIV_ID,imgid_callback4); } // This is the asynchronous callback handler function callback5(transId, eventCode, result) { console.info("exportAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); checkError("IDataSource::exportAsync",result,DIV_ID,imgid_callback5); } // This is the asynchronous callback handler function callback6(transId, eventCode, result) { console.info("organiseAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); checkError("IDataSource::organiseAsync",result,DIV_ID,imgid_callback6); } // This is the asynchronous callback handler function callback7(transId, eventCode, result) { console.info("getListAsync: transId: %d eventCode: %d result.ErrorCode: %d", transId, eventCode, result.ErrorCode); if(!checkError("IDataSource::getListAsync",result,DIV_ID,imgid_callback7)) { document.getElementById(DIV_ID).innerHTML = showContactList(result.ReturnValue); } }