cordova-plugin-contacts
Advanced tools
Comparing version 0.2.5 to 0.2.6
{ | ||
"name": "cordova-plugin-contacts", | ||
"version": "0.2.5", | ||
"version": "0.2.6", | ||
"description": "Cordova Contacts Plugin", | ||
@@ -5,0 +5,0 @@ "cordova": { |
@@ -6,1 +6,7 @@ cordova-plugin-contacts | ||
If you are not using the Cordova Command-line Interface, follow [Using Plugman to Manage Plugins](http://cordova.apache.org/docs/en/edge/plugin_ref_plugman.md.html). | ||
## Using Contacts in Firefox OS | ||
Edit manifest.webapp and add permissions field as described in [Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest#permissions). | ||
There is also a need to change the webapp type to "privileged" - [Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest#type). | ||
All privileged apps enforce [Content Security Policy](https://developer.mozilla.org/en-US/Apps/CSP) which forbids inline script. Initialize your application in another way. |
@@ -45,1 +45,24 @@ <!-- | ||
* [CB-5010] Incremented plugin version on dev branch. | ||
### 0.2.6 (Dec 4, 2013) | ||
* Fix bad commit/merge | ||
* CB-3035 Fix issue with windows new line char \n\r | ||
* wrong example given | ||
* docs added | ||
* FxOS name fields are arrays hackedSearch refactored search based on find commented out | ||
* search hacked via getAll | ||
* search added - no idea if this is working | ||
* createMozillaFromCordova and vice versa are used to translate contact objects from one API to another. | ||
* add/remove working | ||
* save is working | ||
* attempt to save is failing trying to limit the translated contact fields to name and familyName, but still failing | ||
* save is linked with the proxy contact.name doesn't exist www/Contact.js#Contact.prototype.save check on which side is the error | ||
* CB-5214 Make mobile spec tests on WP8 to run w/o user interaction + Sync with cordova-mobile-spec | ||
* CB-5525 WP8. Contacts Api fails in case of there is special character in contact field | ||
* fixed ubuntu policy error | ||
* [ubuntu] specify policy_group | ||
* add ubuntu platform | ||
* CB-3035 Fix issue with windows new line char \n\r | ||
* 1. Added amazon-fireos platform. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'. | ||
* CB-5198 [BlackBerry10] Update dependencies to point to registry | ||
* handle null filter when fields are specified. ( long standing pull-req from @kevfromireland ) |
@@ -28,81 +28,274 @@ /* | ||
// https://developer.mozilla.org/en-US/docs/Web/API/mozContact | ||
function saveContact(contacts, success, fail) { | ||
// success and fail will be called every time a contact is saved | ||
for (var contact in contacts) { | ||
var moz = new mozContact(), | ||
request; | ||
function exportContactFieldArray(contactFieldArray, key) { | ||
if (!key) { | ||
key = 'value'; | ||
} | ||
var arr = []; | ||
for (var i in contactFieldArray) { | ||
arr.push(contactFieldArray[i][key]); | ||
}; | ||
return arr; | ||
} | ||
function exportAddress (addresses) { | ||
// TODO: check moz address format | ||
var arr = []; | ||
for (var i in addresses) { | ||
var addr = {}; | ||
for (var key in addresses[i]) { | ||
addr[key] = addresses[i][key]; | ||
} | ||
arr.push(addr); | ||
} | ||
return arr; | ||
var Contact = require('./Contact'); | ||
var ContactField = require('./ContactField'); | ||
var ContactName = require('./ContactName'); | ||
function createMozillaFromCordova(contact) { | ||
function exportContactFieldArray(contactFieldArray, key) { | ||
if (!key) { | ||
key = 'value'; | ||
} | ||
var arr = []; | ||
for (var i=0; i < contactFieldArray.length; i++) { | ||
arr.push(contactFieldArray[i][key]); | ||
}; | ||
return arr; | ||
} | ||
function exportAddress(addresses) { | ||
// TODO: check moz address format | ||
var arr = []; | ||
for (var i=0; i < addresses.length; i++) { | ||
var addr = {}; | ||
for (var key in addresses[i]) { | ||
addr[key] = addresses[i][key]; | ||
} | ||
// prepare mozContact object | ||
// TODO: find a way to link existing mozContact and Contact | ||
// (by ID?) | ||
moz.init({ | ||
name: [contact.name.familyName, | ||
contact.name.givenName, | ||
contact.name.middleName, | ||
contact.name.nickname], | ||
honorificPrefix: [contact.name.honorificPrefix], | ||
givenName: [contact.name.givenName], | ||
familyName: [contact.name.familyName], | ||
honorificSuffix: [contact.name.honorificSuffix], | ||
nickname: [contact.nickname], | ||
email: exportContactFieldArray(contact.emails), | ||
// photo: Blob | ||
// url: Array with metadata (?) | ||
category: exportContactFieldArray(contact.categories), | ||
adr: exportAddress(contact.addresses), | ||
tel: exportContactFieldArray(contact.phoneNumbers), | ||
org: exportContactFieldArray(contact.organizations, 'name'), | ||
jobTitle: exportContactFieldArray(contact.organizations, 'title'), | ||
bday: contact.birthday, | ||
note: contact.note, | ||
// impp: exportIM(contact.ims), TODO: find the moz impp definition | ||
// anniversary | ||
// sex | ||
// genderIdentity | ||
// key | ||
arr.push(addr); | ||
} | ||
return arr; | ||
} | ||
function exportPhoneNumbers(phoneNumbers) { | ||
var mozNumbers = []; | ||
for (var i=0; i < phoneNumbers.length; i++) { | ||
var number = phoneNumbers[i]; | ||
mozNumbers.push({ | ||
type: number.type, | ||
value: number.value, | ||
pref: number.pref | ||
}); | ||
request = navigator.mozContacts.save(moz); | ||
request.onsuccess = success; | ||
request.onerror = fail; | ||
} | ||
return mozNumbers; | ||
} | ||
// prepare mozContact object | ||
var moz = new mozContact(); | ||
if (contact.id) { | ||
moz.id = contact.id; | ||
} | ||
// adding simple fields [contactField, eventualMozContactField] | ||
var arrayFields = [['givenName'], ['familyName'], ['displayName', 'name']]; | ||
var simpleFields = [['honorificPrefix'], ['honorificSuffix'], ['nickname'], ['birthday', 'bday'], ['note']]; | ||
j = 0; while(field = arrayFields[j++]) { | ||
if (contact.name[field[0]]) { | ||
moz[field[1] || field[0]] = contact.name[field[0]].split(' '); | ||
} | ||
} | ||
j = 0; while(field = simpleFields[j++]) { | ||
if (contact.name[field[0]]) { | ||
moz[field[1] || field[0]] = contact.name[field[0]]; | ||
} | ||
} | ||
if (contact.emails) { | ||
moz.email = exportContactFieldArray(contact.emails); | ||
} | ||
if (contact.categories) { | ||
moz.category = exportContactFieldArray(contact.categories); | ||
} | ||
if (contact.addresses) { | ||
moz.adr = exportAddress(contact.addresses); | ||
} | ||
if (contact.phoneNumbers) { | ||
moz.tel = exportPhoneNumbers(contact.phoneNumbers); | ||
} | ||
if (contact.organizations) { | ||
moz.org = exportContactFieldArray(contact.organizations, 'name'); | ||
moz.jobTitle = exportContactFieldArray(contact.organizations, 'title'); | ||
} | ||
/* Find out how to translate these parameters | ||
// photo: Blob | ||
// url: Array with metadata (?) | ||
// impp: exportIM(contact.ims), TODO: find the moz impp definition | ||
// anniversary | ||
// sex | ||
// genderIdentity | ||
// key | ||
*/ | ||
return moz; | ||
} | ||
function createCordovaFromMozilla(moz) { | ||
function exportPhoneNumbers(mozNumbers) { | ||
var phoneNumbers = []; | ||
for (var i=0; i < mozNumbers.length; i++) { | ||
var number = mozNumbers[i]; | ||
phoneNumbers.push( | ||
new ContactField( number.type, number.value, number.pref)); | ||
} | ||
return phoneNumbers; | ||
} | ||
var contact = new Contact(); | ||
if (moz.id) { | ||
contact.id = moz.id; | ||
} | ||
var arrayFields = [['givenName'], ['familyName'], ['name', 'displayName']]; | ||
var simpleFields = [['honorificPrefix'], ['honorificSuffix'], ['nickname'], ['bday', 'birthday'], ['note']]; | ||
var name = new ContactName(); | ||
var j = 0; while(field = arrayFields[j++]) { | ||
if (moz[field[0]]) { | ||
name[field[1] || field[0]] = moz[field[0]].join(' '); | ||
} | ||
} | ||
j = 0; while(field = simpleFields[j++]) { | ||
if (moz[field[0]]) { | ||
name[field[1] || field[0]] = moz[field[0]]; | ||
} | ||
} | ||
contact.name = name; | ||
// emails | ||
// categories | ||
// addresses | ||
if (moz.tel) { | ||
contact.phoneNumbers = exportPhoneNumbers(moz.tel); | ||
} | ||
// organizations | ||
return contact; | ||
} | ||
function saveContacts(successCB, errorCB, contacts) { | ||
// a closure which is holding the right moz contact | ||
function makeSaveSuccessCB(moz) { | ||
return function(result) { | ||
// create contact from FXOS contact (might be different than | ||
// the original one due to differences in API) | ||
var contact = createCordovaFromMozilla(moz); | ||
// call callback | ||
successCB(contact); | ||
} | ||
} | ||
var i=0; | ||
var contact; | ||
while(contact = contacts[i++]){ | ||
var moz = createMozillaFromCordova(contact); | ||
var request = navigator.mozContacts.save(moz); | ||
// success and/or fail will be called every time a contact is saved | ||
request.onsuccess = makeSaveSuccessCB(moz); | ||
request.onerror = errorCB; | ||
} | ||
} | ||
function remove(successCB, errorCB, ids) { | ||
var i=0; | ||
var id; | ||
for (var i=0; i < ids.length; i++){ | ||
var moz = new mozContact(); | ||
moz.id = ids[i]; | ||
var request = navigator.mozContacts.remove(moz); | ||
request.onsuccess = successCB; | ||
request.onerror = errorCB; | ||
} | ||
} | ||
var mozContactSearchFields = ['name', 'givenName', 'additionalName', | ||
'familyName', 'nickname', 'email', 'tel', 'jobTitle', 'note']; | ||
// function search(successCB, errorCB, params) { | ||
// var options = params[1] || {}; | ||
// var filter = []; | ||
// // filter out inallowed fields | ||
// for (var i=0; i < params[0].length; i++) { | ||
// if (mozContactSearchFields.indexOf([params[0][i]])) { | ||
// filter.push(params[0][i]); | ||
// } else if (params[0][i] == 'displayName') { | ||
// filter.push('name'); | ||
// } else { | ||
// console.log('FXOS ContactProxy: inallowed field passed to search filtered out: ' + params[0][i]); | ||
// } | ||
// } | ||
// | ||
// var request; | ||
// // TODO find out how to handle searching by numbers | ||
// // filterOp: The filter comparison operator to use. Possible values are | ||
// // equals, startsWith, and match, the latter being specific | ||
// // to telephone numbers. | ||
// var mozOptions = {filterBy: filter, filterOp: 'startsWith'}; | ||
// if (!options.multiple) { | ||
// mozOptions.filterLimit = 1; | ||
// } | ||
// if (!options.filter) { | ||
// // this is returning 0 contacts | ||
// request = navigator.mozContacts.getAll({}); | ||
// } else { | ||
// // XXX This is searching for regardless of the filterValue !!! | ||
// mozOptions.filterValue = options.filter; | ||
// console.log('mozoptions: filterBy: ' + mozOptions.filterBy.join(' ') + '; fiterValue: ' + mozOptions.filterValue); | ||
// request = navigator.mozContacts.find(mozOptions); | ||
// } | ||
// request.onsuccess = function() { | ||
// var contacts = []; | ||
// var mozContacts = request.result; | ||
// for (var i=0; i < mozContacts.length; i++) { | ||
// contacts.push(createCordovaFromMozilla(mozContacts[i])); | ||
// } | ||
// successCB(contacts); | ||
// }; | ||
// request.onerror = errorCB; | ||
// } | ||
/* navigator.mozContacts.find has issues - using getAll | ||
* https://bugzilla.mozilla.org/show_bug.cgi?id=941008 | ||
*/ | ||
function hackedSearch(successCB, errorCB, params) { | ||
// [contactField, eventualMozContactField] | ||
var arrayFields = ['givenName', 'familyName', 'name']; | ||
var options = params[1] || {}; | ||
var filter = []; | ||
// filter out inallowed fields | ||
for (var i=0; i < params[0].length; i++) { | ||
if (mozContactSearchFields.indexOf([params[0][i]])) { | ||
filter.push(params[0][i]); | ||
} else if (params[0][i] == 'displayName') { | ||
filter.push('name'); | ||
} else { | ||
console.log('FXOS ContactProxy: inallowed field passed to search filtered out: ' + params[0][i]); | ||
} | ||
} | ||
var getall = navigator.mozContacts.getAll({}); | ||
var contacts = []; | ||
function isValid(mozContact) { | ||
if (!options.filter) { | ||
// get all | ||
return true; | ||
} | ||
for (var j=0; j < filter.length; j++) { | ||
var field = filter[0]; | ||
var value = (arrayFields.indexOf(field) >= 0) ? mozContact[field].join(' ') : mozContact[field]; | ||
if (value.indexOf(options.filter) >= 0) { | ||
return true; | ||
} | ||
} | ||
} | ||
getall.onsuccess = function() { | ||
if (getall.result) { | ||
if (isValid(getall.result)) { | ||
contacts.push(createCordovaFromMozilla(getall.result)); | ||
} | ||
getall.continue(); | ||
} else { | ||
successCB(contacts); | ||
} | ||
}; | ||
getall.onerror = errorCB; | ||
} | ||
module.exports = { | ||
saveContact: saveContact, | ||
cleanup: function(){} | ||
save: saveContacts, | ||
remove: remove, | ||
search: hackedSearch | ||
}; | ||
require("cordova/firefoxos/commandProxy").add("Contacts", module.exports); |
@@ -24,4 +24,5 @@ /* | ||
// all of the setup/teardown test methods can reference the following variables to make sure to do the right cleanup | ||
var gContactObj = null; | ||
var gContactId = null; | ||
var gContactObj = null, | ||
gContactId = null, | ||
isWindowsPhone = cordova.platformId == 'windowsphone'; | ||
@@ -69,2 +70,22 @@ var removeContact = function(){ | ||
it("success callback should be called with an array, even if partial ContactFindOptions specified", function () { | ||
var win = jasmine.createSpy().andCallFake(function (result) { | ||
expect(result).toBeDefined(); | ||
expect(result instanceof Array).toBe(true); | ||
}), | ||
fail = jasmine.createSpy(); | ||
runs(function () { | ||
navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], win, fail, { | ||
multiple: true | ||
}); | ||
}); | ||
waitsFor(function () { return win.wasCalled; }, "win never called", Tests.TEST_TIMEOUT); | ||
runs(function () { | ||
expect(fail).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
it("contacts.spec.4 should throw an exception if success callback is empty", function() { | ||
@@ -108,2 +129,6 @@ var fail = function() {}; | ||
it("contacts.spec.6 should be able to find a contact by name", function() { | ||
// this api requires manual user confirmation on WP7/8 so skip it | ||
if (isWindowsPhone) return; | ||
var foundName = jasmine.createSpy().andCallFake(function(result) { | ||
@@ -169,3 +194,3 @@ var bFound = false; | ||
it("contacts.spec.1 should exist", function() { | ||
it("contacts.spec.7 should exist", function() { | ||
expect(navigator.contacts.create).toBeDefined(); | ||
@@ -309,2 +334,6 @@ expect(typeof navigator.contacts.create).toBe('function'); | ||
it("contacts.spec.20 should be able to save a contact", function() { | ||
// this api requires manual user confirmation on WP7/8 so skip it | ||
if (isWindowsPhone) return; | ||
var bDay = new Date(1976, 6,4); | ||
@@ -340,2 +369,6 @@ gContactObj = navigator.contacts.create({"gender": "male", "note": "my note", "name": {"familyName": "Delete", "givenName": "Test"}, "emails": [{"value": "here@there.com"}, {"value": "there@here.com"}], "birthday": bDay}); | ||
it("contacts.spec.21 update a contact", function() { | ||
// this api requires manual user confirmation on WP7/8 so skip it | ||
if (isWindowsPhone) return; | ||
expect(gContactObj).toBeDefined(); | ||
@@ -417,5 +450,7 @@ | ||
describe("Round trip Contact tests (creating + save + delete + find).", function () { | ||
afterEach(removeContact); | ||
it("contacts.spec.24 Creating, saving, finding a contact should work, removing it should work, after which we should not be able to find it, and we should not be able to delete it again.", function() { | ||
it("contacts.spec.24 Creating, saving, finding a contact should work, removing it should work, after which we should not be able to find it, and we should not be able to delete it again.", function() { | ||
// this api requires manual user confirmation on WP7/8 so skip it | ||
if (isWindowsPhone) return; | ||
var done = false; | ||
@@ -479,2 +514,33 @@ runs(function () { | ||
}); | ||
describe("Contacts autotests cleanup", function () { | ||
it("contacts.spec.26 Cleanup any DeleteMe contacts from Contacts tests.", function() { | ||
var done = false; | ||
var obj = new ContactFindOptions(); | ||
obj.filter="DeleteMe"; | ||
obj.multiple=true; | ||
runs(function () { | ||
var findSuccess = function (cs) { | ||
var contactObj = new Contact(); | ||
if (cs.length>0){ | ||
contactObj = cs[0]; | ||
contactObj.remove(function(){ | ||
console.log("[CONTACTS CLEANUP] DeleteMe contact successfully removed"); | ||
navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findSuccess, findFail, obj); | ||
},function(){ | ||
console.log("[CONTACTS CLEANUP ERROR]: failed to remove DeleteMe contact"); | ||
}); | ||
} else { | ||
done = true; | ||
} | ||
}; | ||
var findFail = function(e) { | ||
throw("Failure callback invoked in navigator.contacts.find call, test failed."); | ||
}; | ||
navigator.contacts.find(["displayName", "name", "phoneNumbers", "emails"], findSuccess, findFail, obj); | ||
}); | ||
waitsFor(function () { return done; }, Tests.TEST_TIMEOUT); | ||
}); | ||
}); | ||
}); |
@@ -23,3 +23,5 @@ /* | ||
var PLAT; | ||
if (/Android/.exec(navigator.userAgent)) { | ||
if (/cordova-amazon-fireos/.exec(navigator.userAgent)) { | ||
PLAT = 'amazon-fireos'; | ||
}else if (/Android/.exec(navigator.userAgent)) { | ||
PLAT = 'android'; | ||
@@ -65,3 +67,3 @@ } else if (/(iPad)|(iPhone)|(iPod)/.exec(navigator.userAgent)) { | ||
function backHome() { | ||
if (window.device && device.platform && device.platform.toLowerCase() == 'android') { | ||
if (window.device && device.platform && (device.platform.toLowerCase() == 'android' || device.platform.toLowerCase() == 'amazon-fireos')) { | ||
navigator.app.backHistory(); | ||
@@ -68,0 +70,0 @@ } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
585962
70
7862
12