4

I'm pulling my hair out with this bug, although I'm sure it's something obvious. Apologies if it is.

The following javascript successfully sets my cookie:

<script type="text/javascript">
$(document).ready(function(){
    $.post('../setCookie.php',{'region':'test'});
});
</script>

But as soon as I tie the same code to an onclick event, like so...

<script type="text/javascript">
$(document).ready(function(){
    $("#us a").click(function(){
        $.post('../setCookie.php',{'region':'en-us'});
    });
    $("#uk a").click(function(){
        $.post('../setCookie.php',{'region':'en-gb'});
    });
});
</script>

<ul>
    <li id="uk"><a href="http://www.example.com/uk">
        <span>Enter UK site</span></a></li>
    <li id="us"><a href="http://www.example.com/us">
        <span>Enter US site</span></a></li>
</ul>

..it no longer sets a cookie! Even though the same code is called an executed in exactly the same way (I step through it fine, and see everything as it's supposed to be).

Repeat: The javascript is firing fine. I am stepping through setCookie.php and everything is the same... except no cookie at the end of it.

What's going on? I'm guessing it's browser security or something?


For anyone who's interested, here's how I solved it:

<script type="text/javascript">
$(document).ready(function(){
$("#us a").click(function(e){
    e.preventDefault();
    $.post('../setCookie.php',{'region':'en-us'},
        function() {
            window.location = "http://www.example.com/us";
        }
    );
});

$("#uk a").click(function(e){
    e.preventDefault();
    $.post('../setCookie.php',{'region':'en-gb'},
        function() {
            window.location = "http://www.example.com/uk";
        }
    );
});
});
</script>
Chuck Le Butt
  • 47,570
  • 62
  • 203
  • 289
  • Any reason you're using an ajax call for this cookie, instead of just doing `document.cookie = ...`? JS is perfectly capable of setting cookies on its own without involving PHP via AJAX. – Marc B May 29 '11 at 00:55
  • @Marc, I've tied it to a class that I'm using elsewhere in the project. It's just tidier to keep it all together, I think. But otherwise, no. – Chuck Le Butt May 29 '11 at 01:04
  • @Marc, Would $_COOKIE[] even have time to fire anyway? – Chuck Le Butt May 29 '11 at 01:11
  • $_COOKIE is populated by the cookies sent from the client at the time the script starts up. it will NOT change to accomodate any setcookie() calls you make from within the script. Any cookies you do set in PHP will only show up in $_COOKIE on the NEXT invocation of the script. – Marc B May 29 '11 at 17:01
  • Good point. I meant $.cookie (via JQuery), but it's ok now, it's working fine, thanks. – Chuck Le Butt May 29 '11 at 18:57

4 Answers4

9

I don't see anything stopping the normal link click going through? If you have nothing preventing the normal a href to go through, there won't be any time to do the $.post request before the page changed already.

Try the following:

$(document).ready(function(){
    $('a').click(function(e){
        e.preventDefault();
        $.post('../setCookie.php',{'region':'test'});
    });
});

It will stop the page change for links, but at least should pass the cookie. Now, if you want the page to be loaded as well, then add a onComplete method to the request, so that once the cookie data has been succesfully sent, you can then continue the page change.

Niklas
  • 29,752
  • 5
  • 50
  • 71
  • Well even though the setCookie.php was being fired, and I stepped through it all the way through to completion, you're absolutely right: As soon as I put "preventDefault" in there, the cookie was written! I thought this sort of this was supposed to be _asynchronous_? Back to the drawing board. Thanks! – Chuck Le Butt May 29 '11 at 01:10
  • I don't suppose there's any reason I can't just put `window.location = 'http://www.newurl.com';` after the `$.post`? – Chuck Le Butt May 29 '11 at 01:14
  • You need to wait for the request to be sent, or it will just defeat the purpose of the e.preventDefault(). – Niklas May 29 '11 at 01:16
  • It's precisely because it's asynchronous that you need to to preventDefault(). You'll need your window.location = '' to be called in the success handler for your post. – timdev May 29 '11 at 01:41
1

Place this code where the < script > tags is at: (I assume the < head >)

$(document).ready(function(){
    $("#us a").click(function(){
        $.post('../setCookie.php',{'region':'en-us'});
    });

    $("#uk a").click(function(){
        $.post('../setCookie.php',{'region':'en-gb'});
    });
});
Tyler Diaz
  • 152
  • 1
  • 9
  • This is probably a cleaner way of doing it, thanks, but it still doesn't work. – Chuck Le Butt May 29 '11 at 00:58
  • I suggest getting [Firebug](http://getfirebug.com/) (if you don't already have it) and looking at the ajax post and it's response. It might just have something to do with your setCookie.php source. If you find that it is, feel free to post it here and I'll give you a hand with it. – Tyler Diaz May 29 '11 at 01:01
0

If it was a security issue , you will see an error on your console (firebug\webkit\IE dev tools)

I suppose what I would do in this situation is changing the click event and put it here:

<script type="text/javascript">
$(document).ready(function(){
$("#someid > li").click(function(){
    $.post('../setCookie.php',{'region':$(this).attr("id")});
}); 
});
</script>

and then..:

<ul id="someID">
    <li id="uk"><a href="http://www.example.com/uk">
            <span>Enter UK site</span></a></li>
    <li id="us"><a href="www.example.com/us">
                <span>Enter US site</span></a></li>
</ul>

I advice not to use JavaScript \ jQuery inside your HTML , just use document.ready() and bind your events (if you use jQuery of course)

Shaked KO
  • 399
  • 2
  • 11
-1

Most likely because it's trying to access jQuery ($) before it's created. It would be best to use document.ready from your first example for this.

Shaz
  • 15,637
  • 3
  • 41
  • 59
  • As I state in my question, everything fires fine. I step through the code (i.e. "setCookie.php"). Repeat: The javascript is firing fine. – Chuck Le Butt May 29 '11 at 00:53