29

I am using this type of line in an JS response

if (history && history.pushState){
     history.pushState(null, null, '<%=j home_path %>');
}

but when I click back in the browser, I see the JS code of the response instead of the previous page.

Is there a way to make the back button work so it would re-request the page of the last url (before home_path as pushStated in?

Update:

I've found this.. it seems other have the same issue with.. History.js doesn't fix it either

So to confirm some of the comments there.. This happens only in chrome

What I think

I think the root of all this is that the popstate requests the same type of the pushstate document (js response). What needs to be done is on popstate request the html response.. I just don't know how

More updates:

seeing http://railscasts.com/episodes/246-ajax-history-state it mentions to use

 $(window).bind("popstate", function() {
      $.getScript(location.href);
    });

this solves the issue but according to understanding jQuery $.getScript() withtout ajax caching it will add timestamps.. which pollutes the url.. turning it off makes it not work again with the same effect..

Anyone knows how to solves this?

Even more Updates

I tracked the trails of the issue all over the interweb and ended with an issue in chrome which points to a rails issue (firefox works fine however) and an issue in rails-ujs concerning not including Vary Header in the responses

Example can be found here

Mohsen Safari
  • 6,669
  • 5
  • 42
  • 58
Nick Ginanto
  • 31,090
  • 47
  • 134
  • 244

4 Answers4

12

I am currently playing around with doing

 response.headers['Vary'] = 'Accept'

which seems to solve the problem, at first look.

If anyone has the same issue, please check it and let me know

Nick Ginanto
  • 31,090
  • 47
  • 134
  • 244
  • 2
    Thankx, this header solved my problem too. It was unusual issue, in which I didn't experience this problem ,but my swedish client did. In apache, this header can be set this way. Hope this is useful to someone who is having the same issue. In .htaccess write the following code ` Header append Vary: Accept ` – Dipesh KC May 02 '13 at 08:44
  • 1
    Thanks! But `response.headers['Vary'] = 'X-Requested-With'` would fit better. – tomasbedrich Nov 10 '17 at 14:25
9

You need to add a listener to the popstate event

window.onpopstate = function(event) {
    //load the page
};

When the back button is pressed the url is changed and then the popstate event is fired. It's your responsibility to load the details in your popstate listener that match the changed url.

A nice popstate example

Some browsers fire a popstate event when the page first loads, causing an infinite page loading loop. This can be avoided by adding the following check

var loadPage = window.history.state;
window.onpopstate = function(event) {
    if (loadPage) 
        //load the page
};

Then set the loadPage to true when pushState is called

history.pushState(null, null, '<%=j home_path %>');
loadPage = true;

This technique works in all browsers that support html5 history api.

graham mendick
  • 1,839
  • 1
  • 17
  • 15
3

It happened my with sinatra & chrome.

Solved it with:

$.ajaxSetup({ cache: false });
Simon
  • 1,716
  • 1
  • 21
  • 37
trompa
  • 1,967
  • 1
  • 18
  • 26
  • Strange, althought in console i can see the ajax xhr asking for the timestamped url, it isnt showing in the browser url bar. You can try to strip the timestamp from the url name youre saving on the pushstate – trompa Apr 04 '13 at 08:34
  • Thank you! I tried many solutions out there but this one was the only working for me. 100 points for you –  May 15 '13 at 10:18
  • This wasn't the exact fix for me, but it led me in the right direction - I had specified `cache: true` on an ajax request. Removing it solved the issue. Thanks - 100 points (and one upvote) for you! – Brad Werth Apr 26 '18 at 04:17
0

I've tested this code on my browser using a local HTML file and I've gotten a console security error:

SecurityError: The operation is insecure.
  history.pushState(null, null, '<%=j home_path %>');

I can see how manipulating browser history may be considered a potentially dangerous behaviour, so I guess you should check that this is not happening for you as well. Try using the Firebug Javascript console. It is also possible that there might be differences in behaviour between local and http:// HTML files.

Said this, for what I've seen the last element of the history array is basically the current page, so if you want to change the previous one, you might do it by using two pushState() commands - first you push the previous element that you desire, then you push the current path again. If I understood your problem correctly.

Okarin
  • 864
  • 1
  • 8
  • 20
  • note that `<%=j home_path %>` is in erb so after preprocessing it will equal a valid path. maybe I should do a full path – Nick Ginanto Mar 19 '13 at 10:26
  • I don't know, I tried it locally and it would work only if I used a file:// path. Everything outside the local domain would not work. I think checking out that you haven't got any security errors is the first thing, you could use a `try...catch` instruction. – Okarin Mar 19 '13 at 10:40
  • What FF version are you using @Okarin? The code provided works just fine for me in FF19. – Simon Mar 19 '13 at 13:05
  • FF17, I found out now, on Mageia Linux. I will try with the new version as well, I guess. – Okarin Mar 21 '13 at 09:26