views:

777

answers:

3

I'm new to JavaScript, and working on a hobby project with a few developers. We have a simple page that is used to submit requests to a database.

I decided to try learning JQuery, and started implementing some AJAX functionality into this request page. It works fine in FireFox, IE and Safari, but for some odd reason, I can't get it to work in Chrome.

I've been debugging it for a couple of hours now, and I have no idea why it's not working. Here's the relevant part of the HTML form (post action removed due to JavaScript):

        <form method="POST">
            <input type="text" name="amount" value="0" size="7" />
            <input type="submit" value="Fulfill!" /><br />
            <input type="hidden" name="index" value="69" />
            <input type="hidden" name="item" value="Iron Ore" />
        </form>

And here's the PHP form that it posts to:

<?php
require_once("../classes/Database.php");
$database = new Database();

$amount = $database->sanitizeString($_POST['amount']);
$index = $database->sanitizeString($_POST['index']);
$username = $database->sanitizeString($_POST['username']);
$item =  $database->sanitizeString($_POST['item']);
$database->connect();
$database->setRequest($amount, $index, $username, $item);
$database->setKarma($username, $amount, $item);
?>

And most importantly, here's my newbie JavaScript code that's simply in the HTML file:

<script language="JavaScript">
    var amount = 0;
    var index = 0;
    var item = 0;
    var username = "";
    var data = "";
    $(document).ready(function(){
        $("form input[type=submit]").click(function(){
            amount = $(this).siblings("input[name=amount]").val();
            index = $(this).siblings("input[name=index]").val();
            item = $(this).siblings("input[name=item]").val();
            username = "<?=$_SESSION['username']; ?>";
            //var stuff = $.post("pages/ajaxfulfill.php", {amount:amount,index:index,item:item, username:username}, function(data){alert(data)}, "html");
            var stuff = $.ajax(
                                    {
                                        url: "pages/ajaxfulfill.php",
                                        type: "POST", data:"amount=" + amount + "&index=" + index + "&item=" + item + "&username=" + username,
                                        success: function(data)
                                        {
                                            alert("Success")
                                        },
                                        error: function (XMLHttpRequest, textStatus, errorThrown)
                                        {
                                            alert("error" + XMLHttpRequest.status);
                                            alert("error" + XMLHttpRequest.responseText);
                                        }
                                    }
                               )
            $(this).parents("td").text("Submitted");

        });

    });

</script>

At first, I was using the commented out $.post function, which works with the above mentioned browsers. I attempted to switch to the $.ajax function during my debug process, and found out that FF, IE, and Safari always return a "Success" alert, whereas Chrome is returning an Error with status 0 and a blank response.

Being a JavaScript newbie, I'm completely lost at why this would fail. If anyone could point me in the right direction, you'll have my profound respect and well wishes. Thanks.

+2  A: 
Dan Loewenherz
+1  A: 

You can do a few things to diagnose this yourself:

  1. Shift + Ctrl + J in Chrome to launch the Javascript console and enable debugging. Stick breakpoints and step through your function
  2. Watch the Javascript error/warnings console (even in your other browsers)
psychotik
Thank you. I've never used Chrome before today, so I did not know about this.But one thing that has me even more confused.I debugged it, line by line, stepping over each expression. When I debug it this way, the code works! However, when I run it without debugging, it fails?!What does this mean?
Foo
+4  A: 

You don't seem to be preventing the default action on the submit button. So after your click function fires, the form still submits, presumably cancelling your XMLHttpRequest.

(What might make a difference cross-browser here is that at the end of the function you remove the form from the page by calling the text() function. Should that stop the form getting submitted? Don't know... some browsers might, but there is no specification that says so.)

Use event.preventDefault(); on the argument passed into the handler function(event) { ... } to stop the button click going through to submit the form.

But don't bind form submission code to an input button. Your script may (depending on browser and other attributes of the form) fail to fire on another kind of submission such as an Enter press. Always bind validation and AJAX-form-replacement using the submit event on the form itself. event.preventDefault(); still applies.

Omitting the action attribute of a <form> is invalid; the browser typically chooses the existing page's URL to submit to. If you want form fields without a form to submit (and you don't need radio inputs), just omit the <form> element. But really you should be using progressive enhancement: make the form work from plain HTML first, with a proper method="POST" action="ajaxfulfill.php", and then build a trivial AJAX function on top of that.

username = "<?=$_SESSION['username']; ?>";

Script injection. Instead:

username= <?= json_encode($_SESSION['username'], JSON_HEX_TAG); ?>

And:

data:"amount=" + amount + "&index=" + index + "&item=" + item + "&username=" + username,

You would need to use encodeURIComponent(...) over each of the values in a URL-encoded-form-submission, or special characters will break it. Better to let jQuery do that for you:

data: {amount: amount, index: index, item: item, username: username},

or even simpler, drop all the manual reading of field.val() and just use the existing serialize function that does it all for you:

data: $(this).serialize(),

(Assuming this is now the form you're handling onsubmit for... if it were the submit button, you'd have to say $(this.form).)

Do you really want to be taking the username from user-submitted POST data, which they might have changed? Unless usernames are deliberately security-free, it would seem a better idea to get it from the session whence it came.

bobince
You sir, are a gentlemen and a genius. I've modified my script and got it working. I've taken your other suggestions to heart and will be modifying my script accordingly.Thank you for your help.
Foo
wow. thank you!! I just spent 3 hours trying to figure out what was going in, and your post fixed it in 1 second. THANK YOU!
solefald