Additional data point: if I modify the page to replace jQuery with
native Javascript+DOM, the problem goes away. This seems to be because
hitting the 'back' button reverts straight to the previous page as it
was (complete with its AJAX updates), rather than refreshing the
original HTML and then re-running the Javascript to re-insert the AJAX
bits.

You can see the difference simply by inserting

<script type="text/javascript" src="/jquery.js">
</script>

before

<script language="javascript">
function update_bottom() {

If you do this, you'll find that pressing 'Back' on your browser
causes the AJAX request to be re-issued. So: something about loading
jQuery is changing the behaviour of Firefox, even if you don't call
any jQuery functions!

And yet this still isn't a problem, because the Javascript is fetching
a new version of the AJAX page, rather than the wrong cached one with
HTML layout.

Regards,

Brian.

---- 8< -----
# Program to demonstrate an issue with AJAX getting wrong page from
cache.
# Install ruby and 'gem install sinatra'. Then:
#
#    ruby js-xhr-moz.rb      (this file)
#
# and point web browser to http://127.0.0.1:4567/

require 'rubygems'
require 'sinatra'

get '/' do
  head = <<'EOS'
<script language="javascript">
function update_bottom() {
  var request = new XMLHttpRequest();
  request.onreadystatechange = function() {
    if (request.readyState ==4 && request.status == 200) {
      document.getElementById('bottom').innerHTML =
request.responseText;
      alert("Lower pane updated");
    }
  }

  request.open('GET', '/docs/1234');
  request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  request.send(null);
}

window.onload = update_bottom;
</script>
EOS

  content = <<'EOS'
<div id='top'>
  This is the top pane. The bottom is updated by AJAX.
  <br />
  Click to go to <a href="/docs/1234">the doc page</a>,
  then click your browser's Back button
  <br />
  Click to <a href="#" onclick="update_bottom();false">update lower
pane</a>
</div>
<hr />
<div id='bottom'>
</div>
EOS

  layout(content, head)
end

get '/docs/:id' do
  #response.headers['Cache-Control'] = 'max-age=0, private, must-
revalidate'
  #response.headers['Expires'] = 'Mon, 20 Dec 1998 01:00:00 GMT'
  layout("<div id='docs_#{params[:id]}'>This is document with id #
{params[:id]}</div>")
end

# Apply layout to object unless request is from AJAX
def layout(content, head=nil)
  return content if request.xhr?
  <<EOS
<html>
<head>
<title>My awesome app</title>
#{head}
</head>
<body>
  <h1>My awesome app layout page</h1>
  <hr />
  #{content}
</body>
EOS
end

Reply via email to