browserstate / history.js

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.
http://browserstate.github.com/history.js/demo/
Other
10.75k stars 1.35k forks source link

URLs can be shortened further. #28

Open balupton opened 13 years ago

balupton commented 13 years ago

Currently for HTML4 browsers, the entire URL besides the hostname is included in the hash. This could be optimised further to just include the relative path to the mother location.

For instance instead of: http://localhost/products/history.js/demo/#/products/history.js/demo/?state=2

It can become: http://localhost/products/history.js/demo/#?state=2 or http://localhost/products/history.js/demo/#./?state=2

Which is a lot leaner.

marksyzm commented 13 years ago

Looking forward to this one - this might be something people should be made aware when using this in conjunction with rewritten URLs though

balupton commented 13 years ago

Will be in v1.6.1.

marksyzm commented 13 years ago

Would you be forcing the paths to be relative to something in particular i.e. the document loaded and can we still use absolute paths? I thought I'd ask at this point before it gets published

balupton commented 13 years ago

Correct.

The long url: http://localhost/products/history.js/demo/#/products/history.js/demo/?state=2

Will be shortened to: http://localhost/products/history.js/demo/#./?state=2

However the long url: http://localhost/products/history.js/demo/#/pages/about

Cannot be shortened further.

So only hashes which are relative to the parent document location will be shortened further by using a relative path.

mattwright commented 13 years ago

Excellent -- I was also hoping for this! Thanks for all the hard work on this library. If it perfectly matches, can it end up with nothing after the hashtag?

For instance, the long URL:

http://localhost/products/history.js/demo/#/products/history.js/demo/

shortened to:

http://localhost/products/history.js/demo/#

balupton commented 13 years ago

This has been added to dev.

balupton commented 13 years ago

v1.7 is now out which resolves this issue :)

balupton commented 13 years ago

Hey guys. Opening this back up for some discussion.

In v1.7 url structure is like so: (option 1)

I'm considering changing it to: (option 2)

Or: (option 3)

Thoughts? As currently in v1.7 the sudden removal of ./ when traversing states from ./bbb to bbb/ccc could potentially be confusing in terms of url hierarchy for unfamiliar users. All feedback is appreciated. Option 3 is the most consistent.

The reason for the ./ in the first place is because #bbb could be a traditional anchor to an element on the page.

joeybaker commented 13 years ago

+1 for option 3 – as you say, it's the most consistent.

josefrichter commented 13 years ago

+1 for option 3

and +1 for just /#/ if user starts from homepage :-)

deleteme commented 13 years ago

+1 for option 3

mattwright commented 13 years ago

I agree a consistent format is nice (option 3). One other thing I would like to see is, if you have a URL like:

http://mysite.com/aaa/filename.html

It will appear in the location bar as:

http://mysite.com/aaa/filename.html#./filename.html

Since it is finding the base directory /aaa/ and then going from there. Is there any chance that if the filename is exactly the same as used in the URL, it just uses an empty hashtag (or something much shorter)? Not being familiar enough with the codebase, that may be a very difficult request, in which case nevermind.

Matt

balupton commented 13 years ago

Thanks everyone for your feedback. I'll make the change to option 3 in the next release :)

@mattwright The issue with having an empty hashtag is that it is ambiguous on whether or not it is a traditional anchor or a state hash. So unfortunately that won't be possible.

marksyzm commented 13 years ago

Is there any reason why you can't have all those options?

balupton reply@reply.github.com wrote:

Thanks everyone for your feedback. I'll make the change to option 3 in the next release :)

@mattwright The issue with having an empty hashtag is that it is ambiguous on whether or not it is a traditional anchor or a state hash. So unfortunately that won't be possible.

Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/28#comment_1022906

mattwright commented 13 years ago

ok, thanks! I just realized all I need to do is add a trailing slash and it should be closer to what I want...

balupton commented 13 years ago

@marksyzm "Is there any reason why you can't have all those options?"

;-)

In regards to software:

http://gettingreal.37signals.com/ch05_It_Just_Doesnt_Matter.php

http://gettingreal.37signals.com/ch05_Start_With_No.php

http://webappsatwork.blogspot.com/2009/07/system-feature-death-spiral.html

Apple and 37Signals follow this religiously.

In regards to life:

This isn't just applicable to programming but applicable with life too. Ever tried buying an after-shave? Do you want the re-vitalise or the re-energise, or the one with Q10 or the one without, or ... - honestly I would prefer it if there was just one after-shave, no frills, straight to the point like the way of the Gillete Fusion Brand - one way, it works. Nivia gives me a big headache and makes me spend an hour reading the packaging finding out which is "better", leaving me with whichever one I chose it isn't the right one - when really in the end, it just doesn't matter.

http://www.ted.com/talks/dan_gilbert_asks_why_are_we_happy.html

http://www.youtube.com/watch?v=YYOAslBbURI - "too many options may kill a man"

georgyangelov commented 13 years ago

Why don't we just use #!path. The "!" would suggest it's not a normal hashtag plus it is recognisable by google and it's kind of an undocumented standart. So there's no need for "./".

I really like your lib, and I'm looking forward to using it.

marksyzm commented 13 years ago

Don't start us on that topic... the gist of that is it will be deprecated in a couple of years due to HTML5 history already existing and it's not even that great for seo. It's basically unnecessary.

stormbreakerbg reply@reply.github.com wrote:

Why don't we just use #!path. The "!" would suggest it's not a normal hashtag plus it is recognisable by google and it's kind of an undocumented standart. So there's no need for "./".

I really like your lib, and I'm looking forward to using it.

Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/28#comment_1068679

georgyangelov commented 13 years ago

It's just that you stated "The reason for the ./ in the first place is because #bbb could be a traditional anchor to an element on the page." and that makes it clear. I don't see what's wrong about using a special character and what's the difference between "#!", "#$", "#%", "#./" or any other that you can choose.

marksyzm commented 13 years ago

On 28/04/2011 13:48, stormbreakerbg wrote:

It's just that you stated "The reason for the ./ in the first place is because #bbb could be a traditional anchor to an element on the page." and that makes it clear. I don't see what's wrong about using a special character and what's the difference between "#!", "#$", "#%", "#./" or any other that you can choose.

./ isn't a special character in it's essence though - it's just the

usual nature for linux based directory pathing for current directory? The point of having those options is merely so you can have absolute and relative paths

balupton commented 13 years ago

Marksyzm hit it right on, the ./ and / refer to the UNIX standard for relative and absolute file system paths. The hashbang #! refers to the google recommendation for breaking the web by the use of escaped fragments, duplicate state locations, and google only SEO.

drewish commented 13 years ago

Yeah I'm kind of scratching my head wondering why this plugin doesn't use #! which could make it google compatible. I only noticed this bit of wonkyness when I was debugging some IE issues. I'd just sort of assumed it did the "right" thing.

balupton commented 13 years ago

@drewish, for more info on the #! problems - https://github.com/balupton/history.js/wiki/Intelligent-State-Handling

drewish commented 13 years ago

My though is that the history API handles modern browsers so all I need to do is have #! work for IE and old browsers until they die off.

I'm aware of and prepared to work around the issues you identified—I wish I'd seen that list before I had to figure them out myself ;). I hadn't started on the the server side URL rewriting for the escaped_fragment but built a custom ajax page callback to render just the changed portion of the page and pass it back along with meta info like page title and new JS and CSS. In both the full page and partial page callbacks I'm sending back full links that would work for non-JS browsers, the browser rewrites the links to point to the ajax callback.

So given all that what do you think the cleanest way to fork/customize your code to support #! would be?

marksyzm commented 13 years ago

You can't rewrite hashed URLs on any apache server - it is never read in the request URI as it is regarded by web servers as a comment

drewish reply@reply.github.com wrote:

My though is that the history API handles modern browsers so all I need to do is have #! work for IE and old browsers until they die off.

I'm aware of and prepared to work around the issues you identified—I wish I'd seen that list before I had to figure them out myself ;). I hadn't started on the the server side URL rewriting for the escaped_fragment but built a custom ajax page callback to render just the changed portion of the page and pass it back along with meta info like page title and new JS and CSS. In both the full page and partial page callbacks I'm sending back full links that would work for non-JS browsers, the browser rewrites the links to point to the ajax callback.

So given all that what do you think the cleanest way to fork/customize your code to support #! would be?

Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/28#comment_1214744

drewish commented 13 years ago

You misunderstood what I was saying. I'm only concerned about rewriting Google's escaped_fragment version of my path back into the proper path that the server expects.

marksyzm commented 13 years ago

On 21/05/2011 19:12, drewish wrote:

You misunderstood what I was saying. I'm only concerned about rewriting Google's escaped_fragment version of my path back into the proper path that the server expects.

What would you expect an escaped fragment to look like then? (URI please)

balupton commented 13 years ago

@drewish the HTML5 History API deprecates the hashbang. With the HTML5 History API it requires absolutely no effort to achieve SEO, as the HTML5 History API URLs point to traditional urls, traditional urls as in those indexable by ANY search engine. If you are not wanting to use the HTML5 History API with traditional urls, then you should not be using the HTML5 History API. History.js will never support the hashbang, as it does not make any sense, and if you do try, it will kill your SEO in google - as suddenly there are two indexable urls for google (the traditional, and the hashbanged one). Please direct any hashbang queries elsewhere to projects which do not use the HTML5 History API.

drewish commented 13 years ago

I'm either doing a very poor job of explaining myself, or I'm completely misunderstanding something. In either case I appreciate your patience.

I agree that HTML5's history API works great and has no-SEO concerns. It's older browsers and all versions of IE that's I'm not sure how to deal with. My understanding was that Google would let you use the hashbang paths along side clean URLs and that you could use the canonical link to avoid the duplicate content penalty. Based on the comments here and re-reading their docs (http://code.google.com/web/ajaxcrawling/docs/faq.html#linkrelcanonical) I'm less certain this will work.

What's unclear to me now is how you'd avoid loosing all the search value of people using IE who copy paste the hashed link into a link on their site or Facebook. Google won't recognize that as the same as the clean URL, will it? Is there any way to deal with that?

marksyzm commented 13 years ago

That's a very good point... I'm even less impressed about Google doing that now.

drewish reply@reply.github.com wrote:

I'm either doing a very poor job of explaining myself, or I'm completely misunderstanding something. In either case I appreciate your patience.

I agree that HTML5's history API works great and has no-SEO concerns. It's older browsers and all versions of IE that's I'm not sure how to deal with. My understanding was that Google would let you use the hashbang paths along side clean URLs and that you could use the canonical link to avoid the duplicate content penalty. Based on the comments here and re-reading their docs (http://code.google.com/web/ajaxcrawling/docs/faq.html#linkrelcanonical) I'm less certain this will work.

What's unclear to me now is how you'd avoid loosing all the search value of people using IE who copy paste the hashed link into a link on their site or Facebook. Google won't recognize that as the same as the clean URL will it? Is there any way to deal with that?

Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/28#comment_1222203

balupton commented 13 years ago

Google won't recognize that as the same as the clean URL will it? Is there any way to deal with that?

Correct, when a user posts a link that contains a hash, it won't (or is extremely unlikely) that it will be recognised by search engines. The only solution to this is to disable html4 support in history.js so hashed are not used. Another solution would be to ensure the user copies the permalink instead of the URL.

marksyzm commented 13 years ago

You could do that by changing the content the user copies with JavaScript when they right click and copy a URL perhaps.

balupton reply@reply.github.com wrote:

Google won't recognize that as the same as the clean URL will it? Is there any way to deal with that?

Correct, when a user posts a link that contains a hash, it won't (or is extremely unlikely) that it will be recognised by search engines. The only solution to this is to disable html4 support in history.js so hashed are not used. Another solution would be to ensure the user copies the permalink instead of the URL.

Reply to this email directly or view it on GitHub: https://github.com/balupton/history.js/issues/28#comment_1225344

balupton commented 13 years ago

You could do that by changing the content the user copies with JavaScript when they right click and copy a URL perhaps.

Well by default the a.href should link to traditional url, the issue is with copying the url from the url bar.

rzepcio commented 13 years ago

Could you tell me if possibility to turn it off exists? I rewrite URL if it contain hash and more than domain address before... and I can't rewrite it correctly if there is not full link.

e.g. I turned http://example.pl/Main/Home#Main/AboutMe to http://example.pl/#Main/AboutMe by reloading a page.

balupton commented 13 years ago

@rzepcio not sure what you mean, or why turning it off would solve the problem... can you elaborate further?

rzepcio commented 13 years ago

Well, I have already worked around this problem (by doing the same as you do but in different direction) but here you go. I don't like solution with shortened links, because it still can have redundant data, so I reload the page and load the shortest possible version of link like I wrote earlier:

http://example.pl/Main/Home#Main/AboutMe to http://example.pl/#Main/AboutMe

or from your shortened version:

http://example.pl/Main/Home#./AboutMe to http://example.pl/#Main/AboutMe

Problem was that I need to turn that "." to "Main" again to have full address which I should load.

$(document).ready(function () { _hash = window.location.hash; if ((_hash.length > 0)) { _hash = _hash.replace('.', '').replace('#', ''); var _link = _hash; History.pushState(null, null, _link); load(_link); } });

With the code above I reload site if it contains hash, it works for two actions:

For second case I use code in statechange:

if ((_hash.length > 0) && (window.location.pathname.length > 1)) { var _hashSplitted = _hash.split('/'); var _pathSplitted = window.location.pathname.split('/'); if (_hashSplitted[0] === '#.') { _hash = '#/' + _pathSplitted[1]; for (var i = 1; i < _hashSplitted.length; i++) { _hash += '/' + _hashSplitted[i]; } }

window.location = window.location.protocol + '//' + window.location.host + '/' + _hash;
return;

}

fterenzani commented 12 years ago
Google won't recognize that as the same as the clean URL will it? Is there any way to deal with that?
Correct, when a user posts a link that contains a hash, it won't (or is extremely unlikely) that it will be recognised by search engines. The only solution to this is to disable html4 support in history.js so hashed are not used. Another solution would be to ensure the user copies the permalink instead of the URL.

And what do you think about hashbang + _escaped_fragment= that redirects with a 301 status code to the html5 version of the URL? Would it be the perfect solution for SEO?