Assigning to document.location.href without clobbering history - javascript

In testing document.location.href, I have observed that when the user initiates an action that results in javascript that assigns to document.location.href, the new URL is added to the history.
However, if the call is initiated by javascript that is result of, say, state change of an XMLHTTPRequest, the entry for the current page in the history is over-written. Have I characterized this correctly? Is there a way to get the page change to be reflected in the history in this latter case?

I was facing the same problem and found this workaround which worked for me
instead of
function onAjaxCallback(evt){
location.href=newLocation;
}
i wrapped the location.href call around a setTimeout. Seems to do the trick. My history's behaving fine now. Hope that helps
function onAjaxCallback(evt){
setTimeout(function(){
location.href=newLocation;
},0)
}

You could change the location without having the browser display a Back button like this:
window.location.replace(new_url);
However, the original address remains in the browser's history and may be accessed using something like CTRL+H
Reference:
https://developer.mozilla.org/en/DOM/window.location#replace
https://developer.mozilla.org/En/DOM/Window.history#Notes

study: window.location.replace() and window.location.assign()

URL can be manually added to history before redirecting the user.
if (window.history) {
history.pushState({}, window.location.href);
}
window.location.replace("/login/?next=" + window.location.pathname);

Read the original question more carefully. The question is not about content loaded by an XHR, but about content loaded by a script loaded by an XHR. I had the same problem and the setTimeout method seems to work well.

Alas, your question can't be answered, AJAX requests have nothing to do with browser history, and if you loaded some dynamic content with them, then the user clicked the browser back button, the previous page is loaded (this which was loaded with an ordinary GET or POST request), which corrupts the sequence you display content in.
Dmitri's answers means that you will maintain your own history for the dynamic content using the fragment part of the url (this after the # symbol), maybe you'll provide your own back and forward buttons, but still you're not protected from the effect of the browser back and forward buttons.
If only they had provided some kind of events to handle user clicks on these buttons with the ability to cancel.

Related

Reloading ajax retrieved data after page refresh

So, I have a page that has several links with onClick events that will retrieve data from external files and fill a div with this data. This works as intended. When I refresh the page, however, the div empties again. What I would like to happen is that after a refresh, the div will maintain the last content retrieved.
I'd prefer not to go down the road of cookies and have looked into adding data to the URL which I think is the way I want to go with this.
Is there some nice JQuery calls that can append data to url when a link is clicked and then on refresh restore the required content to the div?
My loadContent function is:
function loadContent (url, container) {
var target = $(container);
target.load(url, function (text, statusText) {
if (statusText === "success") {
target.find("a[rel^='gridnav']").initgn();
}
});
}
edit: I forgot to mention, the line
target.find("a[rel^='gridnav']").initgn();
is used to re-initialise a script on the new content loaded.
So when I click a link, the onClick event calls the function like this
TEST</li>
where xyz.html contains only the data I want inside the div "#right"
Is there a way to edit this function to do what I want ?
You can append data to the url by using
window.location.hash
https://developer.mozilla.org/en-US/docs/DOM/window.location
If you search for QueryString in jQuery plugins, there should be dozens of plugins that simplify this task.
I'd use localStorage. It's like cookies but much, much easier to maintain. The only downside is that it's not supported by all legacy browsers (See http://caniuse.com/#search=localStorage for browser support). For an orview on thhe feature, see https://developer.mozilla.org/en-US/docs/DOM/Storage If you want to go with completely no cookie like features at all; well then it has to be done server side to the best of my knowledge
Without cookies, your task will be a little bit harder. But I may have two solution for you:
Using session on server, you can control which ajax has been call, so next time when the main page is loaded, you can append the new content to it.
Using url hash to append ajax anchor has been click #anchorname so you can click it a gain after reload.
The comment tells you how you can modify the url without a page load. You could use that. If you have to work with older browsers, then you can still use the fragment (or do both things).
There are some history plugins for jQuery/JavaScript that manage this .. it's a technique called "deep linking." You may be able to find something simple to work with. Basically when loadContent runs you would want to update the url from /whatever to /whatever#right with the fragment indicating the load-content ID or something like that.
Another alternative would be to set some flag on the server that loads into that div when the page loads initially, which would save you an ajax request too. Depending on how your server code is set up that may not work for you, though.

Is there a way in History.js to know when the back button was pressed

I've started to test History.js. After understanding how it works and that there is no popstate, instead there is statechange. I'm looking for a way to differ when the back button of the browser has been pressed.
The reason is that I need to know the URL before the state moved, from the one I'm going to. With the gist the project includes, only the URL we go to is looked.
I hope the solution is not to track latest URL visited in a global variable.
Thanks
I found the solutions on github to be a bit overdone for my purposes. I created a bool that is always true except right before when I used History to change the state.
var manualStateChange = true;
History.Adapter.bind(window,'statechange',function(){
if(manualStateChange == true){
// BACK BUTTON WAS PRESSED
}
manualStateChange = true;
});
Any time I change the state programmatically, set the bool to false:
manualStateChange = false;
History.pushState(null, null, currentPath);
I know this is a pretty dated question, but I came up to a solution to issues with the back/forward button when switching between a standard page and a History-state page.
Scenario:
Use HTML5 History (or history.js plugin) on a set of pages
Then other pages we need real loads, aka a standard page (don't ask why, but there are certain use cases that this may be needed)
When you go from a History-state page, and do a real load to a standard page. You cannot go BACK: it changes the url, but doesn't load the page--it only fires a statechange; which I assume is the issue of the original post. My personal opinion is that this is a browser bug (all browsers have the issue, though), because the browser should know the page you're on was reloaded outside of the History-state page.
I fixed this with something really simple:
Listening to the statechange event and tell the browser to refresh when it does fire. This way I don't care if they go back or forward out of this page. If the browser thinks the state is changing (links don't fire the statechange event), only back/forward INTO a History state page fires this event, so it solves the issue.
Code, using jQuery + History.js plugin:
$(window).on('statechange', function() {
window.location.reload();
});
If this doesn't make sense, you're probably not having this issue. However, I've noticed this on many sites that do use HTML 5 History (even pinterest.com has this issue if you reload when on an image modal and then try to go back).
Hopefully, if you do have this issue, you'll find this answer and have a huge sigh of relief :)
I finally managed all links using History.pushState, that way there is no need to differ a back button pressed. We handle all state changes the same way.
Edit: Found these two issues in History.js' Github, might help someone.
https://github.com/browserstate/history.js/issues/70
https://github.com/browserstate/history.js/issues/47
In the 'offical' version this feature is not available. Try to use this file in the main while:
https://github.com/danger89/history.js/blob/master/scripts/bundled/html5/jquery.history.js
I can't guarantee that his solution works for every browser. But it's a nice solution. If you applied his changes, you can use:
var State = History.getState();
if (State.navigation) {
// Back / forward button is pressed.
}
More information can be found on Github issue 47.
Similar answer than that of James Wagoner.
the 'statechange' event was being fired both ways, so instead I only check for a 'popstate' event, which in my case is only called when the user goes back.
window.addEventListener('popstate', function() {
window.location.reload();
});

Can I load new content using AJAX, but change the URL in the omnibar?

I don't want to use hashbangs, or shebangs, as they are known. I want to do it the way Facebook does. You click on Profile, the bar remains unchanged and the content is loaded using AJAX. I was wondering if the new HTML5 History API could be used.
EDIT: I think I'm going to go ahead and dive into HTML5's history API. Keeping the question open in case anyone has better suggestions.
The HTML 5 history API is the right way to go.
see here: https://www.new-bamboo.co.uk/blog/2011/02/03/degradable-javascript-applications-using-html5-pushstate/
The pushState and replaceState methods will allow you to change the URL without making an HTTP request. The difference being that pushState pushes a new state on to the history stack, while replaceState replaces the item at the top of the stack.
Also take a look at jquery-pjax
You don't need to do that. You can just prevent the default action from occuring. For instance, with jQuery we have;
function(event) {
event.preventDefault();
// this is different from event.stopPropogation()
// do some stuff
}
this will prevent the link's default action (following the url) from occurring.
P.S. I've always heard shebang refers specifically to this: #!, and not just #, but I could be misinformed...

Hash doesn't work with back button; Need javascript to call function on url change

Hey everyone, this code is meant to read what comes after the hash in the url and display a specific div depending on that value. Right now it works fine, except for when you try changing the hash while you're already on the site (or if you hit the back button, which has the same effect: changes the hash, but the div isnt changed). The site is made so that it doesnt reload with every div change (the main content of the page), so I'm assuming the reason the div doesnt change when you hit the back button or type in a different value after the hash is because the page is already loaded, and the javascript code is only called once on page load. I need a way for it to be called whenever the url is changed. Here's the code:
function hash() {
var hash = window.location.hash.replace('#','');
InsertContent(hash);
}
I'm afraid it's not a bug, it's a feature. Opera for example stores the exact state of a page in memory. So if you hit the back button, that state will be restored exactly. It's like you've never change the page.
Changing the hash should work though, by calling InsertContent() right after you've changed the hash. Doesn't that work? Can you show us the code?
You need to poll the window.location.hash and see if it changes. Some browsers support onhashchange event.
Another discussion: On - window.location.hash - Change?
jQuery has a plugin called "address" to address this problem

Changing the URL with jQuery without reloading the page

How do I change the URL with jQuery without reloading the page?
Set location.hash
jQuery has nothing to do with it though, this is basic DOM 0.
You can only change the hash part of an url without a page refresh through location.hash.
Adding get parameters (?foo=bar) or a complete url change will always reload the page.
In HTML5 you get more options to change URL's, but right now (2010) it's not yet viable since crappy browser die out hard.
In general, leaving aside the new HTML history API, you can't.
It is possible to add data to the URL after the hash (using location.hash as David Dorward describes). However, if you want to do this to affect behaviour of the page, you will also need to read these changes via jQuery (or triggered by the same process that sets the hash.)
Outside of the History API you will not be able to add a parameter, and have the page 'just know about it'.

Categories