views:

268

answers:

3

Like so many lost souls before me, I'm floundering in the snake pit that is Ajax form submission and IE browser caching.

I'm trying to write a simple script using the jQuery Form Plugin to Ajaxify Wordpress comments. It's working fine in Firefox, Chrome, Safari, et. al., but in IE, the response text is cached with the result that Ajax is pulling in the wrong comment.

    jQuery(this).ajaxSubmit({
        success: 
            function(data) {
                var response = $("<ol>"+data+"</ol>");
                response.find('.commentlist li:last').hide().appendTo(jQuery('.commentlist')).slideDown('slow');
            }           
        });

ajaxSubmit sends the comment to wp-comments-post.php, which inelegantly spits back the entire page as a response. So, despite the fact that it's ugly as toads, I'm sticking the response text in a variable, using :last to isolate the most recent comment, and sliding it down in its place.

IE, however, is returning the cached version of the page, which doesn't include the new comment. So ".commentlist li:last" selects the previous comment, a duplicate of which then uselessly slides down beneath the original.

I've tried setting "cache: false" in the ajaxSubmit options, but it has no effect. I've tried setting a url option and tacking on a random number or timestamp, but it winds up being attached to the POST that submits the comment to the server rather than the GET that returns the response, and so has no effect. I'm not sure what else to try. Everything works fine in IE if I turn off browser caching, but that's obviously not something I can expect anyone viewing the page to do.

Any help will be hugely appreciated. Thanks in advance!

EDIT WITH A PROGRESS REPORT: A couple of people have suggested using PHP headers to prevent caching, and this does indeed work. The trouble is that wp-comments-post is spitting back the entire page when a new comment is submitted, and the only way I can see to add headers is to put them in the Wordpress post template, which disables caching on all posts at all times--not quite the behavior I'm looking for.

Is there a way to set a php conditional--"if is_ajax" or something like that--that would keep the headers from being applied during regular pageloads, but plug them in if the page was called by an Ajax GET?

A: 

The way I have been doing this is by adding a rand=new Date().getTime() to the end

if(url.replace("?") != url)
   url = url+"&rand="+new Date().getTime();
else
   url = url+"?rand="+new Date().getTime();

The function above will append the rand=time to the address of the url [address to the .php] If you have supplied get parameters, it will add &rand=time... otherwise it will add ?rand=time The browser keeps caching, but the pages won't overlap.

You could also use PHP's header() to disable caching by setting Cache-control: and Expires:

ItzWarty
Harfleur
Follow-up: just tried using a PHP header() to set cache-control to no-cache, and it worked like a charm. So that's progress! The problem is that it then prevents caching in all cases on all Wordpress posts, which is not what I want. Still a step in the right direction, though.
Harfleur
You should only put the header for your .php that you don't want to have cache for. Otherwise, you should be sending the browser a "yes, do cache for me" header
ItzWarty
See the edit above. Since the wp-comments-post is returning the entire page, I'm not sure how to apply the headers without sticking them in the Wordpress post template.
Harfleur
A: 

Put this in the beginning of Your php:

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");

This should help. If it doesn't - try putting a random number as a filename with the headers.

The post is redirected to a get request and You would have to send some info to the get page to control if it should be cached or not.

naugtur
The header function works great, but wp-comments-post is returning the entire page. So adding cache-busting headers at the beginning of my php means adding it to the Wordpress post template, which kills caching on all posts--obviously not a great move. Is there a way to target an "only if the page is being returned by wp-comments-post" condition?
Harfleur
I don't know wordpress, but You should try looking through the HTTP information avaliable when outputing the headers. It should be traceable if the call is made after AJAX POST call instead of being triggered by a client browser.
naugtur
+1  A: 

jQuery.ajaxSubmit() takes any of the options for the standard jQuery.ajax(). You can thus use the standard cache: false option to turn off caching:

jQuery(this).ajaxSubmit({
    cache: false,
    success: 
        function(data) {
            var response = $("<ol>"+data+"</ol>");
            response.find('.commentlist li:last').hide().appendTo(jQuery('.commentlist')).slideDown('slow');
        }           
    });
ICodeForCoffee