{"id":17,"date":"2006-03-01T12:50:10","date_gmt":"2006-03-01T18:50:10","guid":{"rendered":"http:\/\/thepizzy.net\/blog\/?p=17"},"modified":"2008-09-16T12:33:25","modified_gmt":"2008-09-16T18:33:25","slug":"project-tsnxchat","status":"publish","type":"post","link":"https:\/\/thepizzy.net\/blog\/2006\/03\/project-tsnxchat\/","title":{"rendered":"Project: tsnXchat"},"content":{"rendered":"<p>After using a flooble chatterbox from www.flooble.com, and trying to (unsuccessfully) hack it to get rid of the ads at the bottom, I have resolved to putting my newly developed AJAX skills to the test, to create an open-source version, with no ads. I&#8217;ll explain how you can make one too in this entry.<br \/>\n<!--more--><\/p>\n<p>It only requires 3 files, a MYSQL database, access to a server running PHP, and a basic understanding of JavaScript, HTML, PHP, MySQL, and about 10-30 minutes (depending on your understanding of this stuff). I&#8217;ll try to keep things as basic as possible so that anyone who reads this can understand what&#8217;s going on.<\/p>\n<p>Before you get started, you need to have a couple things.<\/p>\n<ul>\n<li>A database that you can access, with a known username and password, and that you&#8217;re able to write to. You&#8217;ll be creating a table and populating it with data. If you don&#8217;t have that, go to <a href=\"http:\/\/www.mysql.com\" target=\"_blank\">mysql.com<\/a> and get one there. (If you want to facilitate the use of MySQL, then you should probably go with something like <a href=\"http:\/\/sourceforge.net\/projects\/phpmyadmin\" target=\"_blank\">phpMyAdmin<\/a>.<\/li>\n<li>PHP engine. If you don&#8217;t have PHP, you&#8217;ll need to <a href=\"http:\/\/www.php.net\" target=\"_blank\">get that also<\/a>.<\/li>\n<li>A web server. <a href=\"http:\/\/www.apache.org\" target=_blank\">Apache works fine.<\/a> I haven&#8217;t used MS IIS in about 5 years, and I don&#8217;t think you should either really. But there&#8217;s not anything wrong with it&#8230;just setting it up take time.<\/li>\n<li>Also, if you don&#8217;t have a good coding program, I recommend using <a href=\"http:\/\/notepad-plus.sourceforge.net\/uk\/site.htm\" target=\"_blank\">Notepad++<\/a>. It&#8217;s opensource, free, and rawks face.<\/li>\n<\/ul>\n<p>Now if you don&#8217;t have the ability to set all these things up on your own, or don&#8217;t already have them on a web server somewhere &#8211; then you can <a href=\"http:\/\/www.en.wampserver.com\/index.php\" target=\"_blank\">always get WAMP<\/a> and it will have everything you need, bundled together, and in one install file. (Note: I don&#8217;t offer support for setting these services up. There is documentation, and they are all freeware\/opensource, so everything you need is out there on their website)<\/p>\n<p>Moving on&#8230;.<\/p>\n<p>Once you have your empty database created, you&#8217;ll need to run some SQL Commands to set up the table&#8230;<\/p>\n<blockquote>\n<pre><code>CREATE TABLE `ajax_chat` \r\n(`id` INT NOT NULL AUTO_INCREMENT ,\r\n`ajaxchat_username` VARCHAR( 255 ) NOT NULL ,\r\n`ajaxchat_text` TEXT NOT NULL ,\r\nPRIMARY KEY ( `id` ) ,\r\nFULLTEXT (`ajaxchat_text`)) \r\nTYPE = MYISAM ;<\/code><\/code><\/pre>\n<\/blockquote>\n<p>This code creates a table <code>ajax_chat<\/code> with 3 fields: <code>id, ajaxchat_username, and ajaxchat_text<\/code>. <code>id<\/code> is used for the primary key to sort the entries by number, since we&#8217;re not keeping track of the time they were entered. <code>ajaxchat_username<\/code> is going to be the username that the user inputs on the chat dialogue page. And <code>ajaxchat_text<\/code> is the chat text itself. It&#8217;s set up for a full text box, not just a 255 input box, like the <code>ajaxchat_username<\/code> is.<\/p>\n<p>And then some sample data so you can test it&#8217;s functionality&#8230;<\/p>\n<blockquote>\n<pre><code>INSERT INTO `ajax_chat` (`ajaxchat_username` , `ajaxchat_text` )\r\nVALUES ('User1', 'hello world!'), \r\n('User2', 'testing...hello world again');<\/code><\/code><\/pre>\n<\/blockquote>\n<p>Here we enter two records. Note that in the first set of SQL code we created a field called &#8216;id&#8217; but here we leave it out of the Values() section because it&#8217;s auto-incremented.So we have (&#8216;username&#8217;, &#8216;chat_text&#8217;) as the format for entering this in the database manually.<\/p>\n<p>Now let&#8217;s move on to the pages&#8230;<br \/>\n__________________________________________________<\/p>\n<p>Inside the <code>index.htm<\/code> we&#8217;ll have the only page that the user will see:<\/p>\n<blockquote>\n<pre><code>&lt;html&gt;\r\n\r\n&lt;head&gt;\r\n&lt;title&gt;AJAXchatbox&lt;\/title&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;script type=\"text\/javascript\"&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Called by getchatdata.php\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function requestChatInfo() \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top.frames[\"hiddenFrame\"].location = \"getchatdata.php\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function displayChatInfo(sText) \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var divChatInfo = document.getElementById(\"divChatInfo\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divChatInfo.innerHTML = sText;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Called by sendchat.php\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function clearChatBox () \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var sayBox = document.getElementById(\"txtChat\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sayBox.value = \"\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function saveResult(sMessage)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requestChatInfo();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (sMessage)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var divStatus = document.getElementById(\"divStatus\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divStatus.innerHTML = sMessage;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&lt;\/script&gt;   \r\n&lt;\/head&gt;\r\n\r\n&lt;body onload=\"requestChatInfo()\"&gt;\r\n\r\n&lt;div id=\"divChatInfo\"&gt;&lt;\/div&gt;\r\n&lt;div id=\"divStatus\"&gt;&lt;\/div&gt;\r\n&lt;form method=\"post\" action=\"sendchat.php\" target=\"hiddenFrame\"&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;p&gt;Name: &lt;input type=\"text\" name=\"txtName\" value=\"\" style=\"width: 100px\" \/&gt;&lt;br \/&gt;\r\n&nbsp;&nbsp;&nbsp;Say: &lt;input type=\"text\" id=\"txtChat\" name=\"txtChat\" value=\"\" style=\"width: 113px\"&gt;&lt;br \/&gt;&lt;\/p&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;p&gt;&lt;input type=\"submit\" value=\"Send\" \/&gt; &lt;input type=\"button\" value=\"Refresh\" onclick=\"requestChatInfo()\" \/&gt;&lt;\/p&gt;\r\n&lt;\/form&gt;\r\n&lt;iframe src=\"about:blank\" name=\"hiddenFrame\" width=\"0\" height=\"0\" frameborder=\"0\"&gt;&lt;\/iframe&gt;\r\n&lt;\/body&gt;\r\n\r\n&lt;\/html&gt;<\/code><\/code><\/pre>\n<\/blockquote>\n<p>Let&#8217;s break this down a bit&#8230;we&#8217;ll start at the bottom to understand the layout of the page:<\/p>\n<blockquote>\n<pre><code>&lt;body onload=\"requestChatInfo()\"&gt;\r\n\r\n&lt;div id=\"divChatInfo\"&gt;&lt;\/div&gt;\r\n&lt;div id=\"divStatus\"&gt;&lt;\/div&gt;\r\n&lt;form method=\"post\" action=\"sendchat.php\" target=\"hiddenFrame\"&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;p&gt;Name: &lt;input type=\"text\" name=\"txtName\" value=\"\" style=\"width: 100px\" \/&gt;&lt;br \/&gt;\r\n&nbsp;&nbsp;&nbsp;Say: &lt;input type=\"text\" id=\"txtChat\" name=\"txtChat\" value=\"\" style=\"width: 113px\"&gt;&lt;br \/&gt;&lt;\/p&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;p&gt;&lt;input type=\"submit\" value=\"Send\" \/&gt; &lt;input type=\"button\" value=\"Refresh\" onclick=\"requestChatInfo()\" \/&gt;&lt;\/p&gt;\r\n&lt;\/form&gt;\r\n&lt;iframe src=\"about:blank\" name=\"hiddenFrame\" width=\"0\" height=\"0\" frameborder=\"0\"&gt;&lt;\/iframe&gt;\r\n&lt;\/body&gt;<\/code><\/blockquote>\r\n\r\nThe first line is the <code>&lt;body&gt;<\/code> tage with the call to requestChatInfo() when the page loads. That way it automatically shows the chat text. Then there is <code>&lt;div id=\"divChatInfo\"&gt;&lt;\/div&gt;<\/code>. This is where the chat text is going to show up.\r\nNext is <code>&lt;div id=\"divStatus\"&gt;&lt;\/div&gt;<\/code>. Any error messages will appear here if there is a problem.\r\nThen the form for posting. The form calls <code>sendchat.php<\/code> when submitted, and loads it in <code>target=\"hiddenFrame\"<\/code>. The hiddenFrame is at the end of the html segment. When the form is submitted it sends two input boxes, <code>txtName<\/code> and <code>txtChat<\/code>. There is also a \"Refresh\" button. This makes the function call to the function <code>requestChatInfo()<\/code> which will be explained in a bit.\r\n\r\nThen the <code>iframe<\/code> is the hiddenFrame mentioned earlier. It has a width and height both of 0px and a border of 0px. This hides it from the user's view. And since there is no useful information displayed on this page for the user to read, they don't need to know it's there. When you're debugging though, if you choose to edit the .php pages, you might want to put some greater values in for the width and height so you can see any SQL error messages that might show up.\r\n\r\nNow for the top half...the javascript codes.\r\n\r\n<blockquote><pre><code>&nbsp;&nbsp;&nbsp;&lt;script type=\"text\/javascript\"&gt;\r\n&nbsp;&nbsp;&nbsp;\/\/Called by getchatdata.php\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function requestChatInfo() {\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top.frames[\"hiddenFrame\"].location = \"getchatdata.php\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function displayChatInfo(sText) {\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var divChatInfo = document.getElementById(\"divChatInfo\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divChatInfo.innerHTML = sText; \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Called by sendchat.php\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function clearChatBox () {\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txtChat.value = \"\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function saveResult(sMessage)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requestChatInfo();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (sMessage)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var divStatus = document.getElementById(\"divStatus\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;divStatus.innerHTML = sMessage;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&lt;\/script&gt;<\/code><\/code><\/pre>\n<\/blockquote>\n<p>The first set of functions are called by the <code>getchatdata.php<\/code> page<br \/>\nThe first function is <code>requestChatInfo(sText)<\/code>. This function goes to the hiddenFrame, and loads the <code>getchatdata.php<\/code>.<br \/>\nThe second function is to display the chat messages. It is going to be called by <code>getchatinfo.php<\/code> to send a variable across from the hiddenFrame to this visible page, denoted in the function call as <code>sText<\/code>.<\/p>\n<p>The next set of functions are for the <code>sendchat.php<\/code>.<br \/>\nThe first function is <code>clearChatBox<\/code>. This one gave me the most trouble to come up with. It clears the text from the chat box after the information has been sent to the database and back to your page. You'll note in the html code above that the <code>&lt;input&gt;<\/code> for <code>txtChat<\/code> has an <code>ID=\"txtChat\" NAME=\"txtChat\"<\/code> tag, while the input for <code>txtName<\/code> does not, only the <code>NAME=<\/code> tag. This makes the txtChat an object so we can call the attributes as variables and set them. If for some reason you wanted to clear the name text box, you could add <code>ID=\"txtName\"<\/code> to the name input box, and add another line to the <code>clearChatBox<\/code> function that said:<\/p>\n<blockquote>\n<pre><code>txtName.value = \"\";<\/code><\/code><\/pre>\n<\/blockquote>\n<p>The second function is the error message function, <code>saveResult(sMessage)<\/code>. This function first calls <code>requestChatInfo()<\/code> to load the chat messages. Then it brings over any error messages from <code>sendchat.php<\/code>, and loads them to the <code>divStatus<\/code> element.<br \/>\n________________________________________________<\/p>\n<p>On to the <code>getchatdata.php<\/code> page. This page operates in the hiddenFrame, making a database connection, quering the data, and returning it to the visible page every 10 seconds.<\/p>\n<blockquote>\n<pre><code>&lt;html&gt;\r\n&lt;head&gt;\r\n&lt;title&gt;Get Chat Data&lt;\/title&gt;\r\n&lt;?php\r\n&nbsp;&nbsp;&nbsp;\/\/php code\r\n&nbsp;&nbsp;&nbsp;$sInfo = \"\"; \/\/Variable for storing chat messages\r\n&nbsp;&nbsp;&nbsp;$max_id = \"\"; \/\/Upper Limit of chat record IDs to show in the chat.\r\n&nbsp;&nbsp;&nbsp;$min_id = 0; \/\/Lower Limit of chat record IDs to show in the chat.\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;$sDBServer = \"localhost\"; \/\/your server name, can usually be localhost,\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/unless you're connecting across sites.\r\n&nbsp;&nbsp;&nbsp;$sDBName = \"ajax_chat_db\"; \/\/your database name\r\n&nbsp;&nbsp;&nbsp;$sDBUsername = \"ajax_chat_user123\"; \/\/user name to connect to the database\r\n&nbsp;&nbsp;&nbsp;$sDBPassword = \"sdf07hw2df\"; \/\/password for user to connect to the database\r\n&nbsp;&nbsp;&nbsp;\/\/SQL query to grab the max record id from the database.\r\n&nbsp;&nbsp;&nbsp;$sQuery1 = \"SELECT MAX(id) as id FROM ajax_chat\";\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/Connect to the database here\r\n&nbsp;&nbsp;&nbsp;$oLink = mysql_connect($sDBServer,$sDBUsername,$sDBPassword);\r\n&nbsp;&nbsp;&nbsp;@mysql_select_db($sDBName) or $sInfo=\"Unable to open database\";\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Check if the Query worked, and that there is at least one row.\r\n&nbsp;&nbsp;&nbsp;if ($oResult = mysql_query($sQuery1) and mysql_num_rows($oResult) &gt; 0)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Grab the row from the results and put it to variable $max_id\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$max_id = mysql_fetch_array($oResult,MYSQL_ASSOC);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Is max_id bigger than 15?\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($max_id['id'] &gt; 15)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/It is...so we'll set the lower limit to only grab 15 records.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$min_id = $max_id['id'] - 15;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/It's not...so we'll set the lower limit to 0\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/so that we don't go negative with records.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$min_id = 0;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/SQL Query number 2 to go get our records from\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/the database located between min and max ids.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sQuery2 = \"SELECT * FROM ajax_chat \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ORDER BY id LIMIT \" . $min_id . \", \" . $max_id['id'];\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Did the query work? And is there at least one record?\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($oResult2 = mysql_query($sQuery2) and mysql_num_rows($oResult2) &gt; 0)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Loop-de-loop...grab up the data.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for ($i=0; $i &lt; mysql_num_rows($oResult2); $i++ )\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Get the array of data, and store it\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$aValues = mysql_fetch_array($oResult2,MYSQL_ASSOC);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Let's add all the arrayed data to one variable to \r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/simplify passing it back to the visible page.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sInfo .= \"&lt;font face=\\\"Trebuchet MS\\\" size=\\\"x-small\\\" color=\\\"#003366\\\"&gt;\" .\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"&lt;b&gt;\" . $aValues['ajaxchat_username'] . \"&lt;\/b&gt;\" .\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\"&lt;\/font&gt;&lt;font face=\\\"Trebuchet MS\\\" size=\\\"x-small\\\"\" .\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\" color=\\\"#000000\\\"&gt;: $aValues['ajaxchat_text'] . \"&lt;br \/&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Crap, something didn't work if you see this.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sInfo = \"Error getting ajaxchat info.\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/Shucks...something is wrong with your code if you see this.\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sInfor = \"Error getting Max ID.\";\r\n&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Thank you, come again.\r\n&nbsp;&nbsp;&nbsp;mysql_close($oLink);\r\n?&gt;\r\n\r\n&nbsp;&nbsp;&nbsp;&lt;script type=\"text\/javascript\"&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.onload = function () {\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var divInfoToReturn = document.getElementById(\"divInfoToReturn\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.displayChatInfo(divInfoToReturn.innerHTML);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};\r\n&nbsp;&nbsp;&nbsp;&lt;\/script&gt;\r\n&lt;meta http-equiv=\"refresh\" content=\"10\"&gt;&nbsp;&nbsp;&nbsp;\r\n\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;div id=\"divInfoToReturn\"&gt;&lt;?php echo $sInfo ?&gt;&lt;\/div&gt;\r\n&lt;\/body&gt;\r\n\r\n&lt;\/html&gt;<\/code><\/code><\/pre>\n<\/blockquote>\n<p>I have commented each line to show you what is going on with each segment of code. Basically, without repeating the comments, if there is an error, then an error message is stored to $sInfo. If it is successful, then the chat is stored to $sInfo. Regardless, $sInfo is then passed to the <code>&lt;div&gt;<\/code> tag as an innerHTML, which will be called by the <code>requestChatInfo()<\/code> function in <code>index.htm<\/code>.<br \/>\n__________________________________________________<\/p>\n<p>Finally, is the <code>sendchat.php<\/code> page. This page takes what you put in the text input boxes, gets them from the variables passed to the hiddenFrame, and runs an SQL query on it to either show an error message or input the data and update the chat screen.<\/p>\n<blockquote>\n<pre><code>&lt;html&gt;\r\n&lt;head&gt;\r\n&lt;title&gt;Send Chat Data&lt;\/title&gt;\r\n&lt;?php\r\n&nbsp;&nbsp;&nbsp;$sName = $_POST[\"txtName\"]; \/\/Input Box for Name passed from index.htm\r\n&nbsp;&nbsp;&nbsp;$sChat = $_POST[\"txtChat\"]; \/\/Input Box for Say passed from index.htm\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/Did the person enter a name in the box?\r\n&nbsp;&nbsp;&nbsp;\/\/If not, call them Guest\r\n&nbsp;&nbsp;&nbsp;if(!$_POST[\"txtName\"])\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sName = \"Guest\";\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Initiate status message for errors.\r\n&nbsp;&nbsp;&nbsp;$sStatus = \"\";\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/enter the same info from getchatdata.php for connecting\r\n&nbsp;&nbsp;&nbsp;$sDBServer = \"localhost\"; \/\/your server name, can usually be localhost,\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/unless you're connecting across sites.\r\n&nbsp;&nbsp;&nbsp;$sDBName = \"ajax_chat_db\"; \/\/your database name\r\n&nbsp;&nbsp;&nbsp;$sDBUsername = \"ajax_chat_user123\"; \/\/user name to connect to the database\r\n&nbsp;&nbsp;&nbsp;$sDBPassword = \"sdf07hw2df\"; \/\/password for user to connect to the database\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/SQL Statement to enter the data into the database.\r\n&nbsp;&nbsp;&nbsp;\/\/No spaces, and backquotes for column header declaration\r\n&nbsp;&nbsp;&nbsp;\/\/and single quotes for data. Remember that `id` is auto-incremented\r\n&nbsp;&nbsp;&nbsp;\/\/so we don't need a value for that section, just to declare it.\r\n&nbsp;&nbsp;&nbsp;$sSQL = \"INSERT INTO ajax_chat(`ajaxchat_username`,`ajaxchat_text`)\" .\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\" values ('$sName','$sChat')\";\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Connect to the database\r\n&nbsp;&nbsp;&nbsp;$oLink = mysql_connect($sDBServer,$sDBUsername,$sDBPassword);\r\n&nbsp;&nbsp;&nbsp;@mysql_select_db($sDBName) or $sStatus=\"Unable to open database\";\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Did it work? If not create an error message\r\n&nbsp;&nbsp;&nbsp;if(!$oResult = mysql_query($sSQL))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$sStatus = \"&lt;font color=\\\"red\\\"&gt;An error occurred while sending; chat not sent.&lt;\/font&gt;\";\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;\/\/Buh-bye now...g'bye...byebye now.\r\n&nbsp;&nbsp;&nbsp;mysql_close($oLink);\r\n?&gt;\r\n&nbsp;&nbsp;&nbsp;&lt;script type=\"text\/javascript\"&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.onload = function ()\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.saveResult(\"&lt;?php echo $sStatus ?&gt;\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent.clearChatBox();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&lt;\/script&gt;\r\n\r\n&lt;\/head&gt;\r\n\r\n&lt;body&gt;\r\n&lt;\/body&gt;\r\n\r\n&lt;\/html&gt;<\/code><\/pre>\n<\/blockquote>\n<p>I have also commented this code in the php section, so I won't bother to repeat myself here. There is no body for this page in html, only the header info where there is a javascript call to the <code>window.onload<\/code> event.<br \/>\nWhen the window finishes loading, it calls the <code>saveResult()<\/code> function and passes it the $sStatus variable to be displayed on <code>index.htm<\/code>. If there is no error message, then there will be nothing displayed.<br \/>\nThen it calls the <code>clearChatBox()<\/code> function to clear the Say box so that you can continue typing like normal.<\/p>\n<p>Now, load them all up to your server, and call it in Firefox or IE, and see if it works. <a href=\"http:\/\/www.the-spot.net\/ajax\/tsnXchat\" target=\"_blank\">Go here to see a demo verison<\/a>. I'll be adding more functionality to this as I create it for the homepage of the-spot.net, and integrate it with the phpbb forums. I'm new to AJAX, therefore I may not have the most optimized code possible, but I'm open for suggestions for streamlining and security if you would like to add to the project. I'll comment your credits into the code. Also, you can feel free to bookmark this site and check back for update posts for this project. I don't offer any personal tech support for this (because to do so would be extremely trying on my time and availability), and you may have to modify it to meet your server's requirements. If you do use this though, and find it useful, all I ask is that you give me a little credit for the work I put into it (instead of doing homework) :-).<\/p>\n<p>A side feature is that if you save the url to your Bookmark Toolbar of FF (or Links Toolbar in IE) you can load the page into the Sidebar of FF and IE. In Firefox just drag the url to the Bookmark Toolbar, and right click on the button > Properties > Check \"Load link in sidebar\". For IE users (hopefully there are none) create a new shortcut with the url: <\/p>\n<blockquote><p><code>javascript:Q='';if(top.frames.length==0)Q=document.selection.createRange().text;<br \/>\nvoid(_search=open('<b>http:\/\/your.domain.com\/page.htm<\/b>?popuptitle='+escape(document.title)<br \/>\n+'&popupurl='+escape(location.href)+'&text='+escape(Q),'_search'))<\/code><\/p><\/blockquote>\n<p>and change the web address that's bolded.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After using a flooble chatterbox from www.flooble.com, and trying to (unsuccessfully) hack it to get rid of the ads at the bottom, I have resolved to putting my newly developed AJAX skills to the test, to create an open-source version, with no ads. I&#8217;ll explain how you can make one too in this entry.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[11,3,15],"tags":[289,286,290,285,294,295,133,291,288,284,287,292,137,293,283],"class_list":["post-17","post","type-post","status-publish","format-standard","hentry","category-projects","category-tech","category-thought_experiments","tag-ajax","tag-auto-increment","tag-database-access","tag-flooble-chatterbox","tag-hiddenframe","tag-innerhtml","tag-localhost","tag-ms-iis","tag-mysql-database","tag-open-source-version","tag-php-engine","tag-sql","tag-user","tag-variable","tag-web-server-apache"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_likes_enabled":false,"jetpack_shortlink":"https:\/\/wp.me\/prOO4-h","jetpack-related-posts":[{"id":1116,"url":"https:\/\/thepizzy.net\/blog\/2011\/02\/how-to-connect-to-sql-through-windows-authenticated-odbc-in-php\/","url_meta":{"origin":17,"position":0},"title":"How to Connect to SQL through Windows Authenticated ODBC in PHP","author":"[[Neo]]","date":"February 6, 2011","format":false,"excerpt":"If you use MSSQL over ODBC, connecting w\/ PHP is simply a DOMAIN\\WEBSERVER acct on the MSSQL server & the DSN in PHP's odbc_connect()","rel":"","context":"In &quot;How To&quot;","block_context":{"text":"How To","link":"https:\/\/thepizzy.net\/blog\/category\/how-to\/"},"img":{"alt_text":"ODBC Connection","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/8787717937219497341-150x150.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1750,"url":"https:\/\/thepizzy.net\/blog\/2014\/05\/skywarn-storm-spotter-status-released\/","url_meta":{"origin":17,"position":1},"title":"SKYWARN Storm Spotter Status released!","author":"[[Neo]]","date":"May 27, 2014","format":false,"excerpt":"A technical look at the SKYWARN Storm Spotter status service offered by thepizzy.net","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/programming\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/2014-05-26_1510.png?fit=900%2C525&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/2014-05-26_1510.png?fit=900%2C525&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/2014-05-26_1510.png?fit=900%2C525&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/2014-05-26_1510.png?fit=900%2C525&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1132,"url":"https:\/\/thepizzy.net\/blog\/2011\/02\/jasper-just-a-store-platform-experience-reworked\/","url_meta":{"origin":17,"position":2},"title":"Jasper: Just a store platform experience, reworked","author":"[[Neo]]","date":"February 13, 2011","format":false,"excerpt":"Jasper is an experiment in creating a Yahoo! Store Editor and CMS using only the cloud-based coding solution from Kodingen.com","rel":"","context":"In &quot;Jasper&quot;","block_context":{"text":"Jasper","link":"https:\/\/thepizzy.net\/blog\/category\/projects\/jasper\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/logo-name1.png?fit=600%2C343&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/logo-name1.png?fit=600%2C343&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2011\/02\/logo-name1.png?fit=600%2C343&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":71,"url":"https:\/\/thepizzy.net\/blog\/2006\/09\/oracle-reborn-tsnlocal-goes-up-beta\/","url_meta":{"origin":17,"position":3},"title":"[[Oracle]] Reborn, tsnlocal goes up beta","author":"[[Neo]]","date":"September 11, 2006","format":false,"excerpt":"This weekend, I hung out with [wizard] and we worked on our servers. He created his [m3rlin] server, and I created my [[Oracle]] server. Originally, as you might recall from previous posts, [[Oracle]] is an IRC bot that we use for auto responding and chanserv purposes. Our bots are still\u2026","rel":"","context":"In &quot;Technology&quot;","block_context":{"text":"Technology","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2007\/10\/oracle.png?fit=500%2C500&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1518,"url":"https:\/\/thepizzy.net\/blog\/2014\/03\/tsn8-in-the-works\/","url_meta":{"origin":17,"position":4},"title":"tsn8 in the works","author":"[[Neo]]","date":"March 18, 2014","format":false,"excerpt":"Development of tsn8 has begun, with better technology, a new user experience, social media integration, and a planned release of Summer 2014!","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/thepizzy.net\/blog\/category\/tech\/programming\/"},"img":{"alt_text":"tsn logo","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/03\/tsnlogo-featured.png?fit=690%2C405&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/03\/tsnlogo-featured.png?fit=690%2C405&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/03\/tsnlogo-featured.png?fit=690%2C405&ssl=1&resize=525%2C300 1.5x"},"classes":[]},{"id":1718,"url":"https:\/\/thepizzy.net\/blog\/2014\/05\/pizzylabs-stormspotter-activation-forecasts\/","url_meta":{"origin":17,"position":5},"title":"PizzyLabs: StormSpotter Activation Forecasts","author":"[[Neo]]","date":"May 24, 2014","format":false,"excerpt":"A little update about a SKYWARN-related project I've been working on this week.","rel":"","context":"In &quot;Labs&quot;","block_context":{"text":"Labs","link":"https:\/\/thepizzy.net\/blog\/category\/labs\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/skywarn_650.png?fit=650%2C650&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/skywarn_650.png?fit=650%2C650&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/thepizzy.net\/blog\/wp-content\/uploads\/2014\/05\/skywarn_650.png?fit=650%2C650&ssl=1&resize=525%2C300 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":3,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":127,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions\/127"}],"wp:attachment":[{"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thepizzy.net\/blog\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}