Server Time:
Sunday May 11 2008 08:17 PM  
Your Time:
  
HostMySite.Com is sponsoring this tutorial, please visit their site today!
This tutorial is sponsored by HostMySite.Com - ColdFusion Hosting

Creating a Chat System in ColdFusion without using a database!
by: Chris A.
Email this tutorial to a friend Display Printer Friendly Format
[Download in PDF Format] [Download in FlashPaper Format]

Creating a Chat System in ColdFusion without using a database!

Being a ColdFusion Developer a little over a year now [Ex-ASP Developer], I try to find ways to make my existing applications faster and lighter at the same time. I originally created this chat room back in the year 2000 in ASP using a Microsoft Access Database. Since I have been learning ColdFusion, I naturally wanted to change all my previous ASP applications to ColdFusion code. This is the end-result of the chat room from ASP to ColdFusion. (I also wanted to thank Pablo and everyone at EasyCFM, even though I have not yet signed up for a forum account, I use the site and forum often to help me learn, so thank all of you!) You can download all the code for this tutorial here.

This tutorial will have a total of 6 ColdFusion pages.

  • Application.cfm
  • Index.cfm
  • Logout.cfm
  • Messages.cfm
  • PostMessages.cfm
  • User_List.cfm

I will give a brief explanation of each page so you can understand the application a little better. The actual code is directly below the explanations!

APPLICATION.CFM
This is the page were we set the Application and Session variables that are used throughout the application.
INDEX.CFM
This is the page the loads either the login page or the chat window frames.
LOGOUT.CFM
This page will log the user out and alert everyone in the chat room about it.
MESSAGES.CFM
This is the page that displays the chat conversations.
POSTMESSAGES.CFM
This is the page you can use to post your message to the room.
USER_LIST.CFM
This page shows you who is currently in the chat room!

The following is the actual code that the files mentioned above contain!

APPLICATION.CFM
<cfsetting enablecfoutputonly="Yes">
<!--- ^^^^^^^^^^^^^^^^
         Define a new application
        ^^^^^^^^^^^^^^^^ --->

<cfapplication name="ChatRoom"
                     clientmanagement=
"Yes"
                     sessionmanagement=
"Yes"
                     sessiontimeout=
"#CreateTimeSpan(0,0,15,0)#"
                     applicationtimeout=
"#CreateTimeSpan(0,2,0,0)#">

<!--- ^^^^^^^^^^^^^^^
        Define default variables
        ^^^^^^^^^^^^^^^ --->

<cfparam name="Application.UserList" default="">
<cfparam name=
"Application.MessageLog" default="">
<cfset Application.Title =
"My Chat Room!">

<!--- ^^^^^^^^^^^^^^^^^
        First define default session
        ^^^^^^^^^^^^^^^^^ --->

<cfparam name="session.MyUsername" default="">
<cfparam name=
"session.goodUser" default="No">

<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        Now see if the user has logged themselves in 
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->
<cfif IsDefined("FORM.MyUsername") and FORM.MyUsername neq "">
        <!--- ^^^^^^^^^^^^^^^^^^^^^^^
                First see if the username is available 
                ^^^^^^^^^^^^^^^^^^^^^^^ --->
        <cfset UserOkToUse = ListFind(Application.UserList, FORM.MyUsername, "#chr(9)#")>

        <!--- ^^^^^^^^^^^^^
                Username ok to use
                ^^^^^^^^^^^^^ --->
        <cfif UserOkToUse eq 0>
                <cfset session.MyUsername = FORM.MyUsername>
                <cfset session.goodUser =
"Yes">
                <!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                         Now add user to list of users
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->
                <cfset Application.UserList = ListAppend(Application.UserList, FORM.MyUsername, "#chr(9)#")>
                <cfset Application.MessageLog =
"<font color=Green><b>#session.MyUserName# Logged In at #DateFormat(now())# #TimeFormat(now())#</b></font><br>" & Application.MessageLog>
        <cfelse>
                <cfset UserMessage =
"Username taken, try another!">
        </cfif>
</cfif>
<cfsetting enablecfoutputonly=
"No">
INDEX.CFM
<cfoutput>
<html>
  <head>
     <title>
#Application.Title#</title>
  </head>


<cfif session.goodUser eq "Yes"
  <frameset rows="64,*">
     <frame name=
"postmessage" scrolling="no" noresize src="postmessage.cfm">
      <frameset cols=
"150,*">
          <frame name=
"users" target="main" src="user_list.cfm">
          <frame name=
"main" src="messages.cfm">
      </frameset>
      <noframes>

         <body>
            <p>This page uses frames, but your browser doesn't support them.</p>
         </body>

      </noframes>
  </frameset>
<cfelse>

  <body>
    <form action="index.cfm" method="post">
    <cfif IsDefined("UserMessage")>
       #UserMessage#
    </cfif>
    <table width="300" border="0">
      <tr>
          <td width=
"50%">Screen Name:</td>
          <td width=
"50%"><input type="text" name="MyUsername" value=""></td>
      </tr>
      <tr>
          <td width=
"100%" colspan="2"><input type="submit" name="LogMeIn" value="Log In"></td>
      </tr>
    </table>

    </form>
  </body>
</cfif>

</html>
</cfoutput>
LOGOUT.CFM
<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        LET EVERYONE KNOW THAT THIS USER LOGGED OUT
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->

<cfset Application.MessageLog = "<font color=red><b>#session.MyUserName# Logged Out at #DateFormat(now())# #TimeFormat(now())#</b></font><br>" & Application.MessageLog>
<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        TAKE USER OUT OF THE LIST OF LOGGED IN USERS
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->

<cfset Application.UserList = ListDeleteAt(Application.UserList, ListFindNoCase(Application.UserList, session.MyUsername, "#chr(9)#"), "#chr(9)#")>
<!--- ^^^^^^^^^^^^^
         LOG THE USER OUT
        ^^^^^^^^^^^^^ --->

<cfset session.MyUsername = "">
<cfset session.goodUser =
"No">
<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^
        TAKE USER BACK TO THE LOGIN PAGE
        ^^^^^^^^^^^^^^^^^^^^^^^^^ --->

<cflocation url="index.cfm" addtoken="Yes">
MESSAGES.CFM
<html>
  <head>
     <title>
Message Log</title>
     <META HTTP-EQUIV=REFRESH CONTENT=
"5">
  </head>


  <body>

  <cfoutput>
     #Application.MessageLog#
  </cfoutput>

  </body>
</html>
POSTMESSAGES.CFM
<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        If a new message if posted, put into the application variable so everyone can see it
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->

<cfif IsDefined("FORM.new_message") and FORM.new_message IS NOT "">
     <cfset Application.MessageLog =
"<b>#session.MyUserName#</b>: #FORM.new_message#<br>" & Application.MessageLog>
</cfif>

<!--- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         DISPLAY THE FORM THAT ALLOWS NEW MESSAGE TO BE ENTERED
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ --->

<html>
  <head>
     <title>
Post New Message</title>
  </head>

  <body bgcolor=
"#000000">

  <form action="postmessage.cfm" method="post">
  <table width="100%" border="0">
    <tr>
       <td width=
"100%"><input type="text" name="new_message" value="" size="50">
                                    <input type=
"submit" name="PostIt" value="Post Message">
                                    <a href="logout.cfm" target="_top">Logout</a></td>
   </tr>
  </table>

</form>

</body>
</html>
USER_LIST.CFM
<html>
  <head>
    <title>
Logged In Users</title>
  </head>

  <body>


  <cfoutput>
   <form>
    <strong>Logged In Users:</strong><BR>
    <ul>
    <cfloop list="#Application.UserList#" index="UserName" delimiters="#chr(9)#">
        <li>#UserName#</li>
    </cfloop>
    </ul>
    <input type="submit" name="Refresh" value="Refresh User List">
   </form>

  </cfoutput>

</body>
</html>

That's it, if you find anything wrong with the example or a better way to do that chat, let me know. I'm always looking for ways to improve my applications.
- chris


Date added: Sat. May 10, 2003
Posted by: Chris A. | Views: 21161 | Tested Platforms: CF5,CFMX | Difficulty: Intermediate
Categories Listed: Best Practices Full Applications Other

HostMySite.Com is sponsoring this tutorial, please visit their site today!
This tutorial is sponsored by HostMySite.Com - ColdFusion Hosting

Please rate this tutorial:
5 Stars 4 Stars 3 Stars 2 Stars 1 Stars
Comments on this tutorial
Read previous comments on this particular tutorial
missin file
Pleas i am try to migtrate to CFM i use ASP b4 i try runing your code its not displaying properly i think

Appllication.Userlist and
messagelog is not found what should i do

Posted by: Don
Posted on: 04/19/2004 08:37 AM
frameset in cf
Dear Sir;
I need your help to provide me about how i can use Application.cfm page that include a design for the whole web distributed in web pages, inspite of that i was do the steps for the application and calling the page that contain the frameset, but i found that the page call one frame and ignore the other where the calling frame is saved as *.html at the first but i found no calling to the whole content of the page.

The Application.cfm page should include
1- Three Frameset
2- frame one could design the look of the site to distributed.

Thank for Help

B. Rayyan
Arab American University
West Bank - Israel
Posted by: Baher Rayyan
Posted on: 05/09/2004 04:56 AM
Capture Browser Close?
What if someone decides to simply close the browser rather than click logout? How do you remove them from the "chatter list" in a timely manner?

Note: onUnload won't work in Netscape when closing the browser.

I'm stumped on this one.

Thanks.
Posted by: tom
Posted on: 06/11/2004 06:07 PM
Log user off...
Finally solved my onunload issue. Interesting story...kind of.

The original Google popup blocker, which I have, blocks all onunload events in IE, regardless of whether or not it's being used to launch a popup. Netscape 7 is developed to block onunload="window.open()" events to stop popups. So, it became obvious that popping up a window to run a script to log someone off wouldn't work (like in the old days).

So, I decided to use onunload in Netscape to simply change the parent doc url to log the person off when the chat window is closed, which worked, but amazingly not in IE.

Still though, onunload is blocked in IE 5.5+ if you have google popup blocker even if you are simply changing an url of an existing window. However, google doesn't block onBeforeUnload, and Netscape doesn't recognize that one.

Anyway, just put them both in the body tag, and you'll get results in both browsers with popup blockers.

<SCRIPT LANGUAGE="JavaScript">
function changeurl() {
parent.opener.location.href = "../chat.cfm?logged_out=1";
}
</SCRIPT>

<BODY onUnload="changeurl()" onBeforeUnload="changeurl()">

PS. windows.onclose() was causing the action to occur onload when loading pages in a framed set of windows, not unloading for some reason.

Posted by: tom
Posted on: 06/15/2004 09:43 AM
A couple of small improvements
First to get rid of the annoying 'click' sound in IE when the messages.cfm frame refreshes, replace the Meta refresh tag with a bit of javascript...

<script language="JavaScript1.2">
window.setInterval(reloadpage, 5000);
function reloadpage(){location.reload();}
</script>

Second add a bit of filtering - add two lines to application.cfm...

<cfset Application.WordBanList = "f__k,s__t,c__t,p___y">
<cfset Application.WordReplace = "****,****.****,*****">

Next add one line in postmessage.cfm after the <cfif...>
<cfset FORM.new_message = ReplaceList(FORM.new_message, Application.WordBanList, Application.WordReplace)>


Third, when the user enters a chat statement put the focus back into the submit box. In postmessage.cfm... (I named the form 'post')
<body onload="document.post.new_message.focus()">

The final big thing is the garbage collection of users who didn't specifically logout. My idea here was to constantly tell the Application that my session was still active by resetting a counter every reload of the message pane. It works like this...

Add a new array that coresponds to the username array containing a counter for each user. When the page reloads set my counter to 0 and increment my neighbor's counter. If someone's counter gets to 5 or so, remove them and their counter from the list.

There are several things to add in Application.cfm, message.cfm, and logout.cfm

Application.cfm

<cfparam name="Application.UserListCounter" default="">

and right after <cfset Application.UserList =.....

<cfset Application.UserListCounter = ListAppend(Application.UserListCounter, 0, "#chr(9)#")>

messages.cfm

<!---Set mycounter to 0 and increment my neighbor's counter --->
<cfset myplace = ListFindNoCase(Application.UserList, session.MyUsername)>
<cfset nextplace = myplace +1>
<cfif nextplace gt ListLen(Application.UserListCounter)><cfset nextplace = 1></cfif><!---wrap around list--->
<cfset Application.UserListCounter = ListSetAt(Application.UserListCounter, myplace, 0)>
<cfset value = ListGetAt(Application.UserListCounter, nextplace) + 1>
<cfset Application.UserListCounter = ListSetAt(Application.UserListCounter, nextplace, value)>

<!---Perform Cleanup operation by looking for 4's --->
<cfset counters = listtoarray(Application.UserListCounter)>
<cfloop from="1" to="#ArrayLen(counters)#" index="i">
<cfif counters[i] gte 5>
<cfset delete = i>
</cfif>
</cfloop>
<cfif isDefined("delete")>
<cfset Application.UserListCounter = ListDeleteAt(Application.UserListCounter, delete)>
<cfset Application.UserList = ListDeleteAt(Application.UserList, delete)>
</cfif>


logout.cfm

Add this BEFORE the <cfset Application.UserList =... statement
<cfset Application.UserListCounter = ListDeleteAt(Application.UserListCounter, ListFindNoCase(Application.UserList, session.MyUsername))>



Posted by: Troy
Posted on: 06/17/2004 01:46 AM
I should note about my above submission
For the most part I removed all the chr(9) delimiter's and just went with the default comma's - if you keep the chr(9) delimiter you need to add it accordingly above.

Likewise you should then not allow usernames with comma's.

Hope this helps

Troy
Posted by: Troy
Posted on: 06/17/2004 01:51 AM
cool

Posted by: Hasan
Posted on: 07/04/2004 05:40 AM
question about refresh
great tutorial! when the page refreshes, it naturally returns to the top of the page. This is fine unless you are trying to read older posts that are currently off the page. Is there a way to have it refresh without starting at the top?
thanks!
Posted by: Dano
Posted on: 07/07/2004 10:02 AM
Thanks man pretty cool for freebie
Thanks, I'll probably use this on my little website just to talk to friends and whatnot. Pretty cool of you to post.
Posted by: Shawn Becker
Posted on: 09/09/2004 02:12 PM
private chatting
Thanks,I am keen to use it in my web site but the probs is that it has only public chatting and i want use private chatting too.
thanks!
Posted by: poordhendu singh chauhan
Posted on: 09/15/2004 05:55 PM
You should be working for Macromedia
I have been through many tutorials, you have a natural gift for teaching. The code was well written and the results were ease of use. Thank you again "I see the light"!
Posted by: Sir Christopher
Posted on: 09/22/2004 01:32 PM

I want to put a java chat on my site, but they are already logged into a session before that chat - would it still work? if not, what would i need to edit for it to work
Posted by: Mysti
Posted on: 10/17/2004 11:15 PM
How to clear frameset
I have many screens to accessed with frameset. When I moved 2nd screen from 1st frameset, there is still 1st frame scrren. How can I clear previous frame?

Thanks,
HD
Posted by: HD
Posted on: 12/20/2004 02:14 PM
not working logout
the second tutorial you wrote is not working, look out the message:

Invalid list index 0.
In function ListSetAt(list, index [, delimiters]), the value of index, 0, is not a valid as the first argument (this list has 1 elements). Valid indexes are in the range 1 through the number of elements in the list.

The Error Occurred in E:\HTML\mitcha\chat\messages.cfm: line 6

4 : <cfset nextplace = myplace +1>
5 : <cfif nextplace gt ListLen(Application.UserListCounter)><cfset nextplace = 1></cfif><!---wrap around list--->
6 : <cfset Application.UserListCounter = ListSetAt(Application.UserListCounter, myplace, 0)>
7 : <cfset value = ListGetAt(Application.UserListCounter, nextplace) + 1>
8 : <cfset Application.UserListCounter = ListSetAt(Application.UserListCounter, nextplace, value)>
Posted by: mitcha
Posted on: 01/04/2005 06:26 PM
Chat system with database
Bravo Chris! very cool Tutorial "Public Chat System"! I could n't stop without writing this comment. It would be much better, if it can be modified to Private Chat System with multiple chat rooms.

Troy! if you could respond to mitch's problem, it would be much help to modify this chat system.

All chat informaiton can be stored in the databsse. If anybody wants this chat system with database connection, write me. That's simple.
Posted by: Raj
Posted on: 01/05/2005 10:31 PM
Emoticons
Is that what they are called? Anyway, can anyone give me a hint on including smileys and that with this kind of chat room? Thanks!!
Posted by: Valerie
Posted on: 02/23/2005 07:10 PM
To answer the question about - "not working logout"
I've looked over the code I posted above looking for some error, I didn't see anything wrong, other than error detection.

Notice that the myplace variable is set in the following statement:
<cfset myplace = ListFindNoCase(Application.UserList, session.MyUsername)>

I've assumed that the user would be properly registered in the list of logged in users. When the ListFindNoCase function executes - if it does not find the person, it returns 0.

Why would I not be in the list? Either my login didn't work, or my counter got too high (my browser stopped refreshing or my Internet bogged down). When I implemented this, I must of ran into the same problem, because I added this to my code right after the above statement:
<cfif myplace eq 0><cflocation url="index.cfm?timeout=1"></cfif>

This will just take me back to the login.

I also added this to the delete partreplaced the user removal part above (right after <cfif isDefined("delete")>):
<cfset kickeduser = ListGetAt(Application.UserList, delete)>
<cfset Application.MessageLog = "<font color=red size=1>#kickeduser# Timed Out at #DateFormat(now())# #TimeFormat(now())#</font><br>" & Application.MessageLog>

This will report to everyone that the person got logged out.


Posted by: Troy
Posted on: 03/13/2005 12:37 AM
chat message list
Hi everybody, could somebody please tell me how to get rid of all messages and all user so the chat room starts from 0 and blank, hope you know what I mean.
Many thanks
Posted by: akos
Posted on: 09/15/2005 10:06 AM
Nice code...question though
Question, is there a way to delete old lines or does this code just keep all chat lines forever?

Even when you log out and back in, the original text is still there for the user. I even deleted the files off my server and reloaded it and it still kept the text there.
Posted by: JfWebdesign
Posted on: 03/03/2006 03:04 AM
How to delete old chat lines
put this in the begining of index cfm
<cfif isDefined("url.clean")>
<cfif url.clean eq 1>
<cfset Application.MessageLog = "">
</cfif>
</cfif>
than type in your browser index.cfm?clean=1
hit refresh
this will clean the lines
AB
Posted by: AB
Posted on: 04/22/2006 10:14 PM
Thanks!!
I can't thank you enough. I was dying for a way to get a 'users online' list and couldn't find ANYTHING in many searches of cfdocs about it. Along the way I found that not only did you reinvent the chat (I did too, but using a database) but yours is cleaner and faster! way cool! Thanks a ton man. It was super helpful.
Posted by: PJ
Posted on: 08/07/2006 04:09 AM
Little Help
I made the changes in the second part and now the following error comes up. Can you help me out?

Element USERLISTCOUNTER is undefined in APPLICATION.


The error occurred in C:\CFusionMX\wwwroot\dewbrellc\chat\Application.cfm: line 17

15 :
16 : <!--- New Code from CF Tutorials 061003 --->
17 : <cfset Application.UserListCounter = ListAppend(Application.UserListCounter, 1, "#chr(9)#")>
18 :
19 : <cfparam name="Application.MessageLog" default="">



Posted by: cfpadawan
Posted on: 10/04/2006 10:10 PM
Things to consider.
This seems like a novel idea but has anyone considered any possible issues around storing the chat messages in the application scope? The more messages you have in your chat session the more memory it will use up on the server. A site with alot of traffic could pose a problem with server resources. The only way to clear these messages is to either restart the coldfusion server or clear the application structure manually. Another thing to consider, looking at the source code you have users reading and writing to the same variable stored in the application scope and there is no locking being used. This in it's self could cause some undesireable issues in addition to server performance, memory leaks and race conditions...
Posted by: JB
Posted on: 11/02/2006 12:50 PM
Error
Hi Chris:

Congratulations for being a winner! I downloaded the code, but I get an error like tat the bottom. Also, do you a version that uses database?

Thanks a lot!

Danny


Error Occurred While Processing Request

Error Diagnostic Information

An error has occurred while processing the expression: Application.UserList=CFTempOnlyForSetVariableNeverUseThisNameInYourCFMLCode122333444455555654321

Error near line 1, column 1.

Symbol Application.UserList is in a scope that contains data shared across threads and cannot be accessed without an active lock

The error occurred while processing an element with a general identifier of (CFPARAM), occupying document position (14:1) to (14:48).

Date/Time: 03/20/07 15:33:25
Browser: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 (ax)
Remote Address: 192.168.12.29
Posted by: danny
Posted on: 03/20/2007 03:38 PM
Database version
Does any one has the database version of chat room? Please be so kind to post it.

Thanks
Posted by: Danielson
Posted on: 03/21/2007 02:11 PM
Relaince on Meta Refresh
Meta-refresh can readily be disabled - as such this thing would not work at all. Better to use an event driven method.
Posted by: RIch
Posted on: 12/12/2007 07:27 PM
Ban List Output and Message Log Clearing
I updated my ban list to stick out when something was banned... here's what I said:

--- Application.cfm page
<cfset Application.WordBanList = "b__ch">
<cfset Application.WordReplace = "<em style='color:red;'> DELETED </em>,">

These are both comma separated and I have more, but just for the sake of example I left off the list and just used one.


I also did this on the page index.cfm.

-- index.cfm

<cfif isDefined("url.clean")>
<cfset Application.MessageLog = "* * * Message Log Cleaned at #timeformat(now(), 'hh:mm')#!!!">
<cflocation url="index.cfm" addtoken="no">
</cfif>

Just FYI. :)
Posted by: Justin
Posted on: 01/30/2008 08:06 PM
re:private chat
Any one was able to change this chat to private chat and if so would you mind sharing some of the code or ideas on this.
Also, the refresh is annoying to push the messages any idea on this.

thanks
Ken
Posted by: Ken
Posted on: 04/30/2008 10:14 AM
Post a new comment on this tutorial
post a new comment on this particular tutorial
Your Name:
Your Email:
Comment Title:
Comments:
Key Phrase:
 
Skyscrapper Banner Advertisement
Daily Razor - ColdFusion Hosting

You are 1 of 774 active sessions! | Privacy | Company
Copyright © 2002 EasyCFM.Com, LLC. (Easy ColdFusion Tutorials) All Rights Reserved
All other trademarks and copyrights are the property of their respective holders.
ColdFusion Hosting ColdFusion Hosting
ADD TO:
Blink
Del.icio.us
Digg
Furl
Google
Simpy
Spurl
Y! MyWeb