Ajax, back button and DOM updates - javascript

If javascript modifies DOM in page A, user navigates to page B and then hits back button to get back to the page A. All modifications to DOM of page A are lost and user is presented with version that was originally retrieved from the server.
It works that way on stackoverflow, reddit and many other popular websites. (try to add test comment to this question, then navigate to different page and hit back button to come back - your comment will be "gone")
This makes sense, yet some websites (apple.com, basecamphq.com etc) are somehow forcing browser to serve user the latest state of the page. (go to http://www.apple.com/ca/search/?q=ipod, click on say Downloads link at the top and then click back button - all DOM updates will be preserved)
where is the inconsistency coming from?

One answer: Among other things, unload events cause the back/forward cache to be invalidated.
Some browsers store the current state of the entire web page in the so-called "bfcache" or "page cache". This allows them to re-render the page very quickly when navigating via the back and forward buttons, and preserves the state of the DOM and all JavaScript variables. However, when a page contains onunload events, those events could potentially put the page into a non-functional state, and so the page is not stored in the bfcache and must be reloaded (but may be loaded from the standard cache) and re-rendered from scratch, including running all onload handlers. When returning to a page via the bfcache, the DOM is kept in its previous state, without needing to fire onload handlers (because the page is already loaded).
Note that the behavior of the bfcache is different from the standard browser cache with regards to Cache-Control and other HTTP headers. In many cases, browsers will cache a page in the bfcache even if it would not otherwise store it in the standard cache.
jQuery automatically attaches an unload event to the window, so unfortunately using jQuery will disqualify your page from being stored in the bfcache for DOM preservation and quick back/forward. [Update: this has been fixed in jQuery 1.4 so that it only applies to IE]
Information about the Firefox bfcache
Information about the Safari Page Cache and possible future changes to how unload events work
Opera uses fast history navigation
Chrome doesn't have a page cache ([1], [2])
Pages for playing with DOM manipulations and the bfcache:
This page will be stored in the regular cache
This page will not, but will still be bfcached

I've been trying to get Chrome to behave like Safari does, and the only way I've found that works is to set Cache-control: no-store in the headers. This forces the browser to re-fetch the page from the server when the user presses the back button. Not ideal, but better than being shown an out-of-date page.

Facebook remembers page state by modifying the hash identifier in the URL for ajax requests. These changes are recorded in browser history, so when the user clicks the back button, the hash changes to what it was before. So then it is implied that you will need some Javascript to monitor the has identifier and react when it is changed by the browser. Andreas Blixt has a hash monitoring script available.

This has nothing to do with the hash (#) symbol.
If you would check apple's HTTP headers, it's simply caching the page.

Using the URL hash/fragment identifier is a pretty common way to hook/remember state in a web application that relies on Ajax and DOM updates.
Check out the Really Simple History project for some ideas. It's possible to monitor the URL for changes to the hash, and rsh does this, taking into account browser differences.

For anybody running in problems with Rails and this -- your issue isn't bfcache (I thought it was) -- it's the turbolinks gem. Here is how to remove it.
Hopefully this'll save you some time and banging your head against the wall.

What you are looking for is for some type of URL hash management. The # in the url is for client side only.
When you change the state of the back with JS, then you update the data in the # of the url.
Also you add some type of polling that monitors if the hash has changed, and loads the state of the page based off the new data in the hash.
Take a look at this:
http://ajaxpatterns.org/Unique_URLs

Related

Hitting back on browser to return to a react page does not cause any code on the page to run - why?

So we have a portion of our website as a React.js website. The rest is a Legacy site. After taking the user thru a few steps on a wizard, we transfer the user to our Legacy Page. In test its found that when the back browser button is pressed in the Legacy page, then we return to the previous React page, but none of the code in the React page runs. I've proven this by putting alerts and the code is simply not being run. What's happening is that the page is getting displayed with all the previous rendered output, but without any of the code running. So not sure how/where its getting cached.
I've checked the Cache-Control headers on the React page, and its set to Cache-Control: max-age=0, so the Browser should not be caching the page.
Even if there was any code in our legacy app using history.back() then i've tested that history.back() still makes the code to run on the page being moved back to.
So a bit of a mystery as to where its getting cached. Any thoughts as to what may be the issue?
As mentioned you are using React.js for your project, I think the best solution for your problem is to use React Router. This will render your components according to your current route. In case you are using the case route for the legacy page then, you will have to think for some other alternatives
On December 6th, 2021, Chrome 96 was released, it has a feature called bfcache, or rather back / forward cache and this is different to the Http cache. This caches the entire page in memory,including the Javascript heap, so its like a pause on the page. This is a browser optimisation and is the reason when you go back to the page using the back button on the browser, no code runs as it simply loads it back into memory including all the react state.
more info on bfcache

AJAX activities disappear when browsing forward and back

This is not a Meta question.
I am trying to technically understand what principle is hidden behind the following behaviour. It's very easy to reproduce:
Vote up/down anything on this page1,
Click on any other link on this page,
Come back by pressing the back button.
Your upvote is not there anymore as well as any AJAX activities having appeared on the page.
Why is that? Why is the browser acting like so? How could StackOverflow prevent that?
1 If you are not connected, just wait for someone else's activity on the page (new comment, answer, vote) before moving page.
It’s the browser’s cache that is at play here.
Since you’re asked how SO could “prevent” this, it could be done by advising the browser to check for whether the document has changed every time. But SO not doing so, for performance reasons. So the HTML document is seen as “still valid” for a certain amount of time, during which the browser takes it straight from its cache, without making a round-trip to the server.
If you look at the HTTP response headers in your browser’s developer tools for the request your browser made for this page, you will see something like this,
Cache-Control: public, no-cache="Set-Cookie", max-age=60
– so this HTML document is to be considered valid for 60 seconds. If you navigate away from it and back in your browser, or close the tab and reopen it from history, within that 60 seconds, the browser is supposed to take the cached version of it and display it, without checking again with the server whether or not something has changed. And since your vote did not manipulate this original HTML document (only the DOM was updated with your vote), you still get the previous vote count shown.
But if you press [F5] in your browser, the cache will be circumvented – it will request the document from SO again, and then you see your vote, because this time the updated numbers are part of the updated HTML document that SO serves you.
If you want to delve more into HTTP caching, some resources of the top of Google that seem worth a look:
Caching Tutorial for Web Authors and Webmasters
A Beginner's Guide to HTTP Cache Headers
You are not "unvoting", you just are not seeing your vote because your browser is caching the ajax request.
If your press F12 on Chrome, click on Settings icon and then "Disable cache (while DevTools is open)", when you press back the browser will resend the request.
To prevent that you must specify on your code that you never want that specific request to be cached.
You may want to check the following post:
Prevent browser caching of jQuery AJAX call result
-
Ps. You must stay with the Console (F12) opened while doing the test.

Chrome: disable pre-render of hash change

We're developing a web application that handles state change via change of the hash of the page (e.g. example.com/#/page1).
Lately, I've been running into an issue with Google Chrome, when the prefetch option is enabled ("Predict network actions to improve page load performance"). Among the different routes, we have #/logout that performs the logout.
In the "normal" state, I'm on the page example.com/#/ (the main page), and as I start typing "l" after that (example.com/#/l), Chrome autocompletes with logout. However, not only it does autocomplete, but it also calls the "haschange" event, so the client is sending a request to log out to the server... Even just by typing a l!
This behaviour is not only unexpected, but it's also dangerous. Aside from unchecking "Predict network actions to improve page load performance" in the settings page (which is on by default), is there a way to prevent Chrome to do this?
EDIT
A small new "discovery". Actually, Chrome is not firing the "hashchange" event, as a console.log in the event handler is not being executed. Chrome learnt that, when visiting the #/logout page, a request to the server (GET /auth/destroy) is called, and so it's firing it by itself! What can we do to stop this?
Answering my own question. This is not really a solution, but rather a workaround.
According to this documentation, prendering is disabled in certain situations: with POST requests (not an option in our case) and when the resources are served via HTTPS.
Since we were already going to enable HTTPS in the production environment, we just enabled it in the development one as well and the issue disappeared. However, I still feel like this is more of a workaround than a real solution.

Doing links like Twitter, Hash-Bang #! URL's [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What’s the shebang/hashbang (#!) in Facebook and new Twitter URLs for?
I was wondering how Twitter works its links.
If you look in the source code, you use the links are done like /#!/i/connect or /#!/i/discover, but they don't have a JavaScript function attached to them like load('connect') or something, and that it doesn't require a page reload. It just changes out the page content.
I saw this page, but then all of those files would have to exist, and you couldn't just go straight to one of them. I imagine that on Twitter each of those files don't exist, and that it is handled in some other method. Please correct me if I'm wrong, though.
Is there a way I could replicate this effect? If so, is there a tutorial on how to go about doing this?
"Hash-Bang" navigation, as it's sometimes called, ...
http://example.com/path/to/#!/some-ajax-state
...is a temporary solution for a temporary problem that is quickly becoming a non-issue thanks to modern browser standards. In all likelihood, Twitter will phase it out, as Facebook is already doing.
It is the combination of several concepts...
In the past, a link served two purposes: It loaded a new document and/or scrolled down to an embedded anchor as indicated with the hash (#).
http://example.com/script.php#fourth-paragraph
Anything in a URL after the hash was not requested from the server, but was searched for in the page by the browser. This all still works just fine.
With the adoption of AJAX, new content could be loaded into the current (already loaded) page. With this dynamic loading, several problems arose: 1) there was no unique URL for bookmarking or linking to this new content, 2) search would never see it.
Some smart people solved the first problem by using the hash as a sort of "state" reference to be included in links & bookmarks. After the document loads, the browser reads the hash and runs the AJAX requests, displaying the page plus its dynamic AJAX changes.
http://example.com/script.php#some-ajax-state
This solved the AJAX problem, but the search engine problem still existed. Search engines don't load pages and execute Javascript like a browser.
Google to the rescue. Google proposed a scheme where any URL with a hash-bang (#!) in lieu of just a hash (#) would suggest to the search bot that there was an alternate URL for indexing, which involved an "_escaped_fragment_" variable, among other things. Read about it here: Ajax Crawling: Getting Started.
Today, with the adoption of Javascript's pushstate in most major browsers, all of this is becoming obsolete. With pushstate, as content is dynamically loaded or changed, the current page URL can be altered without causing a page load. When desired, this provides a real working URL for bookmarks & history. Links can then be made as they always were, without hashes & hash-bangs.
As of today, if you load Facebook in an older browser, you'll see the hash-bangs, but a current browser will demonstrate the use of pushstate.
You might wanna check out more on Unique URLs.
It's loading the page via AJAX, and parsing the "hash" (the values that come after the "#") to determine which page it's going to load. Also, this method is used due to the nature that AJAX requests don't count to the browser's history thus the "back button breaks". But the browser does however store into history the hash changes.
Using hashes plus the fact that you can use hashes to determine pages, you can say that you can keep AJAX requested pages "in history". Added to that, hashed URLs are just URLs, and they are bookmarkable including the hash, so you can also bookmark AJAX requested pages.

How do you keep content from your previous web page after clicking a link?

I'm sorry if this is a newbie question but I don't really know what to search for either. How do you keep content from a previous page when navigating through a web site? For example, the right side Activity/Chat bar on facebook. It doesn't appear to refresh when going to different profiles; it's not an iframe and doesn't appear to be ajax (I could be wrong).
Thanks,
I believe what you're seeing in Facebook is not actual "page loads", but clever use of AJAX or AHAH.
So ... imagine you've got a web page. It contains links. Each of those links has a "hook" -- a chunk of JavaScript that gets executed when the link gets clicked.
If your browser doesn't support JavaScript, the link works as it normally would on an old-fashioned page, and loads another page.
But if JavaScript is turned on, then instead of navigating to an HREF, the code run by the hook causes a request to be placed to a different URL that spits out just the HTML that should be used to replace a DIV that's already showing somewhere on the page.
There's still a real link in the HTML just in case JS doesn't work, so the HTML you're seeing looks as it should. Try disabling JavaScript in your browser and see how Facebook works.
Live updates like this are all over the place in Web 2.0 applications, from Facebook to Google Docs to Workflowy to Basecamp, etc. The "better" tools provide the underlying HTML links where possible so that users without JavaScript can still get full use of the applications. (This is called Progressive Enhancement or Graceful degradation, depending on your perspective.) Of course, nobody would expect Google Docs to work without JavaScript.
In the case of a chat like Facebook, you must save the entire conversation on the server side (for example in a database). Then, when the user changes the page, you can restore the state of the conversation on the server side (with PHP) or by querying your server like you do for the chat (Javascript + AJAX).
This isn't done in Javascript. It needs to be done using your back-end scripting language.
In PHP, for example, you use Sessions. The variables set by server-side scripts can be maintained on the server and tied together (between multiple requests/hits) using a cookie.
One really helpful trick is to run HTTPFox in Firefox so you can actually monitor what's happening as you browse from one page to the next. You can check out the POST/Cookies/Response tabs and watch for which web methods are being called by the AJAX-like behaviors on the page. In doing this you can generally deduce how data is flowing to and from the pages, even though you don't have access to the server side code per se.
As for the answer to your specific question, there are too many approaches to list (cookies, server side persistence such as session or database writes, a simple form POST, VIEWSTATE in .net, etc..)
You can open your last closed web-page by pressing ctrl+shift+T . Now you can save content as you like. Example: if i closed a web-page related by document sharing and now i am on travel web page. Then i press ctrl+shift+T. Now automatic my last web-page will open. This function works on Mozilla, e explorer, opera and more. Hope this answer is helpful to you.

Categories