There's nothing that makes you so aware of the improvisation of human existence as a song unfinished. Or an old address book. - Carson McCullers

In Part 1 I showed you how to get started with the MapQuest Advantage API by getting a developer key. In Part 2 I put that key to use by providing access to a basic map in the Map It! widget. Part 3 showed you how to incorporate basic geocoding. In Part 4 I discussed more advanced geocoding topics - including handling multiple matches and specifying geocode search options. Part 5 discussed adding widget options including the default zoom level, specifying point of interest icons, and the default map type. Part 6 discussed how to add direction capabilities to the widget. In this final installment I'll talk about how easy it is to integrate address searching with the Mac OS X Address Book application.

Address Book Searching

The Mac OS X Address Book application is bundled with the OS X operating system, providing a way for users to organize their contacts and associated information including their addresses. Also included with Mac OS X is an Address Book widget, which provides access to the Address Book database from a widget. I've explored the Address Book widget code, and extracted the AddressBookPlugIn. Plug-ins are native code that can be used to access operating system levels features from a widget's JavaScript interface.

Listing 1 demonstrates how I've modified the address parsing method. If an address is entered that does not match one of the pre-defined formats I will assume that it's a name to retrieve from the Address Book. The address book is searched for the name with the best match. Then the street, city, state, and zip code are retrieved from the best match. The retrieved address is then parsed as discussed in Part 3!

Listing 1 - Retrieving From the Address Book

function onAddressSearch(event)
{
  // user hit a return?
    if(event.keyCode == 13) {
    if(!$(address).value.blank()) {

    var street = "";
    var city = "";
    var state = "";
    var zip = "";
    var country = "";

     $(lblErrorMsg).innerText = "";
       $(multMatches).style.visibility = "hidden";
     $(lblMultMatch).style.visibility = "hidden";

       var splitAddr = $(address).value.split(',');

     // if we only get 2 elements assume address, zip
     if(splitAddr.length == 2) {
      street = splitAddr[0];
      zip = splitAddr[1];

    // for three elements assume address, city, state
     } else if(splitAddr.length == 3) {
      street = splitAddr[0];
      city = splitAddr[1];
      state = splitAddr[2];

    // for 4 elements assume address, city, state, zip
     } else if(splitAddr.length == 4) {
      street = splitAddr[0];
      city = splitAddr[1];
      state = splitAddr[2];
      zip = splitAddr[3];

    // for 5 elements assume address, city, state, zip, country
     } else if(splitAddr.length == 5) {
      street = splitAddr[0];
      city = splitAddr[1];
      state = splitAddr[2];
      zip = splitAddr[3];
      country = splitAddr[4];

     } else {
        // otherwise assume it's a name to look up in the Address Book
      AddressBookPlugin.searchForStringWithBestMatch($(address).value);
      // retrieve the values from the address book
      street = AddressBookPlugin.displayedValueAtIndex(7);
      city = AddressBookPlugin.displayedValueAtIndex(8)
      state = AddressBookPlugin.displayedValueAtIndex(9);
      zip = AddressBookPlugin.displayedValueAtIndex(10);
     }

     var result = widget.system('java -classpath .:mq.jar GetLocations
       -street "' + street + '" -city "' + city + '" -state "' + state +
       '" -zip "' + zip + '" -country "' +country + '"',null).outputString;

     // any errors?
     if(result == "ERROR") {
      $(lblErrorMsg).innerText = "Error! Unknown Address Format!";
     // address not found?
     } else if (result == "NOT FOUND") {
      $(lblErrorMsg).innerText = "Address Was Not Found!";
     } else {
      // split on return - a line is printed for each individual result
      var eachresult = result.split('\n');

      // just one result returned? - then just plot the point -
      // there are two extra returns so 3 really means 1 item
      if(eachresult.length == 3) {
        // get the coordinates from the returned string
        var coords = eachresult[0].split('|');
        // create a new point based on the coordinates
        newCenter = new MQLatLng(parseFloat(coords[0]),parseFloat(coords[1]));

        //create a new icon object
        myIcon = new MQMapIcon();

        // set the icon image: icon file location, width, height, recalc infowindow offset,
        // is it a PNG image?

        if(defIcon == "pin") {
          myIcon.setImage("images/pinpoint_red.gif",32,32,true,false);
        } else if(defIcon == "star") {
          myIcon.setImage("images/starsmall_red",18,18,true,false);
        } else if(defIcon == "x") {
          myIcon.setImage("images/xspot.gif",17,17,true,false);
        }

        // create a point
        myPoint = new MQPoi(newCenter);

        // set the custom icon
        myPoint.setIcon(myIcon);

        // recenter the map on the point,
        // the second parameter specifies the zoom level
        myMap.setCenter(newCenter,defZoom);
        // add the point as a Point of Interest
        myMap.addPoi(myPoint);
      } else {
        // clear out existing items
        $(multMatches).options.length = 0;
        for(var i=0; i

Conclusion

For your reference, here are some references for the MapQuest Platform: