views:

58

answers:

3

I'm trying to build a basic chat site and have four files: chat.html, scripts.html, load.php, and send.php.

Here they are:

chat.html:

<html>
    <head>
        <title>Josh's Python Chat Website</title>
        <script type="text/javascript" src="chatscripts.js">
        </script>
    </head>
    <body>
        <div id="divUsername" style="
            position: absolute;
            padding: 0px;
            margin: 0px;
            top: 10px; 
            left: 10px; 
            height: 26px; 
            width: 400px;">
            Username: <input type="text" id="username" />
        </div>

        <div id="display" style="
            border-style: solid;
            border-width: 1px;
            overflow:auto; 
            position: absolute;
            padding: 0px;
            margin: 0px;
            top: 46px;
            left: 10px;
            height:400px; 
            width:400px;">
        </div>

        <div id="divLineInput" style="
            position: absolute;
            padding: 0px;
            margin: 0px;
            top: 456px;
            left: 10px;
            height: 26px;
            width: 400px;">
            <input type="text" id="line" size="50" onkeydown="if(event.keyCode==13) send()" />
            <input type="button" id="sendbutton" value="Send" onclick="send()" />
        </div>
    </body>
</html>

scripts.js:

function load(){
    var xmlhttp = new XMLHttpRequest();
    var params="";
    xmlhttp.open("GET", "load.php", true);
    // xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlhttp.onreadystatechange = function() {
        if(xmlhttp.readyState==4 && xmlhttp.status==200){
            var display = document.getElementById("display");           
            display.innerHTML = xmlhttp.responseText;
            display.scrollTop = display.scrollHeight;
        }
    }
    xmlhttp.send(params);
}

function send(){
    var xmlhttp = new XMLHttpRequest();
    var url="send.php";
    var d = new Date();
    var username = document.getElementById("username");

    if (username.value==null || username.value==""){
        alert("Please enter a username.");
        username.focus();
        return false;
    }

    var line = document.getElementById("line");
    var params= "time=" + d.getTime().toString() + "&user=" + username.value + "&line=" + line.value;
    xmlhttp.open("POST", url, true);
    xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlhttp.onreadystatechange = function(){}
    xmlhttp.send(params);

    document.getElementById("line").value = "";

    load();
    line.focus();
}

load();
setInterval("load()", 3000);

load.php:

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);

$dbhost = "localhost";
$dbuser = "root";
$dbpass = "password";
$dbname = "website";

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ("Error connecting to database");
mysql_select_db($dbname);

$query = "select * from chat";
$result = mysql_query($query);
$num = mysql_numrows($result);

$response = "";
$i = 0;
while($i < $num){
    $response .= "<p>" . mysql_result($result, $i, "user") . ": " . mysql_result($result, $i, "line") . "</p>";
    $i++;
}

mysql_free_result($result);
mysql_close($conn);

echo $response;
?>

and finally, send.php:

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);

$dbhost = "localhost";
$dbuser = "root";
$dbpass = "password";
$dbname = "website";

$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ("Error connecting to database");
mysql_select_db($dbname);

$query = "insert into chat (time, user, line) values ('" . $_GET['time'] . "', '" . $_GET['user'] . "', '" . $_GET['line'] . "')";
mysql_query($query);
mysql_close($conn);
?>

The site loads chat entries I put insert into the mysql database using the command line client. send.php works as well, since when i call

localhost/send.php?time=12345&user=Herrturtur&line=HelloWorld

in my browser's address bar, "Herrturtur: HelloWorld" shows up in the chat window upon reload.

The script for creating the database is as follows:

create table chat (time INT(16), user VARCHAR(256), line TEXT);

So I figure it must be the send() function in scripts.js. After changing the request type to GET I had no more luck than this way, so I'm posting this version. What's wrong with my code?

+1  A: 

Calling XMLHttpRequest directly is like using the blink tag: nothing good ever comes from it.

Use a library!

  • Do you want to do a lot of Javascript? Then try a larger library such as JQuery or YUI.
  • If you just want the minimum, you can use mooTools or other small libraries.
  • Google serves up the most popular libraries from their CDN (Content Delivery Network). See http://code.google.com/apis/ajaxlibs/
Larry K
Use a library if you decide you need to use several of its features, such as DOM manipulation or visual effects. Loading up a 30KB library simply because you need help with 10 lines of code is way overdoing it. If you want something light-weight and fast, there's no substitute for writing your own code. Plus you might learn something about how browsers work.
Andrew
+1  A: 

is the event getting fired? start putting some console.logs in theres and diagnose if your function is being called.

edit -- wait, is the your script name doesn't match what is in the tag.

hvgotcodes
What do you by the script name doesn't match what's in the tag? I double checked, and the script name in both tags is "send()" and in the scripts.js it is "send()". I'll look up what the console.logs means.
Joshua Moore
<script type="text/javascript" src="chatscripts.js">you indicated your file is script.js, but you are sourcing chatscripts.js.
hvgotcodes
+1  A: 

Several things:

  1. If your PHP uses $_POST then the AJAX open() that points at that script should also be POST. Likewise, if your PHP uses $_GET, your open() should use GET.
  2. Use your browser console to check what is actually getting set in your params. This string should be able to go at the end of your URL in a GET request [edit: by this I mean you should be able to put it at the end of your address in a browser] and still work. If it doesn't, make sure every element going into the params is URL encoded.
  3. I know this isn't part of the question, but as it is now, your DB queries are wide open to SQL injection attacks. Make sure you escape every value that will into your database. Also, if you can store your time as a number rather than a string, your queries will speed up considerably. The performance cost of using a string never shows up during development when you have only a few hundred or thousand records, but it will when your DB starts to fill up.

And I don't get why so many people are against rolling your own XHR requests. Using a library takes a lot of the mystery out of building AJAX applications early on, but it won't help you if you're using the wrong method (POST instead of GET) and debugging can actually be more difficult because you need to dig through a lot of code to see where things are failing. And it's actually not even remotely difficult and doing it yourself helps you understand the request life-cycle. A common cross-browser snippet is below. This will make XMLHttpRequest available even in early IE browsers:

if (typeof XMLHttpRequest === "undefined")
  XMLHttpRequest = function () {
    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP"); }
      catch (e) {}
    //Microsoft.XMLHTTP points to Msxml2.XMLHTTP.3.0 and is redundant
    throw new Error("This browser does not support XMLHttpRequest.");
  };
Andrew
I fixed changed GET to POST in send.php, but still no luck.
Joshua Moore
Two things:1. If you are using a browser with a console (Firefox with the Firebug plug-in, Chrome, or IE8/Safari with the Developer tool bars turned on), add this debug code above your `xmlhttp.send()`: `console.log(params,url);`. Post back here what you see in the console. Don't deploy this code in your production version. It is for debug only.2. If the request is failing on the server side, those failures will be in your log. You can also check for errors with this: ` xmlhttp.onreadystatechange = function(){alert(xmlhttp.readyState+', '+xmlhttp.statusText);}` What alerts do you see?
Andrew
Joshua Moore
For 2: I get "2, OK", "3, OK" and "4, OK".
Joshua Moore
Ah. I also just noticed that your `time` column is an `INT(16)`, but your update query is trying to insert a string. Remove the single-quotes from around the `time` value: `$query = "insert into chat (time, user, line) values (" . $_POST['time'] . ", '" . $_POST['user'] . "', '" . $_POST['line'] . "')";` And one other thing, if you use Firefox+Firebug or Safari/Chrome, you can view the server response in the "Net console." It's a critical tool in debugging AJAX applications. If you use IE, you should download and use Fiddler2. It is a very complex tool, but the best of the bunch. Get it!`
Andrew
I removed the single quotes around $_POST['time'] but no luck. I'm using Chrome to debug the site, and I see when sites are done loading, but where do I see the server response?Either way, send() doesn't receive anything, I just call load() in send().
Joshua Moore
First, Chrome: Turn on Developer Tools (probably under View). That brings up the console. Click on the Resources tab and turn on Resource tracking. When you refresh the page, you will see every file coming in, and if you click on the file, you can see what the actual response from the server is. You can also filter by XHR to see only AJAX requests.
Andrew
And next, are you expecting to see the new comments show up when you `load()`? If so, you should move it into the `onreadystatechange()`. You have to treat these requests as asynchronous. You can't guarantee that they will return in the order you sent them and you especially can't guarantee the server will be done with the first request in time for the arrival of the second request. You either have to build in a delay (which causes a race condition) or you need to order your requests: Send. Then Load. Like this: `xmlhttp.onreadystatechange = function(){ load(); }`
Andrew