[SmartFox] Advanced chat (part 1)
[ August 10, 2004 ] by Marco Lapi, a.k.a Lapo
Article 5: learn how to build a more advanced chat application (part 1)


The related source file for this article is found in the "Examples/advancedChat" folder under the name of "advancedChat.fla".

In this tutorial we will expand the concepts learned so far and we will enhance the "SimpleChat" demo to make it a more advanced chatting application.

The picture below shows the main GUI (graphical user interaface) of the "AdvancedChat"

Here's a list of the features that we're going to add to our previous example:

- A roomlist:
it will show every room available with realtime user count
you will be able join any room by clicking on it
you will be able to join password protected rooms
you will be able to create new rooms (with password also)

- A better UserList:
by clicking on one user you will be able to send a private message

- An exit button:
by clicking it you will log out of the chat.


[ THE ROOMLIST ]

By opening the source .FLA file you will notice that the code in the first two labels is almost identical to the previous sample, so you can safely position the playhead on the "chat" label.

The first thing you should notice in the GUI is the presence of a new listbox called roomList_lb.

Now open the Actionscript panel (F9) and inspect the code for the onRoomListUpdate() event:

smartfox.onRoomListUpdate = function(roomList)
{
roomList_lb.removeAll()
for (var i in roomList)
{
var room = roomList[i]
roomList_lb.addItem(room.getName() + " (" + room.getUserCount() + ")", room.getId())
}
roomList_lb.sortItemsBy("label", "ASC")
 
// Join the default room
this.autoJoin()
}

The first line makes sure that no item is present in the listbox. Then we proceed by iterating through the roomList array and we add each room name to the listbox (plase note that the label is built by joining the room name and the user count for that room).

Once the list is populated we can sort it in ascending alphabetical order.

Just like we did in the other tutorials we call the autoJoin() method to automagically join the default room.


NOTE:
using the autoJoin() method is not mandatory but it is usually easier, if you always need to bring the "just-arrived" users in a default room.
Also the autoJoin() method works only if you have defined an autoJoin room in the zone, if none was defined the call will fail.


[ UPDATING THE ROOM STATUS ]

Now that we have a complete list of rooms with the number of users for each of them how do we know when something changes? What happens if two users exit one room?

SmartFoxServer will send you notices of these changes, so all we need to do is writing the appropriate handler for the onUserCountChange event.

smartfox.onUserCountChange = function(roomObj)
{
updateRoomStatus(roomObj.getId())
}

Every time the event is fired the server passes a Room object that represents the room in which the change occured.
We have setup a simple function called updateRoomStatus that will take care of changing the label in the room list component.

function updateRoomStatus(roomId)
{
var room = smartfox.roomList[roomId]
var newLabel = room.name + " (" + room.getUserCount() + ")"
for (i=0; i < roomList_lb.getLength(); i++)
{
var item = roomList_lb.getItemAt(i)
if (roomId == item.data)
{
roomList_lb.replaceItemAt(i, newLabel, item.data)
break;
}
}
}

The function takes the id of the room and loops through the list box items until it finds the right item.Then it changes its label updating the user count.

This technique should feel familiar to you at this point.


[ JOINING ANOTHER ROOM ]
At the very beginning of the code you will find these lines:

//----------------------------------------------------------
// Setup components callback functions
//----------------------------------------------------------
roomList_lb.setChangeHandler("changeRoom")
userList_lb.setChangeHandler("userSelected")

They set the name of the function to call when an item in the list component is clicked. We'll concentrate on the changeRoom() method for now:

function changeRoom()
{
var item = roomList_lb.getSelectedItem()
 
// new Room id
var newRoom = item.data
if (newRoom != smartfox.activeRoomId)
{
// Check if new room is password protected
var priv = smartfox.getRoom(newRoom).isPrivate()
if (priv)
{
// Save newroom as _global for later use
_global.newRoom = newRoom
showWindow("passwordWindow")
}
else
{
// Pass the room id
smartfox.joinRoom(item.data)
}
}
}

The code checks that the room we've selected is different from the one we're currently in, and it uses a SmartFoxClient property that we haven't met yet: activeRoomId. This property always holds the id of the last room we've joined.

Another important check we have to do is controlling if the room is password protected.

var priv = smartfox.getRoom(newRoom).isPrivate()

The getRoom(id) method returns a Room object. The isPrivate() is a Room method: it returns a boolean (true = password needed, false = no password).

If the room has no access restrictions we can join it by simply using smartfox.joinRoom() and passing the room id to it.

smartfox.joinRoom(item.data)

If the room needs a password we need to do some extra operations:

1) save the id of the room we want join somewhere for later use (_global.newRoom = newRoom)
2) show a dialog box and wait for user input (link to prev article)
3) finally send the login and password: smartfox.joinRoom(_global.newRoom, pwd)

Once the password is submitted the dialog box will call the loginProtectedRoom() method in the main timeline:

function loginProtectedRoom(pwd)
{
hideWindow("passwordWindow")
smartfox.joinRoom(_global.newRoom, pwd)
}

which in turn sends the previously saved room Id and the password.


NOTE:
We have used the joinRoom() method with one argument for rooms with no passwords and with two arguments when a password is needed. To tell the truth the full set of arguments is this:

joinRoom = function(newRoom, pword, dontLeave, oldRoom)

SmartFoxServer allows a user to be present in more than one room at a time. This can be useful for complex applications where you need more advanced user interaction. However to keep things simple the joinRoom method leaves the current room by default before entering a new one as this is the most common behaviour for most applications.
If you need to stay in one room while joining a new one you can pass the dontLeave parameter as true.
One more thing about the newRoom argument. You can both pass the room Id or the room name as first parameter.

Now that we have sent our joinRoom request we should be prepared to receive complaints by the server.
For example the server may generate an error if the room we're trying to join is already full. Antoher error could be generated if the password sent is wrong.

The onJoinRoomError is responsible of handling such event:

smartfox.onJoinRoomError = function(errorMsg)
{
var win = showWindow("errorWindow")
win.errorMsg.text = errorMsg
 
// Put the selected room in the combo box back to its old value
resetRoomSelected(smartfox.activeRoomId)
}

The first two lines will show an error window and the text box inside the dialog box will show the error message passed by the server.
The next line invokes the resetRoomSelected(): this is a little "trick" that we use to restore the selected item in the room list component if the joinRoom request fails.

That's all for the first part of our "Advanced Chat" application.


See you in the next article.

Lapo


    
 
 
Name: Marco Lapi, a.k.a Lapo
Location: Fossano, Italy
Age: 34
Flash experience: started out with Flash 4 back in 1999
Job: web designer/developer
Website: http://www.gotoandplay.it/
 
 
| Homepage | News | Games | Articles | Multiplayer Central | Reviews | Spotlight | Forums | Info | Links | Contact us | Advertise | Credits |

| www.smartfoxserver.com | www.gotoandplay.biz | www.openspace-engine.com |

gotoAndPlay() v 3.0.0 -- (c)2003-2008 gotoAndPlay() Team -- P.IVA 03121770048