Building an Address Book > The ContactManager Class

 

The ContactManager Class

The ContactManager class provides convenient methods that write information to a local SharedObject named "addressBook". If the SharedObject does not exist, ContactManager creates it.

Let's first look at the constructor for ContactManager. Its primary task is to retrieve the local "addressBook" SharedObject and store it in the property so:

  this.so = SharedObject.getLocal("addressBook");

If the returned SharedObject has not been used before, we create a new property called contacts in which to store our Contact objects.

  if (typeof this.so.data.contacts == "undefined") {
    // Use a generic object as a hash.
    this.so.data.contacts = new Object();
  } 

The contacts property will be assigned named Contact objects as properties; these are our individual contact records.

Finally, the constructor initializes a unique identification number to assign to each contact. If the SharedObject has no uniqueid property, we create one and set it to 0. Otherwise, the SharedObject's uniqueid property is not modified.

  if (typeof this.so.data.uniqueid == "undefined") {
    this.so.data.uniqueid = 0;
  }

That takes care of our SharedObject setup. We now proceed with creating three methods to access the contact records: addContact(), removeContact() and updateContact(). Each of these methods manipulates a Contact object stored as a property of our SharedObject's contacts property.

The addContact() method creates a new Contact object and adds it to the local SharedObject. Each Contact object is named in the sequence record0, record1, record2...recordn. The number after "record" is the unique id for that contact. In general terms, here's how addContact() assigns a new record property to the SharedObject's contacts property:

  this.so.data.contacts.record0 = new Contact(firstName,...);

In our actual code, we must create the record0 property dynamically, according to the contact's unique id. We use the array access operator (square brackets "[" and "]") to specify the record property as a string expression as follows:

  this.so.data.contacts["record" + this.so.data.uniqueid] = 
                                    new Contact(firstName, 
                                                lastName, 
                                                email, 
                                                phone,
                                                phonetype,
                                                company,
                                                comments,
                                                this.so.data.uniqueid);

Notice that we store all information added to the SharedObject in the property data. While not formally required, this provides a single point of access to the SharedObject's data. If we need to, we can then add other properties that remember our application's state without cluttering our data.

Once the new record property is added, the addContact() method updates the uniqueid property. This ensures that each contact record gets its own number.

  this.so.data.uniqueid++;

Finally, addContact() returns a reference to the new contact so our program can begin working with it immediately.

  // Return a reference to the new contact.
  return this.so.data.contacts["record" + (this.so.data.uniqueid - 1)];

Now let's turn to a much simpler function, removeContact(). Its single line simply deletes the record property associated with a specified contact:

  delete this.so.data.contacts["record" + id];

And lastly, the updateContact() method sets new values for all properties of a contact. The new values are assigned directly to each of the Contact object's properties. For example:

  this.so.data.contacts["record" + id].firstName = firstName;

The updateContact() method also sets the contact's lastModified property to the current time:

  this.so.data.contacts["record" + id].dateModified = new Date();

To put all these techniques into context, read through the complete code listing for the ContactManager class, below.

/* =================
 * Class constructor
 * =================
 *   Desc: Creates the ContactManager object. Retrieves a local
 *         shared object (this.so) and initializes it if necessary.
 * =================
 */
function ContactManager () {
  // Get a reference to the local shared object.
  this.so = SharedObject.getLocal("addressBook");
  
  // If there's no contact container property yet, make one.
  if (typeof this.so.data.contacts == "undefined") {
    // Use a generic object as a hash.
    this.so.data.contacts = new Object();
  }  
  
  // If there's no existing id to use with contacts, assign a default.
  if (typeof this.so.data.uniqueid == "undefined") {
    this.so.data.uniqueid = 0;
  }
}


/* =================
 * Instance Methods
 * =================
 */
 
/*
 * Method: addContact()
 *   Desc: Creates a new Contact object and stores it in the shared
 *         object's "contacts" hash.
 *   Parameters:
 *     firstName      The new contact's first name, as a string.
 *     lastName       The new contact's last name, as a string.
 *     email          The new contact's email address, as a string.
 *     phone          The new contact's phone number, as a string.
 */
ContactManager.prototype.addContact = function (firstName, 
                                                lastName, 
                                                email, 
                                                phone, 
                                                phonetype, 
                                                company, 
                                                comments) {
                                                
  // Create a new contact object and store it in the "contacts" hash.
  this.so.data.contacts["record" + this.so.data.uniqueid] = 
                                    new Contact(firstName, 
                                                lastName, 
                                                email, 
                                                phone,
                                                phonetype,
                                                company,
                                                comments,
                                                this.so.data.uniqueid);

  // Update the id for next time.
  this.so.data.uniqueid++;

  // Return a reference to the new contact.
  return this.so.data.contacts["record" + (this.so.data.uniqueid - 1)];
}


/*
 * Method: removeContact()
 *   Desc: Deletes the contact object specified by "id".
 *   Parameters:
 *     id             The identifier of the contact object to delete.
 */
ContactManager.prototype.removeContact = function (id) {
  delete this.so.data.contacts["record" + id];
}


/*
 * Method: updateContact()
 *   Desc: Deletes the contact object specified by "id".
 *   Parameters:
 *     id             The identifier of the contact object to update.
 *     firstName      The contact's first name, as a string.
 *     lastName       The contact's last name, as a string.
 *     email          The contact's email address, as a string.
 *     phone          The contact's phone number, as a string.
 *     phonetype      The type of phone number (home, work, cell)
 *     company        The person's place of business.
 *     comments       Arbitrary notes associated with the person.
 */
ContactManager.prototype.updateContact = function (id, 
                                                   firstName, 
                                                   lastName, 
                                                   email, 
                                                   phone,
                                                   phonetype,
                                                   company,
                                                   comments) {
                                                   
  // Set the updated values on the contact.
  this.so.data.contacts["record" + id].firstName = firstName;
  this.so.data.contacts["record" + id].lastName = lastName;
  this.so.data.contacts["record" + id].email = email;
  this.so.data.contacts["record" + id].phone = phone;
  this.so.data.contacts["record" + id].phonetype = phonetype;
  this.so.data.contacts["record" + id].company = company;    
  this.so.data.contacts["record" + id].comments = comments;    
  
  // Note the time the contact was modified.
  this.so.data.contacts["record" + id].dateModified = new Date();
  
  // Return a reference to the updated contact.
  return this.so.data.contacts["record" + id];
}

Though our ContactManager class makes SharedObject access easy, we could improve the class further with methods to retrieve contacts and to set individual Contact object properties. Useful new methods would be: getContact(id), getAllContacts(), setProp(id, prop). These are left as an exercise to the reader to implement.