<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>murz.net: articles</title>
    <link>http://www.murz.net/articles</link>
    <description>murz.net - on constructing the web</description>
    <item>
      <title>Mustache templates in the Play! framework</title>
      <link>http://www.murz.net/articles/mustache-templates-in-the-play-framework--2</link>
      <description>&lt;p&gt;I just published my first &lt;a href="http://playframework.com"&gt;Play!&lt;/a&gt; module to the official repository, it's called &lt;a href="http://www.playframework.org/modules/mustache"&gt;play-mustache&lt;/a&gt;. The aptly named module provides some integration between &lt;a href="http://mustache.github.com"&gt;Mustache&lt;/a&gt; and the &lt;a href="http://playframework.com"&gt;Play!&lt;/a&gt; framework. The goal is to make it easier to re-use markup across all layers of a dynamic web application.&lt;/p&gt;&lt;p&gt;You can take a look at the code and read the manual &lt;a href="http://github.com/murz/play-mustache"&gt;on github&lt;/a&gt;. For a complete reference of the mustache template language checkout &lt;a href="http://mustache.github.com/mustache.5.html"&gt;their manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The markup snippets can be defined in an external file, but the module also provides a tag to define the snippets in a view. To define snippets inline you use the &lt;code&gt;mustache.template&lt;/code&gt; tag.&lt;/p&gt;&lt;pre class="code"&gt;#{mustache.template &amp;#39;task_item&amp;#39;}
	&lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;task&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;task_{{id}}&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Task {{id}}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;details&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{details}}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
		&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;priority&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{priority}}&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
	&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
#{/mustache.template}&lt;/pre&gt;&lt;p&gt;The template can then be used in your view using the &lt;code&gt;mustache.print&lt;/code&gt; tag.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tasks&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
#{list tasks, as: &amp;#39;task&amp;#39;}
	#{mustache.print &amp;#39;task_item&amp;#39;, context:task /}
#{/list}
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;And it can be used within your JavaScript using the &lt;code&gt;PlayMustache.to_html&lt;/code&gt; method.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
	&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Finish the project&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
	&lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;High&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PlayMustache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;task_item&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#tasks&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;If you don't want to specify your snippet inline, you can move it into an external file. By default the module will look in &lt;strong&gt;app/views/mustaches&lt;/strong&gt; for template files, but you can configure this path by specifying &lt;strong&gt;mustache.dir&lt;/strong&gt; in your &lt;strong&gt;application.conf&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To reference an external snippet, just use the relative filename as the template name. For example, if your file is called &lt;strong&gt;app/views/mustaches/my_template.html&lt;/strong&gt; then you would use it server-side like this:&lt;/p&gt;&lt;pre class="code"&gt;#{mustache.print &amp;#39;my_template.html&amp;#39;, context:data /}&lt;/pre&gt;&lt;p&gt;And client-side like this:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="nx"&gt;PlayMustache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my_template.html&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/pre&gt;</description>
      <guid>http://www.murz.net/articles/mustache-templates-in-the-play-framework--2</guid>
    </item>
    <item>
      <title>"Invalid argument." when using window.open in Internet Explorer</title>
      <link>http://www.murz.net/articles/invalid-argument-when-using-windowopen-in-internet-explorer</link>
      <description>&lt;p&gt;If you see the error "Invalid argument." while trying to use window.open in IE (all versions), it's probably because you used a space or special character in the &lt;code&gt;windowName&lt;/code&gt; parameter. As far as I can tell the only special characters allowed are underscores.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;windowName&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;</description>
      <guid>http://www.murz.net/articles/invalid-argument-when-using-windowopen-in-internet-explorer</guid>
    </item>
    <item>
      <title>IETest User Password</title>
      <link>http://www.murz.net/articles/ietest-user-password</link>
      <description>&lt;p&gt;For a while now, Microsoft has offered a free suite of &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=21EABB90-958F-4B64-B5F1-73D0A413C8EF&amp;displaylang=en"&gt;Windows VirtualPC images&lt;/a&gt;, which enable web developers to test their web applications in legacy versions of Internet Explorer.&lt;/p&gt;

&lt;p&gt;If you've ever used one of the images you will know that if you alt+tab away and let the image idle, eventually windows brings you to the locked screen, which you cannot unlock without knowing the password to the account "IETest".&lt;/p&gt;&lt;p&gt;&lt;img src="http://cdn.murz.net/images/article_photos/ie-test-password.jpg" alt="Screenshot of the WindowsXP Locked Screen" /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately Microsoft has done a pretty poor job of communicating what the password is, but after a bit of digging I discovered that the password to IETest is: &lt;/p&gt;&lt;pre class="code"&gt;P2ssw0rd&lt;/pre&gt;&lt;p&gt;Hopefully that saves you some hair pulling.&lt;/p&gt;</description>
      <guid>http://www.murz.net/articles/ietest-user-password</guid>
    </item>
    <item>
      <title>Creating a responsive chat room using old-school AJAX and PHP</title>
      <link>http://www.murz.net/articles/creating-a-responsive-chat-room-using-old-school-ajax-and-php</link>
      <description>&lt;p&gt;With all of the "new school" JavaScript frameworks out there like &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and &lt;a href="http://www.dojotoolkit.org/"&gt;Dojo&lt;/a&gt;, it's extremely easy to get AJAX HTTP requests going without even knowing what the XMLHttpRequest object is. However, I think it's still important to understand what kind of magic jQuery is doing underneath the hood. So here is a beginner's tutorial I've recently resurrected and revised that describes how to create a responsive chat room using JavaScript and PHP.&lt;/p&gt;&lt;p&gt;Before we begin, you can get the example code &lt;a href="../../../../_lab/downloads/chat.zip"&gt;here&lt;/a&gt; and &lt;del&gt;checkout the demo here&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;We're going to start out with our database model. Since this is a chat room we will probably need to keep track of the users in the room and all of the messages people have sent. After fleshing out the tables I came up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;chatroom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;USE&lt;/span&gt; &lt;span class="n"&gt;chatroom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;--&lt;/span&gt;
&lt;span class="c1"&gt;-- Definition of table `messages`&lt;/span&gt;
&lt;span class="c1"&gt;--&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;unsigned&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;unsigned&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;dateCreated&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;FK_messages_1&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;FK_messages_1&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;--&lt;/span&gt;
&lt;span class="c1"&gt;-- Definition of table `users`&lt;/span&gt;
&lt;span class="c1"&gt;--&lt;/span&gt;
&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;unsigned&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="n"&gt;tinyint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;dateJoined&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;dateUpdated&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;ipAddress&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now that our tables are defined we can get started on a basic web service that our JavaScript code will use to communicate with the server. To keep this tutorial short and sweet we will be creating the service in PHP using &lt;a href="http://us2.php.net/pdo"&gt;PHP Data Objects (PDO)&lt;/a&gt;. So create a new file called chat.php and setup your MySQL connection:&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;$dbh = new PDO(&amp;quot;mysql:host=localhost;dbname=chatroom&amp;quot;, &amp;quot;YOUR_DB_USERNAME&amp;quot;, &amp;quot;YOUR_DB_PASSWORD&amp;quot;);&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The main purpose of this basic service will be to recieve new messages and to return the current state of our chatroom. However, we also need to recieve new users so lets handle that scenario first. Since this is not exactly a high-security chat room we won't have a lengthy registration process. All we really care about is the username. If there is a POSTed username on the request, we check if that username already exists. If it does, we assign this new IP to that username. If it doesn't, we simply push a new user to the database with the specified username. Be sure to use &lt;a href="http://us2.php.net/manual/en/pdo.prepare.php"&gt;prepared statements&lt;/a&gt; to prevent MySQL injection attacks.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;/* persist user if theres a username on the request */&lt;/span&gt;
&lt;span class="x"&gt;if(isset($_POST[&amp;quot;username&amp;quot;]) &amp;amp;&amp;amp; strlen(trim($_POST[&amp;quot;username&amp;quot;])) &amp;gt; 0){&lt;/span&gt;
&lt;span class="x"&gt;  $dateNow = date(&amp;quot;Y-m-d H:i:s&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $ip = $_SERVER[&amp;quot;REMOTE_ADDR&amp;quot;];&lt;/span&gt;
&lt;span class="x"&gt;    &lt;/span&gt;
&lt;span class="x"&gt;  $psUsernameCheck = $dbh-&amp;gt;prepare(&amp;quot;SELECT * FROM `users` WHERE `username` = ? AND `isActive` = 0 limit 1&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psUsernameCheck-&amp;gt;execute(array($_POST[&amp;#39;username&amp;#39;]));&lt;/span&gt;
&lt;span class="x"&gt;  if($psUsernameCheck-&amp;gt;rowCount() &amp;gt; 0){&lt;/span&gt;
&lt;span class="x"&gt;    $user = $psUsernameCheck-&amp;gt;fetchObject();&lt;/span&gt;
&lt;span class="x"&gt;    if(!$user-&amp;gt;isActive){&lt;/span&gt;
&lt;span class="x"&gt;      $psUpdateUser = $dbh-&amp;gt;prepare(&amp;quot;UPDATE `users` SET `ipAddress` = ?, `dateUpdated` = ?, `isActive` = 1 WHERE `id` = ? limit 1&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;      $psUpdateUser-&amp;gt;execute(array($ip,$dateNow,$user-&amp;gt;id));&lt;/span&gt;
&lt;span class="x"&gt;    }&lt;/span&gt;
&lt;span class="x"&gt;    outputStatus();&lt;/span&gt;
&lt;span class="x"&gt;  }else{&lt;/span&gt;
&lt;span class="x"&gt;    /* otherwise, insert a new one */&lt;/span&gt;
&lt;span class="x"&gt;    $psNewUser = $dbh-&amp;gt;prepare(&amp;quot;INSERT INTO `users` (`username`,`isActive`,`dateJoined`,`dateUpdated`,`ipAddress`) VALUES (?, ?, ?, ?, ?)&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;    $isActive = true;&lt;/span&gt;
&lt;span class="x"&gt;    $dateJoined = $dateUpdated = $dateNow;&lt;/span&gt;
&lt;span class="x"&gt;    $psNewUser-&amp;gt;execute(array($_POST[&amp;#39;username&amp;#39;], $isActive, $dateJoined, $dateUpdated, $ip));&lt;/span&gt;
&lt;span class="x"&gt;    outputStatus($dbh);&lt;/span&gt;
&lt;span class="x"&gt;  }&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now that we have our extremely basic registration system in place, we will setup an even more basic authentication system. If there's a userId posted we will look it up in the database and make sure that the IP is the same as the one making the request. If it is then the user appears to be authentic so we update their dateUpdated column and move on.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;if(isset($_POST[&amp;quot;userId&amp;quot;]) &amp;amp;&amp;amp; is_numeric($_POST[&amp;quot;userId&amp;quot;])){&lt;/span&gt;
&lt;span class="x"&gt;  $psUserIdCheck = $dbh-&amp;gt;prepare(&amp;quot;SELECT * FROM `users` WHERE `id` = ? AND `isActive` = 0&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psUserIdCheck-&amp;gt;execute(array(intval($_POST[&amp;quot;userId&amp;quot;])));&lt;/span&gt;
&lt;span class="x"&gt;  if($psUserIdCheck-&amp;gt;rowCount() &amp;gt; 0){&lt;/span&gt;
&lt;span class="x"&gt;    $user = $resUserIdCheck-&amp;gt;fetchObject();&lt;/span&gt;
&lt;span class="x"&gt;    if($user-&amp;gt;ipAddress == $_SERVER[&amp;quot;REMOTE_ADDR&amp;quot;]){&lt;/span&gt;
&lt;span class="x"&gt;      $psUpdateUser = $dbh-&amp;gt;prepare(&amp;quot;UPDATE `users` SET `dateUpdated` = ? WHERE `id` = ?&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;      $psUpdateUser-&amp;gt;execute(array(date(&amp;quot;Y-m-d H:i:s&amp;quot;),$user-&amp;gt;id));&lt;/span&gt;
&lt;span class="x"&gt;    }&lt;/span&gt;
&lt;span class="x"&gt;  }&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now that we have an authentic user we can modify our basic service to handle incoming messages. This process will be as easy as checking for a message on the request and persisting it if it's there.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;if(isset($_POST[&amp;quot;message&amp;quot;]) &amp;amp;&amp;amp; strlen(trim($_POST[&amp;quot;message&amp;quot;])) &amp;gt; 0){&lt;/span&gt;
&lt;span class="x"&gt;  $id = null;&lt;/span&gt;
&lt;span class="x"&gt;  $userId = intval($_POST[&amp;quot;userId&amp;quot;]);&lt;/span&gt;
&lt;span class="x"&gt;  $message = $_POST[&amp;quot;message&amp;quot;];&lt;/span&gt;
&lt;span class="x"&gt;  $dateCreated = date(&amp;quot;Y-m-d H:i:s&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;          &lt;/span&gt;
&lt;span class="x"&gt;  $psNewMessage = $dbh-&amp;gt;prepare(&amp;quot;INSERT INTO `messages` VALUES (?, ?, ?, ?)&amp;quot;);   &lt;/span&gt;
&lt;span class="x"&gt;  $psNewMessage-&amp;gt;execute(array($id,$userId,$message,$dateCreated));&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then we need to provide a way for the user to log out. We like short and sweet so we will just look for a posted value and log the user out if they are authentic and the value is there.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;if($_POST[&amp;quot;logout&amp;quot;] == &amp;quot;true&amp;quot;){&lt;/span&gt;
&lt;span class="x"&gt;  $dateNow = date(&amp;quot;Y-m-d H:i:s&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psUpdateUser = $dbh-&amp;gt;prepare(&amp;quot;UPDATE `users` SET `dateUpdated` = ?, `isActive` = 0 WHERE `id` = ?&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psUpdateUser-&amp;gt;execute(array($dateNow,$user-&amp;gt;id));&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And finally, we will dump the current status of the chatroom in xml format.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;$xml = &amp;quot;&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="nx"&gt;xml&lt;/span&gt; &lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt; &lt;span class="nx"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;&lt;span class="x"&gt;&amp;quot; . &amp;quot;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;chatroom&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;users&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;$psAllUsers = $dbh-&amp;gt;query(&amp;quot;SELECT * FROM `users` WHERE `isActive` = 1&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;while($resUser = $psAllUsers-&amp;gt;fetchObject()){&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;user&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;username&amp;gt;&amp;quot;.$resUser-&amp;gt;username.&amp;quot;&amp;lt;/username&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;/user&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;/users&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;$psNewMessages = $dbh-&amp;gt;prepare(&amp;quot;SELECT * from `messages` where `dateCreated` &amp;gt; ?&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;$psNewMessages-&amp;gt;execute(array($user-&amp;gt;dateUpdated));&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;messages&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;while($newMessage = $psNewMessages-&amp;gt;fetchObject()){&lt;/span&gt;
&lt;span class="x"&gt;  $psUser = $dbh-&amp;gt;prepare(&amp;quot;SELECT `username` FROM `users` WHERE `id` = ? limit 1&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psUser-&amp;gt;execute(array($newMessage-&amp;gt;id)); &lt;/span&gt;
&lt;span class="x"&gt;  $user = $psUser-&amp;gt;fetchObject();&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;message&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;author&amp;gt;&amp;quot;.$user-&amp;gt;username.&amp;quot;&amp;lt;/author&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;content&amp;gt;&amp;quot;.$newMessage-&amp;gt;message.&amp;quot;&amp;lt;/content&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;  $xml .= &amp;quot;&amp;lt;/message&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;}&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;/messages&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;$xml .= &amp;quot;&amp;lt;/chatroom&amp;gt;\n&amp;quot;;&lt;/span&gt;
&lt;span class="x"&gt;echo $xml;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now that we're done with the service we can move to the front end. We will start by defining our markup in a new html file called index.html.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.1//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;xml:lang=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/html; charset=iso-8859-1&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;AJAX Chatroom&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;chat.js&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;chatroom&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;messages&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;fieldset&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;legend&amp;gt;&lt;/span&gt;Users (&lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user_count&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;)&lt;span class="nt"&gt;&amp;lt;/legend&amp;gt;&lt;/span&gt;
          
        &lt;span class="nt"&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;form&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;chat.php&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;post&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;message&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Send&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Notice the JavaScript at the bottom of the document. That call to &lt;code&gt;init&lt;/code&gt; will be the entry point for our client side scripts, it's at the bottom because it has to be called after the rest of the document has loaded. After we've got the markup ready to go we'll finally get started on the JavaScript. Create a new JavaScript file called chat.js and get started by defining an attachEvent function. Attaching an event is a little tricky in JavaScript because it's implemented differently depending on the user's browser. Checking which method to use is simple enough, but it's something we will do a lot so lets stuff it in a function.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;addEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCapture&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCapture&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attachEvent&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attachEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;on&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;evType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Handler could not be attached&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;To create HTTP requests using JavaScript we have to use the &lt;code&gt;XMLHttpRequest&lt;/code&gt; object which has the same problem as event handling. IE5.x and IE6 have implemented it differently. Again, since we use this everywhere, we will write another function to get an &lt;code&gt;XMLHttpRequest&lt;/code&gt; object that accomodates everyone.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getXmlHttp&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="c1"&gt;// If IE7, Mozilla, Safari, etc: Use native object&lt;/span&gt;
    &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;XMLHttpRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// ...otherwise, use the ActiveX control for IE5.x and IE6&lt;/span&gt;
      &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ActiveXObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Microsoft.XMLHTTP&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now lets create a function that will initialize the chatroom. The first thing we need to do when we initialize is ask the user for their username. Once they give it to us we will need to send it up to the server using an &lt;code&gt;XMLHttpRequest&lt;/code&gt; object. The process is fairly simple, we open the request, set our headers, then call send passing our parameters. Then we add a listener to the object's &lt;code&gt;onreadystatechange&lt;/code&gt; event, the &lt;code&gt;readyState&lt;/code&gt; value we are looking for is 4 because that means the response is ready. You can read more about the &lt;code&gt;readyState&lt;/code&gt; property over at &lt;a href="http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_r_2.html"&gt;quirksmode&lt;/a&gt;. After we know there's a response we check the &lt;code&gt;status&lt;/code&gt; property which exposes the HTTP status code our server returned. We're looking for a 200 OK status code, which means the operation was successful. You can read more about HTTP status code's from at &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;the W3C's website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Please enter your username...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getXmlHttp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;chat.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/x-www-form-urlencoded&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;username=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onreadystatechange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* everything went ok, lets parse! */&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If no one else is using the username the server will send us down some xml, otherwise the response will be empty and we will tell the user that they were not logged in. &lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/* log in successful */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;you were not logged in!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;In the case that we get some xml, lets start to parse it. We will use the DOM element methods like &lt;code&gt;getElementById&lt;/code&gt;, &lt;code&gt;getElementsByTagName&lt;/code&gt;, and &lt;code&gt;createElement&lt;/code&gt; to parse out what we need from the XML DOM and place it into our HTML DOM. For an in-depth reference of Gecko DOM methods I highly recommend &lt;a href="https://developer.mozilla.org/en/DOM/element"&gt;Mozilla Developer Center&lt;/a&gt;. Lets start simple by just grabbing the current user id and storing it in a variable.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;currentUser&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Then we will get the list of users and add each user to the unordered list inside the user &lt;code&gt;fieldset&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;user_count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;userList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ul&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;user&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;username&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;userItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;li&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;userItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;users&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;fieldset&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userList&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;After we get the users updated, lets parse out the messages and add them to our message list.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;messageList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message_list&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;author&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;firstChild&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;messageItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;li&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;messageItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;lt;strong&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;:&amp;lt;/strong&amp;gt; &amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;messageList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageItem&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The process of extracting the current chatroom state from XML and updating the DOM is one thats going to happen quite a bit, so lets move it into a method called &lt;code&gt;updateDOM&lt;/code&gt; that takes the value of &lt;code&gt;xmlhttp.responseXML&lt;/code&gt; as a parameter. Now lets move on and start building our synchronization function. We will basically just send a request and call &lt;code&gt;updateDOM&lt;/code&gt; with the response every five seconds.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;synch&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getXmlHttp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;chat.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Send the POST request&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/x-www-form-urlencoded&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;userId=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onreadystatechange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;updateDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;you were not logged in!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;updateDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;synch()&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Be sure to modify your &lt;code&gt;init&lt;/code&gt; method to call &lt;code&gt;synch&lt;/code&gt; after you recieve the initial response. Then get started on the &lt;code&gt;send&lt;/code&gt; method, which will be called when our message form is submit. This method needs to take the value from the message text field, make sure it's not blank, and post it to the server. Immediately after we send the request we will clear the form.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You must enter a message!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getXmlHttp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;chat.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Send the POST request&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/x-www-form-urlencoded&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;userId=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;amp;message=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onreadystatechange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readyState&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;updateDOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseXML&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Message could not be sent!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;message&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The final javascript function we ned to write is the logout function. This function will send a post request to &lt;code&gt;chat.php&lt;/code&gt; just like the others, the only difference will be that this request will have &lt;code&gt;logout=true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getXmlHttp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;POST&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;chat.php&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setRequestHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Content-Type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/x-www-form-urlencoded&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;userId=&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;amp;logout=true&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;xmlhttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onreadystatechange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="c1"&gt;//we can&amp;#39;t really do anything except hope it worked&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Now lets create a function to wire up all the events call it at the end of &lt;code&gt;init&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bindEvents&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="nx"&gt;addEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;form&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;submit&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;addEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;unload&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;We are almost done, but there's one more modification I'd like to make. Since we can't reliably count on the logout function always being called, lets modify chat.php so that it clears "stale" users with every request. We will consider any user that hasn't been updated in the past day to be "stale".&lt;/p&gt;
&lt;p&gt;&lt;pre class="code"&gt;&lt;span class="x"&gt;$yesterday = date(&amp;quot;Y-m-d H:i:s&amp;quot;,strtotime(&amp;quot;yesterday&amp;quot;));&lt;/span&gt;
&lt;span class="x"&gt;  $psClearStaleUsers = $dbh-&amp;gt;prepare(&amp;quot;UPDATE `users` SET `isActive` = 0 WHERE `dateUpdated` &amp;lt;= ?&amp;quot;);&lt;/span&gt;
&lt;span class="x"&gt;  $psClearStaleUsers-&amp;gt;execute(array($yesterday));&lt;/span&gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And there you have it! Your own responsive chat-room that you built using just the bare essentials, congratulations! With just a tiny bit of CSS you can make your chat-room look &lt;a href="../../../../_lab/chatroom/chat.html"&gt;like this&lt;/a&gt; (if you're interested in that CSS it's in the example code zip).&lt;/p&gt;</description>
      <guid>http://www.murz.net/articles/creating-a-responsive-chat-room-using-old-school-ajax-and-php</guid>
    </item>
    <item>
      <title>How to fix common CSS bugs in IE6</title>
      <link>http://www.murz.net/articles/how-to-fix-common-css-bugs-in-ie6</link>
      <description>&lt;p class="excerpt"&gt;Today we take on an opponent that few dare to challenge. It's the arch nemesis of web developers across the globe, it's antics have caused countless hours of sheer agony, and it's mere presence will mutilate even the most standards-compliant designs. You better believe I'm talking about the infamous anti-browser known as Internet Explorer 6, and today I am going to share a few tricks I use to beat it into submission.&lt;/p&gt;&lt;p&gt;Okay, so maybe it's not quite &lt;em&gt;evil&lt;/em&gt;, but what it does to some designs is just plain wrong. And I've recently learned that it still holds close to &lt;a href="http://www.w3schools.com/browsers/browsers_stats.asp"&gt;twenty-percent&lt;/a&gt; of the market share by most estimates. This is pretty surprising considering version 7 has now been out for three years and version 8 is already in beta testing. But what does it mean for web developers? It means we have to get over our fears and learn to play nice with the vicious monster in the corner. And just in case the monster bites back, I've put together a list of a few common bugs and fixes that every web developer should have in their arsenal. These are just some tricks I've picked up after fixing a handful of designs in Internet Explorer 6.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;Targeting the monster&lt;br /&gt;&lt;/h3&gt;
&lt;p&gt;There are several CSS hacks out there that allow you to apply style to IE6 without effecting other browsers. In my opinion, the safest and cleanest way is to use conditional comments. The following markup is treated as a simple HTML comment when parsed in most browsers:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="c"&gt;&amp;lt;!--[if lte IE 6]&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;/style/ie6.css&amp;quot; /&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;However, most versions of Internet Explorer will recognize the conditional statement inside the comment. If the browser meets the condition, it will treat the content as if it was regular HTML. So we can easily use the conditional comment to grab a specific external stylesheet for anyone viewing the site in IE6 or earlier, while keeping our markup and CSS virtually the same for all other users. For an overview of all the availible conditional comments, take a look at &lt;a href="http://jamielesouef.com/web-design/internet-explorer-conditional-comments/"&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;Double the margins, double the fun!&lt;/h3&gt;
&lt;p&gt;This is probably the most common problem I see when I first pull down my sites from IE6. All of my div's appear to be sized and positioned in odd ways, usually due to a known bug in Internet Explorer 6 that causes the browser to double padding and margins on certain floated divs. When I first encountered this problem I would go through and redefine all of the problem-divs' left and right margins to half of what they should be. This worked okay, but it was obviously a pain to go through and redeclare the margins for all of the effected divs. After stumbling across &lt;a href="http://www.positioniseverything.net/explorer/doubled-margin.html"&gt;an article on the subject&lt;/a&gt; I learned that the double margin effect can be countered by adding the following css property to all of the problem-divs:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span class="nf"&gt;#an-ie6-victim&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;display&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="k"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Browsers that follow W3C standards will ignore the &lt;code&gt;display:inline&lt;/code&gt; attribute on any floated div, but for some reason it forces IE6 to render your div with correct margins and padding. Although very strange, the fix works. And I like it better than my original approach because I don't have to redefine all of my margins.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;Standards, shmandards!&lt;/h3&gt;
&lt;p&gt;After fixing the double margins problem, you may still see some oddly sized elements on your page. This is probably due to Internet Explorer's faulty box model. Basically, Internet Explorer will treat an element's &lt;code&gt;width&lt;/code&gt; definition as the width of it's content, padding, and border. This is in contrast to the W3C's box model which treats an element's &lt;code&gt;width&lt;/code&gt; definition as the width of it's content only. The following diagram clearly illustrates the difference:&lt;/p&gt;
&lt;div class="article-image autoMargin" style="width: 280px;"&gt;&lt;img src="http://cdn.murz.net/images/article_photos/box-model.gif" alt="Diagram illustrating IE6 box model" /&gt;
&lt;div class="article-image-caption"&gt;Diagram illustrating the box model mismatch.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Unfortunately there isn't an obscure attribute we can define to magicly fix the problem this time. I recommend using a conditional comment to redefine your element's width when the page is rendered with the IE box model. Other developers will recommend that you modify your markup and styles to avoid the issue altogether. For further reading about this problem, I strongly suggest you check out &lt;a href="http://www.456bereastreet.com/archive/200612/internet_explorer_and_the_css_box_model/"&gt;this article by Roger Johansson&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;You want quirks? I'll give you quirks...&lt;/h3&gt;
&lt;p&gt;This is one I didn't run into until later in my career. Apparantly when IE6 is pushed into quirks mode it completely neglects to recognize and calculate automatic margins (&lt;code&gt;margin:0 auto 0 auto;&lt;/code&gt;). And to make the situation worse, Microsoft decided to add an extra quirks mode condition: IE6 will revert to quirks mode if there is anything preceding your doc-type declaration. This is a problem because it is very common practice to include an XML prologue before a doc-type definition. In fact, the &lt;a href="http://www.w3.org/TR/xhtml11/conformance.html#uaconf"&gt;W3C recommends that you do&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;XHTML document authors are strongly encouraged to use XML declarations in all their documents. Such a declaration is required when the character encoding of the document is other than the default UTF-8 or UTF-16.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My solution is to check the request and if it's from a user-agent that is known to handle an XML declaration incorrectly (such as Internet Explorer 6), I will omit the declaration from my markup. It's probably a good idea to note that this is not a bullet-proof solution, because I'm sure there are user-agents out there that are unchecked by my server yet cannot handle an XML prologue. You may decide that physically removing the declaration from your markup is a better solution for your website. If you would like further reading on quirks mode, wander on over to &lt;a href="http://www.quirksmode.org/css/quirksmode.html"&gt;the site named after it&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;Show me the alpha!&lt;/h3&gt;
&lt;p&gt;A 32-bit PNG has something called an alpha-channel, which can define a variable level of transparency for each pixel in an image (a feature known as per-pixel-transparency). The alpha channel allows web designers to do some really cool things with their graphics, but unfortunately it is not supported in IE6. Microsoft does offer a work-around in the form of &lt;a href="http://msdn.microsoft.com/en-us/library/ms532969.aspx"&gt;a proprietary filter called AlphaImageLoader&lt;/a&gt;. Any element that uses a transparent PNG will need an additional attribute that looks something like this:&lt;/p&gt;
&amp;nbsp;&lt;pre class="code"&gt;&lt;span class="nt"&gt;filter&lt;/span&gt;&lt;span class="nd"&gt;:progid:DXImageTransform&lt;/span&gt;&lt;span class="nc"&gt;.Microsoft.AlphaImageLoader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/path/to/transparent-img.png&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;filter&lt;/code&gt; attribute is not defined in the W3C's CSS specification and will make your CSS invalid. Since it only applies to IE6 or earlier, I highly recommend that you use a conditional comment to include any of your stylesheets that utilize the AlphaImageLoader.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After fixing all of those bugs, I usually find that my page starts rendering like it should in IE6. The next step is to break out Firebug-Lite and start debugging the inevitable IE6 JavaScript bugs, but I'll save that for another article.&lt;/p&gt;</description>
      <guid>http://www.murz.net/articles/how-to-fix-common-css-bugs-in-ie6</guid>
    </item>
  </channel>
</rss>

