In this chapter we will build the chat object portion of the Model as shown in fig- ure 6.1.
In the last chapter we designed, built, and tested the people object portion of the Model. In this chapter we’ll design, build, and test the chat object. Let’s revisit the API specification we first presented in chapter 4:
...
// * chat_model - the chat model object provides methods // to interact with our instant messaging
// * people_model - the people model object which provides methods // to interact with the list of people the model maintains ...
The description provided for the chat object—“an object that provides methods to interact with our instant messaging”—is a good start but too broad for implementa- tion. Let’s design the chat object by first analyzing what we’d like it to accomplish.
6.1.1 Design methods and events
We know we want the chat object to provide instant messaging capabilities, but we need to determine what those capabilities are in detail. Let’s consider figure 6.2, which shows a mockup of the SPA with some notes about our chat interface.
We know from experience that we’ll probably need to initialize a chat room. We also expect that the user may change the chatee (the person with whom they’re chatting), and
Figure 6.1 We’ll work the Model’s chat object in this chapter
may send messages to this person. And from our discussion about avatars, we know the user may update avatar information. The user won’t be the only source driving the UI, as we expect other people to join and leave the chat room, send and receive messages, and change avatar information. Based on this analysis, we can list the capabilities that we need to be exposed by the chat object API:
■ Provide methods to join or leave a chat room.
■ Provide a method to change the chatee.
■ Provide a method to send messages to other people.
■ Provide a method to tell the server that an avatar has been updated by the user.
■ Publish an event if the chatee is changed for any reason. For example, if the chatee goes offline or a new chatee is selected by the user.
■ Publish an event when the message pane needs to change for any reason. For example, if the user sends or receives a message.
■ Publish an event if the list of online persons changes for any reason. For example, if a person joins or leaves the chat room, or if an avatar is moved by any user.
Our chat object API will use two channels of communication. One channel is the clas- sic method-return-value mechanism. This channel is synchronous—the data transfer happens in a known sequence. The chat object may invoke external methods and receive information as return values. And other code may invoke the chat object’s public methods and receive information from the return values.
The other channel of communication that will be used by the chat object is the event mechanism. This channel is asynchronous—events may happen at any time regardless of the actions of the chat object. The chat object will receive events (like messages from the server) and publish events for use by the UI.
Let’s start designing the chat object by first considering the synchronous methods we will provide.
We need to be notified of incoming messages.
We must be able to send messages.
The “chatee” is Betty.
The user needs to modify this on a whim.
The user needs this list of people online kept up to date.
We probably need to join a chat room.
Figure 6.2 A mockup of our SPA—chat focus
181 Design the chat object
DESIGN CHAT METHODS
As we discussed in chapter 5, a method is a publicly exposed function, like spa.model.chat.get_chatee, which can be used to perform an action and return data synchronously. Given our requirements, this list of methods seems about right:
■ join()—Join the chat. If the user is anonymous, this method should abort and return false.
■ get_chatee()—Return the person object of the user with whom we’re chat- ting. If there’s no chatee, return null.
■ set_chatee( <person_id> )—Set the chatee to the person object uniquely identified by person_id. This method should publish an spa-setchatee event with chatee information provided as data. If a matching person object can’t be found in the collection of online people, set the chatee to null. If the requested person is already the chatee, return false.
■ send_message(<msg_text>)—Send a message to the chatee. We should pub- lish an spa-updatechat event with message information provided as data. If the user is anonymous or the chatee is null, this method should take no action and return false.
■ update_avatar(<update_avatar_map>)—Adjust avatar information for a per- son object. The argument (update_avatar_map) should include the properties person_id and css_map.
These methods appear to meet our requirements. Now let's consider in more detail the events that the chat object should publish.
DESIGN CHAT EVENTS
As we discussed earlier, events are used to publish data asynchronously. For example, if a message is received, the chat object will need to notify subscribed jQuery collec- tions of the change and provide the data necessary to update the presentation.
We expect that the collection of online people, and the chatee, will change often.
These changes won’t always be due to the user’s actions—for example, a chatee may send a message at any time. Here are the events that should communicate these changes to the feature modules:
■ spa-listchange should be published when the list of online people changes.
An updated people collection should be provided as data.
■ spa-setchatee should be published when the chatee changes. A map of the old and new chatee should be provided as data
■ spa-updatechat should be published when a new message is sent or received. A map of message information should be provided as data.
As we did in chapter 5, we’ll use jQuery global events as our publishing mechanism.
Now that we’ve thought through the methods and events we will need, let’s proceed to documentation and implementation.
6.1.2 Document the chat object API
Let’s consolidate our plans into an API specification that we can place into the Model code for reference.
// The chat object API // ---
// The chat object is available at spa.model.chat.
// The chat object provides methods and events to manage // chat messaging. Its public methods include:
// * join() - joins the chat room. This routine sets up // the chat protocol with the backend including publishers // for 'spa-listchange' and 'spa-updatechat' global
// custom events. If the current user is anonymous, // join() aborts and returns false.
// * get_chatee() - return the person object with whom the user // is chatting. If there is no chatee, null is returned.
// * set_chatee( <person_id> ) - set the chatee to the person // identified by person_id. If the person_id does not exist // in the people list, the chatee is set to null. If the // person requested is already the chatee, it returns false.
// It publishes a 'spa-setchatee' global custom event.
// * send_msg( <msg_text> ) - send a message to the chatee.
// It publishes a 'spa-updatechat' global custom event.
// If the user is anonymous or the chatee is null, it // aborts and returns false.
// * update_avatar( <update_avtr_map> ) - send the // update_avtr_map to the backend. This results in an // 'spa-listchange' event which publishes the updated // people list and avatar information (the css_map in the // person objects). The update_avtr_map must have the form // { person_id : person_id, css_map : css_map }.
//
// jQuery global custom events published by the object include:
// * spa-setchatee - This is published when a new chatee is // set. A map of the form:
// { old_chatee : <old_chatee_person_object>, // new_chatee : <new_chatee_person_object>
// }
// is provided as data.
// * spa-listchange - This is published when the list of // online people changes in length (i.e. when a person // joins or leaves a chat) or when their contents change // (i.e. when a person's avatar details change).
// A subscriber to this event should get the people_db // from the people model for the updated data.
// * spa-updatechat - This is published when a new message // is received or sent. A map of the form:
// { dest_id : <chatee_id>, // dest_name : <chatee_name>, // sender_id : <sender_id>,
Listing 6.1 The chat object API—spa/js/spa.model.js
183 Build the chat object
// msg_text : <message_content>
// }
// is provided as data.
//
Now that we’ve completed a specification for the chat object, let’s implement it and test the API. After that, we’ll adjust the Shell and the feature modules to use the chat object API to provide new capabilities.