How do I get one address book?

Address Books are uniquely identified by a URI. This can be obtained via nsIAbDirectory.URI. The code stores URIs in various places (e.g. preferences, in address book trees etc). Assuming you have the URI, then use the Address Book Manager to get an nsIAbDirectory representing the address book:

How do I search for a particular contact property (name, email)?

Once you have an object that implements nsIAbCollection (see above), you can search for cards with particular properties within that collection using getCardFromProperty. This function will return the first match that it finds in the collection or null.

If you are searching for a card with a particular email address, you can use the cardForEmailAddress function that will match against multiple email addresses stored in one card. Again, this function returns the first match that it finds in the collection, or null.

Note: Both of these functions may raise an NS_ERROR_NOT_IMPLEMENTED exception if the collection has not implemented that function. This is currently true in the case of LDAP, but may be true in other cases as well.

Note: Local (mork) address books are currently the only built-in type of address book that supports saving of non-built-in properties. However, outlook directories are the only other built-in write capable directories.

var parentDirectory = ...; // An nsIAbDirectory for the parent of the mailing list.
parentDirectory.addMailList(mailList);

Modifying a Mailing List

To modify a mailing list, you first need an object that implements nsIAbCard. This can be obtained via searching in address books as mentioned above. Once you have the nsIAbCard object you can modify the names and description of it like this:

Deleting a Mailing List

There are two ways to delete a mailing list. If you have it in its nsIAbCard form, then you can delete it in the same way as per deleting a contact. If you have it in its nsIAbDirectory form, then you can delete it like this:

Note: There is no new address book dialog for the OS X address book. As this is a system address book, there is only one address book represented, and therefore a new address book dialog does not make sense. In Thunderbird a menu option is provided instead.

Edit Address Book Dialog

addressbook is an nsIAbDirectory that provides the chrome URI that is used in the call to openDialog. Using the propertiesChromeURI means that the different implementations can call up their own dialog.

If you are using C++, you can inherit from nsAbDirProperty and override functions for your specific implementation to save implementing all the functions on nsIAbDirectory yourself. The best example of a binary implementation of an address book is the OS X Address Book source code.

If you are implementing in JavaScript then you will have to implement the full interfaces mentioned above. At the moment, the best example of this is the EDS contacts integration add-on.

Once you've added your own address book implementation, you might also want to extend the address book user interface.

How do I extend the address book user interface?

There are several hooks in the address book code exposed to add-on developers to help extend the behavior of the address book.

Load and save listeners

Edit dialogs for both contacts and mailing lists expose functions for registering load and save listeners. For example, in order to register a load listener for a contact, the following should take place within the scope of the contact editor dialog:

/* An example load listener for a contact * aCard the nsIAbCard being loaded
* aDocument a reference to the contact editor document
*/
function foo(aCard, aDocument) {
// Do something useful, like disabling // input fields that cards for this
// address book type do not support.
} RegisterLoadListener(foo);

Save listeners are functions that take the same parameters, and can be registered with:

RegisterSaveListener(foo);

Load and save listeners can be unregistered using UnregisterLoadListener(foo) and UnregisterSaveListener(foo), respectively.

Photo handlers

Photo handlers allow developers to customize the behavior of the contact editor when loading or saving contact photos. This is useful if, for example, cards within your address book implementation need to save contact photos within a database.

A photo handler defines the behavior of the contact editor for a particular photo type. Each photo handler must implement the following interface:

/*
* onLoad: function(aCard, aDocument):
* Called when the editor wants to populate the contact editor
* input fields with information about aCard's photo. Note that
* this does NOT make aCard's photo appear in the contact editor -
* this is left to the onShow function. Returns true on success.
* If the function returns false, the generic photo handler onLoad
* function will be called.
*
* onShow: function(aCard, aDocument, aTargetID):
* Called when the editor wants to show this photo type.
* The onShow method should take the input fields in the document,
* and render the requested photo in the IMG tag with id
* aTargetID. Note that onShow does NOT save the photo for aCard -
* this job is left to the onSave function. Returns true on success.
* If the function returns false, the generic photo handler onShow
* function will be called.
*
* onSave: function(aCard, aDocument)
* Called when the editor wants to save this photo type. The
* onSave method is responsible for analyzing the photo of this
* type requested by the user, and storing it, as well as the
* other fields required by onLoad/onShow to retrieve and display
* the photo again. Returns true on success. If the function
* returns false, the generic photo handler onSave function will
* be called.
*/

Photo handlers are registered within the context of the contact editor dialog using the registerPhotoHandler function, as follows:

registerPhotoHandler(aType, aPhotoHandler)

...where aType is a string with a unique identifier for that particular photo type. In order for a photo handler to be used for a contact, the PhotoType property of the contact must return a string equal to aType.

The address book defaults with three photo handler types, identified by "generic", "file" and "web". These can be overridden by calling registerPhotoHandler with these identifiers and a custom photo handler.

Photo display handlers

A photo display handler determines how a contact photo can be extracted from a contact and displayed in an IMG element. This is useful in the contact viewer within the address book.

Photo display handlers are registered with the registerPhotoDisplayHandler function within the context of the address book card view overlay.

A photo display handler is a function that behaves as follows:

/*
* function(aCard, aImg):
* The function is responsible for determining how to retrieve
* the photo from nsIAbCard aCard, and for displaying it in img
* img element aImg. Returns true if successful. If it returns
* false, the generic photo display handler will be called.
*/

How do I set up autocomplete to use the address book?

There are 3 address book autocomplete widgets:

"mydomain" - use to autocomplete a domain for an email identity, e.g. for a user @bar.com, entering foo would become foo@bar.com

"addrbook" - use to autocomplete from a local address book, e.g. a Mork based local store or a OS X address book

LDAP - use for searching in LDAP address books.

MyDomain and Addrbook Autocomplete

"mydomain" and "addrbook" both use the toolkit interfaces to provide autocomplete facilities. To use them in code all you need to do is set up your text box as follows: