Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
464 lines
10 KiB
JavaScript
Executable file
464 lines
10 KiB
JavaScript
Executable file
/*global Utils, Promise */
|
|
|
|
'use strict';
|
|
|
|
/* ***********************************************************
|
|
|
|
Code below is for desktop testing!
|
|
|
|
Adapted from:
|
|
|
|
https://mxr.mozilla.org/mozilla-b2g18/source/dom/contacts/fallback/ContactDB.jsm
|
|
https://mxr.mozilla.org/mozilla-b2g18/source/dom/contacts/ContactManager.js
|
|
apps/sms/js/contacts.js
|
|
|
|
|
|
*********************************************************** */
|
|
(function(window) {
|
|
function getAsset(filename) {
|
|
return new Promise(function(resolve, reject) {
|
|
var req = new XMLHttpRequest();
|
|
req.open('GET', filename, true);
|
|
req.responseType = 'blob';
|
|
req.onload = function() {
|
|
resolve(req.response);
|
|
};
|
|
req.send();
|
|
});
|
|
}
|
|
|
|
function stringOrBust(aObj) {
|
|
if (typeof aObj !== 'string') {
|
|
return undefined;
|
|
} else {
|
|
return aObj;
|
|
}
|
|
}
|
|
|
|
function sanitizeStringArray(aArray) {
|
|
if (!Array.isArray(aArray)) {
|
|
aArray = [aArray];
|
|
}
|
|
return aArray.map(stringOrBust).filter(function(el) {
|
|
return el !== undefined;
|
|
});
|
|
}
|
|
|
|
function _isVanillaObj(aObj) {
|
|
return Object.prototype.toString.call(aObj) == '[object Object]';
|
|
}
|
|
|
|
function Normalize(opts) {
|
|
opts.fields.forEach(function(field) {
|
|
var value = opts.record[field.name];
|
|
|
|
this[field.name] = typeof value !== 'undefined' ?
|
|
field.filter(value) : null;
|
|
}, this);
|
|
}
|
|
|
|
function ContactField(field) {
|
|
Normalize.call(this, {
|
|
fields: [
|
|
{ name: 'type', filter: sanitize },
|
|
{ name: 'value', filter: stringOrBust }
|
|
],
|
|
record: field
|
|
});
|
|
}
|
|
|
|
function ContactTelField(tel) {
|
|
Normalize.call(this, {
|
|
fields: [
|
|
{ name: 'type', filter: sanitize },
|
|
{ name: 'value', filter: stringOrBust },
|
|
{ name: 'carrier', filter: stringOrBust }
|
|
],
|
|
record: tel
|
|
});
|
|
}
|
|
|
|
function ContactAddress(address) {
|
|
Normalize.call(this, {
|
|
fields: [
|
|
{ name: 'type', filter: sanitize },
|
|
{ name: 'streetAddress', filter: stringOrBust },
|
|
{ name: 'locality', filter: stringOrBust },
|
|
{ name: 'region', filter: stringOrBust },
|
|
{ name: 'postalCode', filter: stringOrBust },
|
|
{ name: 'countryName', filter: stringOrBust }
|
|
],
|
|
record: address
|
|
});
|
|
}
|
|
|
|
function multiValue(source, ctor) {
|
|
var result = [];
|
|
source = Array.isArray(source) ? source : [source];
|
|
|
|
for (var entry of source) {
|
|
if (_isVanillaObj(entry)) {
|
|
result.push(new ctor(entry));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function Contact(contact) {
|
|
Normalize.call(this, {
|
|
fields: [
|
|
{ name: 'name', filter: sanitize },
|
|
{ name: 'honorificPrefix', filter: sanitize },
|
|
{ name: 'honorificSuffix', filter: sanitize },
|
|
{ name: 'givenName', filter: sanitize },
|
|
{ name: 'additionalName', filter: sanitize },
|
|
{ name: 'familyName', filter: sanitize },
|
|
{ name: 'nickname', filter: sanitize },
|
|
{ name: 'email', filter: sanitize },
|
|
{ name: 'photo', filter: sanitize },
|
|
{ name: 'url', filter: sanitize },
|
|
{ name: 'category', filter: sanitize },
|
|
{ name: 'org', filter: sanitize },
|
|
{ name: 'jobTitle', filter: sanitize },
|
|
{ name: 'note', filter: sanitize },
|
|
{ name: 'impp', filter: sanitize }
|
|
],
|
|
record: contact
|
|
});
|
|
|
|
this.id = ++cid;
|
|
|
|
this.name = [
|
|
this.givenName[0] + ' ' + this.familyName[0]
|
|
];
|
|
|
|
this.email = typeof contact.email !== 'undefined' ?
|
|
multiValue(contact.email, ContactField) : null;
|
|
|
|
this.adr = typeof contact.adr !== 'undefined' ?
|
|
multiValue(contact.adr, ContactAddress) : null;
|
|
|
|
this.tel = typeof contact.tel !== 'undefined' ?
|
|
multiValue(contact.tel, ContactTelField) : null;
|
|
|
|
this.url = typeof contact.url !== 'undefined' ?
|
|
multiValue(contact.url, ContactField) : null;
|
|
|
|
this.bday = typeof contact.bday !== 'undefined' ?
|
|
new Date(contact.bday) : null;
|
|
|
|
this.anniversary = contact.anniversary ?
|
|
new Date(contact.anniversary) : null;
|
|
}
|
|
|
|
var ContactsDB = [];
|
|
var sanitize = sanitizeStringArray;
|
|
var cid = 0;
|
|
var methods = {
|
|
contains: 'startsWith',
|
|
match: 'includes',
|
|
equals: 'includes'
|
|
};
|
|
|
|
function isMatch(contact, filter) {
|
|
/**
|
|
* Validation Strategy
|
|
*
|
|
* 1. Let _found_ be a register of confirmed terms
|
|
* 2. Let _contact_ be a contact record.
|
|
* 3. For each _term_ [...input list], with the label _outer_
|
|
* - For each _field_ of [givenName, familyName]
|
|
* - For each _value_ in _contact_[ _field_ ]
|
|
* - Let _found_[ _term_ ] be the result of calling
|
|
* _value_.startsWith( _term_ )
|
|
* - If _found_[ _term_ ] is **true**, continue to
|
|
* loop labelled _outer_
|
|
* 4. If every value of _key_ in _found_ is **true** return **true**,
|
|
* else return **false**
|
|
*/
|
|
var found = {};
|
|
var method = methods[filter.filterOp];
|
|
var term = filter.filterValue.toLowerCase();
|
|
|
|
// The outer loop is specifically labelled to allow the
|
|
// nested condition a way out of the second and third loop.
|
|
outer:
|
|
for (var field of filter.filterBy) {
|
|
if (!contact[field]) {
|
|
continue;
|
|
}
|
|
for (var value of contact[field]) {
|
|
if (typeof value !== 'string') {
|
|
value = value.value;
|
|
}
|
|
if ((found[term] = value.toLowerCase()[method](term))) {
|
|
return true;
|
|
}
|
|
|
|
if (field === 'tel') {
|
|
if (Utils.probablyMatches(value, term)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// // Do not use the native API.
|
|
navigator.mozContacts = {
|
|
addEventListener: function(type, handler, capture) {
|
|
return this;
|
|
},
|
|
find: function(filter) {
|
|
// attribute DOMString filterValue; // e.g. 'Tom'
|
|
// attribute DOMString filterOp; // e.g. 'contains'
|
|
// attribute DOMString[] filterBy; // e.g. 'givenName'
|
|
// attribute DOMString sortBy; // e.g. 'givenName'
|
|
// attribute DOMString sortOrder; // e.g. 'descending'
|
|
// attribute unsigned long filterLimit;
|
|
|
|
// Implement a mock that gives results that appear to
|
|
// match the real behaviour of filtered contacts results
|
|
var result = ContactsDB.filter(function(contact) {
|
|
return isMatch(contact, filter);
|
|
});
|
|
|
|
return readyPromise.then(() => result);
|
|
}
|
|
};
|
|
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Turing',
|
|
givenName: 'Alan',
|
|
tel: {
|
|
value: '101',
|
|
type: 'Mobile',
|
|
carrier: 'Telco'
|
|
}
|
|
})
|
|
);
|
|
|
|
/**
|
|
// 102 is omitted intentionally.
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: '',
|
|
givenName: '',
|
|
tel: {
|
|
value: '102'
|
|
}
|
|
})
|
|
);
|
|
*/
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Shannon',
|
|
givenName: 'Claude',
|
|
tel: {
|
|
value: '103',
|
|
type: 'Mobile'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Lovelace',
|
|
givenName: 'Ada',
|
|
tel: {
|
|
value: '104'
|
|
},
|
|
email: {
|
|
value: 'ada@lovelace.com'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Tesla',
|
|
givenName: 'Nikola',
|
|
email: {
|
|
value: 'nikola@tesla.com'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Babbage',
|
|
givenName: 'Charles',
|
|
tel: {
|
|
value: '105'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Backus',
|
|
givenName: 'John',
|
|
tel: {
|
|
value: '106'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'McCarthy',
|
|
givenName: 'John',
|
|
tel: {
|
|
value: '107'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Steele',
|
|
givenName: 'Guy',
|
|
tel: {
|
|
value: '108'
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Kay',
|
|
givenName: 'Alan',
|
|
tel: {
|
|
value: '109',
|
|
type: 'Mobile',
|
|
carrier: 'Nynex'
|
|
}
|
|
})
|
|
);
|
|
|
|
|
|
var grace = new Contact({
|
|
familyName: 'Hopper',
|
|
givenName: 'Grace',
|
|
tel: {
|
|
value: '999'
|
|
}
|
|
});
|
|
|
|
var tom = new Contact({
|
|
familyName: 'O\'Hare',
|
|
givenName: 'Tom',
|
|
tel: {
|
|
value: '123456',
|
|
type: 'Mobile',
|
|
carrier: 'Nynex'
|
|
}
|
|
});
|
|
|
|
var longname = new Contact({
|
|
familyName: 'Taumatawhakatangihangakoauauota',
|
|
givenName: 'Mateapokaiwhenuakitanatahu',
|
|
tel: [{
|
|
value: '+18001114321',
|
|
type: ['Mobile']
|
|
}]
|
|
});
|
|
|
|
var rtlName = new Contact({
|
|
familyName: 'الخيام',
|
|
givenName: 'عمر',
|
|
tel: [{
|
|
value: '+97121111111',
|
|
type: ['Mobile'],
|
|
carrier: 'اتصالات'
|
|
}]
|
|
});
|
|
|
|
var readyPromise = Promise.all([
|
|
getAsset('/desktop-mock/assets/photo-man.jpg'),
|
|
getAsset('/desktop-mock/assets/photo-woman.jpg'),
|
|
getAsset('/desktop-mock/assets/photo-man-bowtie.jpg')
|
|
]).then(function gotall(blobs) {
|
|
tom.photo = [blobs[0]];
|
|
grace.photo = [blobs[1]];
|
|
longname.photo = [blobs[2]];
|
|
});
|
|
|
|
ContactsDB.push(grace);
|
|
ContactsDB.push(tom);
|
|
ContactsDB.push(longname);
|
|
ContactsDB.push(rtlName);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Carrier',
|
|
givenName: 'Igotno',
|
|
tel: {
|
|
value: '436797',
|
|
type: 'Mobile',
|
|
carrier: null
|
|
}
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Jekyll',
|
|
givenName: 'Doctor',
|
|
tel: [
|
|
{
|
|
value: '+12125551234',
|
|
type: ['Mobile']
|
|
},
|
|
{
|
|
value: '+15551237890',
|
|
type: ['Home']
|
|
}
|
|
]
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: 'Non-digit',
|
|
givenName: 'Multiple',
|
|
tel: [
|
|
{
|
|
value: '900-BUY-A-CAR',
|
|
type: ['Mobile'],
|
|
carrier: 'Megaphones'
|
|
},
|
|
{
|
|
value: '800-BUY-A-CAR',
|
|
type: ['Home'],
|
|
carrier: 'Nynex'
|
|
}
|
|
]
|
|
})
|
|
);
|
|
|
|
ContactsDB.push(
|
|
new Contact({
|
|
familyName: '',
|
|
givenName: 'Bob',
|
|
tel: [
|
|
{
|
|
value: '555-666-1234',
|
|
type: ['Mobile'],
|
|
carrier: 'ScamCo'
|
|
}
|
|
]
|
|
})
|
|
);
|
|
|
|
// console.log( ContactsDB );
|
|
|
|
|
|
|
|
|
|
}(window));
|