Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Writing ASP Chat using JavaScript and XML (Part 2)

0.00/5 (No votes)
2 Mar 2004 1  
Step-by-step article about writing web-based chat. This article explains the chat with users list.

Sample Image - UserFriendlyChat.gif

Introduction

Next level of chatting is User-friendly chat. In addition to previous functionality, this provides active users list. Quantity of users on start page is also required. It has logoff possibility and expiration of inactive users after specified timeout.

User-friendly chat

Upgrading Simple chat to User-friendly chat requires a shared location to store active users. The convenient way to do this is to use the XML DOM. The main principles are similar, with storing messages from previous example. To generalize tasks, active user term is replaced with user session. User session, for this type of chat, should basically contain a unique session identifier and the user name.

Our storage functionality is implemented with two classes: SharedXML and Session. The first class provides the possibility for standard accessing functions to shared data. These are item insertion, removal, quick search for items by identifier or name, and unique ID generation for new fields. It encapsulates XML DOM processing. The second class provides convenient accessing methods to XML node with session information.

Let's come back to a chat user interface. Before entering a chat, many users would be interested in knowing how many people are currently available to chat. To access this information, server-side logic should contain the getActiveUsersCount() function, located in ChatProcessing.asp.

The login operation will complete successfully only if no active users have the same name. But there are also possible situations where a user is disconnected from the network or closed their chat by mistake. In these cases, a mechanism is required to repeat user authorization. It can be the first and second time login comparing, to be requested from a same computer. In this example, it is implemented using client IP address tracking. On the server-side, it is handled using the loginUser(userName) function.

After logon, the user would be interested in knowing who is available to chat to. For this purpose, we provide a third pane - an active users list. This is a frame, reloaded every several seconds. The implementation of this frame reloading is the same as in the messages frame:

<META HTTP-EQUV="Refresh" Content="<%=getUsersRefreshTime();%>">

On this page is performed active users list representation formatting for specified session. It is performed using a server-side function formatUsers(sessionID) from ChatProcessing.asp.

When a user has finished chatting, they will want to logout from the chat, therefore logout toolbar button and logoutUser(sessionID) function are required. Pressing this will immediately remove the user. But it should be possible for a user to exit without logging out via the button, for example, if they close the browser window or browse to another web page. Handling these situations requires a session expiration mechanism. A possible implementation is to track the time of the last session accessed by the user. This time is a part of session information. Periodical checking of expired sessions will remove unused sessions. Illustrated below is FormatUsers function.

Summary of functions to implement:

  • loginUser(userName) - adds user to active users list;
  • logoutUser(sessionID) - removes user from active users list;
  • getActiveUsersCount() - retrieves quantity of currently logged users;
  • formatUsers(sessionID) - formats users list for specified session.

Session information consists of:

  • Unique session ID,
  • User name,
  • Client IP address,
  • Last time accessed.

To maintain the good architecture design provided by the UserManager class, this class encapsulates users and session management functions, working in conjunction with SharedXML and Session classes. The design is illustrated in Figure 4.

Figure 4 - Class diagram of User-friendly chat.

All implementation is clear. loginUser() checks for existent user with same name. If not found, it creates a new session with unique ID. Also it associates the user name and client IP address with the newly created session. logoutUser() searches for existent session by ID and removes it. getActiveUsersCount() retrieves the number of active users by calculating a length of shared collection of sessions. formatUsers() method implements double functionality: formatting users to represent in active users pane and checking for session expiration. The second functionality is placed here because it does not require additional records iteration. Thus, active users formatting and checking for expired sessions is performed in a single loop. The listing of this method is followed:

function UserManager_formatUsers(sessionID) {
    if(!this.isValidSession(sessionID)) {
        return "";
    }
    var users = new SharedXML(this.identifier);
    var strUsers = "";
    var items = users.getItems();
    var i = 0;
    while(i < items.length) {
        var x = items.item(i);
        if(!this.checkExpiration(x)) {
            var s = new Session(x, false);
            var id = s.getSessionID();
            if(sessionID == id) {
                var continueSession = new Session(x, true);
                continueSession.markLastAccessTime();
            }
            strUsers += s.getUserNick();
            strUsers += "<BR>\n";
        }
        i++;
    }
    return strUsers;
}

Another important detail of this method is preventing other users from marking the last access times for somebody else's session. For this purpose, the Session object here is created with a false second constructor argument.

var session = new Session(xmlNode, false);

This value says to not mark the last access time of the session, when working with this object.

function Session_markLastAccessTime() {
    if(this.markAccesssing) {
        var currentTime = new Date();
        var lastAccessTime = currentTime.valueOf();
        this.setAttribte("ACCESSED", lastAccessTime);
    }
}

Conclusion

An inconvenience of this chat is that it is possible for several users to share a single name at different times. In the next part, it will be fixed by implementing registration mechanism.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here