The Chat System
The chat system will have a
Testing
Testing should be implemented early in the development process so that you can identify any problems that could
TSC has also
The chat-system development consists of creating three user interfaces. The first allows the user to change his user
TSC will be developing the client-side user interface in Flash MX, which gives the ability for the client-side application to interact with both the FCS and CFMX server. Flash ComponentsThe Flash components used were the PushButton, TextField, and ListBox. I will not go into these components, as they've been covered in the previous chapter.
Local Shared objects on the clientside have also been discussed and demonstrated in previous chapters, so discussing them here would not be beneficial. However, the server-side shared object gives the FCS the ability to synchronize data to all
Shared objects can be local (clientside) or remote (serverside). The local shared object can hold persistent data on the client side for writing and retrieval only by itself or other Flash MX applications from the same domain. These local objects are similar in functionality to Web-browser cookies but are more powerful. ColdFusion Components
To create CFCs, related functions are grouped into a file or component. These are in
There are four straightforward component tags that can make up a CFC: cfcomponent , cfproperty , cffunction and cfargument .
instant message
Inheriting allows not only for using the methods of the parent component but also for creating additional methods within the child component. This means that all code that
Access specifiers: Public: Available to any calling code. Private: Access is restricted to calls from code within the same CFC. Package: Accessible from within the same package (directory). Remote: Accessible from external systems such as Web services and Flash MX. As we have already seen, CFCs have much more power than just organizing the code into relevant components. Remote invocation can broaden the CFC's functionality beyond the ColdFusion MX server to other services such as Flash MX. Remote access to components is allowed through the <cffunction> tag's remote attribute. As you have seen in previous chapters, this enables a Flash MX system to call a server-side component and invoke a method, and then receive the result. The following is an example of creating a log-in object in ActionScript, and then calling a server CFC and invoking the setNewSession method.
//Theresultfromthecfcomponentau.com.tatam.chatwillbe
passedtothismethodasanobject.
//CreateaLogin_objectobjecttosendtotheCFcomponent.
//TheObjectpropertieswillbereceivedasargumentstothe
Server-sidecomponentsfunction
varLogin_object=newObject();
Login_object.userID=Username;
Login_object.password=Password;
Login_object.status="Online";
login_object.datasourceName="chat";
login_object.datasourceType="ODBC";
Login_object.message="Iwanttologin";
chatserverSession=
this.chat_conn.getService("au.com.tatam.chat.Controller",
this);
status_Window.text=status_Window.Text+chr(10)+
"connectingtoserver...";
chatserverSession.setNewSession(Login_object);
this.onResult=function(result)
}
this.onStatus=function(result)
}
The methods in this component are wrappers around other components which perform all the actual processing. Each method
Controller.cfcThe controller is used to direct the traffic of calls to the specific CFC and method. This CFC is called from within the Flash MX client-side Chat center user interface. <cfcomponentname="Controller"hint="controlstheChatCenter"> <cffunctionname="setNewSession"access="remote"> <cfinvokecomponent="au.com.tatam.chat.session.Session" method="setNewSession" argumentCollection="#ARGUMENTS#" returnVariable="result"/> <cfreturnresult/> </cffunction> <cffunctionname="CreateChatRequest"access="remote"> <cfinvokecomponent="au.com.tatam.chat.dialog.Request" method="CreateChatRequest" argumentCollection="#ARGUMENTS#" returnVariable="result"/> <cfreturnresult/> </cffunction> <cffunctionname="getSpecificUserSessionID"access="remote"> <cfinvokecomponent="au.com.tatam.chat.session.Session" method="getSpecificUserSessionID" argumentCollection="#ARGUMENTS#" returnVariable="result"/> <cfreturnresult/> </cffunction> </cfcomponent>
If a new version of the Chat were to be produced, then within these methods there could exist a statement that could detect the
<cffunctionname="getSpecificUserSessionID"access="remote"> <cfifparameterexists(arguments.version)ANDarguments. versionEQ"1"> <cfinvoke component="au.com.tatam.chat.session.VideoSession" method="getSpecificUserSessionID" argumentCollection="#ARGUMENTS#" returnVariable="result"/> <cfreturnresult/> <cfelse> <cfinvoke component="au.com.tatam.chat.session.Session" method="getSpecificUserSessionID" argumentCollection="#ARGUMENTS#" returnVariable="result"/> <cfreturnresult/> </cfcif> </cffunction> The Database
The database schema at design time had a lot more tables defined (
Figure IV-3.1
). This was due to the fact that the data was to be stored within a database. With the introduction of the Flash Communication Server, some of the tables in the design document have been
Figure IV-3.1. Initial Database schema.
The Users table can be reused with the user CFC. The present table exists within the chat database but could exist elsewhere if the data needs to be shared by other systems.
The user sessions and chat
Session.cfcThe session CFC holds all the logic to get, set, process, and return the data associated with a user's chat session. It accesses the database as well as calling the User CFC to authenticate the user ID and password.
<cffunctionname="setNewSession"access="remote">
<!---Setuptheargumentsforthefunction--->
<cfargumentname="userID"required="true"/>
<cfargumentname="password"required="true"/>
<cfparamname="UserAuthenticated"default="0"/>
<cfsetst_Return=StructNew()/>
<cfsetst_Return.userID=ARGUMENTS.userID/>
<cfinvoke
component="au.com.tatam.User.User"
method="Authenticate"
datasourceName="#ARGUMENTS.datasourcename#"
datasourceType="#ARGUMENTS.datasourcetype#"
returnVariable="UserAuthenticated">
<cfinvokeargument
name="UserName"
value="#ARGUMENTS.userID#">
<cfinvokeargument
name="password"
value="#ARGUMENTS.password#">
</cfinvoke>
<cfifUserAuthenticated>
<cfsetst_Return.sessionid=createUUID()/>
<!---DefaultexpiryTimeissetinDBasNow+1hr--->
<cfquerydatasource="#DSN_Session#"
dbtype="#DSN_
SessionDBType#"
name="qry_DeleteOldSessions">
DELETE*FROMtblUserSessions
Whereusername='#ARGUMENTS.userid#'
</cfquery>
<cfquerydatasource="#DSN_Session#"
dbtype="#DSN_SessionDBType#"
name="qry_InsertNewSession">
INSERTINTOtblUserSessions
(UserSessionUUID,username)
VALUES
('#st_Return.sessionid#','#ARGUMENTS.userID#')
</cfquery>
<cfelse>
<cfsetst_Return.sessionid=0/>
</cfif>
<cfreturnst_Return/>
</cffunction>
Michelle did research on CFCs and their use, and presented some thoughts at the
Versioning and Backing Up
TSC developers always create a customizable automated process that backs up files that are currently being worked upon. Versioning software is the ideal solution; however, with its small developer team, TSC finds that the reality of cost far outweighs its advantages. To
A TSC junior developer who has learned that code copies are of extreme benefit when major problems arise, uses manual versioning. The usage of
Figure IV-3.2. This is the junior developer's code directory.
User-Account Administration
The user-account administration screen was developed completely in ColdFusion and used a generic user CFC (
Figure IV-3.3
). It will be accessible from any browser and will give the ability to change a user's account details. This interface will
Figure IV-3.3. The user-account-administration screen allows for adding, editing and deleting chat user accounts.
The user-account administration uses the User.cfc file to get and set its
All the user properties have set and get methods, making the calls very generic and thus hiding the details of how the data is actually updated or extracted. This CFC can be extended or reused in other applications very easily.
The cfm file uses a
Displaying users online uses the database to deliver the information required. To update modified data, the edit form is self-posting. When modified data is submitted, a <cfloop> Tag is used to loop over the submitted form fields and calls the <cfinvoke> tag to update the details. <cfloop.....................> <cfinvokecomponent="au.com.tatam.user.user" method="set#form[currentformfield]#" datasourcename="#ARGUMENTS.datasourceName#" datasourceType="#ARGUMENTS.datasourceType#"> <cfargumentname="#currentformfield#" value="#form[currentformfield]#"/> </cfinvoke> </cfloop> This code will only work if the set method's naming is constant on all the fields that can be updated. That is, if a field is userID , then the set method will be setUserID . Chat-Center Development
The second requirement outlined the process of logging in with a user name and password (
Figure IV-3.4
). CFCs are used for authentication and the creation of a session ID. Flash is used for the client-side user interface and server-side shared object. After authentication, a user can request to chat with other users online or participate in a chat room. If a user accepts an
Figure IV-3.4. The chat-center log-in screen.
Figure IV-3.5. The chat-center user interface.
This request of and response to a chat invitation is controlled by the Flash Communication Server, which will be discussed in more detail later in the chapter. Logging out of a session is also the responsibility of this screen, which calls a CFC to terminate the session. The chat center needs both server-side CFCs and client-side Flash interface to provide a solution. The first step in the development required a frame that would set and display a user name as well as providing a password box and a button to submit the details for authentication.
Storage of persistent data needed to be written to the local file system. Flash MX provides such a feature called the shared object. Remote shared objects can be thought of as a real-time system for data storage and transfer.
There is a security feature that is part of the system object that can grant other domain(s) access to a local shared object. The syntax is as
System.security.allowDomain("tatam.com.au", "anotherdomain.com",.......);
For further security-related information,
Access cannot be
Security Concerns
All security-sensitive data will be loaded at run time from the server. The only risk is that the local file system could be compromised and the user ID that is stored could be discovered. TSC has a policy of not hard-coding any values that may compromise the client security. However, be aware that data still needs to be passed from client to server and that the transfer mechanism may need to be addressed (Secure Socket Layer). In this case it has been brought to the client's attention and no further action is required. The hosting environment also needs to be addressed. This means both the physical security as well as electronic security. Security compromises may be
Silicon Coast was satisfied with the proactive stance that TSC had taken to identify any concerns that may have arisen later.
The Flash
Through experience, TSC has realized that due to the many components and objects in Flash, it can be difficult to keep track of the code. Debugging can become a nightmare if some basic conventions are not adhered to. As a rule, most if not all ActionScript code is placed within one layer, which is named ActionScript. Ideally, but not always, the first frame
instant message
This
The following code gets the local shared object and creates a local-user object. The name of the constructor is obviously the name of the class. The constructor for the ChatLocalUser class takes the local shared object and places it in the object's UserDetails attribute:
_global.currentChatLocalUser=newChatLocalUser
(SharedObject.getLocal("ChatUser"));
The constructor for the ChatLocalUser class is as follows:
ChatLocalUser=function(UserDetails)
{
this.Userdetails=UserDetails;
}
The events in the first frame are associated with the button that changes and stores the user name, and the button that logs in the user.
Objects can be created in ActionScript. TSC uses a separate file for all its objects and then includes them in the code. When creating objects, you must be aware of the way in which memory is used. If a function of the object is defined in its constructor, then for every instance of the object that is created an instance of that function exists. To overcome this, an ActionScript object has a prototype property that is created automatically when you define the function. This allows not only functions but also properties to be shared across all instances. Each new instance then has a __proto__ property that can be referenced from within the instance. Here is a code snippet from the ChatLocalUser object (ChatLocalUser.as file).
ChatLocalUser.prototype.getUserID=function()
{
return(this.Userdetails.data.UserID);
}
TSC does not attach code to movie clips or
For your reference, I've included Button events and related methods ( Table IV-3.1 ) and Movie-clip events and related methods ( Table IV-3.2 ). Table IV-3.1. Button events and related methods
Table IV-3.2. Movie-clip events and related methods
The on(press) event is used to call the functions setUserID() and login().
The
setUserID()
function is called on the
localUser
object, which in turn
ChatLocalUser.prototype.setUserID=function(strName) this.Userdetails.data.UserID=strName; //flushingthesharedobjectsavestheinfo'now'ratherthan savingonclose. this.Userdetails.flush(); } The use of the flush() function enables Flash to write all memory data to the local shared object. The login function does exactly that. It creates a log-in object that gets sent to the server, which consists of a user name and password. To communicate with the server, a NetConnection object needs to be created, and a CFC method needs to be called.
The
NetConnection
class allows the developer to create a duplex connection between the server and the client-side. When
The NetConnection object's main method is the connect method. This method must take the targetURI parameter. This parameter is the Uniform resource identifier (URI) of the Flash Communication Server application instance. To create a remote shared object, you must first create the NetConnection object. The call the connect method on this NetConnection object.
IndividualChat_nc=newNetConnection();
IndividualChat_nc.connect("rtmp:/chat/Individual",
_global.userID);
IndividualChat_nc.onStatus=function(info){
}
IndivChatSession_so=SharedObject.getRemote(_global.IndivSessionID,
IndividualChat_nc.uri,false);
IndivChatSession_so.connect(IndividualChat_nc);
The NetConnection.onStatus event is invoked on the NetConnection's .connect method call. On invocation, this onStatus method receives an object that provides information regarding the connection that was attempted. If the connection is successful, the isConnected property is set to true . While your computer is attempting to connect to the FCS server, all data that uses this connection is queued until the connection is successful.
The chat application has three application instances:
Within the chat/general instance are the individual session instances. These objects are named as the UUIDs that are returned by the setNewSession method of the user CFC.
ChatServer_nc=newNetConnection();
ChatServer_nc.connect("rtmp:/chat/users",
_global.currentChatLocalUser.getUserID());
The .connect function opens up a TCP socket connection on the Flash server. This connection then exchanges real-time data through the use of the RTMP. The RTMP encodes the data that is streamed between client and server. This is the code from the ChatServer object (ChatServer.as file):
ChatServer.prototype.login=function(LocalSessionObject,status_Window,Username,Password)
{
varLogin_object=newObject();
Login_object.userID=Username;
Login_object.password=Password;
Login_object.status="Online";
login_object.datasourceName="chat";
login_object.datasourceType="ODBC";
Login_object.message="Iwanttologin";
chatserverSession=
this.chat_conn.getService("au.com.tatam.chat.Controller",
this);
status_Window.text=status_Window.Text+chr(10)+
"connectingtoserver...";
chatserverSession.setNewSession(Login_object);
this.onResult=function(result)
{
status_Window.text=status_Window.Text+chr(10)+
"..Retrieveddata..."+chr(10)+"session="+result.sessionid;
LocalSessionObject.data.SessionID=result.sessionid;
LocalSessionObject.data.userID=result.userID;
LocalSessionObject.flush();
if(result.sessionid!=0)
{
//createaremotesharedobjectforUsersessionaswellrequests
this.createSessionRemoteSharedObject(result.sessionid,
Username);
gotoAndStop(2);
}
}
this.onStatus=function(result)
{
trace(result.description);
status_Window.text=status_Window.Text+chr(10)+"Error"+
result.description;
}
}
The createSessionRemoteSharedObject creates a shared object, using the UUID of the session as its name:
ChatServer.prototype.createSessionRemoteSharedObject=function(SessionID,UserID)
{
newSession_nc=newNetConnection();
newSession_nc.connect("rtmp:/chat/General",UserID);
newSession_nc.onStatus=function(info)
{
trace(info.description);
}
generalSession_so=SharedObject.getRemote(SessionID,
newSession_nc.uri,false);
generalSession_so.connect(newSession_nc);
generalSession_so.setFps(2);
generalSession_so.data.request.SessionID="requested";
generalSession_so.onSync=function(list){.............}
}
Figure IV-3.6 shows the App Inspector. Figure IV-3.6. This is the App Inspector with two user sessions under chat/General.
User.cfcThe User.cfc file manages the user details. Both the chat center and the user-account-administration sections use this CFC. It has also been coded generically, allowing for its reuse or extension in other solutions TSC may deliver. The first line of code after the comments is the cfcomponent tag. This tag takes the Name attribute. Name: is the name of the component: <cfcomponentName="User"> .......... <cffunctionname="createUserTable"access="remote"> ............. </cffunction> </cfcomponent ><!---thenendofthecomponent---> The method createUserTable called is defined with the <cffunction> tag. This tag takes the following attributes:
Within the <cffunction> tag there is the <cfargument> tag. This tag helps define the purpose of the argument as well as throwing an error if the argument was not passed (Required attribute): <cfargumentNAME="DatasourceName"required="yes"/> <cfargumentNAME="DatasourceType"required="yes"/>
The CFC receives the data in its argument's scope. It then calls another CFC with the invoke method, to query the database: <cfinvoke This component call needs the following attributes to execute:
The following is a mixture of arguments that are within the cfinvoke tag as well as that use the <cfinvokeargument> tag:
<cffunctionname="setNewSession"access="remote">
<!---Setuptheargumentsforthefunction--->
<cfargumentname="userID"required="true"/>
<cfargumentname="password"required="true"/>
<cfparamname="UserAuthenticated"default="0"/>
<cfsetst_Return=StructNew()/>
<cfsetst_Return.userID=ARGUMENTS.userID/>
<cfinvokecomponent="au.com.tatam.User.User"
method="Authenticate"
datasourcename="#ARGUMENTS.datasourcename#"
DATASOURCETYPE="#ARGUMENTS.datasourceType#"
returnVariable="UserAuthenticated">
<cfinvokeargument
name="UserName"
value="#ARGUMENTS.userID#"/>
<cfinvokeargument
name="password"
value="#ARGUMENTS.password#"/>
</cfinvoke>
If the user is authenticated, then a new UUID is sent back down to the Flash client; if not, an integer ( ) will be returned:
<cfreturn <cfsetst_Return=StructNew()/> <cfsetst_Return.userID=arguments.userID/> <cfifUserAuthenticated> <cfsetst_Return.sessionid=createUUID()/> <cfelse> <cfsetst_Return.sessionid=0/> </cfif> <cfreturnst_Return/> Once the result is returned, the onResult() function is called and the local shared object is updated with the sessionID . If the sessionID is not , then the movie moves to the next frame.
this.onResult=function(result)
{
status_Window.text=status_Window.Text+chr(10)+
"..Retrieveddata..."+chr(10)+"session="+result.sessionid;
LocalSessionObject.data.SessionID=result.sessionid;
LocalSessionObject.data.userID=result.userID;
LocalSessionObject.flush();
if(result.sessionid!=0)
{
//createaremotesharedobjectforUsersessionaswell
requests
this.createSessionRemoteSharedObject(result.sessionid,
Username);
gotoAndStop(2);
}
}
For the log-in to be a success, a sessionID must be returned on the correct authentication. GotoAndStop() is used to proceed to the chatcenter UI, once the user has been authenticated. This function moves the focus to the next frame in the Flash User Interface. The next frame displays the current users, chat rooms online, and current chat invitations.
This data is
Flash Communication Server
The Flash Communication Server enables you to store an object on the server side. This object can then be accessible by the FCS or any system that can connect to the FCS. If there the object's state changes, the
If the client is not connected to the server, then the next time the client is connected to the object, the data that has been changed is updated.
As this server is a new concept for TSC, the developers needed to research how the management of the shared object's server side was to be implemented. They researched issues such as synchronization and locking, and whether the object would be persistent.
The developers have identified that storage of data on the server-side shared object is the same as that on the client side. It is stored in the object's
data
property. Within this property, each set of
The so.getRemote function returns a reference to an object that is specified in the first parameter of the function call. This getRemote function takes two required parameters:
The final optional parameter is the persistence parameter. This specifies whether the object will be persistent. If it is deemed persistent , then it will be stored in the FlashCom directory. If Flash cannot find the file, then it creates it. If it can't create it, then a null is returned.
The Flash Communication Server directory is specified in the
The so.connect method is then called.
The remote shared object's connect method is used to connect to a remote shared object. There must be a connection to the FCS before a server-side shared object can be accessed. So the connect method must take the parameter of a NetConnectionobject . This method returns a true value if there was a successful connection. Once successful reference has been established, the .onsync event is invoked. The .onsync event handler should be defined so that the application receives notification of a change's failure or success.
ChatServer_nc.onStatus=function(info)
{
trace(info.description);
}
Usersonline_so=SharedObject.getRemote("Usersonline",
ChatServer_nc.uri,false);
Usersonline_so.connect(ChatServer_nc);
Usersonline_so.data[_global.currentChatLocalUser.getUserI
D()]="online";
The onsync method receives an array of objects when it is invoked. This array of objects has properties that represent the server-side shared object's modifications. As previously mentioned, it is invoked on connection as well as when there is a change to the server-side shared object.
Usersonline_so.onSync=function(list){
for(vari=0;i<list.length;i++)
if(Usersonline_so.data[list[i].name]=="online")
{
_root.UsersOnline_lstBx.Additem(list[i].name);
}
elseif(Usersonline_so.data[list[i].name]=="offline")
{
for(varofflinecountr=0;offlinecountr<
_root.UsersOnline_lstBx.getlength();offlinecountr++)
{
if(_root.UsersOnline_lstBx.getItemAt(offlinecountr).label
==list[i].name)
{
_root.UsersOnline_lstBx.removeItemAt(offlinecountr);
}
}
}
};
Logging OutA request is sent to the server to log out. This deletes the session row from the User Session table and then notifies the user of the disconnection. The session's termination can then be tested by checking for its presence in the User session table. Request a Chat ProcessThe development team had a number of different options available for this invitation process. Initially, before the FCS was accepted, the database was to be used to store requests. An ActionScript setInterval method was to be used to poll the server for new requests. With the introduction of the FCS, the development team needed to research other possible techniques that could lever off the new technology. The team decided that as the chat/general instance held a shared object related to the current session, it would be possible to use a requests slot to hold incoming and outgoing requests. The createChatRequest method was declared as a prototype function. It calls the createChatRequest method in the dialog.request CFC. The returned value of the createChatRequest function is a RequestUUID . This value can be accessed as a property of the returned object. This returned object is the result variable that is sent to the onResult function when it is invoked. this.onResult=function(result) The returned value is the result.requestUUID variable.
ChatInvitation.prototype.createChatRequest=function(userID,
Responder,SessionID)
{
NetServices.setDefaultGatewayUrlchatServerGatewayAddress);
this.request_conn=
NetServices.createGatewayConnection();
varRequest_object=newObject();
Request_object.RequestorUserID=userID;
Request_object.ResponderUserID=Responder;
varchatserverRequests=this.request_conn.getService
("au.com.tatam.chat.Controller",this);
//callstheCFCau.com.tatam.chat.Controllerandcallsthe
methodcreateChatRequest
chatserverRequests.createChatRequest(Request_object);
this.onResult=function(result)
{
this.addRequestToGeneralSessionSharedObject(SessionID,
userID,result.requestUUID,Responder);
}
this.onStatus=function(result)
{
trace("inonstatus"+result.description);
}
}
The createChatRequest method called through the controller is as follows:
<cffunctionname="createChatRequest"access="remote">
<cfargumentname="RequestorUserID"Required="Yes"/>
<cfargumentname="ResponderUserID"required="yes"/>
<cfsetrequestUUID=createUUID()/>
<cfquerydatasource="#DSN_Session#"
dbtype="#DSN_SessionDBType#"name="qry_addChatREquest">
INSERTINTOtblChatRequest
(ChatRequestUUID,ChatRequestorUserID,
ChatResponderUserID)
VALUES
('#requestUUID#','#ARGUMENTS.RequestorUserID#',
'#ARGUMENTS.ResponderUserID#')
</cfquery>
<cfsetst_Return=StructNew()/>
<cfsetst_Return.requestUUID=requestUUID/>
<cfreturnst_Return/>
</cffunction>
The addRequestToGeneralSessionSharedObjectfunction is called once a RequestUUID has been returned. this.addRequestToGeneralSessionSharedObject(SessionID, userID,result.requestUUID,Responder); When a user requests a chat with another particular user (the responder), the invitation is updated on the responder's server-side shared object. This immediately invokes the onsync event. Within the onsync method the code notifies the user of a request to chat ( Figure IV-3.7 ). Figure IV-3.7. The Chat Invitation dialog screen.
If the request is accepted, a new window is created that sends the SessionID and other parameters on the URL string to the Chatcontroller.cfm file. Individual Chat DevelopmentThe Chatcontroller.cfm file uses ColdFusion to populate the sessionID and other variables into the JavaScript code. It also populates the JavaScript function that is called from within the .swf Flash MX file. The skeleton JavaScript code is created when Flash MX publishes the .swf file.
Chatcontroller.cfm<cfifparameterexists(url.sessionid)> <cfsetChatSessionID=url.sessionid/> <cfsetusername=url.username/> <cfsetrequestor=url.requestor/> The Chatcontroller.cfm and .swf files have the ability to be re-used in other applications that may require similar chat functionality. By placing URL variables on the URL request, the system can also be a stand-alone chat application.
<HTML>
<HEAD>
<metahttp-equiv=Content-Typecontent="text/html;
charset=ISO-8859-1">
<TITLE>individualChatUI</TITLE>
</HEAD>
<BODYbgcolor="#D4D0C8">
<SCRIPTLANGUAGE=JavaScript>
<!--
varInternetExplorer=navigator.appName.indexOf
("Microsoft")!=-1;
//HandlealltheFSCommandmessagesinaFlashmovie
functionindividualChatUI_DoFSCommand(command,args){
varindividualChatUIObj=InternetExplorer?individualChatUI:document.individualChatUI;
//
//Placeyourcodehere...
//
if(command=="getChatSessionID")
{
<cfoutput>SessionID="#ChatSessionID#";</cfoutput>
individualChatUIObj.SetVariable("SessionID_txt.text",
SessionID);
individualChatUIObj.SetVariable("_global.IndivSessionID",
SessionID);
//mustgetsessionIUDanduseingetremote
alert(SessionID);
}
if(command=="getUsername")
{
<cfoutput>username="#username#";</cfoutput>
alert(username);
individualChatUIObj.SetVariable("userid_txt.text",
username);
individualChatUIObj.SetVariable("_global.userid",
username);
}
if(command=="getRequestor")
{
<cfoutput>requestor="#requestor#";</cfoutput>
//alert(requestor);
individualChatUIObj.SetVariable("invitation_txt.text",requestor+"wantstochat");
}
}
//HookforInternetExplorer
if(navigator.appName&&
navigator.appName.indexOf("Microsoft")!=-1&&
navigator.userAgent.indexOf("Windows")!=-1&&
navigator.userAgent.indexOf("Windows3.1")==-1){
document.write('<SCRIPTLANGUAGE=VBScript\>\n');
document.write('onerrorresumenext\n');
document.write('SubindividualChatUI_FSCommand(ByVal
command,ByValargs)\n');
document.write('call
individualChatUI_DoFSCommand(command,args)\n');
document.write('endsub\n');
document.write('</SCRIPT\>\n');
}
//-->
</SCRIPT>
<!--URLsusedinthemovie-->
<!--textusedinthemovie-->
<!--<PALIGN="LEFT"></P>Hello--><OBJECT
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/ca
bs/flash/swflash.cab#version=6,0,0,0"
ID="individualChatUI"WIDTH="440"HEIGHT="300"ALIGN="">
<PARAMNAME=movieVALUE="individualChatUI.swf"><PARAM
NAME=qualityVALUE=high><PARAMNAME=bgcolorVALUE=#D4D0C8>
<EMBEDsrc="individualChatUI.swf"quality=high
bgcolor=#D4D0C8WIDTH="440"HEIGHT="300"swLiveConnect=true
ID="individualChatUI"NAME="individualChatUI"ALIGN=""
TYPE="application/x-shockwave-flash"
PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer"
></EMBED>
</OBJECT>
</BODY>
</HTML>
Once an acceptance to an invitation is submitted, the user is presented with a screen that records the dialog of the current chat and allows the creation of new messages ( Figure IV-3.8 ). Figure IV-3.8. The individual chat user interface.
There can exist a number of different instances of this UI per user session, compared with the single chat-center UI per user logged-in session. This frame uses Flash MX on both the server and client sides. The FCS will handle the real-time text messaging.
The individual chat UI was
_FSCommand("getUsername");
_FSCommand("getChatSessionID");
The above ActionScript FSCommand code calls the following JavaScript code:
functionindividualChatUI_DoFSCommand(command,args){
varindividualChatUIObj=InternetExplorer?individualChatUI
:document.individualChatUI;
if(command=="getChatSessionID")
{........}
if(command=="getRequestor")
{........}
Once the SWF file has the sessionID , it connects to the chat/individualChat instance to get the server-side shared object that corresponds to the returned sessionID . After the code has populated the variables with the FSCommand , a connection is made to the server. It then calls the server-side shared object (with the sessionID as its instance name). Once the sharedObject is retrieved, the user can enter a message and send it to the server-side shared object, which will then invoke all current connected users .onsync method. This onsync code populates the dialog texfield with HTML text.
IndividualChat_nc=newNetConnection();
IndividualChat_nc.connect("rtmp:/chat/Individual",
_global.userID);
IndividualChat_nc.onStatus=function(info){
trace(info.description);
}
ChatSession_so=
SharedObject.getRemote(_global.IndivSessionID,
IndividualChat_nc.uri,false);
ChatSession_so.connect(IndividualChat_nc);
ChatSession_so.setFps(2);
ChatSession_so.data.chatDialog="";
ChatSession_so.onSync=function(list){
for(vari=0;i<list.length;i++)
if(list[i].name=="chatDialog")
{
_root.dialog_txt.HTMLtext=ChatSession
_so.data.chatDialog;
break;
}
};
Once the chat instance has been instantiated, a server-side shared object is created by the FCS. This gives users the ability to send and receive messages in real-time. You program the application to send messages in HTML format with the following code. ChatSession_so.data.chatDialog="<fontcolor=\"blue\"><b>" +_global.UserID+":</b>"+_root.message_txt.text+chr(10)+ ChatSession_so.data.chatDialog; |