I want to make a page with a lot of Javascript interactions. However, while a user navigates through the page the URL must change too. So, when the user shares the URL or saves it, it can lead him to the actual state he was.
How can I do that?
Examples:
myapp.com/page1
myapp.com/page2
pushState, as seen on github
Answered by this SO question: Change the URL in the browser without loading the new page using JavaScript
The only part of the url (or location) that you can change without reloading the page, is the hash. That is the part behind the #. Many ajax enhanced applications make use of this, including Twitter. You can change this hash on the go, and interpret the hash tag on page load to initialize the page to the correct state.
Set this value: window.location.href
window.location.href = "myapp.com/page2";
Related
I am working on a free domain service provider and it appends its own brand name to my URL on the browser address bar. I want to prevent that by re-writing the URL to give the user a better look and feel. How do I do that using only Javascript (no add-on libraries)?
window.history.pushState(null,'title','/something');
First argument is data, you don't need that.
Second one is the new page title.
Third one is the url. However you cannot completely change it, it will still be relative to the domain.
Okay so there are solutions for this as in Modify the URL without reloading the page but I have one question regarding this.
So here is what I plan to do (let's assume my web address is example.com)
1. using pushState I plan to change the browser address to example.com/myprofile/myalbum. So to be clear, this new url may or may not exists but the browser address is changed regardless. In our case this url doesn't actually exist but we are using the address to mark a changed state of the webpage.
2. use ajax to load data regarding "myprofile > myalbum" to the same page.
But now here's the issue I have been thinking about. What if a user loads example.com/myprofile/myalbum directly on a, let's say, new tab. This page clearly throws a not found error because it doesn't exist.
So how do I load ajax corresponding to this fake url? For example http://www.usatoday.com/news/ seems to do this well (unless that's an iframe, which wouldn't be so nice).
You can add rewrite rules to your webserver, converting either specific URL's or some matching a pattern to something that your scripts can use to show the right page. You can have it rewrite the URL only internally, so the user still see the original URL in the browser. Such as:
RewriteRule /myprofile/(\w*) /index.php?path=/myprofile/$1
Different webservers will probably have different syntax, but they will be similar.
I have a page that dynamically loads content based on a user pushing a button:
${document).ready(function)
{
$("#myButton").click(function()
{
$("#dynamicDiv").load("www.example.com");
});
}
The dynamic content works fine, I can fetch pages all day long. But after you follow a link to another page, then press the browser back button to come back to the page, the page is completely reset as though no dynamic content had ever been loaded.
I swear I've seen different behavior before, but maybe I'm insane. Shouldn't the browser preserve the state of the page, rather than re-rendering it?
EDIT:
By the way, I'm using Play! framework, if that has any bearing on this.
The browser loads the page as it was first received. Any DOM modifications done via javascript will not be preserved.
If you want to preserve the modifications you will have to do some extra work. After you modify the DOM, update the url hash with an identifier that you can later parse and recreate the modification. Whenever the page is loaded you need to check for the presence of a hash and do the DOM modifications based on the identifier.
For example if you are displaying user information dynamically. Every time you display one you would change the url hash to something like this: "#/user/john". Whenever the page loads you need to check if the hash exists (window.location.hash), parse it, and load the user information.
Implementing browser back functionality is hard.
It gets easier when you use a plugin like jquery.history.js.
http://tkyk.github.com/jquery-history-plugin/
A technique I use for this is to serialize state to JSON, store it in the hash string, and then read it back when the page is navigated back to. This has been tested in IE10+, Firefox, Chrome.
Example:
// On state change or at least before navigating away from the page, serialize and encode the state
// data you want to retain into the hash string
window.location.hash = encodeURIComponent(JSON.stringify(myData));
// If navigating away using Javascript, be sure to use window.location.href over window.location.replace
window.location.href = '/another-page-url'
....
// On page load (e.g. in an init function), if there is data in the #hash, overwrite initial state data
// by decoding and parsing the JSON string
if (window.location.hash) {
// Read the hash string omitting the # prefix
var hashJson = window.location.hash.substring(1);
// Restore the deserialized data to memory
myData = JSON.parse(decodeURIComponent(hashJson));
}
epignosisx and Malcolm are both right. It's also known as "deep linking". We used the JQuery Address Plugin to deal with this in a recent Play application.
http://www.asual.com/jquery/address/
Still now I knew Its not Possible to change the contents of location bar without changing the page (and Yes I am not talking about #). I've recently noticed github.com. How they are doing that on their site ? they can easily get an event when user clicks on Browser's back or next button. dojo.back also have this feature. But how to change the addressbar with javascript without leaving the page ?
There are two ways:
HTML5's pushState() function. Facebook and Github use this, for example. It allows you to modify the complete URL and fires event handlers when the history state changes. Mozilla has a good overview.
The old variant is to use the hash part of the URL (this is what Twitter does). This means that you change window.location.hash, monitor it for changes and, based on the value of that hash, load the appropriate content. However, this means that when the user requests, say, http://twitter.com/#!/27c3/status/18331752900591616, only the part before the hash sign is requested form the webserver, everything after the hash is only the client's business. This means that the server can not yet decide what content to hand to the client.
try dojo.hash
What you're referring to on GitHub is the # (hash). When you right click on a line number, it adds the number to your hash.
window.location.hash = 'HELLO';
Put that in a page to try it out. It's not possible to change window.location without the page reloading. The back button stuff is a little trickier, but Dojo is your best bet for that. jQuery doesn't provide this. Dojo has pretty clean code though, so you should be able to reverse engineer their functions (if you chose to include that functionality into your own library).
You'll also notice Google is doing the same with: http://code.google.com/p/digitalxero/source/browse/#svn%2Ftrunk%2Flocale%2Fde
If you click on folders (left), it changes the hash, and provides different content.
I am working on an AJAX website where there are two search parameters. I did some mod-rewrite and checking for $_GET variables so that i can do something like..
site.com/var1/var2/ -> automatically do the search based on the parameters.
Now what I want is for people who do the search manually, to be able to have the url in that format. The only method that I've been able to find has to do w/modifying the url using..
location.hash = 'foo';
which would make it something like.. site.com/#var1
Which isn't as nice as the mod-rewrite. What I have found that works is if in my search function that does the ajax call i have this code
// avoid appending further variables if there are already variables
if(location.href == 'some absolute website path')
location.href = var1+'/'+var2+'/';
This will work, but basically forces the page load and then my auto search php/javascript will kick in due to the mod-rewrite. SO this works, however it involves an extra page refresh that I would rather avoid.
Any better solutions out there? Ideally if i was able to use location.href where it didn't cause the page to load once i change the value, but would just change in the url would be ideal (while maintaining my mod-rewrite links, w/out the # marks).
I am using jquery and php.
It's that way by design, there is no way yo change the url or path without causing a new request. Regards.