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
|