I'm creating a small web application and I'm loading my pages using ajax in div.
Whenever user click on link, ajax request page and then update my div and url..
after ajax request when i try to refresh my pages,
It's working fine and show me current page but when i click on back button it's change top url but not the page and it's content
here is my code
$.ajax({
url: link,
type:'POST',
data : name,
success: function(data) {
$("#main").html(data);
history.pushState({foo:'bar'}, title, link);
}
}
});
As #Slaks says in the comments, you need to handle the window.onpopstate.
Documentation:
going back doesn't change the document's contents from what they were
in the previous step, although the document might update its contents
manually upon receiving the popstate event.
To do this you need a State object, which you pass as a parameter in your pushState call. A state Object is a javascript object that is associated with the new history entry. The popstate event is fired only when the active history entry changes and it will have a copy of the State object as a parameter.
As docs says, history.pushState() (and history.replaceState()) methods only add (and modify) history entries, for this reason:
calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.
Related
I'm building a web app using Google Apps Script, looking to replicate a multi-page site, and struggling to get the history changes to do what I want.
I have links set up with event listeners that use google.script.history.push() like this:
document.getElementById('navPage1').addEventListener('click', function() {
google.script.history.push({timestamp:new Date().getTime(),page:'page1'}, {page:'page1'})
});
When I click on this link, I see the URL update accordingly with the parameters (i.e. to https://script.google.com/a/XXX/macros/s/XXX/dev?page=page1).
In my HTML file I then want to use google.script.history.setChangeHistory() to detect these changes and load content accordingly. However, the event doesn't seem to be triggering at all. I currently have it set up just to log on history change, and I'm not seeing anything at all:
google.script.history.setChangeHandler(function(e) {
console.log('History Change Triggered');
});
Have I misunderstood how these should be used?
As written in the documentation,
Calling history.pushState() or history.replaceState() won't trigger a popstate event. The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.
Related Answer:
Sample web app
I have to maintain a site with an AJAX search form (for lets say books) and I want the search results to be a part of the browser history.
So I set the "popstate" event handler
window.addEventListener('popstate', function(e) {
alert("popstate: " + JSON.stringify(e.state));
});
and call pushState() upon the successfull AJAX request:
var stateObj = { q: "harry potter" };
window.history.pushState(stateObj, "Result", "/search");
Then my clickflow is:
Load the page with the search form - NORMAL request - path is /
Enter a query string and submit the form - AJAX request - path changes to /search
Click on a search result - NORMAL request - path changes to /books/harry-potter
When I now go back by clicking the browser back button I would expect the "popstate" event to be triggered with the according state object. But nothing happens. - path changes to /search
When I then go back one more time I get an alert with popstate: null - path changes to /
And when I go forward after that, I get popstate: {"q":"harry potter"} - path changes to /search
So, the important popstate event (the one with the query string) gets only triggered when going forward, but not when going back.
Is this because im navigating back from a site, whose history entry has been created automatically instead of programmatically by pushState?
But if so, the History API would only make sense for complete single page applications.
Behaviour is the same in any browser. Hope you can help me out :)
For anyone wanting a little more explanation as to why the popstate event only occurs in certain scenarios, this helped me:
On the MDN popstate event page it states:
A popstate event is dispatched to the window each time the active history entry changes between two history entries for the same document.
and
The popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript), when navigating between two history entries for the same document.
So it looks like popstate is only called when navigating to different urls within the same document. This works great for SPAs but not for anything else.
As an additional note, the html5 spec for session history doesn't seem to have much clarity as to when the popstate event is called:
The popstate event is fired in certain cases when navigating to a session history entry.
Which may indicate that different browsers will treat it differently.
I would love more insight from anyone else
I have a web page which updates progressivly therefore I need the windows "back" button to call a function to refresh the data and not go back a page.
I have the first part working I trap the "back" button with
window.onbeforeunload = confirmExit();
and confirmExit()
function confirmExit() {
switch (page) {
case 2:
countries();
break;
case 3:
counties(page3id)
break;
case 4:
cities(page4id)
break;
}
}
Which all works well but after the page is refreshed the back button default action kicks in and it loads the previous page. I have tried returning true and false. I would appreciate any help, thank you.
you need to add virtual sites to the browsers history. this way the back button will not lead to another website.
use history.pushState() to add virtual sites.
Suppose http://mozilla.org/foo.html executes the following JavaScript:
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");
This will cause the URL bar to display
http://mozilla.org/bar.html, but won't cause the browser to load
bar.html or even check that bar.html exists.
Suppose now that the user now navigates to http://google.com, then
clicks back. At this point, the URL bar will display
http://mozilla.org/bar.html, and the page will get a popstate event
whose state object contains a copy of stateObj. The page itself will
look like foo.html, although the page might modify its contents during
the popstate event.
If we click back again, the URL will change to
http://mozilla.org/foo.html, and the document will get another
popstate event, this time with a null state object. Here too, going
back doesn't change the document's contents from what they were in the
previous step, although the document might update its contents
manually upon receiving the popstate event.
from MDN: Manipulating the browser history
the user can now press the back button the number of times you added virtual sites. to detect the back button press use window.onpopstate
The popstate event
A popstate event is dispatched to the window every time the active
history entry changes. If the history entry being activated was
created by a call to pushState or affected by a call to replaceState,
the popstate event's state property contains a copy of the history
entry's state object.
from MDN: Manipulating the browser history
I'm using history.pushState to create a 'fake' results page after the user submits a form. However, when I navigate back, the visible page stays the same. What is an easy way to get the original page - unmodified by javascript, but with the form filled out - after pressing back?
You need to watch the current address for changes and react to it yourself.
See this example:
https://developer.mozilla.org/en/DOM/window.onpopstate
Also have a look at the documentation:
https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history/
You have to handle the onpopstate event and reload the previous page manually:
window.onpopstate = function() {
location.reload();
};
I am trying to modify the content in my page without a reload. Currently my code reads:
window.onpopstate = function(event){
// Ajax Request the Page and replace content with new content
};
This works when I push a state then trigger the popstate event, but if I press the back button in the browser it navigates to the url instead of calling my onpopstate event. How can I prevent a page refresh and update the page with my ajax call instead?
edit: I am trying to update with pushState and popstate. I was hoping to keep my urls hash free.
You have to make sure there is always a history state you've pushed from the current page on the history to prevent the back button from performing a page load.
If you're trying to keep the user "contained" in your web app so the back button always provides some kind of function, you need to push at least two states onto the stack and then make sure to push another state from your popstate handler.
var foo = {foo: true}; // state object
history.pushState(foo, "unused argument", "#newInitialUri");
...
var bar = {bar: true}
history.pushState(bar, "unused argument", "#newStateOfWebApp");
...
window.onpopstate = function(event){
...
var baz = {baz: true}
history.pushState(baz, "unused argument", "#baseState");
};
In the above example say we loaded '/'. The script starts executing and the browser window URI changes to '/#newInitialUri' but no page load occurs. Then immediately after, the browser URI changes to '/#newStateOfWebApp' and no page load occurs.
The user pushes the back button on their browser. Your popstate handler fires. During your handler, event.state equals foo and the browser uri is '/#newInitialUri'. No page load occurs. The handler finishes completing, calling history.pushState and now the browser uri is '/#baseState'. No page load occurs. If the user clicks back again, your popstate event will fire again, event.state will equal foo (again), the browser uri will be '/#newInitialUri' (no page load) and then it will be '/#baseState' again (no page load).
The important thing to remember is that the event.state in your popstate handler always contains the state object for the URI you've just come back to, not the one you just came from. This was confusing to me at first, but made sense when I thought about it. For example, the user may have just come back to your page after perhaps having gone off to Google. The state object is your opportunity to communicate the status of your app to your code.
Keep in mind that some browsers fire the popstate event on page load (which is what's supposed to happen according to the spec from my understanding). Be sure to check for your state object in your handler before executing your code to make sure you don't run code you don't intend to on a page load.
One final note: if you're using jQuery to handle events, you'll need to use event.originalEvent.state to refer to the state object.
This may help
The unload event is sent to the window element when the user navigates away from the page. This could mean one of many things. The user could have clicked on a link to leave the page, or typed in a new URL in the address bar. The forward and back buttons will trigger the event. Closing the browser window will cause the event to be triggered. Even a page reload will first create an unload event.
Reference
http://api.jquery.com/unload/
untested
$(window).unload(function(e){
e.preventDefault();
$(window).trigger('popstate ');
});
$(window).bind('popstate ',function(){
//your ajax call here
});
and finally here is a DEMO click on browser's back button to see it working
update
you are right the unload be canceled but you can do some thing like
$(window).unload(function(e){
e.preventDefault();
$(window).trigger('beforeunload');
});
$(window).bind('beforeunload',function(){
alert('call your ajax here');
return '';
});
yet another DEMO