window.history.pushState refreshing the browser - javascript

I am working on some javascript code, and using window.History.pushState to load new HTML pages, instead of using href tags. My code (which is working fine) looks like this.
window.History.pushState({urlPath:'/page1'},"",'/page1')
strangely, this fails, ie reloads the browser
window.History.pushState({urlPath:'/page2.php'},"",'/page2.php')
But this works, content is updated, browser not refreshed ! (notice the URL is absolute and not relative)
window.History.pushState({urlPath:'www.domain.com/page2.php'},"",'www.domain.com/page2.php')
The documentation for window.History.pushState says that the third parameter URL can be either absolute or relative -
URL — The new history entry's URL is given by this parameter. Note
that the browser won't attempt to load this URL after a call to
pushState(), but it might attempt to load the URL later, for instance
after the user restarts the browser. The new URL does not need to be
absolute; if it's relative, it's resolved relative to the current URL.
The new URL must be of the same origin as the current URL; otherwise,
pushState() will throw an exception. This parameter is optional; if
it isn't specified, it's set to the document's current URL.
Absolute URLs seem to be working but relative seem to be not. Why is this happening?

The short answer is that history.pushState (not History.pushState, which would throw an exception, the window part is optional) will never do what you suggest.
If pages are refreshing, then it is caused by other things that you are doing (for example, you might have code running that goes to a new location in the case of the address bar changing).
history.pushState({urlPath:'/page2.php'},"",'/page2.php') works exactly like it is supposed to in the latest versions of Chrome, IE and Firefox for me and my colleagues.
In fact you can put whatever you like into the function: history.pushState({}, '', 'So long and thanks for all the fish.not a real file').
If you post some more code (with special attention for code nearby the history.pushState and anywhere document.location is used), then we'll be more than happy to help you figure out where exactly this issue is coming from.
If you post more code, I'll update this answer (I have your question favourited) :).

As others have suggested, you are not clearly explaining your problem, what you are trying to do, or what your expectations are as to what this function is actually supposed to do.
If I have understood correctly, then you are expecting this function to refresh the page for you (you actually use the term "reloads the browser").
But this function is not intended to reload the browser.
All the function does, is to add (push) a new "state" onto the browser history, so that in future, the user will be able to return to this state that the web-page is now in.
Normally, this is used in conjunction with AJAX calls (which refresh only a part of the page).
For example, if a user does a search "CATS" in one of your search boxes, and the results of the search (presumably cute pictures of cats) are loaded back via AJAX, into the lower-right of your page -- then your page state will not be changed. In other words, in the near future, when the user decides that he wants to go back to his search for "CATS", he won't be able to, because the state doesn't exist in his history. He will only be able to click back to your blank search box.
Hence the need for the function
history.pushState({},"Results for `Cats`",'url.html?s=cats');
It is intended as a way to allow the programmer to specifically define his search into the user's history trail. That's all it is intended to do.
When the function is working properly, the only thing you should expect to see, is the address in your browser's address-bar change to whatever you specify in your URL.
If you already understand this, then sorry for this long preamble. But it sounds from the way you pose the question, that you have not.
As an aside, I have also found some contradictions between the way that the function is described in the documentation, and the way it works in reality. I find that it is not a good idea to use blank or empty values as parameters.
See my answer to this SO question. So I would recommend putting a description in your second parameter. From memory, this is the description that the user sees in the drop-down, when he clicks-and-holds his mouse over "back" button.

window.history.pushState({urlPath:'/page1'},"",'/page1')
Only works after page is loaded, and when you will click on refresh it doesn't mean that there is any real URL.
What you should do here is knowing to which URL you are getting redirected when you reload this page.
And on that page you can get the conditions by getting the current URL and making all of your conditions.

Related

How can I navigate to a different href first, then let the code continue, using just JavaScript?

When I enter this code into the console on Chrome browser, the alert comes first, followed by the new href, even though the 'window.location.replace()' is in-front of the alert:
window.location.replace('http://stackoverflow.com/');
alert('hi');
I would like to know how to navigate to the new page, and then let the alert happen. How would I do that?
I would like to know how to navigate to the new page, and then let the alert happen. How would i do that?
You can't. The JavaScript environment in browsers is tied to the page. When the page is torn down, the environment is torn down with it. Even if you were to do something like this:
// Example of something that DOESN'T work
window.location.replace('http://stackoverflow.com/');
setTimeout(function() {
alert('hi');
}, 100);
...the timer callback would never fire, because the environment is torn down before it has a chance to.
All you can do is pass information to the next page so that code on that next page runs.
I think #T.J Crowder's answer covers it up very well, but I just wanted to emphasize his last sentence
All you can do is pass information to the next page so that code on
that next page runs.
That would of course only be implying you are redirecting the user to a location you own (unless you own Stack Overflow and I wasn't aware...), and a solution would be to pass GET parameters for example to alert the message you want, like this
window.location.replace('http://stackoverflow.com/?msg=hi');
Then in the other page, you would get the parameter msg and simply do
alert(get_msg);
The message can of course be passed via other way than GET (POST for example), and it is how most "known" frameworks work with their "flash" messages (which is no more JavaScript related)

Javascript state is saved when using back button to get to page

I am using Firefox, and I have noticed something interesting while working on my website. One page has a table of information, but also maintains Javascript variables indicating the table's contents so it can look up information more easily.
When I navigate away from the page by typing in a URL, then hit the back button to return, I have noticed that the page seems to retain its state. The table still has the same contents as when I left, and further interactions with the page indicate that the Javascript variables have maintained their values as well.
I had assumed that my $(document).ready(); functions would run again when the back button was hit, but this is clearly not the case as I wrote those functions to ensure the page is its initial state, regardless of the page's current content.
I think it is perfectly acceptable for the page to be restored this way as long as I can depend on the page being restored properly. If instead, the page is restored to its initial state, that would be acceptable as well.
Is it safe to rely on this behavior? Would I be better off using something like onunload to ensure that the page's state is not saved? Should I just assume the browser will do things properly?
I would say that my website's state is defined by the HTML on the page and the contents of Javascript variables. It uses AJAX (or I guess technically AJAJ) to interact with PHP pages, but all interactions are discrete transactions. The only state/session needed by the server are login authentication cookies, which should be unaffected by this.

Javascript: Rewrite anchor or hash to ampersand

How can i rewrite part of an URL to alter the anchor or has tag to an ampersand? Example:
http://www.test.com/?database=demo#option=set
changed to:
..website../?database=demo&option=set
Notice the change from #option to &option.
I know the # is only processed client side (it never reaches server), so Javascript seemed like the only way to go.
Can Javascript change this on the fly, even without reloading the page? That would eliminate an IF check to find if an instance exists. A reload if the page would work to1...
Thanks for your time and expertise.
"Can Javascript change this on the fly, even without reloading the page?"
No. What you think is a cosmetic change, in reality means totally different resource as represented by URL, because &option would mean new GET parameter.
So page redirect would be needed in order to change this part of URL.

history.pushState - not working?

I want to change html without reload. I do it like:
$('#left_menu_item').click(function(e) {
if (!!(window.history && history.pushState)) {
e.preventDefault();
history.pushState(null, null, newUrl);
}
});
It works correctly. But if I want to go back with "Back" button - browser change url on previous, but it not reload page. Why?
this behaviour is expected and is in accordance with the specifications of manipulating the history stack.
this is a relatively complex problem to explain. but in short think of it as this: any history entry the user pushes on the history stack (using pushState etc) doesn't merit a page load when you move from it because it is considered a fake (user generated) history entry.
why?
this behaviour is a good thing and is consistent with the intent of giving the developer more control over the page without being forced to reload it (think of it like ajax: you can do things that were previously only possible by page reloading like fetching data but now you can do it without reloading the page using the XMLHttpRequest object).. if you want to mimic the behaviour of reloading the page when clicking the back button.. you can simply call location.reload() when you handle the window.onpopstate event
how?
this may be outside the scope of your question but i just wanted to put it there to describe what we're talking about
let me explain by using an existing example here (excerpted text will be italicised):
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.
think of it as that you are creating an entry in the history stack that is not associated with an actual page load.. rather a 'fake' page load (ie you are just using javascript to manipulate the dom and insert html)..
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.
the point here is that bar.html is a fake history entry that sits on top of the original http://mozilla.org/foo.html.. so you will see on the url http://mozilla.org/bar.html but the contents will belong to foo (in this example notice that we didnt manipulate the content of the dom when we pushed bar.html.. if we did like in your example.. then that content will also show up). the key thing here is that the page reloads!.. because we are serving a page that has a genuin entry on the history stack (even if on the url.. we are displaying a url that is associated with a fake entry on the history stack).
also separate this discussion from the page manually handling the popstate event.. that's a different story and will just complicate things.
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.
here.. the page will not load!.. that's because we are making the transfer from a fake history stack entry to the real one (and the real one was already loaded in the previous step.. so the page reloaded and that's it).
that's it for the example. the concept is kind of hard to explain and i encourage you to test your code by clicking through a combination of real and fake pages and you will see a pattern of when the page actually loads and when it doesn't..
window.onpopstate = function(event) {
if(event && event.state) {
location.reload();
}
}
This is what I use :)

In Javascript, preferably JQuery, how do I add something to the URL when the user clicks "back" button in the browser?

When the browser clicks "back" button, I want to append "&page=3" to the URL.
How do I bind it, and then do this?
Edit: I want this very simple.
BIND the event{
window.location(that-url + "&page=3")
}
Can it be done that simply?
It sounds like you're trying to create a history plugin.
Have you tried using using the mikage history plugin?
I wouldn't recommend changing the URL when they navigate away from the current page (which is what the back button does), because you immediately erase the forward history (thus breaking the forward button). When trying to handle the back button with pagination and javascript/ajax it is more typical to use the browser hash to pass parameters. The JavaScript namespace doesn't get cleared when the forward and backward buttons are used and the hash is updated according to what navigation was used. These history plugins have a couple of methods to detect when navigation is used (as the doc load event doesn't fire).
So beware, writing a history plugin isn't straightforward because of the way browsers fail to consistently handle hash property of the location object (part of the window object). You will definitely want to look at what others have done.
We use the window.location.hash to handle the history in our app.
I guess it works well in single page apps and is very simple.
For multiple pages app, I don't think it's a good idea to try to control and change the natural page history of the browser.
When the user clicks "back" or "next", the hash key gets the previous or next value.
Because of IE7 you need to use a polling technique (but it is ok in all browsers), with a setInterval(...) and a fast function that checks for instance every 300ms if the hash has changed.
Then, if a change occurs, act accordingly.
ie: call the server and refresh some areas in the page.
It works very well, and does not kill at all the responsiveness of the application.

Categories

Resources