If I go to a sub-path of a domain, the normal way is to do Some Path. This will reload the page completely.
But on Facebook, when you open a photo, the url on the address bar changes, however the entire page doesn't reload, it only loads the photo platform. So in this way people can share url of photos. I'm wondering how is this done?
I've done some search and some people suggested using history.pushState, however, this is only working on most modern browsers. The one on Facebook also works on IE 7, I'm wondering how they did it?
As you said, history.pushState is only available on modern browsers (noteably IE>=10).
For older browsers, the only way (as far as I'm aware) to change the URL in any way, was to use the "hashbang" technique - using/abusing the ability of hashs in URLs to retain page information. You'd then end up with a URL similar to index.php#!page=x&foo=bar where the hash would be used to represent the current page. The URL would then map one to one with a link such as index.php?page=x&foo=bar, and on refreshing the page, the JavaScript could read back the hash and display the page appropriately. It was by no means a great solution, in particular the browser doesn't correctly store your history, but it was still very popular.
If you're looking to use Ajax to reload pages and change the URL at the same time, then perhaps look into libraries such as History.js / Ajaxify, which will try to use pushState where available, but fall back to using hashbangs where it has to.
You seem to think that facebook supports Ajax for Legacy IE. I'm not aware of this as I can't say IE7 is very often my go-to browser, but IIRC Twitter has far less time for older, less feature-full browsers, and falls back to a much simplified interface (I think it even uses a basic mobile view). I'd probably take a similar stance if it was my website, and make use of pushState where available, and simply offer standalone pages where not. Working on backwards compatibility in these areas has the tendency to be fairly arduous (although the above-mentioned plugins will take quite a considerable load off), and unless you need to offer support, maybe it's just not worth it?
I do not know, how facebook did it, but if you look in the "routing" chapter of Backbone.JS you will see, that
For browsers which don't yet support the History API, the Router handles graceful fallback and transparent translation to the fragment version of the URL.
And if you look further, the sourcecode says:
// Backbone.History
// ----------------
// Handles cross-browser history management, based on either
// [pushState](http://diveintohtml5.info/history.html) and real URLs, or
// [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
// and URL fragments. If the browser supports neither (old IE, natch),
// falls back to polling.
This is the mentioned article to onhashchange.
That is probably the way to go.
Related
Recently, we found that Firefox had made a change towards plugins, such that the user will be temporarily blocked from running them if they are not using the latest version. Our site requires Flash to play sound and interact with the user's webcam/microphone, so we need to do whatever we can to ensure they're not getting these warnings.
One way suggested to me is to create a small Flash control, and wait for it to tell Javascript that it's been initialized. If not (and the user is using Firefox) then they are taken to a page prompting them to update. This may work, but I worry about its reliability, and about running it on every page in our site.
Alternatively, I've been researching a way to use Javascript to detect versions, without making a Flash control. I not only need the user's current version of Flash, but also the version Firefox will expect - and I haven't found an autonomous way of doing so. I don't want an admin to have to change a small value each time Adobe releases a new version. Does anyone have any advice how I could find Flash's latest available version, or an alternate way to solve my problem?
I recommend you have a look at SWFOject and the Express Install option which should ease upgrading considerably.
I just noticed someone upvoting this question, so I thought that I would provide my eventual solution, which I think reduced the impact of a recent issue where Firefox blocked the most recent edition of Flash, pending Adobe's fix.
Basically, I went with a variation on the second paragraph in my question. It does not direct the user to a new page; instead, it opens a dialog over the current page that explains it's having issues communicating with Flash. (It does not specifically say "Your Flash is out of date" because this can also happen if the browser is hiding flash under a Yes/No user dialog). It also contains a small fake flash object, with the idea being that if the browser wants to display a security warning, accept prompt, etc., it can do it inside that space.
The dialog goes away on its own if said Flash control ends up making its callback to JavaScript. It also installs a variable under sessionStorage so we don't bother checking for it again (Flash takes enough time on some computers that you might see the dialog for a split second).
I am attempting to create a login button for web application which either loads an iFrame or a pop up window. Similar to that of Facebook login button. Im currently using the postMessage() method which works a treat.
However I know that it wont work in IE6/IE7 which I need to support. Is their any alternatives I could possibly use? or am I hoping for to much from the "awesome browser" that is IE6?
Back in the day, I used to write IE6-based websites that opened popups and communicated between the popup and the original window.
So it can be done.
The browser provides a few objects you can use for this -- window.caller is the one you'll most likely want for passing calls back from the opened window to the original one, in addition to the object returned by the window.open() call, which you can use to pass calls from the original window back to the new one.
These two together will allow you to communicate in both directions.
You might also have some joy with jQuery, as I believe there are several plugins that wrap these methods in more friendly interfaces.
However, be aware that what you can do is a lot more limited in these older browsers than what's possible now, so even though you will be able to do to cross-window comms, you may find there are things you need that can't be done in older browsers.
Hope that helps.
Which one is better? Using fragment identifiers...
http://www.alinkthatdoesnotwork.com/#!/dir1/dir2/file.html
...or the new Javascript History API?
https://github.com/examplethatdoesnotwork/project/src/script.js
Or should I use both? (via fallback)
Aspects:
Compatibility/Support
Speed
Convenience
Hashtags are a means to categorise content on Twitter, you mean fragment identifiers.
Using fragment identifiers to indicate what content to load via Ajax is a terrible idea. They are a hack that is fragile, search engine unfriendly (except with more hacks on both sides) and depends on JavaScript.
The history API is a robust system that is actually designed to do that job. The only problem with it is browser support, but (unlike the fragment identifier approach) it gracefully degrades to real URIs that will be passed directly to your server (which is what Github does).
Even Twitter appear to be about to switch to the history API.
The new history methods are incredibly useful for AJAX navigation. For example, pushState or replaceState allow you to update the browser's address bar so the user sees a clean URL instead of an ugly hashtagged thing.
However, as I'm sure you're aware, support for the new API is still limited. location.hash is much more widely supported at this point, meaning that you'd have to write a hash fallback for browsers that can't take advantage of the newer window.history stuff.
The history API is vastly preferable, so long as normal links work normally in browsers that do not support it.
You could use a library such as History.js to enable it in these browsers.
More information here: It's About The Hashbangs, Side Effects of Hash-Bang URLs.
In a nutshell, URLs are important. URLs are forever, and cool URLs do not change, and finally: Once you hashbang, you can’t go back.
I think the question is what is support. You can't go solely with History API at the moment because it is not supported by IE. You'll need a fallback solution like GitHub does.
You've listed "compatibility" as your first criterion. Since the history API isn't yet supported by all major vendors (I'm looking at you, Microsoft), not even in their most-recent releases (IE9 doesn't have it), that pretty much means you have to use the hash. (Which is too bad, but there we are.) And it's not just Microsoft, lots of mobile devices are using one- or two-versions back of their mobile browser, and so still don't have it.
How can I save history with AJAX just how github or google+ do. I use jQuery and I do not want to use some kind of hack like the # and #! tricks, because if I do, I'll need to change my whole project and make my life much more complicated?
Github and Google+ are using history.pushState.
You can change the current url like this:
history.pushState(null, null, '/the-new-url');
This is supported by Firefox, Chrome, Opera, Safari; not IE.
See https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history#The_pushState%28%29.c2.a0method
There are basically two options when it comes to AJAX and history.
The # method (which isn't a hack btw). Since you don't want that one you only have option 2 left.
Use PushState. This is what Facebook, GitHub and a few others use. It's not supported by all browsers though and if you want complete cross-browser compatibility you will have to use a system which can degrade to option 1.
A very simple way to implement this is Backbone.js Router class.
There is a simple jQuery hashchange plugin that is designed to solve this specific problem.
I haven't used it; I don't know how it keeps track of the url history.
Background
Detection of hash change in the URL and fixing the forward/back button are two requirements for libraries that deal with Ajax history. There's two schools of thought for implementing these libraries. You can have a poller constantly check the URL (bad browsers don't have the onHashChange event). Or you can use a hidden iFrame to add points in your browser history. One may think the hidden iFrame is better than polling, but the hidden iFrame does not update the outer browser's URL. So if a user wanted to share her current state in the web application, she would always be sharing her initial state.
Question
Is there any technique for Ajax history that both doesn't require polling and also updates the main browser's URL?
How about a combination of the two techniques? change the url, as well as use the iframe. ignore hashChanged (on good browsers), and just parse the hash code on dom:ready
Looking at your comments from the original question, I would recommend using the iframes method for IE and polling for other browsers.
Check out Real Simple History if you are looking for a library that handles this specifically and you want a basis to help roll your own.
If you are just looking for the functionality of keeping your page's state in an Ajax UI, dojo supports this with the dojo.hash() shim. This method creates the onhashchange event for browsers that do not support it and manages the state of your back button. It uses a mix of polling and iframes depending on the browser (iFrames are used specifically in IE versions < 8).